From 9a5ac265391c87b4f75498668382df136e1d1210 Mon Sep 17 00:00:00 2001 From: albert Date: Wed, 7 Sep 2022 14:28:44 +0200 Subject: [PATCH 1/2] Remove Git submodule'd pd-lib-builder We'll add it back as a Git subtree soon, as recommended by pd-lib-builder's tips-and-tricks doc, https://github.com/pure-data/pd-lib-builder/blob/master/tips-tricks.md#keeping-pd-lib-builder-up-to-date --- .gitmodules | 3 --- pd-lib-builder | 1 - 2 files changed, 4 deletions(-) delete mode 160000 pd-lib-builder diff --git a/.gitmodules b/.gitmodules index 4362a05..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "pd-lib-builder"] - path = pd-lib-builder - url = https://github.com/pure-data/pd-lib-builder.git diff --git a/pd-lib-builder b/pd-lib-builder deleted file mode 160000 index d187d47..0000000 --- a/pd-lib-builder +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d187d4792978ceb4bcc8e68bd347f13fca24f11c From d9769fca61c2dd7c1d97d177f2d132d9192c749f Mon Sep 17 00:00:00 2001 From: albert Date: Thu, 8 Sep 2022 10:59:33 +0200 Subject: [PATCH 2/2] Squashed 'pd-lib-builder/' content from commit e6cff66 git-subtree-dir: pd-lib-builder git-subtree-split: e6cff665a3a30a967c72c382c6fe92bcdedd7b44 --- CHANGELOG.txt | 104 ++ Makefile.pdlibbuilder | 1340 +++++++++++++++++++++++++ README.md | 199 ++++ tests/Makefile | 15 + tests/_template_/Makefile | 24 + tests/_template_/_template_-help.pd | 4 + tests/_template_/_template_-meta.pd | 9 + tests/_template_/_template_.c | 13 + tests/make-from-template.sh | 46 + tests/multifor/Makefile | 39 + tests/multifor/README.md | 9 + tests/multifor/multifor-help.pd | 7 + tests/multifor/multifor-meta.pd | 9 + tests/multifor/multiforA.c | 13 + tests/multifor/multiforB.c | 13 + tests/multilib/Makefile | 32 + tests/multilib/README.md | 8 + tests/multilib/multilib-help.pd | 9 + tests/multilib/multilib-meta.pd | 9 + tests/multilib/multilib.c | 8 + tests/multilib/multilibA.c | 13 + tests/multilib/multilibB.c | 13 + tests/multiple/Makefile | 28 + tests/multiple/README.md | 8 + tests/multiple/multiple-help.pd | 7 + tests/multiple/multiple-meta.pd | 9 + tests/multiple/multipleA.c | 13 + tests/multiple/multipleB.c | 13 + tests/multiplexx/Makefile | 28 + tests/multiplexx/README.md | 8 + tests/multiplexx/multiplexx-help.pd | 7 + tests/multiplexx/multiplexx-meta.pd | 9 + tests/multiplexx/multiplexxA.cpp | 19 + tests/multiplexx/multiplexxB.c | 13 + tests/multishared/Makefile | 41 + tests/multishared/README.md | 9 + tests/multishared/multishared-help.pd | 7 + tests/multishared/multishared-meta.pd | 9 + tests/multishared/multishared.h | 3 + tests/multishared/multisharedA.c | 14 + tests/multishared/multisharedB.c | 14 + tests/multishared/shared.c | 5 + tests/single/Makefile | 24 + tests/single/README.md | 8 + tests/single/single-help.pd | 4 + tests/single/single-meta.pd | 9 + tests/single/single.c | 13 + tests/subdir/Makefile | 27 + tests/subdir/README.md | 8 + tests/subdir/src/subdir.c | 13 + tests/subdir/src/subdir~.c | 13 + tests/subdir/subdir-help.pd | 4 + tests/subdir/subdir-meta.pd | 9 + tests/subdir/subdir~-help.pd | 4 + tests/test-patches.sh | 70 ++ tips-tricks.md | 231 +++++ 56 files changed, 2637 insertions(+) create mode 100644 CHANGELOG.txt create mode 100644 Makefile.pdlibbuilder create mode 100644 README.md create mode 100644 tests/Makefile create mode 100644 tests/_template_/Makefile create mode 100644 tests/_template_/_template_-help.pd create mode 100644 tests/_template_/_template_-meta.pd create mode 100644 tests/_template_/_template_.c create mode 100755 tests/make-from-template.sh create mode 100644 tests/multifor/Makefile create mode 100644 tests/multifor/README.md create mode 100644 tests/multifor/multifor-help.pd create mode 100644 tests/multifor/multifor-meta.pd create mode 100644 tests/multifor/multiforA.c create mode 100644 tests/multifor/multiforB.c create mode 100644 tests/multilib/Makefile create mode 100644 tests/multilib/README.md create mode 100644 tests/multilib/multilib-help.pd create mode 100644 tests/multilib/multilib-meta.pd create mode 100644 tests/multilib/multilib.c create mode 100644 tests/multilib/multilibA.c create mode 100644 tests/multilib/multilibB.c create mode 100644 tests/multiple/Makefile create mode 100644 tests/multiple/README.md create mode 100644 tests/multiple/multiple-help.pd create mode 100644 tests/multiple/multiple-meta.pd create mode 100644 tests/multiple/multipleA.c create mode 100644 tests/multiple/multipleB.c create mode 100644 tests/multiplexx/Makefile create mode 100644 tests/multiplexx/README.md create mode 100644 tests/multiplexx/multiplexx-help.pd create mode 100644 tests/multiplexx/multiplexx-meta.pd create mode 100644 tests/multiplexx/multiplexxA.cpp create mode 100644 tests/multiplexx/multiplexxB.c create mode 100644 tests/multishared/Makefile create mode 100644 tests/multishared/README.md create mode 100644 tests/multishared/multishared-help.pd create mode 100644 tests/multishared/multishared-meta.pd create mode 100644 tests/multishared/multishared.h create mode 100644 tests/multishared/multisharedA.c create mode 100644 tests/multishared/multisharedB.c create mode 100644 tests/multishared/shared.c create mode 100644 tests/single/Makefile create mode 100644 tests/single/README.md create mode 100644 tests/single/single-help.pd create mode 100644 tests/single/single-meta.pd create mode 100644 tests/single/single.c create mode 100644 tests/subdir/Makefile create mode 100644 tests/subdir/README.md create mode 100644 tests/subdir/src/subdir.c create mode 100644 tests/subdir/src/subdir~.c create mode 100644 tests/subdir/subdir-help.pd create mode 100644 tests/subdir/subdir-meta.pd create mode 100644 tests/subdir/subdir~-help.pd create mode 100755 tests/test-patches.sh create mode 100644 tips-tricks.md diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..5bdfce6 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,104 @@ +Changelog for Makefile.pdlibbuilder. + +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 +- no longer build OSX/MacOS fat binaries by default (#21, #50) +- do build fat binaries when 'extension=d_fat' is specified for OSX/MacOS +- fix bug where minimum OSX/MacOS version wasn't defined, and set it to 10.6 + +v0.5.1, dated 2018-03-15 +Fixes and improvements for Windows builds: +- properly evaluate variables 'PDDIR' and 'PDBINDIR' to find pd.dll +- define default path of 32 bit Pd on 64 bit Windows +- link C++ externals with standard C libs on Windows, they don't load otherwise +- strip installed Windows binaries by default +(issues #34, #39, #41, #42 respectively) +Warning for all platforms: variable 'PD_PATH' is no longer supported, use the +equivalent 'PDDIR'. + +v0.5.0, dated 2018-01-23 +Implement target architecture detection for Windows builds, +and set appropriate options for 32 and 64 bit (used to be for 32 bit only). +(feature, issue #37 #38, merge commit 215bf3e) + +v0.4.4, dated 2016-11-22 +Use variable 'system' when evaluating 'for{Linux,Darwin,Windows}' +(bugfix, issue #31, commit 2c14110) + +v0.4.3, dated 2016-11-02 +Replace flags '-fpic' by 'fPIC'. +(bugfix, issue #29, commit 426b38b) + +v0.4.2, dated 2016-10-30 +Fix issue where incorrect message about m_pd.h is given. +(bugfix, commit 2e13d8f) + +v0.4.1, dated 2016-10-27 +Respect cflag for minimum OSX version when defined by lib makefile. +(bugfix, pull request #22, commit 48c4127) + +v0.4.0, dated 2016-10-14 +Introduced path variables PDDIR, PDINCLUDEDIR, PDBINDIR, PDLIBDIR which can +also be defined in environment. +(feature, issue #27, commit b0dab72) + +v0.3.1, dated 2016-10-13 +Fix bug where pd.dll wouldn't be found. +(bugfix, commit a0c87be) + +v0.3.0, dated 2016-10-09 +Variable 'PD_PATH' introduced for pd-extended / pd-l2ork compatibility. +(feature, issue #26, commit 41e9743) + +v0.2.8, dated 2016-10-09 +Allow installed files to contain weird characters (notably '$'). +(bugfix, pull request #20, commit 5b920b1) + +v0.2.7, dated 2016-10-04 +Remove all default pd search paths except vanilla's. +(discussion, issue #25, commit a6a89dc) + +v0.2.6, dated 2016-09-20 +Redefined dependency checking so it won't stall rebuilds on OSX. +(bugfix, issue #16, commit 9fd1795) + +v0.2.5, dated 2016-06-26 +Fixed dependency checking for object files in other directories. +(bugfix, commit f06e550) + +v0.2.4, dated 2016-06-25 +Fixed regression bug that disabled all dependency checking. +(bugfix, commit 1d7bb5e) + +v0.2.3, dated 2016-03-29 +Disabled dependency checking for OSX <= 10.5 because it stalled rebuilds. +(bugfix, issue #16, commit eb614fd) + +v0.2.2, dated 2016-03-28 +Removed target 'pre' because it forced rebuild of everything in 'all'. +(bugfix, issue #17, commit c989c8e) + +v0.2.1, dated 2015-12-27 +Implement / respect 'CPPFLAGS','CFLAGS'and 'LDFLAGS'. +(bugfix, issue #5, commit 98f3582) + +v0.2.0, dated 2015-12-19 +Added per-platform multiline defines 'forLinux', 'forDarwin', 'forWindows'. +(feature, pull request #9, commit 3946ea5) + +v0.1.0, dated 2015-12-08 +Added targets 'pre' and 'post' to automatically run before and after 'all'. +(feature, pull request #4, commit a5678ac) + +v0.0.2, dated 2015-12-06 +Improved methods for searching pd paths. +(bugfix, commit ed37e6b) + +v0.0.1, dated 2015-10-31 +Fixed expansion of variable 'lib.version'. +(bugfix, issue #1, commit 974b617) + +v0.0.0, dated 2015-06-24 +Initial version. +(commit 16517a2) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder new file mode 100644 index 0000000..40160bc --- /dev/null +++ b/Makefile.pdlibbuilder @@ -0,0 +1,1340 @@ +# Makefile.pdlibbuilder dated 2019-12-21 +version = 0.6.0 + +# Helper makefile for Pure Data external libraries. +# Written by Katja Vetter March-June 2015 for the public domain. No warranties. +# Inspired by Hans Christoph Steiner's Makefile Template and Stephan Beal's +# ShakeNMake. +# +# Grab the newest version of Makefile.pdlibbuilder from +# https://github.com/pure-data/pd-lib-builder/ +# +# GNU make version >= 3.81 required. +# +# +#=== characteristics =========================================================== +# +# +# - defines build settings based on autodetected OS and architecture +# - defines rules to build Pd class- or lib executables from C or C++ sources +# - defines rules for libdir installation +# - defines convenience targets for developer and user +# - evaluates implicit dependencies for non-clean builds +# +# +#=== basic usage =============================================================== +# +# +# In your Makefile, define your Pd lib name and class files, and include +# Makefile.pdlibbuilder at the end of the Makefile. Like so: +# +# ________________________________________________________________________ +# +# # Makefile for mylib +# +# lib.name = mylib +# +# class.sources = myclass1.c myclass2.c +# +# datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt +# +# include Makefile.pdlibbuilder +# ________________________________________________________________________ +# +# +# For files in class.sources it is assumed that class basename == source file +# basename. The default target builds all classes as individual executables +# with Pd's default extension for the platform. For anything more than the +# most basic usage, continue reading. +# +# +#=== list of Makefile.pdlibbuilder API variables =============================== +# +# +# Variables available for definition in your library Makefile: +# +# - lib.name +# - lib.setup.sources +# - class.sources +# - common.sources +# - shared.sources +# - .class.sources +# - .class.ldflags +# - .class.ldlibs +# - cflags +# - ldflags +# - ldlibs +# - datafiles +# - datadirs +# - makefiles +# - makefiledirs +# - externalsdir +# +# Optional multiline defines evaluated per operating system: +# +# - forLinux +# - forDarwin +# - forWindows +# +# Variables available for your makefile or make command line: +# +# - make-lib-executable +# - suppress-wunused +# +# Path variables for make command line or environment: +# +# - PDDIR +# - PDINCLUDEDIR +# - PDBINDIR +# - PDLIBDIR +# +# Standard make variables for make command line or environment: +# +# - CPPFLAGS +# - CFLAGS +# - LDFLAGS +# - CC +# - CXX +# - INSTALL +# - STRIP +# - DESTDIR +# +# Optional user variables for make command line or environment: +# +# - PLATFORM +# +# Deprecated path variables: +# +# - pdincludepath +# - pdbinpath +# - objectsdir +# +# +#=== descriptions of Makefile.pdlibbuilder API variables ======================= +# +# +# lib.name: +# Name of the library directory as it will be installed / distributed. Also the +# name of the lib executable in the case where all classes are linked into +# a single binary. +# +# lib.setup.sources: +# Source file(s) (C or C++) which must be compiled only when linking all classes +# into a single lib binary. +# +# class.sources: +# All sources files (C or C++) for which the condition holds that +# class name == source file basename. +# +# .class.sources: +# Source file(s) (C or C++) specific to class . Use this for +# multiple-source classes or when class name != source file basename. +# +# common.sources: +# Source file(s) which must be statically linked to each class in the library. +# +# shared.sources: +# Source file(s) (C or C++) to build a shared dynamic link lib, to be linked +# with all class executables. +# +# cflags, ldflags, ldlibs: +# Define cflags (preprocessor&compiler), ldflags (linker) and ldlibs (dynamic +# link libs) for the whole library. These flags are added to platform-specific +# flags defined by Makefile.pdlibbuilder. +# +# .class.ldflags and .class.ldlibs: +# Define ldflags resp. ldlibs specific to class . These flags are +# added to platform-specific flags defined by Makefile.pdlibbuilder, and flags +# defined in your Makefile for the whole library. Note: cflags can not be +# defined per class in the current implementation. +# +# datafiles and datadirs: +# All extra files you want to include in binary distributions of the +# library: abstractions and help patches, example patches, meta patch, readme +# and license texts, manuals, sound files, etcetera. Use 'datafiles' for all +# files that should go into your lib rootdir and 'datadirs' for complete +# directories you want to copy from source to distribution. +# +# forLinux, forDarwin, forWindows: +# Shorthand for 'variable definitions for Linux only' etc. Use like: +# define forLinux +# cflags += -DLINUX +# class.sources += linuxthing.c +# endef +# +# makefiles and makefiledirs: +# Extra makefiles or directories with makefiles that should be made in sub-make +# processes. +# +# make-lib-executable: +# When this variable is defined 'yes' in your makefile or as command argument, +# Makefile.pdlibbuilder will try to build all classes into a single library +# executable (but it will force exit if lib.setup.sources is undefined). +# If your makefile defines 'make-lib-executable=yes' as the library default, +# this can still be overridden with 'make-lib-executable=no' as command argument +# to build individual class executables (the Makefile.pdlibbuilder default.) +# +# suppress-wunused: +# When this variable is defined ('yes' or any other value), -Wunused-variable, +# -Wunused-parameter, -Wunused-value and -Wunused-function are suppressed, +# but the other warnings from -Wall are retained. +# +# PDDIR: +# Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and +# PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. +# +# PDINCLUDEDIR: +# Directory where Pd API m_pd.h should be found, and other Pd header files. +# Overrides the default search path. +# +# PDBINDIR: +# Directory where pd.dll should be found for linking (Windows only). Overrides +# the default search path. +# +# PDLIBDIR: +# Root directory for installation of Pd library directories. Overrides the +# default install location. +# +# DESTDIR: +# Prepended path component for staged install. +# +# PLATFORM: +# Target platform for cross compilation in the form of GNU triplet: +# cpu-vendor-os. Example: x86_64-w64-mingw32. This specifies the tool chain that +# pdlibbuilder will use, if installed and locatable. System and architecture +# will then be autodefined accordingly. In most cases no other variables need to +# be overridden. +# +# CPPFLAGS: +# Preprocessor flags which are not strictly required for building. +# +# CFLAGS: +# Compiler flags which are not strictly required for building. Compiler flags +# defined by Makefile.pdlibbuilder for warning, optimization and architecture +# specification are overriden by CFLAGS. +# +# LDFLAGS: +# Linker flags which are not strictly required for building. Linker flags +# defined by Makefile.pdlibbuilder for architecture specification are overriden +# by LDFLAGS. +# +# CC and CXX: +# C and C++ compiler programs as defined in your build environment. +# +# INSTALL +# Definition of install program. +# +# STRIP +# Name of strip program. Default 'strip' can be overridden in cross compilation +# environments. +# +# objectsdir: +# Root directory for installation of Pd library directories, like PDLIBDIR but +# not overridable by environment. Supported for compatibility with pd-extended +# central makefile, but deprecated otherwise. +# +# pdincludepath, pdbinpath: +# As PDINCLUDEDIR and PDBINDIR but not overridable by environment. Deprecated +# as user variables. +# +# +#=== paths ===================================================================== +# +# +# Source files in directories other than current working directory must be +# prefixed with their relative path. Do not rely on VPATH or vpath. +# Object (.o) files are built in the directory of their source files. +# Executables are built in current working directory. +# +# Default search path for m_pd.h and other API header files is platform +# dependent, and overridable by PDINCLUDEDIR: +# +# Linux: /usr/include/pd +# +# OSX: /Applications/Pd*.app/Contents/Resources/src +# +# Windows: %PROGRAMFILES%/Pd/src +# %PROGRAMFILES(X86)%/Pd/src (32 bit builds on 64 bit Windows) +# +# Default search path for binary pd.dll (Windows), overridable by PDBINDIR +# +# %PROGRAMFILES%/Pd/bin +# %PROGRAMFILES(X86)%/Pd/bin (32 bit builds on 64 bit Windows) +# +# Default location to install pd libraries is platform dependent, and +# overridable by PDLIBDIR: +# +# Linux: /usr/local/lib/pd-externals +# OSX: ~/Library/Pd +# Windows: %APPDATA%/Pd +# +# https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files +# The rationale for not installing to ~/pd-externals by default on Linux +# is that some people share the home dir between 32 and 64 bit installations. +# +# +#=== targets =================================================================== +# +# +# all: build $(executables) plus optional post target +# post: target to build after $(executables) +# alldebug: build all with -g option turned on for debug symbols +# : force clean build of an individual class +# .pre: make preprocessor output file in current working directory +# .lst: make asm/source output file in current working directory +# +# install: install executables and data files +# clean: remove build products from source tree +# +# help: print help text +# vars: print makefile variables +# allvars: print all variables +# depend: print generated prerequisites +# dumpmachine: print compiler output of option '-dumpmachine' +# coffee: dummy target +# +# Variable $(executables) expands to class executables plus optional shared lib, +# or alternatively to single lib executable when make-lib-executable=true. +# Targets pre and post can be defined by library makefile. Make sure to include +# Makefile.pdlibbuilder first so default target all will not be redefined. +# +# +#=== Pd-extended libdir concept ================================================ +# +# +# For libdir layout as conceived by Hans-Christoph Steiner, see: +# +# https://puredata.info/docs/developer/Libdir +# +# Files README.txt, LICENSE.txt and -meta.pd are part of the libdir +# convention. Help patches for each class and abstraction are supposed to be +# available. Makefile.pdlibbuilder does not force the presence of these files +# however. It does not automatically include such files in libdir installations. +# Data files you want to include in distributions must be defined explicitly in +# your Makefile. +# +# +#=== Makefile.pdlibbuilder syntax conventions ================================== +# +# +# Makefile.pdlibbuilder variable names are lower case. Default make variables, +# environment variables, and standard user variables (CC, CXX, CFLAGS, DESTDIR) +# are upper case. Use target 'allvars' to print all variables and their values. +# +# 'Fields' in data variables are separated by dots, like in 'foo.class.sources'. +# Words in variables expressing a function or command are separated by dashes, +# like in 'make-lib-executable'. +# +# +#=== useful make options ======================================================= +# +# +# Use 'make -d ' to print debug details of the make process. +# Use 'make -p ' to print make's database. +# +# +#=== TODO ====================================================================== +# +# +# - decide whether to use -static-libgcc or shared dll in MinGW +# - cygwin support +# - android support +# - figure out how to handle '$' in filenames +# - add makefile template targets dpkg-source dist libdir distclean tags? +# +# +#=== end of documentation sections ============================================= +# +# +################################################################################ +################################################################################ +################################################################################ + + +# GNU make version 3.81 (2006) or higher is required because of the following: +# - function 'info' +# - variable '.DEFAULT_GOAL' + +# force exit when make version is < 3.81 +ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))), 3.81) + $(error GNU make version 3.81 or higher is required) +endif + +# Relative path to externals root dir in multi-lib source tree like +# pd-extended SVN. Default is parent of current working directory. May be +# defined differently in including makefile. +externalsdir ?= .. + +# variable you can use to check if Makefile.pdlibbuilder is already included +Makefile.pdlibbuilder = true + + +################################################################################ +### target platform detection ################################################## +################################################################################ + + +#=== target platform =========================================================== + + +# PLATFORM: optional user variable to define target platform for cross +# compilation. Redefine build tools accordingly. PLATFORM should match +# the exact target prefix of tools present in $PATH, like x86_64-w64-mingw32, +# x86_64-apple-darwin12 etc. Tool definitions are exported to ensure submakes +# will get the same. + +ifneq ($(PLATFORM),) + ifneq ($(findstring darwin, $(PLATFORM)),) + export CC = $(PLATFORM)-cc + export CXX = $(PLATFORM)-c++ + export CPP = $(PLATFORM)-cc + else + export CC = $(PLATFORM)-gcc + export CXX = $(PLATFORM)-g++ + export CPP = $(PLATFORM)-cpp + endif + STRIP = $(PLATFORM)-strip +endif + +# Let (native or cross-) compiler report target triplet and isolate individual +# words therein to facilitate later processing. +target.triplet := $(subst -, ,$(shell $(CC) -dumpmachine)) + + +#=== operating system ========================================================== + + +# The following systems are defined: Linux, Darwin, Windows. GNU and +# GNU/kFreeBSD are treated as Linux to get the same options. + +ifneq ($(filter linux gnu% kfreebsd, $(target.triplet)),) + system = Linux +endif + +ifneq ($(filter darwin%, $(target.triplet)),) + system = Darwin +endif + +ifneq ($(filter mingw% cygwin%, $(target.triplet)),) + system = Windows +endif + +# evaluate possible system-specific multiline defines from library makefile +$(eval $(for$(system))) + + +# TODO: Cygwin, Android + + +#=== architecture ============================================================== + + +# The following CPU names can be processed by pdlibbuilder: +# i*86 Intel 32 bit +# x86_64 Intel 64 bit +# arm ARM 32 bit +# aarch64 ARM 64 bit + +target.arch := $(firstword $(target.triplet)) + + +################################################################################ +### variables per platform ##################################################### +################################################################################ + + +#=== flags per architecture ==================================================== + + +# Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, +# arch.c.flags are overriden below. To see gcc's default architecture flags: +# $ gcc -Q --help=target + +# ARMv6: Raspberry Pi 1st gen, not detectable from target.arch +ifeq ($(shell uname), armv6l) + arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard + +# ARMv7: Beagle, Udoo, RPi2 etc. +else ifeq ($(target.arch), arm) + arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard + +# ARMv8 64 bit, not tested yet +else ifeq ($(target.arch), aarch64) + arch.c.flags = -mcpu=cortex-a53 + +# Intel 32 bit, build with SSE and SSE2 instructions +else ifneq ($(filter i%86, $(target.arch)),) + arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 + +# Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions +else ifeq ($(target.arch), x86_64) + arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 + +# if none of the above architectures detected +else + arch.c.flags = +endif + + +#=== flags and paths for Linux ================================================= + + +ifeq ($(system), Linux) + prefix = /usr/local + libdir := $(prefix)/lib + pkglibdir = $(libdir)/pd-externals + pdincludepath := $(wildcard /usr/include/pd) + extension = pd_linux + cpp.flags := -DUNIX + c.flags := -fPIC + c.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags + c.ldlibs := -lc -lm + cxx.flags := -fPIC -fcheck-new + cxx.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags + cxx.ldlibs := -lc -lm -lstdc++ + shared.extension = so + shared.ldflags = -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) +endif + + +#=== flags and paths for Darwin ================================================ + + +# LLVM-clang doesn't support -fcheck-new, therefore this flag is only used when +# compiling with g++. + +ifeq ($(system), Darwin) + pkglibdir = $(HOME)/Library/Pd + pdincludepath := $(firstword $(wildcard \ + /Applications/Pd*.app/Contents/Resources/src)) + extension = pd_darwin + cpp.flags := -DUNIX -DMACOSX -I /sw/include + c.flags := + c.ldflags := -undefined suppress -flat_namespace -bundle + c.ldlibs := -lc + cxx.ldflags := -undefined suppress -flat_namespace -bundle + cxx.ldlibs := -lc + shared.extension = dylib + shared.ldflags = -dynamiclib -undefined dynamic_lookup \ + -install_name @loader_path/$(shared.lib) \ + -compatibility_version 1 -current_version 1.0 + ifneq ($(filter %g++, $(CXX)),) + cxx.flags := -fcheck-new + endif + ifeq ($(extension), d_fat) + arch := i386 x86_64 + else + arch := $(target.arch) + endif + ifneq ($(filter -mmacosx-version-min=%, $(cflags)),) + version.flag := $(filter -mmacosx-version-min=%, $(cflags)) + else + version.flag = -mmacosx-version-min=10.6 + endif + arch.c.flags := $(addprefix -arch , $(arch)) $(version.flag) + arch.ld.flags := $(arch.c.flags) +endif + + +#=== flags and paths for Windows =============================================== + + +# Standard paths on Windows contain spaces, and GNU make functions treat such +# paths as lists, with unintended effects. Therefore we must use shell function +# ls instead of make's wildcard when probing for a path, and use double quotes +# when specifying a path in a command argument. + +# Default paths in Mingw / Mingw-w64 environments. 'PROGRAMFILES' is standard +# location for builds with native architecture, 'ProgramFiles(x86)' for i686 +# builds on x86_64 Windows (detection method by Lucas Cordiviola). Curly braces +# required because of parentheses in variable name. +ifeq ($(system), Windows) + pkglibdir := $(APPDATA)/Pd + ifeq ($(target.arch), i686) + programfiles := ${ProgramFiles(x86)} + else + programfiles := $(PROGRAMFILES) + endif + pdbinpath := $(programfiles)/Pd/bin + pdincludepath := $(programfiles)/Pd/src +endif + +# Store default path to pd.dll in PDBINDIR if the latter is not user-defined. +# For include path this is done in the platform-independent paths section below, +# but for PDBINDIR it is done here so ld flags can be evaluated as immediate +# variables. +ifeq ($(system), Windows) + ifdef PDDIR + PDBINDIR := $(PDDIR)/bin + endif + PDBINDIR ?= $(pdbinpath) +endif + +# TODO: decide whether -mms-bitfields should be specified. +ifeq ($(system), Windows) + cpp.flags := -DMSW -DNT + ifeq ($(target.arch), i686) + arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse + else ifeq ($(target.arch), x86_64) + cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 + arch.c.flags := -march=core2 -msse -msse2 -msse3 -mfpmath=sse + else + arch.c.flags = + endif + extension = dll + c.flags := + c.ldflags := -static-libgcc -shared \ + -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" + c.ldlibs := + cxx.flags := -fcheck-new + cxx.ldflags := -static-libgcc -static-libstdc++ -shared \ + -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" + cxx.ldlibs := + shared.extension = dll + shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" + stripflags = --strip-all +endif + + +#=== paths ===================================================================== + + +# Platform-dependent default paths are specified above, but overridable. +# Path variables in upper case can be defined as make command argument or in the +# environment. Variable 'objectsdir' is supported for compatibility with +# the build system that pd-l2ork has inherited from pd-extended. + +PDINCLUDEDIR ?= $(pdincludepath) +PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) + +ifdef PDDIR + PDINCLUDEDIR := $(wildcard $(PDDIR)/src) +endif + +# base path where all components of the lib will be installed by default +installpath := $(DESTDIR)$(PDLIBDIR)/$(lib.name) + +# check if include path contains spaces (as is often the case on Windows) +# if so, store the path so we can later do checks with it +pdincludepathwithspaces := $(if $(word 2, $(PDINCLUDEDIR)), $(PDINCLUDEDIR)) + + +#=== accumulated build flags =================================================== + + +# From GNU make docs: 'Users expect to be able to specify CFLAGS freely +# themselves.' So we use CFLAGS to define options which are not strictly +# required for compilation: optimizations, architecture specifications, and +# warnings. CFLAGS can be safely overriden using a make command argument. +# Variables cflags, ldflags and ldlibs may be defined in including makefile. + +optimization.flags = -O3 -ffast-math -funroll-loops -fomit-frame-pointer +warn.flags = -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing + +# suppress -Wunused-variable & Co if you don't want to clutter a build log +ifdef suppress-wunused + warn.flags += $(addprefix -Wno-unused-, function parameter value variable) +endif + +CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) + +# preprocessor flags +cpp.flags := -DPD -I "$(PDINCLUDEDIR)" $(cpp.flags) $(CPPFLAGS) + +# flags for dependency checking (cflags from makefile may define -I options) +depcheck.flags := $(cpp.flags) $(cflags) + +# architecture specifications for linker are overridable by LDFLAGS +LDFLAGS := $(arch.ld.flags) + +# now add the same ld flags to shared dynamic lib +shared.ldflags += $(LDFLAGS) + +# accumulated flags for C compiler / linker +c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) +c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS) +c.ldlibs := $(c.ldlibs) $(ldlibs) + +# accumulated flags for C++ compiler / linker +cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS) +cxx.ldflags := $(cxx.ldflags) $(ldflags) $(LDFLAGS) +cxx.ldlibs := $(cxx.ldlibs) $(ldlibs) + + +################################################################################ +### variables: library name and version ######################################## +################################################################################ + + +# strip possibles spaces from lib.name, they mess up calculated file names +lib.name := $(strip $(lib.name)) + +# if meta file exists, check library version +metafile := $(wildcard $(lib.name)-meta.pd) + +ifdef metafile + lib.version := $(shell sed -n \ + 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' \ + $(metafile)) +endif + + +################################################################################ +### variables: files ########################################################### +################################################################################ + + +#=== sources =================================================================== + + +# (re)define .class.sources using file names in class.sources + +define add-class-source +$(notdir $(basename $v)).class.sources += $v +endef + +$(foreach v, $(class.sources), $(eval $(add-class-source))) + +# derive class names from .class.sources variables +sourcevariables := $(filter %.class.sources, $(.VARIABLES)) +classes := $(basename $(basename $(sourcevariables))) + +# accumulate all source files specified in makefile +classes.sources := $(sort $(foreach v, $(sourcevariables), $($v))) +all.sources := $(classes.sources) $(lib.setup.sources) \ + $(shared.sources) $(common.sources) + + +#=== object files ============================================================== + + +# 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))) +all.objects = $(classes.objects) $(common.objects) $(shared.objects) \ + $(lib.setup.objects) + + +#=== executables =============================================================== + + +# 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. +ifdef shared.sources + ifeq ($(extension), $(shared.extension)) + shared.lib = lib$(lib.name).$(shared.extension) + else + shared.lib = lib$(lib.name).$(extension).$(shared.extension) + endif +else + shared.lib := +endif + + +################################################################################ +### variables: tools ########################################################### +################################################################################ + + +# aliases so we can later define 'compile-$1' and set 'c' or 'cxx' as argument +compile-c := $(CC) +compile-cxx := $(CXX) + + +################################################################################ +### checks ##################################################################### +################################################################################ + + +# At this point most variables are defined. Now do some checks and info's +# before rules begin. + +# print Makefile.pdlibbuilder version before possible termination +$(info ++++ info: using Makefile.pdlibbuilder version $(version)) + +# Terminate if target triplet remained empty, to avoid all sorts of confusing +# scenarios and spurious bugs. +ifeq ($(target.triplet),) + $(error Command "$(CC) -dumpmachine" did not return a target triplet, \ + needed for a build. \ + Is compiler "$(CC)" installed in your PATH? ($(PATH)). \ + Does compiler "$(CC)" support option "-dumpmachine"?) +endif + +# 'forward declaration' of default target, needed to do checks +all: + +# To avoid unpredictable results, make sure the default target is not redefined +# by including makefile. +ifneq ($(.DEFAULT_GOAL), all) + $(error Default target must be 'all'.) +endif + +# find out which target(s) will be made +ifdef MAKECMDGOALS + goals := $(MAKECMDGOALS) +else + goals := all +endif + +# store path to Pd API m_pd.h if it is found +ifdef PDINCLUDEDIR + mpdh := $(shell ls "$(PDINCLUDEDIR)/m_pd.h") +endif + +# store path to pd.dll; if not found, ls will give a useful error +ifeq ($(system), Windows) + pddll := $(shell ls "$(PDBINDIR)/pd.dll") +endif + +# when making target all, check if m_pd.h is found and print info about it +ifeq ($(goals), all) + $(if $(mpdh), \ + $(info ++++ info: using Pd API $(mpdh)), \ + $(warning Where is Pd API m_pd.h? Do 'make help' for info.)) +endif + +# print target info +$(info ++++ info: making target $(goals) $(if $(lib.name),in lib $(lib.name))) + +# when installing, print installpath info +$(if $(filter install install-lib, $(goals)), $(info ++++ info: \ + installpath is '$(installpath)')) + + +#=== define executables ======================================================== + + +# By default we build class executables, and optionally a shared dynamic link +# lib. When make-lib-executable=yes we build all classes into a single lib +# executable, on the condition that variable lib.setup.sources is defined. + +ifeq ($(make-lib-executable),yes) + $(if $(lib.setup.sources), ,\ + $(error Can not build library blob because lib.setup.sources is undefined)) + executables := $(lib.name).$(extension) +else + executables := $(classes.executables) $(shared.lib) +endif + + +################################################################################ +### rules: special targets ##################################################### +################################################################################ + + +# Disable built-in rules. If some target can't be built with the specified +# rules, it should not be built at all. +MAKEFLAGS += --no-builtin-rules + +.PRECIOUS: +.SUFFIXES: +.PHONY: all post build-lib \ + $(classes) $(makefiledirs) $(makefiles) \ + install install-executables install-datafiles install-datadirs \ + force clean vars allvars depend help + + +################################################################################ +### rules: build targets ####################################################### +################################################################################ + + +# Target all forces the build of targets [$(executables) post] in +# deterministic order. Target $(executables) builds class executables plus +# optional shared lib or alternatively a single lib executable when +# make-lib-executable=true. Target post is optionally defined by +# library makefile. + +all: post +post: $(executables) + +all: + $(info ++++info: target all in lib $(lib.name) completed) + +# build all with -g option turned on for debug symbols +alldebug: c.flags += -g +alldebug: cxx.flags += -g +alldebug: all + + +#=== class executable ========================================================== + + +# recipe for linking objects in class executable +# argument $1 = compiler type (c or cxx) +# argument $2 = class basename +define link-class + $(compile-$1) \ + $($1.ldflags) $($2.class.ldflags) \ + -o $2.$(extension) \ + $(addsuffix .o, $(basename $($2.class.sources))) \ + $(addsuffix .o, $(basename $(common.sources))) \ + $($1.ldlibs) $($2.class.ldlibs) $(shared.lib) +endef + +# general rule for linking object files in class executable +%.$(extension): $(shared.lib) + $(info ++++ info: linking objects in $@ for lib $(lib.name)) + $(if $(filter %.cc %.cpp, $($*.class.sources)), \ + $(call link-class,cxx,$*), \ + $(call link-class,c,$*)) + + +#=== library blob ============================================================== + + +# build all classes into single executable +build-lib: $(lib.name).$(extension) + $(info ++++ info: library blob $(lib.name).$(extension) completed) + +# recipe for linking objects in lib executable +# argument $1 = compiler type (c or cxx) +define link-lib + $(compile-$1) \ + $($1.ldflags) $(lib.ldflags) \ + -o $(lib.name).$(extension) $(all.objects) \ + $($1.ldlibs) $(lib.ldlibs) +endef + +# rule for linking objects in lib executable +# declared conditionally to avoid name clashes +ifeq ($(make-lib-executable),yes) +$(lib.name).$(extension): $(all.objects) + $(if $(filter %.cc %.cpp, $(all.sources)), \ + $(call link-lib,cxx), \ + $(call link-lib,c)) +endif + + +#=== shared dynamic lib ======================================================== + + +# recipe for linking objects in shared executable +# argument $1 = compiler type (c or cxx) +define link-shared + $(compile-$1) \ + $(shared.ldflags) \ + -o $(shared.lib) $(shared.objects) \ + $($1.ldlibs) $(shared.ldlibs) +endef + +# rule for linking objects in shared executable +# build recipe is in macro 'link-shared' +$(shared.lib): $(shared.objects) + $(info ++++ info: linking objects in shared lib $@) + $(if $(filter %.cc %.cpp, $(shared.sources)), \ + $(call link-shared,cxx), \ + $(call link-shared,c)) + + +#=== object files ============================================================== + + +# recipe to make .o file from source +# argument $1 is compiler type (c or cxx) +define make-object-file + $(info ++++ info: making $@ in lib $(lib.name)) + $(compile-$1) \ + $($1.flags) \ + -o $@ -c $< +endef + +# Three rules to create .o files. These are double colon 'terminal' rules, +# meaning they are the last in a rules chain. + +%.o:: %.c + $(call make-object-file,c) + +%.o:: %.cc + $(call make-object-file,cxx) + +%.o:: %.cpp + $(call make-object-file,cxx) + + +#=== explicit prerequisites for class executables ============================== + + +# For class executables, prerequisite rules are declared in run time. Target +# 'depend' prints these rules for debugging purposes. + +# declare explicit prerequisites rule like 'class: class.extension' +# argument $v is class basename +define declare-class-target +$v: $v.$(extension) +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))) +endef + +# evaluate explicit prerequisite rules for all classes +$(foreach v, $(classes), $(eval $(declare-class-target))) +$(foreach v, $(classes), $(eval $(declare-class-executable-target))) + + +#=== implicit prerequisites for class executables ============================== + + +# Evaluating implicit prerequisites (header files) with help from the +# preprocessor is 'expensive' so this is done conditionally and selectively. +# Note that it is also possible to trigger a build via install targets, in +# which case implicit prerequisites are not checked. + +# When the Pd include path contains spaces it will mess up the implicit +# prerequisites rules. +disable-dependency-tracking := $(strip $(pdincludepathwithspaces)) + +ifndef disable-dependency-tracking + must-build-everything := $(filter all, $(goals)) + must-build-class := $(filter $(classes), $(goals)) + must-build-sources := $(foreach v, $(must-build-class), $($v.class.sources)) +endif + +# declare implicit prerequisites rule like 'object.o: header1.h header2.h ...' +# 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) +endef + +# evaluate implicit prerequisite rules when rebuilding everything +ifdef must-build-everything + $(if $(wildcard $(all.objects)), \ + $(info ++++ info: evaluating implicit prerequisites in lib $(lib.name).....) \ + $(foreach v, $(all.sources), $(eval $(call declare-object-target, $v)))) +endif + +# evaluate implicit prerequisite rules when selectively building classes +ifdef must-build-class + $(foreach v, $(must-build-sources), \ + $(eval $(call declare-object-target, $v))) + $(foreach v, $(shared.sources), \ + $(eval $(call declare-object-target, $v))) +endif + + +################################################################################ +### rules: preprocessor and assembly files ##################################### +################################################################################ + + +# Preprocessor and assembly output files for bug tracing etc. They are not part +# of the build processes for executables. By default these files are created in +# the current working directory. Dependency tracking is not performed, the build +# is forced instead to make sure it's up to date. + +force: + + +#=== preprocessor file ========================================================= + + +# make preprocessor output file with extension .pre +# argument $1 = compiler type (c or cxx) +define make-preprocessor-file + $(info ++++ info: making preprocessor output file $(notdir $*.pre) \ + in current working directory) + $(compile-$1) -E $< $(c.flags) $($1.flags) -o $(notdir $*.pre) +endef + +%.pre:: %.c force + $(call make-preprocessor-file,c) + +%.pre:: %.cc force + $(call make-preprocessor-file,cxx) + +%.pre:: %.cpp force + $(call make-preprocessor-file,cxx) + + +#=== assembly file ============================================================= + + +# make C / assembly interleaved output file with extension .lst +# argument $1 = compiler type (c or cxx) +define make-assembly-file + $(info ++++ info: making assembly output file $(notdir $*.lst) \ + in current working directory) + $(compile-$1) \ + -c -Wa,-a,-ad -fverbose-asm \ + $($1.flags) \ + $< > $(notdir $*.lst) +endef + +%.lst:: %.c force + $(call make-assembly-file,c) + +%.lst:: %.cc force + $(call make-assembly-file,cxx) + +%.lst:: %.cpp force + $(call make-assembly-file,cxx) + + +################################################################################ +### rules: installation targets ################################################ +################################################################################ + + +#=== strip ===================================================================== + + +# Stripping of installed binaries will only be done when variable 'stripflags' +# is defined non-empty. No default definition is provided except for Windows +# where the unstripped binaries are large, especially in the case of Mingw-w64. + +# Note: while stripping all symbols ('-s' or '--strip-all') is possible for +# Linux and Windows, in the case of OSX only non-global symbols can be stripped +# (option '-x' or '--discard-all'). + +# Make definition of strip command overridable so it can be defined in an +# environment for cross-compilation. +STRIP ?= strip + +# Commands in 'strip-executables' will be executed conditionally in the rule for +# target 'install-executables'. +strip-executables = cd "$(installpath)" && \ + $(foreach v, $(executables), $(STRIP) $(stripflags) '$v';) + + +#=== install =================================================================== + + +# Install targets depend on successful exit status of target all because nothing +# must be installed in case of a build error. + +# -p = preserve time stamps +# -m = set permission mode (as in chmod) +# -d = create all components of specified directories +INSTALL = install +INSTALL_PROGRAM := $(INSTALL) -p -m 644 +INSTALL_DATA := $(INSTALL) -p -m 644 +INSTALL_DIR := $(INSTALL) -m 755 -d + +# strip spaces from file names +executables := $(strip $(executables)) +datafiles := $(strip $(datafiles)) +datadirs := $(strip $(datadirs)) + +# Do not make any install sub-target with empty variable definition because the +# install program would exit with an error. +install: $(if $(executables), install-executables) +install: $(if $(datafiles), install-datafiles) +install: $(if $(datadirs), install-datadirs) + +install-executables: all + $(INSTALL_DIR) -v "$(installpath)" + $(foreach v, $(executables), \ + $(INSTALL_PROGRAM) '$v' "$(installpath)";) + $(info ++++ info: executables of lib $(lib.name) installed \ + from $(CURDIR) to $(installpath)) + $(if $(stripflags), $(strip-executables),) + +install-datafiles: all + $(INSTALL_DIR) -v "$(installpath)" + $(foreach v, $(datafiles), \ + $(INSTALL_DATA) '$(v)' "$(installpath)";) + $(info ++++ info: data files of lib $(lib.name) installed \ + from $(CURDIR) to $(installpath)) + +install-datadirs: all + $(foreach v, $(datadirs), $(INSTALL_DIR) "$(installpath)/$v";) + $(foreach v, $(datadirs), \ + $(INSTALL_DATA) $(wildcard $v/*) "$(installpath)/$v";) + $(info ++++ info: data directories of lib $(lib.name) installed \ + from $(CURDIR) to $(installpath)) + + +################################################################################ +### rules: distribution targets ################################################ +################################################################################ + + +# TODO +# These targets are implemented in Makefile Template, but I have to figure out +# how to do it under the not-so-strict conditions of Makefile.pdlibbuilder. + +# make source package +dist: + @echo "target dist not yet implemented" + +# make Debian source package +dpkg-source: + @echo "target dpkg-source not yet implemented" + +$(ORIGDIR): + +$(DISTDIR): + + +################################################################################ +### rules: clean targets ####################################################### +################################################################################ + + +# delete build products from build tree +clean: + rm -f $(all.objects) + rm -f $(classes.executables) $(lib.name).$(extension) $(shared.lib) + rm -f *.pre *.lst + +# remove distribution directories and tarballs from build tree +distclean: clean + @echo "target distclean not yet implemented" + + +################################################################################ +### rules: submake targets ##################################################### +################################################################################ + + +# Iterate over sub-makefiles or makefiles in other directories. + +# When 'continue-make=yes' is set, sub-makes will report 'true' to the parent +# process regardless of their real exit status. This prevents the parent make +# from being aborted by a sub-make error. Useful when you want to quickly find +# out which sub-makes from a large set will succeed. +ifeq ($(continue-make),yes) + continue = || true +endif + +# These targets will trigger sub-make processes for entries in 'makefiledirs' +# and 'makefiles'. +all alldebug install clean distclean dist dkpg-source: \ + $(makefiledirs) $(makefiles) + +# this expands to identical rules for each entry in 'makefiledirs' +$(makefiledirs): + $(MAKE) --directory=$@ $(MAKECMDGOALS) $(continue) + +# this expands to identical rules for each entry in 'makefiles' +$(makefiles): + $(MAKE) --directory=$(dir $@) --makefile=$(notdir $@) $(MAKECMDGOALS) $(continue) + + +################################################################################ +### rules: convenience targets ################################################# +################################################################################ + + +#=== show variables ============================================================ + + +# Several 'function' macro's cause errors when expanded within a rule or without +# proper arguments. Variables which are set with the define directive are only +# shown by name for that reason. +functions = \ +add-class-source \ +declare-class-target \ +declare-class-executable-target \ +declare-object-target \ +link-class \ +link-lib \ +link-shared \ +make-object-file \ +make-preprocessor-file \ +make-assembly-file + + +# show variables from makefiles +vars: + $(info ++++ info: showing makefile variables:) + $(foreach v,\ + $(sort $(filter-out $(functions) functions, $(.VARIABLES))),\ + $(if $(filter file, $(origin $v)),\ + $(info variable $v = $($v)))) + $(foreach v, $(functions), $(info 'function' name: $v)) + @echo + +# show all variables +allvars: + $(info ++++ info: showing default, automatic and makefile variables:) + $(foreach v, \ + $(sort $(filter-out $(functions) functions, $(.VARIABLES))), \ + $(info variable ($(origin $v)) $v = $($v))) + $(foreach v, $(functions), $(info 'function' name: $v)) + @echo + + +#=== show dependencies ========================================================= + + +# show generated prerequisites rules +depend: + $(info ++++ info: generated prerequisite rules) + $(foreach v, $(classes), $(info $(declare-class-target))) + $(foreach v, $(classes), $(info $(declare-class-executable-target))) + $(foreach v, $(all.sources), $(info $(call declare-object-target, $v))) + @echo + + +#=== show help text ============================================================ + + +# brief info about targets and paths + +ifdef mpdh + mpdhinfo := $(mpdh) +else + mpdhinfo := m_pd.h was not found. Is Pd installed? +endif + +help: + @echo + @echo " Main targets:" + @echo " all: build executables (default target)" + @echo " install: install all components of the library" + @echo " vars: print makefile variables for troubleshooting" + @echo " allvars: print all variables for troubleshooting" + @echo " help: print this help text" + @echo + @echo " Pd API m_pd.h:" + @echo " $(mpdhinfo)" + @echo " You may specify your preferred Pd include directory as argument" + @echo " to the make command, like 'PDINCLUDEDIR=path/to/pd/src'." + @echo + @echo " Path for installation of your libdir(s):" + @echo " $(PDLIBDIR)" + @echo " Alternatively you may specify your path for installation as argument" + @echo " to the make command, like 'PDLIBDIR=path/to/pd-externals'." + @echo + @echo " Default paths are listed in the doc sections in Makefile.pdlibbuilder." + @echo + + +#=== platform test ============================================================= + + +# This target can be used to test if the compiler for specified PLATFORM is +# correctly defined and available. + +dumpmachine: + @$(CC) -dumpmachine + + +#=== dummy target ============================================================== + + +coffee: + @echo "Makefile.pdlibbuilder: Can not make coffee. Sorry." + + +################################################################################ +### end of rules sections ###################################################### +################################################################################ + + +# for syntax highlighting in vim and github +# vim: set filetype=make: + diff --git a/README.md b/README.md new file mode 100644 index 0000000..234d469 --- /dev/null +++ b/README.md @@ -0,0 +1,199 @@ + + +### Makefile.pdlibbuilder ### + +Helper makefile for Pure Data external libraries. Written by Katja Vetter +March-June 2015 for the public domain and since then developed as a Pd +community project. No warranties. Inspired by Hans Christoph Steiner's Makefile +Template and Stephan Beal's ShakeNMake. + +GNU make version >= 3.81 required. + + +### characteristics ### + + +* defines build settings based on autodetected target platform +* defines rules to build Pd class- or lib executables from C or C++ sources +* defines rules for libdir installation +* defines convenience targets for developer and user +* evaluates implicit dependencies for non-clean builds + + +### basic usage ### + + +In your Makefile, define your Pd lib name and class files, and include +Makefile.pdlibbuilder at the end of the Makefile. Like so: + + + # Makefile for mylib + + lib.name = mylib + + class.sources = myclass1.c myclass2.c + + datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt + + include Makefile.pdlibbuilder + + +For files in class.sources it is assumed that class name == source file +basename. The default target builds all classes as individual executables +with Pd's default extension for the platform. For anything more than the +most basic usage, read the documentation sections in Makefile.pdlibbuilder. + + +### paths ### + + +Makefile.pdlibbuilder >= v0.4.0 supports pd path variables which can be +defined not only as make command argument but also in the environment, to +override platform-dependent defaults: + +PDDIR: +Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and +PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. + +PDINCLUDEDIR: +Directory where Pd API m_pd.h should be found, and other Pd header files. +Overrides the default search path. + +PDBINDIR: +Directory where pd.dll should be found for linking (Windows only). Overrides +the default search path. + +PDLIBDIR: +Root directory for installation of Pd library directories. Overrides the +default install location. + + +### platform detection and predefined variables ### + + +Makefile.pdlibbuilder tries to detect architecture and operating system in +order to define platform-specific variables. Since v0.6.0 we let the compiler +report target platform, rather than taking the build machine as reference. This +simplifies cross compilation. The kind of build options that are predefined: + +- optimizations useful for realtime DSP processing +- options strictly required for the platform +- options to make the build work accross a range of CPU's and OS versions + +The exact choice and definition predefined variables changes over time, as new +platforms arrive and older platforms become obsolete. The easiest way to get an +overview for your platform is by checking the flags categories in the output of +target `vars`. Variables written in capitals (like `CFLAGS`) are intentionally +exposed as user variables, although technically all makefile variables can be +overridden by make command arguments. + + +### specific language versions ### + + +Makefile.pdlibbuilder handles C and C++, but can not detect if your code uses +features of a specific version (like C99, C++11, C++14 etc.). In such cases +your makefile should specify that version as compiler option: + + cflags = -std=c++11 + +Also you may need to be explicit about minimum OSX version. For example, C++11 +needs OSX 10.9 or higher: + + define forDarwin + cflags = -mmacosx-version-min=10.9 + endef + + +### documentation ### + + +This README.md provides only basic information. A large comment section inside +Makefile.pdlibbuilder lists and explains the available user variables, default +paths, and targets. The internal documentation reflects the exact functionality +of the particular version. For suggestions about project maintenance and +advanced compilation see tips-tricks.md. + + +### versioning ### + + +The project is versioned in MAJOR.MINOR.BUGFIX format (see http://semver.org), +and maintained at https://github.com/pure-data/pd-lib-builder. Pd lib developers +are invited to regulary check for updates, and to contribute and discuss +improvements here. If you really need to distribute a personalized version with +your library, rename Makefile.pdlibbuilder to avoid confusion. + + +### examples ### + +The list of projects using pd-lib-builder can be helpful if you are looking for +examples, from the simplest use case to more complex implementations. + +- helloworld: traditional illustration of simplest use case +- pd-windowing: straightforward real world use case of a small library +- pd-nilwind / pd-cyclone: more elaborate source tree +- zexy: migrated from autotools to pd-lib-builder + + +### projects using pd-lib-builder ### + +non-exhaustive list + +https://github.com/pure-data/helloworld + +https://github.com/electrickery/pd-nilwind + +https://github.com/electrickery/pd-maxlib + +https://github.com/electrickery/pd-sigpack + +https://github.com/electrickery/pd-tof + +https://github.com/electrickery/pd-windowing + +https://github.com/electrickery/pd-smlib + +https://github.com/porres/pd-cyclone + +https://github.com/porres/pd-else + +https://github.com/porres/pd-psycho + +https://git.iem.at/pd/comport + +https://git.iem.at/pd/hexloader + +https://git.iem.at/pd/iemgui + +https://git.iem.at/pd/iemguts + +https://git.iem.at/pd/iemlib + +https://git.iem.at/pd/iemnet + +https://git.iem.at/pd/iem_ambi + +https://git.iem.at/pd/iem_tab + +https://git.iem.at/pd/iem_adaptfilt + +https://git.iem.at/pd/iem_roomsim + +https://git.iem.at/pd/iem_spec2 + +https://git.iem.at/pd/mediasettings + +https://git.iem.at/pd/zexy + +https://git.iem.at/pd-gui/punish + +https://github.com/residuum/PuRestJson + +https://github.com/libpd/abl_link + +https://github.com/wbrent/timbreID + +https://github.com/MetaluNet/moonlib + + diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..53b261c --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,15 @@ +# recursively build all example projects in the subdirectories + + +makefiledirs := $(filter-out _%, $(dir $(wildcard */Makefile))) + +PDLIBBUILDER_DIR = ../ +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + +buildcheck installcheck: $(makefiledirs) + +runcheck: + PDBINDIR=$(PDBINDIR) ./test-patches.sh $(makefiledirs:%=%*.pd) + +projects: + @echo $(makefiledirs) diff --git a/tests/_template_/Makefile b/tests/_template_/Makefile new file mode 100644 index 0000000..ea5fd4f --- /dev/null +++ b/tests/_template_/Makefile @@ -0,0 +1,24 @@ +# Makefile to build class '_template_' for Pure Data. +# Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build +# settings and rules. + +# library name +lib.name = _template_ + +# input source file (class name == source file basename) +class.sources = _template_.c + +# all extra files to be included in binary distribution of the library +datafiles = _template_-help.pd _template_-meta.pd + +# include Makefile.pdlibbuilder +# (for real-world projects see the "Project Management" section +# in tips-tricks.md) +PDLIBBUILDER_DIR=../.. +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + +# simplistic tests whether all expected files have been produced/installed +buildcheck: all + test -e _template_.$(extension) +installcheck: install + test -e $(installpath)/_template_.$(extension) diff --git a/tests/_template_/_template_-help.pd b/tests/_template_/_template_-help.pd new file mode 100644 index 0000000..94425c6 --- /dev/null +++ b/tests/_template_/_template_-help.pd @@ -0,0 +1,4 @@ +#N canvas 335 160 450 300 12; +#X obj 143 125 _template_; +#X msg 143 93 7; +#X connect 1 0 0 0; diff --git a/tests/_template_/_template_-meta.pd b/tests/_template_/_template_-meta.pd new file mode 100644 index 0000000..7f997bf --- /dev/null +++ b/tests/_template_/_template_-meta.pd @@ -0,0 +1,9 @@ +#N canvas 966 322 200 200 10; +#N canvas 19 51 420 300 META 0; +#X text 10 10 META this is a prototype of a libdir meta file; +#X text 10 51 AUTHOR IOhannes m zmolnig; +#X text 10 110 VERSION 1.0.0; +#X text 10 90 LICENSE CC0; +#X text 10 70 DESCRIPTION Example "_template_" external.; +#X text 10 30 NAME _template_; +#X restore 10 10 pd META; diff --git a/tests/_template_/_template_.c b/tests/_template_/_template_.c new file mode 100644 index 0000000..ef5293e --- /dev/null +++ b/tests/_template_/_template_.c @@ -0,0 +1,13 @@ +#include +t_class*_template__class; +static void _template__float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*_template__new(void) { + return pd_new(_template__class); +} +void _template__setup(void) { + post("%s", __FUNCTION__); + _template__class = class_new(gensym("_template_"), _template__new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(_template__class, _template__float); +} diff --git a/tests/make-from-template.sh b/tests/make-from-template.sh new file mode 100755 index 0000000..d4f6ade --- /dev/null +++ b/tests/make-from-template.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +template=_template_ +template_dir=${0%/*}/${template} + +outdir=$1 +outdir=${outdir%/} +outname=${outdir##*/} + + +usage() { + cat 1>&2 < + creates a new test-directory from _template_; + must not exist yet. +EOL + if [ "x$@" != "x" ]; then + echo + echo " $@" 1>&2 + fi + exit 1 +} + +if [ "x${outdir}" = "x" ]; then + usage +fi + +if [ -d "${outdir}" ]; then + usage "output directory '${outdir}' already exists!" +fi + +if [ ! -d "${template_dir}" ]; then + echo "unable to find '${template_dir}'" 1>&2 + exit 1 +fi + +mkdir -p "${outdir}" || usage "unable to create '${outdir}'!" +rmdir "${outdir}" +cp -r "${template_dir}" "${outdir}" +find "${outdir}" -type f -exec sed -e "s|${template}|${outname}|g" -i {} + +for f in "${outdir}"/*; do + g=$(echo $f | sed -e "s|${template}|${outname}|g") + if [ "x${f}" != "x${g}" ]; then + mv "${f}" "${g}" + fi +done diff --git a/tests/multifor/Makefile b/tests/multifor/Makefile new file mode 100644 index 0000000..48950f2 --- /dev/null +++ b/tests/multifor/Makefile @@ -0,0 +1,39 @@ +# Makefile to build class 'multifor' for Pure Data. +# Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build +# settings and rules. + +# library name +lib.name = multifor + +# input source file (class name == source file basename) +class.sources = multiforA.c + +# additional classes +define forLinux + class.sources += multiforB.c +endef +define forDarwin + class.sources += multiforB.c +endef +define forWindows + class.sources += multiforB.c +endef + +# all extra files to be included in binary distribution of the library +datafiles = multifor-help.pd multifor-meta.pd + +# include Makefile.pdlibbuilder +# (for real-world projects see the "Project Management" section +# in tips-tricks.md) +PDLIBBUILDER_DIR=../.. +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + +# simplistic tests whether all expected files have been produced/installed +buildcheck: all + test -e multiforA.$(extension) + test -e multiforB.$(extension) +installcheck: install + test -e $(installpath)/multiforA.$(extension) + test -e $(installpath)/multiforB.$(extension) + test -e $(installpath)/multifor-help.pd + test -e $(installpath)/multifor-meta.pd diff --git a/tests/multifor/README.md b/tests/multifor/README.md new file mode 100644 index 0000000..6b336c7 --- /dev/null +++ b/tests/multifor/README.md @@ -0,0 +1,9 @@ +multifor +======== + +minimal pd-lib-builder project that shows how to compile +a library that contains multiple C-files that are compiled into +multiple binaries each containing a different Pd-objectclass. +some of the objectclasses are only compiled on specific platforms. + +this is a special case of the one-object-per-binary library structure. diff --git a/tests/multifor/multifor-help.pd b/tests/multifor/multifor-help.pd new file mode 100644 index 0000000..05d9e93 --- /dev/null +++ b/tests/multifor/multifor-help.pd @@ -0,0 +1,7 @@ +#N canvas 335 160 450 300 12; +#X msg 143 93 7; +#X obj 143 125 multiforA; +#X obj 223 125 multiforB; +#X msg 223 93 12; +#X connect 0 0 1 0; +#X connect 3 0 2 0; diff --git a/tests/multifor/multifor-meta.pd b/tests/multifor/multifor-meta.pd new file mode 100644 index 0000000..2c696e3 --- /dev/null +++ b/tests/multifor/multifor-meta.pd @@ -0,0 +1,9 @@ +#N canvas 966 322 200 200 10; +#N canvas 19 51 420 300 META 0; +#X text 10 10 META this is a prototype of a libdir meta file; +#X text 10 51 AUTHOR IOhannes m zmolnig; +#X text 10 110 VERSION 1.0.0; +#X text 10 90 LICENSE CC0; +#X text 10 70 DESCRIPTION Example "multifor" external.; +#X text 10 30 NAME multifor; +#X restore 10 10 pd META; diff --git a/tests/multifor/multiforA.c b/tests/multifor/multiforA.c new file mode 100644 index 0000000..c52f68c --- /dev/null +++ b/tests/multifor/multiforA.c @@ -0,0 +1,13 @@ +#include +t_class*multiforA_class; +static void multiforA_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*multiforA_new(void) { + return pd_new(multiforA_class); +} +void multiforA_setup(void) { + post("%s", __FUNCTION__); + multiforA_class = class_new(gensym("multiforA"), multiforA_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multiforA_class, multiforA_float); +} diff --git a/tests/multifor/multiforB.c b/tests/multifor/multiforB.c new file mode 100644 index 0000000..74618ea --- /dev/null +++ b/tests/multifor/multiforB.c @@ -0,0 +1,13 @@ +#include +t_class*multiforB_class; +static void multiforB_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*multiforB_new(void) { + return pd_new(multiforB_class); +} +void multiforB_setup(void) { + post("%s", __FUNCTION__); + multiforB_class = class_new(gensym("multiforB"), multiforB_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multiforB_class, multiforB_float); +} diff --git a/tests/multilib/Makefile b/tests/multilib/Makefile new file mode 100644 index 0000000..00f20dc --- /dev/null +++ b/tests/multilib/Makefile @@ -0,0 +1,32 @@ +# Makefile to build class 'multilib' for Pure Data. +# Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build +# settings and rules. + +# library name +lib.name = multilib + +make-lib-executable=yes + +# input source file (class name == source file basename) +class.sources = multilibA.c multilibB.c + +# glue for building a multi-object library +lib.setup.sources = $(lib.name).c + +# all extra files to be included in binary distribution of the library +datafiles = multilib-help.pd multilib-meta.pd + +# include Makefile.pdlibbuilder +# (for real-world projects see the "Project Management" section +# in tips-tricks.md) +PDLIBBUILDER_DIR=../.. +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + + +# simplistic tests whether all expected files have been produced/installed +buildcheck: all + test -e multilib.$(extension) +installcheck: install + test -e $(installpath)/multilib.$(extension) + test -e $(installpath)/multilib-help.pd + test -e $(installpath)/multilib-meta.pd diff --git a/tests/multilib/README.md b/tests/multilib/README.md new file mode 100644 index 0000000..4a80535 --- /dev/null +++ b/tests/multilib/README.md @@ -0,0 +1,8 @@ +multilib +======== + +minimal pd-lib-builder project that shows how to compile +a library that contains multiple C-files that are compiled into +a single binary containing different Pd-objectclasses. + +this is the general case of the single-binary library structure. diff --git a/tests/multilib/multilib-help.pd b/tests/multilib/multilib-help.pd new file mode 100644 index 0000000..fc3931d --- /dev/null +++ b/tests/multilib/multilib-help.pd @@ -0,0 +1,9 @@ +#N canvas 335 160 450 300 12; +#X declare -lib multilib; +#X msg 143 93 7; +#X obj 143 125 multilibA; +#X obj 223 125 multilibB; +#X msg 223 93 12; +#X obj 136 47 declare -lib multilib; +#X connect 0 0 1 0; +#X connect 3 0 2 0; diff --git a/tests/multilib/multilib-meta.pd b/tests/multilib/multilib-meta.pd new file mode 100644 index 0000000..ef08c03 --- /dev/null +++ b/tests/multilib/multilib-meta.pd @@ -0,0 +1,9 @@ +#N canvas 966 322 200 200 10; +#N canvas 19 51 420 300 META 0; +#X text 10 10 META this is a prototype of a libdir meta file; +#X text 10 51 AUTHOR IOhannes m zmolnig; +#X text 10 110 VERSION 1.0.0; +#X text 10 90 LICENSE CC0; +#X text 10 70 DESCRIPTION Example "multiple" external.; +#X text 10 30 NAME multiple; +#X restore 10 10 pd META; diff --git a/tests/multilib/multilib.c b/tests/multilib/multilib.c new file mode 100644 index 0000000..82d0eac --- /dev/null +++ b/tests/multilib/multilib.c @@ -0,0 +1,8 @@ + +void multilibA_setup(void); +void multilibB_setup(void); + +void multilib_setup(void) { + multilibA_setup(); + multilibB_setup(); +} diff --git a/tests/multilib/multilibA.c b/tests/multilib/multilibA.c new file mode 100644 index 0000000..4760746 --- /dev/null +++ b/tests/multilib/multilibA.c @@ -0,0 +1,13 @@ +#include +t_class*multilibA_class; +static void multilibA_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*multilibA_new(void) { + return pd_new(multilibA_class); +} +void multilibA_setup(void) { + post("%s", __FUNCTION__); + multilibA_class = class_new(gensym("multilibA"), multilibA_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multilibA_class, multilibA_float); +} diff --git a/tests/multilib/multilibB.c b/tests/multilib/multilibB.c new file mode 100644 index 0000000..ce7c4d8 --- /dev/null +++ b/tests/multilib/multilibB.c @@ -0,0 +1,13 @@ +#include +t_class*multilibB_class; +static void multilibB_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*multilibB_new(void) { + return pd_new(multilibB_class); +} +void multilibB_setup(void) { + post("%s", __FUNCTION__); + multilibB_class = class_new(gensym("multilibB"), multilibB_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multilibB_class, multilibB_float); +} diff --git a/tests/multiple/Makefile b/tests/multiple/Makefile new file mode 100644 index 0000000..eac1412 --- /dev/null +++ b/tests/multiple/Makefile @@ -0,0 +1,28 @@ +# Makefile to build class 'multiple' for Pure Data. +# Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build +# settings and rules. + +# library name +lib.name = multiple + +# input source file (class name == source file basename) +class.sources = multipleA.c multipleB.c + +# all extra files to be included in binary distribution of the library +datafiles = multiple-help.pd multiple-meta.pd + +# include Makefile.pdlibbuilder +# (for real-world projects see the "Project Management" section +# in tips-tricks.md) +PDLIBBUILDER_DIR=../.. +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + +# simplistic tests whether all expected files have been produced/installed +buildcheck: all + test -e multipleA.$(extension) + test -e multipleB.$(extension) +installcheck: install + test -e $(installpath)/multipleA.$(extension) + test -e $(installpath)/multipleB.$(extension) + test -e $(installpath)/multiple-help.pd + test -e $(installpath)/multiple-meta.pd diff --git a/tests/multiple/README.md b/tests/multiple/README.md new file mode 100644 index 0000000..04c8c97 --- /dev/null +++ b/tests/multiple/README.md @@ -0,0 +1,8 @@ +multiple +======== + +minimal pd-lib-builder project that shows how to compile +a library that contains multiple C-files that are compiled into +multiple binaries each containing a different Pd-objectclass. + +this is the general case of the one-object-per-binary library structure. diff --git a/tests/multiple/multiple-help.pd b/tests/multiple/multiple-help.pd new file mode 100644 index 0000000..0e4a43e --- /dev/null +++ b/tests/multiple/multiple-help.pd @@ -0,0 +1,7 @@ +#N canvas 335 160 450 300 12; +#X msg 143 93 7; +#X obj 143 125 multipleA; +#X obj 223 125 multipleB; +#X msg 223 93 12; +#X connect 0 0 1 0; +#X connect 3 0 2 0; diff --git a/tests/multiple/multiple-meta.pd b/tests/multiple/multiple-meta.pd new file mode 100644 index 0000000..ef08c03 --- /dev/null +++ b/tests/multiple/multiple-meta.pd @@ -0,0 +1,9 @@ +#N canvas 966 322 200 200 10; +#N canvas 19 51 420 300 META 0; +#X text 10 10 META this is a prototype of a libdir meta file; +#X text 10 51 AUTHOR IOhannes m zmolnig; +#X text 10 110 VERSION 1.0.0; +#X text 10 90 LICENSE CC0; +#X text 10 70 DESCRIPTION Example "multiple" external.; +#X text 10 30 NAME multiple; +#X restore 10 10 pd META; diff --git a/tests/multiple/multipleA.c b/tests/multiple/multipleA.c new file mode 100644 index 0000000..dc7bfb0 --- /dev/null +++ b/tests/multiple/multipleA.c @@ -0,0 +1,13 @@ +#include +t_class*multipleA_class; +static void multipleA_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*multipleA_new(void) { + return pd_new(multipleA_class); +} +void multipleA_setup(void) { + post("%s", __FUNCTION__); + multipleA_class = class_new(gensym("multipleA"), multipleA_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multipleA_class, multipleA_float); +} diff --git a/tests/multiple/multipleB.c b/tests/multiple/multipleB.c new file mode 100644 index 0000000..aaf50ba --- /dev/null +++ b/tests/multiple/multipleB.c @@ -0,0 +1,13 @@ +#include +t_class*multipleB_class; +static void multipleB_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*multipleB_new(void) { + return pd_new(multipleB_class); +} +void multipleB_setup(void) { + post("%s", __FUNCTION__); + multipleB_class = class_new(gensym("multipleB"), multipleB_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multipleB_class, multipleB_float); +} diff --git a/tests/multiplexx/Makefile b/tests/multiplexx/Makefile new file mode 100644 index 0000000..7438f0a --- /dev/null +++ b/tests/multiplexx/Makefile @@ -0,0 +1,28 @@ +# Makefile to build class 'multiplexx' for Pure Data. +# Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build +# settings and rules. + +# library name +lib.name = multiplexx + +# input source file (class name == source file basename) +class.sources = multiplexxA.cpp multiplexxB.c + +# all extra files to be included in binary distribution of the library +datafiles = multiplexx-help.pd multiplexx-meta.pd + +# include Makefile.pdlibbuilder +# (for real-world projects see the "Project Management" section +# in tips-tricks.md) +PDLIBBUILDER_DIR=../.. +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + +# simplistic tests whether all expected files have been produced/installed +buildcheck: all + test -e multiplexxA.$(extension) + test -e multiplexxB.$(extension) +installcheck: install + test -e $(installpath)/multiplexxA.$(extension) + test -e $(installpath)/multiplexxB.$(extension) + test -e $(installpath)/multiplexx-help.pd + test -e $(installpath)/multiplexx-meta.pd diff --git a/tests/multiplexx/README.md b/tests/multiplexx/README.md new file mode 100644 index 0000000..82aab9b --- /dev/null +++ b/tests/multiplexx/README.md @@ -0,0 +1,8 @@ +multiplexx +======== + +minimal pd-lib-builder project that shows how to compile +a library that contains multiplexx C-files that are compiled into +multiplexx binaries each containing a different Pd-objectclass. + +this is the general case of the one-object-per-binary library structure. diff --git a/tests/multiplexx/multiplexx-help.pd b/tests/multiplexx/multiplexx-help.pd new file mode 100644 index 0000000..b715d1a --- /dev/null +++ b/tests/multiplexx/multiplexx-help.pd @@ -0,0 +1,7 @@ +#N canvas 335 160 450 300 12; +#X msg 143 93 7; +#X obj 143 125 multiplexxA; +#X obj 223 125 multiplexxB; +#X msg 223 93 12; +#X connect 0 0 1 0; +#X connect 3 0 2 0; diff --git a/tests/multiplexx/multiplexx-meta.pd b/tests/multiplexx/multiplexx-meta.pd new file mode 100644 index 0000000..10132c9 --- /dev/null +++ b/tests/multiplexx/multiplexx-meta.pd @@ -0,0 +1,9 @@ +#N canvas 966 322 200 200 10; +#N canvas 19 51 420 300 META 0; +#X text 10 10 META this is a prototype of a libdir meta file; +#X text 10 51 AUTHOR IOhannes m zmolnig; +#X text 10 110 VERSION 1.0.0; +#X text 10 90 LICENSE CC0; +#X text 10 70 DESCRIPTION Example "multiplexx" external.; +#X text 10 30 NAME multiplexx; +#X restore 10 10 pd META; diff --git a/tests/multiplexx/multiplexxA.cpp b/tests/multiplexx/multiplexxA.cpp new file mode 100644 index 0000000..e18b2f1 --- /dev/null +++ b/tests/multiplexx/multiplexxA.cpp @@ -0,0 +1,19 @@ +#include +#include +t_class*multiplexxA_class; +static void multiplexxA_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*multiplexxA_new(void) { + return pd_new(multiplexxA_class); +} +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +extern "C" { + void multiplexxA_setup(void); +} +#endif +void multiplexxA_setup(void) { + std::cerr << __FUNCTION__ << std::endl; + multiplexxA_class = class_new(gensym("multiplexxA"), multiplexxA_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multiplexxA_class, multiplexxA_float); +} diff --git a/tests/multiplexx/multiplexxB.c b/tests/multiplexx/multiplexxB.c new file mode 100644 index 0000000..41cd95a --- /dev/null +++ b/tests/multiplexx/multiplexxB.c @@ -0,0 +1,13 @@ +#include +t_class*multiplexxB_class; +static void multiplexxB_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*multiplexxB_new(void) { + return pd_new(multiplexxB_class); +} +void multiplexxB_setup(void) { + post("%s", __FUNCTION__); + multiplexxB_class = class_new(gensym("multiplexxB"), multiplexxB_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multiplexxB_class, multiplexxB_float); +} diff --git a/tests/multishared/Makefile b/tests/multishared/Makefile new file mode 100644 index 0000000..9ccb169 --- /dev/null +++ b/tests/multishared/Makefile @@ -0,0 +1,41 @@ +# Makefile to build class 'multishared' for Pure Data. +# Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build +# settings and rules. + +# library name +lib.name = multishared + +# common functions +shared.sources = shared.c + +# input source file (class name == source file basename) +class.sources = multisharedA.c multisharedB.c + +# all extra files to be included in binary distribution of the library +datafiles = multishared-help.pd multishared-meta.pd + +# include Makefile.pdlibbuilder +# (for real-world projects see the "Project Management" section +# in tips-tricks.md) +PDLIBBUILDER_DIR=../.. +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + +# simplistic tests whether all expected files have been produced/installed +buildcheck: all +ifeq ($(shared.extension), $(extension)) + test -e lib$(lib.name).$(shared.extension) +else + test -e lib$(lib.name).$(extension).$(shared.extension) +endif + test -e multisharedA.$(extension) + test -e multisharedB.$(extension) +installcheck: install +ifeq ($(shared.extension), $(extension)) + test -e $(installpath)/lib$(lib.name).$(shared.extension) +else + test -e $(installpath)/lib$(lib.name).$(extension).$(shared.extension) +endif + test -e $(installpath)/multisharedA.$(extension) + test -e $(installpath)/multisharedB.$(extension) + test -e $(installpath)/multishared-help.pd + test -e $(installpath)/multishared-meta.pd diff --git a/tests/multishared/README.md b/tests/multishared/README.md new file mode 100644 index 0000000..85bc79b --- /dev/null +++ b/tests/multishared/README.md @@ -0,0 +1,9 @@ +multishared +=========== + +minimal pd-lib-builder project that shows how to compile +a library that contains multiple C-files that are compiled into +multiple binaries each containing a different Pd-objectclass. +a local shared library is used for common components. + +this is an extended case of the one-object-per-binary library structure. diff --git a/tests/multishared/multishared-help.pd b/tests/multishared/multishared-help.pd new file mode 100644 index 0000000..da18aed --- /dev/null +++ b/tests/multishared/multishared-help.pd @@ -0,0 +1,7 @@ +#N canvas 335 160 450 300 12; +#X msg 143 93 7; +#X obj 143 125 multisharedA; +#X obj 223 125 multisharedB; +#X msg 223 93 12; +#X connect 0 0 1 0; +#X connect 3 0 2 0; diff --git a/tests/multishared/multishared-meta.pd b/tests/multishared/multishared-meta.pd new file mode 100644 index 0000000..088f750 --- /dev/null +++ b/tests/multishared/multishared-meta.pd @@ -0,0 +1,9 @@ +#N canvas 966 322 200 200 10; +#N canvas 19 51 420 300 META 0; +#X text 10 10 META this is a prototype of a libdir meta file; +#X text 10 51 AUTHOR IOhannes m zmolnig; +#X text 10 110 VERSION 1.0.0; +#X text 10 90 LICENSE CC0; +#X text 10 70 DESCRIPTION Example "multishared" external.; +#X text 10 30 NAME multishared; +#X restore 10 10 pd META; diff --git a/tests/multishared/multishared.h b/tests/multishared/multishared.h new file mode 100644 index 0000000..2e7712a --- /dev/null +++ b/tests/multishared/multishared.h @@ -0,0 +1,3 @@ +#include + +void multishared_foo(t_float f); diff --git a/tests/multishared/multisharedA.c b/tests/multishared/multisharedA.c new file mode 100644 index 0000000..9e8ae57 --- /dev/null +++ b/tests/multishared/multisharedA.c @@ -0,0 +1,14 @@ +#include "multishared.h" +t_class*multisharedA_class; +static void multisharedA_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); + multishared_foo(f1); +} +static void*multisharedA_new(void) { + return pd_new(multisharedA_class); +} +void multisharedA_setup(void) { + post("%s", __FUNCTION__); + multisharedA_class = class_new(gensym("multisharedA"), multisharedA_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multisharedA_class, multisharedA_float); +} diff --git a/tests/multishared/multisharedB.c b/tests/multishared/multisharedB.c new file mode 100644 index 0000000..ca7b669 --- /dev/null +++ b/tests/multishared/multisharedB.c @@ -0,0 +1,14 @@ +#include "multishared.h" +t_class*multisharedB_class; +static void multisharedB_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); + multishared_foo(f1); +} +static void*multisharedB_new(void) { + return pd_new(multisharedB_class); +} +void multisharedB_setup(void) { + post("%s", __FUNCTION__); + multisharedB_class = class_new(gensym("multisharedB"), multisharedB_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(multisharedB_class, multisharedB_float); +} diff --git a/tests/multishared/shared.c b/tests/multishared/shared.c new file mode 100644 index 0000000..47284a2 --- /dev/null +++ b/tests/multishared/shared.c @@ -0,0 +1,5 @@ +#include "multishared.h" + +void multishared_foo(t_float f) { + post("%s(%f)", __FUNCTION__, f); +} diff --git a/tests/single/Makefile b/tests/single/Makefile new file mode 100644 index 0000000..0d36005 --- /dev/null +++ b/tests/single/Makefile @@ -0,0 +1,24 @@ +# Makefile to build class 'single' for Pure Data. +# Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build +# settings and rules. + +# library name +lib.name = single + +# input source file (class name == source file basename) +class.sources = single.c + +# all extra files to be included in binary distribution of the library +datafiles = single-help.pd single-meta.pd + +# include Makefile.pdlibbuilder +# (for real-world projects see the "Project Management" section +# in tips-tricks.md) +PDLIBBUILDER_DIR=../.. +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + +# simplistic tests whether all expected files have been produced/installed +buildcheck: all + test -e single.$(extension) +installcheck: install + test -e $(installpath)/single.$(extension) diff --git a/tests/single/README.md b/tests/single/README.md new file mode 100644 index 0000000..c752acb --- /dev/null +++ b/tests/single/README.md @@ -0,0 +1,8 @@ +single +====== + +minimal pd-lib-builder project that shows how to compile +a library that contains a single C-file that is compiled into +a single binary containing a single Pd-objectclass. + +this is a degenerate case of the one-object-per-binary library structure. diff --git a/tests/single/single-help.pd b/tests/single/single-help.pd new file mode 100644 index 0000000..1d74e5c --- /dev/null +++ b/tests/single/single-help.pd @@ -0,0 +1,4 @@ +#N canvas 335 160 450 300 12; +#X obj 143 125 single; +#X msg 143 93 7; +#X connect 1 0 0 0; diff --git a/tests/single/single-meta.pd b/tests/single/single-meta.pd new file mode 100644 index 0000000..57923af --- /dev/null +++ b/tests/single/single-meta.pd @@ -0,0 +1,9 @@ +#N canvas 966 322 200 200 10; +#N canvas 19 51 420 300 META 0; +#X text 10 10 META this is a prototype of a libdir meta file; +#X text 10 51 AUTHOR IOhannes m zmolnig; +#X text 10 110 VERSION 1.0.0; +#X text 10 90 LICENSE CC0; +#X text 10 70 DESCRIPTION Example "single" external.; +#X text 10 30 NAME single; +#X restore 10 10 pd META; diff --git a/tests/single/single.c b/tests/single/single.c new file mode 100644 index 0000000..a35f10c --- /dev/null +++ b/tests/single/single.c @@ -0,0 +1,13 @@ +#include +t_class*single_class; +static void single_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*single_new(void) { + return pd_new(single_class); +} +void single_setup(void) { + post("%s", __FUNCTION__); + single_class = class_new(gensym("single"), single_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(single_class, single_float); +} diff --git a/tests/subdir/Makefile b/tests/subdir/Makefile new file mode 100644 index 0000000..ac68c2a --- /dev/null +++ b/tests/subdir/Makefile @@ -0,0 +1,27 @@ +# Makefile to build class 'subdir' for Pure Data. +# Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build +# settings and rules. + +# library name +lib.name = subdir + +# input source file (class name == source file basename) +class.sources = src/subdir.c src/subdir~.c + +# all extra files to be included in binary distribution of the library +datafiles = subdir-help.pd subdir-meta.pd + +# include Makefile.pdlibbuilder +# (for real-world projects see the "Project Management" section +# in tips-tricks.md) + +PDLIBBUILDER_DIR=../.. +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder + +# simplistic tests whether all expected files have been produced/installed +buildcheck: all + test -e subdir.$(extension) + test -e subdir~.$(extension) +installcheck: install + test -e $(installpath)/subdir.$(extension) + test -e $(installpath)/subdir~.$(extension) diff --git a/tests/subdir/README.md b/tests/subdir/README.md new file mode 100644 index 0000000..e5185e5 --- /dev/null +++ b/tests/subdir/README.md @@ -0,0 +1,8 @@ +subdir +====== + +pd-lib-builder project that shows how to compile +a library that contains a single C-file in a separate src/ directory, +that is compiled into a single binary containing a subdir Pd-objectclass. + +this is a special case of the one-object-per-binary library structure. diff --git a/tests/subdir/src/subdir.c b/tests/subdir/src/subdir.c new file mode 100644 index 0000000..cdcc8ce --- /dev/null +++ b/tests/subdir/src/subdir.c @@ -0,0 +1,13 @@ +#include +t_class*subdir_class; +static void subdir_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*subdir_new(void) { + return pd_new(subdir_class); +} +void subdir_setup(void) { + post("%s", __FUNCTION__); + subdir_class = class_new(gensym("subdir"), subdir_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(subdir_class, subdir_float); +} diff --git a/tests/subdir/src/subdir~.c b/tests/subdir/src/subdir~.c new file mode 100644 index 0000000..ca3ed20 --- /dev/null +++ b/tests/subdir/src/subdir~.c @@ -0,0 +1,13 @@ +#include +t_class*subdir_tilde_class; +static void subdir_tilde_float(t_object*x, t_float f1) { + pd_error(x, "%s got %f", __FUNCTION__, f1); +} +static void*subdir_tilde_new(void) { + return pd_new(subdir_tilde_class); +} +void subdir_tilde_setup(void) { + post("%s", __FUNCTION__); + subdir_tilde_class = class_new(gensym("subdir~"), subdir_tilde_new, 0, sizeof(t_object), 0, A_NULL); + class_addfloat(subdir_tilde_class, subdir_tilde_float); +} diff --git a/tests/subdir/subdir-help.pd b/tests/subdir/subdir-help.pd new file mode 100644 index 0000000..725f149 --- /dev/null +++ b/tests/subdir/subdir-help.pd @@ -0,0 +1,4 @@ +#N canvas 335 160 450 300 12; +#X obj 143 125 subdir; +#X msg 143 93 7; +#X connect 1 0 0 0; diff --git a/tests/subdir/subdir-meta.pd b/tests/subdir/subdir-meta.pd new file mode 100644 index 0000000..3e0b529 --- /dev/null +++ b/tests/subdir/subdir-meta.pd @@ -0,0 +1,9 @@ +#N canvas 966 322 200 200 10; +#N canvas 19 51 420 300 META 0; +#X text 10 10 META this is a prototype of a libdir meta file; +#X text 10 51 AUTHOR IOhannes m zmolnig; +#X text 10 110 VERSION 1.0.0; +#X text 10 90 LICENSE CC0; +#X text 10 70 DESCRIPTION Example "subdir" external.; +#X text 10 30 NAME subdir; +#X restore 10 10 pd META; diff --git a/tests/subdir/subdir~-help.pd b/tests/subdir/subdir~-help.pd new file mode 100644 index 0000000..d3a782b --- /dev/null +++ b/tests/subdir/subdir~-help.pd @@ -0,0 +1,4 @@ +#N canvas 335 160 450 300 12; +#X obj 143 125 subdir~; +#X msg 143 93 7; +#X connect 1 0 0 0; diff --git a/tests/test-patches.sh b/tests/test-patches.sh new file mode 100755 index 0000000..0d80177 --- /dev/null +++ b/tests/test-patches.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +## simple script to open patches via Pd, and check for errors +## - each patch is opened separately +## - if an error is encountered, the Pd-printout is displayed +## (else it is suppressed) +## - if any of the patches encountered an error, the script will +## exit with a non-0 code + +if [ "x${PD}" = "x" ]; then + if [ "x${PDBINDIR}" != "x" ]; then + for exe in pd.com pd pd.exe; do + if [ -x "${PDBINDIR}/${exe}" ]; then + PD="${PDBINDIR}/${exe}" + break + fi + done + if [ "x${PD}" = "x" ]; then + echo "WARNING: couldn't find a usable Pd in '${PDBINDIR}'" 1>&2 + fi + fi +fi +if [ "x${PD}" = "x" ]; then + PD=pd +fi +echo "using Pd: ${PD}" + +failed=0 +failed_tests="" +succeeded=0 + +open1patch() { + logfile=$(mktemp) + local patch=$1 + local patchdir=${patch%%/*} + local patchfile=${patch#*/} + patchfile=${patchfile#/} + #echo "INFO: running ${patchfile} in ${patchdir}" + cd "${patchdir}" && \ + ${PD} -batch -nrt -noprefs -nostdpath -open "${patchfile}" -send "pd quit" \ + >"${logfile}" 2>&1 + ret=$? + if grep "error: ... couldn't create" "${logfile}" >/dev/null; then + ret=1 + fi + if [ "x${ret}" != "x0" ]; then + echo "" + cat "${logfile}" + echo "FAILED[$ret]: ${patch}" + else + echo "SUCCEEDED: ${patch}" + fi + rm "${logfile}" + return $ret +} + +for p in "${@}"; do + if (open1patch "${p}"); then + succeeded=$((succeeded+1)) + else + failed=$((failed+1)) + failed_tests="${failed_tests} ${p}" + fi +done + +echo "" +echo "SUCCESS: ${succeeded}" +echo "FAILURE: ${failed}" +test ${failed} -eq 0 || echo "FAILS :${failed_tests}" +test ${failed} -eq 0 diff --git a/tips-tricks.md b/tips-tricks.md new file mode 100644 index 0000000..e8a02a2 --- /dev/null +++ b/tips-tricks.md @@ -0,0 +1,231 @@ +pd-lib-builder cheatsheet +========================= + +# Creating special builds + +## 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 +into path `${PDWIN32}`, to build for Windows 32 bit: + + make PLATFORM=i686-w64-mingw32 PDDIR="${PDWIN32}" + +#### 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`, +`STRIP`. Example: + + make system=Windows target.arch=i686 CC=i686-w64-mingw32-gcc STRIP=i686-w64-mingw32-strip PDDIR="${PDWIN32}" + +#### 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 +amd64 provides them for the following platforms (install g++ with dependencies +for a given platform to get the whole toolchain): + +- `arm-linux-gnueabihf` +- `aarch64-linux-gnu` +- `i686-linux-gnu` +- `i686-w64-mingw32` and `x86_64-w64-mingw32` (install `mingw-w64`) + +Cross toolchains for OSX/MacOS are not generally distributed. Project +`osxcross` from Thomas Poechtraeger can create them for Linux. + +## building double-precision externals + +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" + +## building externals for W64 (64-bit Windows) + +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 CPPFLAGS="-DPD_LONGINTTYPE=__int64" CC=x86_64-w64-mingw32-gcc + + +To build a double-precision external for W64, use something like: + + make CPPFLAGS="-DPD_LONGINTTYPE=__int64 -DPD_FLOATSIZE=64" CC=x86_64-w64-mingw32-gcc + + +## TODO universal binaries on OSX + + +# Project management + +In general it is advised to put the `Makefile.pdlibbuilder` into a separate +subdirectory (e.g. `pd-lib-builder/`). +This makes it much easier to update the `Makefile.pdlibbuilder` later + +You *should* also use a variable to the actual path of the Makefile.pdlibbuilder +(even if you keep it in the root-directory), as this allows easy experimenting +with newer (or older) (or site-specific) versions of the pd-lib-builder +Makefile. + +~~~make +PDLIBBUILDER_DIR=pd-lib-builder/ +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder +~~~ + +## Keeping pd-lib-builder up-to-date + +### `git subtree` + +With git-subtrees, you make the pd-lib-builder repository (or any other +repository for that matter) part of your own repository - with full history and +everything - put nicely into a distinct subdirectory. + +Support for *manipulating* subtrees has been added with Git-v1.7.11 (May 2012). +The nice thing however is, that from "outside" the subtree is part of your +repository like any other directory. E.g. older versions of Git can clone your +repository with the full subtree (and all it's history) just fine. +You can also use git-archive to make a complete snapshot of your repository +(including the subtree) - nice, if you e.g. want self-contained downloads of +your project from git hosting platforms (like Github, Gitlab, Bitbucket,...) + +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` + +~~~sh +git subtree add --prefix=pd-lib-builder/ https://github.com/pure-data/pd-lib-builder v0.5.0 +~~~ + +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: + +~~~sh +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: + +~~~sh +git subtree pull --prefix pd-lib-builder/ https://github.com/pure-data/pd-lib-builder master +~~~ + +#### Pulling the updated subtree into existing clones +Again, nothing special. +Just pull as always: + +~~~sh +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 +- ... + +### ~~`git submodule`~~ [DISCOURAGED] + + +#### Initial setup/check-out +To add a new submodule to your repository, just run `git submodule add` and +commit the changes: + +~~~sh +git submodule add https://github.com/pure-data/pd-lib-builder +git commit .gitmodules pd-lib-builder/ -m "Added pd-lib-builder as git-submodule" +~~~ + +#### Cloning your repository with the submodule + +When doing a fresh clone of your repository, pass the `--recursive` option to +automatically fetch all submodules: + +~~~sh +git clone --recursive https://git.example.org/pd/superbonk~.git +~~~ + +If you've cloned non-recursively, you can initialize and update the submodules +manually: + +~~~sh +git submodule init +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: + +~~~sh +cd pd-lib-builder +git checkout master +git pull +cd .. +git status pd-lib-builder +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: + +~~~sh +git pull +~~~ + +The above will make your repository aware, that the submodule is out-of-sync. + +~~~sh +$ LANG=C git status pd-lib-builder +On branch master +Your branch is up to date with 'origin/master'. + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git checkout -- ..." to discard changes in working directory) + + modified: pd-lib-builder (new commits) +$ +~~~ + +In order to sync the submodule to the correct commit, run the following: + +~~~sh +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. +- you must make sure to use an URL for the submodule that is accessible to your + potential users. e.g. using `git@github.com:pure-data/pd-lib-builder` is bad, + because it requires everybody who wants to checkout your sources to have a + github-account - even if they could checkout *your* repository anonymously. +- submodules will be excluded from `git archive`. This means, that if you use a + mainstream git provider (like Github, GitLab, Bitbucket,...) and make releases + by creating a `git tag`, the automatically generated zipfiles with the sources + will lack the submodule - and your users will not be able to compile your + source code. + +In general, I would suggest to **avoid** `git submodule`, and instead use the +better `git subtree` (above). +