diff --git a/pd-lib-builder/CHANGELOG.txt b/pd-lib-builder/CHANGELOG.txt index 5bdfce6..c432148 100644 --- a/pd-lib-builder/CHANGELOG.txt +++ b/pd-lib-builder/CHANGELOG.txt @@ -1,5 +1,13 @@ Changelog for Makefile.pdlibbuilder. +v0.7.0, dated 2023-07-06 +- build double-precision externals with the 'floatsize' variable +- allow building multiple flavours of an external side-by-side (#78) +- facilitate multiple platform co-installation of shared lib (#58) +- fix use of shared.ldflags with helper-library (#64) +- fix broken armv6l platform detection (#71) +- improve documentation + v0.6.0, dated 2019-12-21 - detect target platform (OS and architecture) rather than build platform (#55) - introduce optional user variable 'PLATFORM' for cross compilation diff --git a/pd-lib-builder/Makefile.pdlibbuilder b/pd-lib-builder/Makefile.pdlibbuilder index 40160bc..38a1220 100644 --- a/pd-lib-builder/Makefile.pdlibbuilder +++ b/pd-lib-builder/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ # Makefile.pdlibbuilder dated 2019-12-21 -version = 0.6.0 +version = 0.7.0 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -102,6 +102,8 @@ version = 0.6.0 # Optional user variables for make command line or environment: # # - PLATFORM +# - extension +# - floatsize # # Deprecated path variables: # @@ -205,6 +207,19 @@ version = 0.6.0 # will then be autodefined accordingly. In most cases no other variables need to # be overridden. # +# extension: +# Extension for the external to use. Example: m_amd64 +# A sane default is picked, but it is useful if you want to provide +# co-installable externals for multiple platforms (for the same operating +# systems) +# +# floatsize: +# the size of the t_float in bits. Example: 32 +# t_float are usually single precision (32bit), which is the default. +# For double precision use floatsize=64 +# When building double precision externals, you will want to set the extension +# as well, e.g. extension=windows-amd64-64.dll (--.) +# # CPPFLAGS: # Preprocessor flags which are not strictly required for building. # @@ -442,6 +457,14 @@ target.arch := $(firstword $(target.triplet)) ### variables per platform ##################################################### ################################################################################ +#=== flags per floatsize == ==================================================== +floatsize = 32 +ifneq ($(filter-out 32,$(floatsize)),) + floatsize.flags = -DPD_FLOATSIZE=$(floatsize) +else + floatsize.flags = +endif + #=== flags per architecture ==================================================== @@ -451,7 +474,7 @@ target.arch := $(firstword $(target.triplet)) # $ gcc -Q --help=target # ARMv6: Raspberry Pi 1st gen, not detectable from target.arch -ifeq ($(shell uname), armv6l) +ifeq ($(shell uname -m), armv6l) arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard # ARMv7: Beagle, Udoo, RPi2 etc. @@ -584,14 +607,14 @@ ifeq ($(system), Windows) extension = dll c.flags := c.ldflags := -static-libgcc -shared \ - -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" + -Wl,--enable-auto-import "$(PDBINDIR)/pd$(filter-out 32,$(floatsize)).dll" c.ldlibs := cxx.flags := -fcheck-new cxx.ldflags := -static-libgcc -static-libstdc++ -shared \ - -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" + -Wl,--enable-auto-import "$(PDBINDIR)/pd$(filter-out 32,$(floatsize)).dll" cxx.ldlibs := shared.extension = dll - shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" + shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd$(filter-out 32,$(floatsize)).dll" stripflags = --strip-all endif @@ -639,7 +662,7 @@ endif CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) # preprocessor flags -cpp.flags := -DPD -I "$(PDINCLUDEDIR)" $(cpp.flags) $(CPPFLAGS) +cpp.flags := -DPD -I "$(PDINCLUDEDIR)" $(floatsize.flags) $(cpp.flags) $(CPPFLAGS) # flags for dependency checking (cflags from makefile may define -I options) depcheck.flags := $(cpp.flags) $(cflags) @@ -683,6 +706,7 @@ endif ### variables: files ########################################################### ################################################################################ +object.extension = $(extension).o #=== sources =================================================================== @@ -709,10 +733,10 @@ all.sources := $(classes.sources) $(lib.setup.sources) \ # construct object filenames from all C and C++ source file names -classes.objects := $(addsuffix .o, $(basename $(classes.sources))) -common.objects := $(addsuffix .o, $(basename $(common.sources))) -shared.objects := $(addsuffix .o, $(basename $(shared.sources))) -lib.setup.objects := $(addsuffix .o, $(basename $(lib.setup.sources))) +classes.objects := $(addsuffix .$(object.extension), $(basename $(classes.sources))) +common.objects := $(addsuffix .$(object.extension), $(basename $(common.sources))) +shared.objects := $(addsuffix .$(object.extension), $(basename $(shared.sources))) +lib.setup.objects := $(addsuffix .$(object.extension), $(basename $(lib.setup.sources))) all.objects = $(classes.objects) $(common.objects) $(shared.objects) \ $(lib.setup.objects) @@ -723,12 +747,13 @@ all.objects = $(classes.objects) $(common.objects) $(shared.objects) \ # construct class executable names from class names classes.executables := $(addsuffix .$(extension), $(classes)) -# Construct shared lib executable name if shared sources are defined. If -# extension and shared extension are not identical, use both to facilitate co- -# installation for different platforms, like .m_i386.dll and .m_amd64.dll. +# Construct shared lib executable name if shared sources are defined. +# If extension does not end with shared extension, use both to facilitate co- +# installation for different platforms, like .m_i386.dll and .linux-amd64-32.so ifdef shared.sources - ifeq ($(extension), $(shared.extension)) - shared.lib = lib$(lib.name).$(shared.extension) + ifneq ($(filter %.$(shared.extension), .$(extension)), ) + # $(extension) already ends with $(shared.extension), no need to duplicate it + shared.lib = lib$(lib.name).$(extension) else shared.lib = lib$(lib.name).$(extension).$(shared.extension) endif @@ -790,7 +815,7 @@ endif # store path to pd.dll; if not found, ls will give a useful error ifeq ($(system), Windows) - pddll := $(shell ls "$(PDBINDIR)/pd.dll") + pddll := $(shell ls "$(PDBINDIR)/pd$(filter-out 32,$(floatsize)).dll") endif # when making target all, check if m_pd.h is found and print info about it @@ -874,8 +899,8 @@ define link-class $(compile-$1) \ $($1.ldflags) $($2.class.ldflags) \ -o $2.$(extension) \ - $(addsuffix .o, $(basename $($2.class.sources))) \ - $(addsuffix .o, $(basename $(common.sources))) \ + $(addsuffix .$(object.extension), $(basename $($2.class.sources))) \ + $(addsuffix .$(object.extension), $(basename $(common.sources))) \ $($1.ldlibs) $($2.class.ldlibs) $(shared.lib) endef @@ -949,13 +974,13 @@ endef # Three rules to create .o files. These are double colon 'terminal' rules, # meaning they are the last in a rules chain. -%.o:: %.c +%.$(object.extension):: %.c $(call make-object-file,c) -%.o:: %.cc +%.$(object.extension):: %.cc $(call make-object-file,cxx) -%.o:: %.cpp +%.$(object.extension):: %.cpp $(call make-object-file,cxx) @@ -974,8 +999,8 @@ endef # declare explicit prerequisites rule like 'class.extension: object1.o object2.o' # argument $v is class basename define declare-class-executable-target -$v.$(extension): $(addsuffix .o, $(basename $($v.class.sources))) \ - $(addsuffix .o, $(basename $(common.sources))) +$v.$(extension): $(addsuffix .$(object.extension), $(basename $($v.class.sources))) \ + $(addsuffix .$(object.extension), $(basename $(common.sources))) endef # evaluate explicit prerequisite rules for all classes @@ -1005,7 +1030,7 @@ endif # argument $1 is input source file(s) # dir is explicitly added because option -MM strips it by default define declare-object-target -$(dir $1)$(filter %.o: %.h, $(shell $(CPP) $(depcheck.flags) -MM $1)) $(MAKEFILE_LIST) +$(dir $1)$(patsubst %.o:,%.$(object.extension):,$(filter %.o: %.h, $(shell $(CPP) $(depcheck.flags) -MM $1))) $(MAKEFILE_LIST) endef # evaluate implicit prerequisite rules when rebuilding everything diff --git a/pd-lib-builder/README.md b/pd-lib-builder/README.md index 234d469..41b37fd 100644 --- a/pd-lib-builder/README.md +++ b/pd-lib-builder/README.md @@ -35,7 +35,8 @@ Makefile.pdlibbuilder at the end of the Makefile. Like so: datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt - include Makefile.pdlibbuilder + PDLIBBUILDER_DIR=. + include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder For files in class.sources it is assumed that class name == source file diff --git a/pd-lib-builder/tips-tricks.md b/pd-lib-builder/tips-tricks.md index e8a02a2..1835687 100644 --- a/pd-lib-builder/tips-tricks.md +++ b/pd-lib-builder/tips-tricks.md @@ -3,7 +3,7 @@ pd-lib-builder cheatsheet # Creating special builds -## building for non-native platform +## Building for non-native platform Using pd-lib-builder >=0.6.0 we can define variable `PLATFORM` to specify a target triplet for cross-compilation. Assuming a W32 package for Pd is unzipped @@ -11,7 +11,7 @@ into path `${PDWIN32}`, to build for Windows 32 bit: make PLATFORM=i686-w64-mingw32 PDDIR="${PDWIN32}" -#### older pd-lib-builder versions +#### Older pd-lib-builder versions Using pd-lib-builder < 0.6.0, in the absence of variable `PLATFORM`, you would instead override variables `system`, `target.arch`, `CC` and / or `CXX`, @@ -19,7 +19,7 @@ instead override variables `system`, `target.arch`, `CC` and / or `CXX`, make system=Windows target.arch=i686 CC=i686-w64-mingw32-gcc STRIP=i686-w64-mingw32-strip PDDIR="${PDWIN32}" -#### toolchains +#### Toolchains To build for non-native OS and/or architecture you need a cross toolchain. On Linux such toolchains are relatively easy to get. For example Debian Buster @@ -34,31 +34,51 @@ for a given platform to get the whole toolchain): Cross toolchains for OSX/MacOS are not generally distributed. Project `osxcross` from Thomas Poechtraeger can create them for Linux. -## building double-precision externals +## Universal binaries on macOS -At the time of writing (2018-02) there is no official Pd that supports -double-precision numbers yet. -However, if you do get hold of an experimental double-precision Pd, you can -easily build your externals for 64-bit numbers: - - make CPPFLAGS="-DPD_FLOATSIZE=64" +The compiler, by default, builds for the native architecture of the build +machine. To make a "universal" multi-arch build, specify the desired +archtectures on the command line using the "arch" pd-lib-builder Makefile +variable. -## building externals for W64 (64-bit Windows) +For example, to build a "fat" external for both 64-bit Intel and Arm (Apple +Silicon): -At the time of writing (2018-02) there is no official Pd that supports -W64 yet. -However, if you do get hold of an experimental W64 Pd, you can -easily build your externals for this environment with + make arch="x86_64 arm64" - make CPPFLAGS="-DPD_LONGINTTYPE=__int64" CC=x86_64-w64-mingw32-gcc +If the build is successful, the compiled architectures in the built external can +be confirmed via the `file` command: +~~~sh +% file vbap.pd_darwin +vbap.pd_darwin: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit bundle x86_64] [arm64:Mach-O 64-bit bundle arm64] +vbap.pd_darwin (for architecture x86_64): Mach-O 64-bit bundle x86_64 +vbap.pd_darwin (for architecture arm64): Mach-O 64-bit bundle arm64 +~~~ -To build a double-precision external for W64, use something like: +Note: The available architectures depend on which macOS version & command line +tools/Xcode combination the build system has. For example, any newer macOS +10.15+ will support both x86_64 (Intel 64-bit) and arm64 (Apple Silicon) while +OSX 10.6 - macOS 10.14 can build for x86_64 and i386 (Intel 32-bit). - make CPPFLAGS="-DPD_LONGINTTYPE=__int64 -DPD_FLOATSIZE=64" CC=x86_64-w64-mingw32-gcc +## Building double-precision externals +At the time of writing (2023-07-06) there is no official Pd that supports +double-precision numbers yet. +However, if you do get hold of an experimental double-precision Pd, you can +easily build your externals for 64-bit numbers, by passing `floatsize=64` +as an argument to `make`. +Starting with Pd>=0.54, double precision externals use different extensions +from traditional (single-precision) externals. +The extension consists of the OS ("linux", "darwin", "windows"), the CPU +architecture ("amd64" (x86_64), "i386" (x86), "arm64",...) and the floatsize +in bits ("64" for double-precision), followed by the system's native extension +for dynamic libraries (".dll" on Windows, ".so" on macOS/Linux/un*xes). +As of pd-lib-builder==0.7.0, you have to manually pass this extension: -## TODO universal binaries on OSX + make floatsize=64 extension=windows-amd64-64.dll + make floatsize=64 extension=linux-arm64-64.so + make floatsize=64 extension=darwin-fat-64.so arch="x86_64 arm64" # Project management @@ -98,6 +118,7 @@ In short, `git subtree` is the better `git submodule`. So here's how to do it: #### Initial setup/check-out + This will create a `pd-lib-builder/` directory containing the full history of the pd-lib-builder repository up to its release `v0.5.0` @@ -109,6 +130,7 @@ This will automatically merge the `pd-lib-builder/` history into your current branch, so everything is ready to go. #### Cloning your repository with the subtree + Nothing special, really. Just clone your repository as always: @@ -117,6 +139,7 @@ git clone https://git.example.org/pd/superbonk~.git ~~~ #### Updating the subtree + Time passes and sooner or later you will find, that there is a shiny new pd-lib-builder with plenty of bugfixes and new features. To update your local copy to pd-lib-builder's current `master`, simply run: @@ -126,6 +149,7 @@ git subtree pull --prefix pd-lib-builder/ https://github.com/pure-data/pd-lib-bu ~~~ #### Pulling the updated subtree into existing clones + Again, nothing special. Just pull as always: @@ -133,8 +157,8 @@ Just pull as always: git pull ~~~ - #### Further reading + More on the power of `git subtree` can be found online - https://medium.com/@v/git-subtrees-a-tutorial-6ff568381844 - https://www.atlassian.com/blog/git/alternatives-to-git-submodule-git-subtree @@ -142,8 +166,8 @@ More on the power of `git subtree` can be found online ### ~~`git submodule`~~ [DISCOURAGED] - #### Initial setup/check-out + To add a new submodule to your repository, just run `git submodule add` and commit the changes: @@ -170,6 +194,7 @@ git submodule update ~~~ #### Updating the submodule + Submodules are usually fixed to a given commit in their repository. To update the `pd-lib-builder` submodule to the current `master` do something like: @@ -184,6 +209,7 @@ git commit pd-lib-builder -m "Updated pd-lib-builder to current master" ~~~ #### Pulling the updated submodule into existing clones + After you have pushed the submodule updates in your repository, other clones of the repository can be updated as follows: @@ -213,6 +239,7 @@ git submodule update ~~~ #### Drawbacks + `git submodule` has a number of drawbacks: - it requires special commands to synchronize the submodules, in addition to synching your repository. @@ -228,4 +255,3 @@ git submodule update In general, I would suggest to **avoid** `git submodule`, and instead use the better `git subtree` (above). -