From 16517a2be6b45c159301b6b81dc3d0d9fe9cd000 Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 25 Jun 2015 12:22:40 +0200 Subject: [PATCH 001/150] Makefile.pdlibbuilder version 0.0.0 --- Makefile.pdlibbuilder | 1138 +++++++++++++++++++++++++++++++++++++++++ README.md | 54 ++ 2 files changed, 1192 insertions(+) create mode 100644 Makefile.pdlibbuilder create mode 100644 README.md diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder new file mode 100644 index 0000000..56674ec --- /dev/null +++ b/Makefile.pdlibbuilder @@ -0,0 +1,1138 @@ +# Makefile.pdlibbuilder version 0.0.0, dated 2015-06-24 +# +# Helper makefile for Pure Data external libraries. +# Written by Katja Vetter March-June 2015 for the public domain. +# 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 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 +# +# 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 +# +# Variables avaialable for (re)definition via command arguments: +# +# - pdbinpath (Windows only) +# - pdincludepath +# - DESTDIR +# - prefix +# - libdir +# - pkglibdir +# - CFLAGS +# - CC +# - CXX +# - INSTALL +# - INSTALL_PROGRAM +# - INSTALL_DATA +# - INSTALL_DIR +# +# Variables available for your makefile or as command argument: +# +# - objectsdir +# - make-lib-executable +# - suppress-wunused +# +# +#=== 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. +# +# externalsdir: +# Relative path to directory 'externals' in the context of pd-extended SVN, or +# any other centralized build layout for multiple libraries. Default value +# is '..', meaning the direct parent. The value is used in search paths for +# pd core components (header files, and executable in the case of Windows). +# +# makefiles and makefiledirs: +# Extra makefiles or directories with makefiles that should be made in sub-make +# processes. +# +# pdbinpath: +# For Windows only. Directory where pd.dll can be found for linking. +# +# pdincludepath: +# Directory where Pd API m_pd.h can be found, and other Pd header files. +# +# DESTDIR, prefix, libdir: +# Components of the path for installation as conventionally used on Linux. +# +# pkglibdir: +# Base path for installation of Pd library directories. Default is specified +# per OS, see section about paths below. +# +# objectsdir: +# Alias of pkglibdir. Can be defined in your makefile to enable project- +# dependent relative install locations. +# +# CFLAGS: +# Compiler (notably optimization) flags which are defined by +# Makefile.pdlibbuilder, but may be overriden via command argument. +# +# CC and CXX: +# C and C++ compiler programs as defined in your build environment. +# +# INSTALL, INSTALL_PROGRAM, INSTALL_DATA, INSTALL_DIR: +# Definitions of install program, may be overriden via command argument. +# +# 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 overriden 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. +# +# +#=== 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. +# +# Variable 'pdincludepath' stores the location where m_pd.h was found. +# Locations where Makefile.pdlibbuilder tries to find it, in order of priority: +# +# any OS: $(externalsdir)../pd/src/ +# +# Linux: /usr/include/pdextended/ +# /usr/include/pd/ +# +# OSX: /Applications/Pd-extended.app/Contents/Resources/include/pdextended/ +# /Applications/Pd.app/Contents/Resources/src/ +# +# Windows: %PROGRAMFILES%/pd/include/pdextended/ +# %PROGRAMFILES%/pd/src/ +# +# The path for installation of all library components is constructed as: +# +# installpath := $(DESTDIR)$(objectsdir)/$(lib.name) +# +# Default for 'objectsdir' is defined per platform and follows this convention: +# https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files +# +# Linux: /usr/local/lib/pd-externals +# OSX: ~/Library/Pd +# Windows: %APPDATA%/Pd +# +# 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 classes (default) or library blob (if make-lib-executable=true) +# 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 +# dist: make source package for distribution (not yet implemented) +# dpkg-source: make debian source package (not yet implemented) +# +# clean: remove build products from source tree +# distclean: not yet implemented +# +# help: print help text +# vars: print makefile variables +# allvars: print all variables +# depend: print generated prerequisites +# coffee: dummy target +# +# +#=== 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 +# - Windows 64 bit support +# - makefile template targets: dpkg-source dist libdir distclean tags +# - figure out how to handle '$' in filenames +# +# +# +#=== 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. This variable is used to probe for +# paths. +externalsdir ?= .. + +# variable you can use to check if Makefile.pdlibbuilder is already included +Makefile.pdlibbuilder = true + + +################################################################################ +### variables: files ########################################################### +################################################################################ + + +# strip possibles spaces from lib.name, they mess up calculated file names +lib.name := $(strip $(lib.name)) + + +#=== 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 =============================================================== + + +# use recursive variables here because executable extension is not yet known + +# construct class executable names from class names +classes.executables = $(addsuffix .$(extension), $(classes)) + +# construct shared lib executable name if shared sources are defined +ifdef shared.sources + shared.lib = lib$(lib.name).$(shared.extension) +else + shared.lib = +endif + + +################################################################################ +### variables per platform ##################################################### +################################################################################ + + +#=== flags per architecture ==================================================== + + +# Set architecture-dependent flags, mainly for Linux. For Mac and Windows, +# arch.flags are overriden below. + +machine := $(shell uname -m) + +# Raspberry Pi 1st generation +ifeq ($(machine), armv6l) + arch.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard +endif + +# Beagle, Udoo, RPi2 etc. +ifeq ($(machine), armv7l) + arch.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard +endif + +# Intel 32 bit, build with SSE and SSE2 instructions +ifeq ($(findstring $(machine), i386 i686), $(machine)) + arch.flags = -march=pentium4 -mfpmath=sse -msse -msse2 +endif + +# Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions +ifeq ($(findstring $(machine), ia64 x86_64), $(machine)) + arch.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 +endif + + +#=== operating system ========================================================== + + +# The following systems are defined: Linux, Darwin, Windows. GNU and +# GNU/kFreeBSD are treated as Linux to get the same options. + +uname := $(shell uname) + +ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname)) + system = Linux +endif + +ifeq ($(uname), Darwin) + system = Darwin +endif + +ifeq ($(findstring MINGW, $(uname)), MINGW) + system = Windows +endif + +# TODO: Cygwin, Android + + +#=== flags and paths for Linux ================================================= + + +ifeq ($(system), Linux) + prefix = /usr/local + libdir := $(prefix)/lib + pkglibdir = $(libdir)/pd-externals + pdincludepath := $(firstword $(dir $(wildcard \ + $(externalsdir)/../pd/src/m_pd.h \ + /usr/include/pdextended/m_pd.h \ + /usr/include/pd/m_pd.h))) + 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) + stripflags = --strip-unneeded -R .note -R .comment +endif + + +#=== flags and paths for Darwin ================================================ + + +# On OSX we try to build fat binaries by default. It is assumed that OSX i386 +# can build for ppc and OSX x86_64 can't. TODO: try to refine this condition. +# LLVM-clang doesn't support -fcheck-new, therefore this flag is omitted for +# OSX x86_64. + +ifeq ($(system), Darwin) + pkglibdir = $(HOME)/Library/Pd + pdincludepath := $(firstword $(dir $(wildcard \ + $(externalsdir)/../pd/src/m_pd.h \ + /Applications/Pd-extended.app/Contents/Resources/include/pdextended/m_pd.h \ + /Applications/Pd.app/Contents/Resources/src/m_pd.h))) + extension = pd_darwin + arch.flags = + 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 + stripflags = -x + ifeq ($(machine), i386) + cxx.flags := -fcheck-new + arch.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + endif + ifeq ($(machine), x86_64) + arch.flags := -arch i386 -arch x86_64 -mmacosx-version-min=10.5 + endif +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, and probe for each standard path individually. +# Using double quotes around paths with spaces is obligatory. Since some path +# variables are assembled or re-expanded later, great care must be taken to put +# quotes at appropriate points throughout the makefile. Thanks, Bill. + +# paths for 32-bit executables on 64-bit Windows aren't yet defined here (TODO) +ifeq ($(system), Windows) + pkglibdir := $(APPDATA)/Pd + pdbinpath := $(wildcard $(externalsdir)/../pd/bin/) + pdincludepath := $(wildcard $(externalsdir)/../pd/src/) + ifndef pdbinpath + pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin/") + endif + ifndef pdincludepath + pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/include/pdextended/") + endif + ifndef pdincludepath + pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src/") + endif +endif + +# On Windows we build 32 bit by default to match Pd(-extended) binary +# distributions. This may change in the future. +# TODO: decide whether -mms-bitfields should be specified. +ifeq ($(system), Windows) + extension = dll + CC = gcc + CXX = g++ + arch.flags := -march=pentium4 -msse -msse2 -mfpmath=sse + cpp.flags := -DMSW -DNT + c.flags := + c.ldflags := -static-libgcc -shared \ + -Wl,--enable-auto-import "$(pdbinpath)pd.dll" + c.ldlibs := + cxx.flags := -fcheck-new + cxx.ldflags := -static-libstdc++ -shared \ + -Wl,--enable-auto-import "$(pdbinpath)pd.dll" + cxx.ldlibs := + shared.extension = dll + shared.ldflags := -static-libgcc -shared "$(pdbinpath)pd.dll" + stripflags = --strip-unneeded -R .note -R .comment +endif + + +#=== paths ===================================================================== + + +# Default pkglibdir is specified above per operating system. It is aliased as +# 'objectsdir' to retain compatibility with pd-extended template. Assignment +# operator '?=' is used to enable a project-relative path definition in the +# including makefile. +objectsdir ?= $(pkglibdir) + +# base path where all components of the lib will be installed by default +installpath := $(DESTDIR)$(objectsdir)/$(lib.name) + +# check if pdincludepath 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, $(pdincludepath)), $(pdincludepath)) + + +#=== accumulated build flags =================================================== + + +# From GNU make docs: 'Users expect to be able to specify CFLAGS freely +# themselves.' So we use CFLAGS to define platform-independent options which +# are not strictly required for compilation: optimizations 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) + +# preprocessor flags +cpp.flags += -DPD -I "$(pdincludepath)" + +# flags for C compiler / linker +c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) +c.ldflags := $(c.ldflags) $(ldflags) +c.ldlibs := $(c.ldlibs) $(ldlibs) + +# flags for C++ compiler / linker +cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS) +cxx.ldflags := $(cxx.ldflags) $(ldflags) +cxx.ldlibs := $(cxx.ldlibs) $(ldlibs) + + +################################################################################ +### 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. + +# '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 + +# check if m_pd.h is found and print info about it +$(if $(shell ls "$(pdincludepath)m_pd.h"), \ + $(info ++++ info: using Pd API $(pdincludepath)m_pd.h), \ + $(warning Where is your m_pd.h? Do 'make help' for info.)) + +# 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 + + +#=== library version =========================================================== + + +# 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' \ + $(lib.name)-meta.pd) +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 build-classes build-lib $(classes) $(makefiledirs) $(makefiles)\ + install install-executables install-datafiles install-datadirs \ + force clean vars allvars depend help + + +################################################################################ +### rules: build targets ####################################################### +################################################################################ + + +# target all builds class executables plus optional shared lib +# or alternatively a single lib executable when make-lib-executable=true +all: $(executables) + $(info ++++ info: $(if $(executables),executables in $(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) \ + $(arch.flags) \ + $($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) \ + $(arch.flags) \ + $($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) \ + $(arch.flags) \ + $(shared.ldflags) \ + -o lib$(lib.name).$(shared.extension) $(shared.objects) \ + $($1.ldlibs) $(shared.ldlibs) +endef + +# rule for linking objects in shared executable +# build recipe is in macro 'link-shared' +lib$(lib.name).$(shared.extension): $(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) \ + $(arch.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 so we do not evaluate them in that case. + +ifndef pdincludepathwithspaces + must-build-everything := $(filter all default lib, $(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) +define declare-object-target +$(filter %.o: %.h, $(shell $(CPP) $(c.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) \ + $(arch.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 ################################################ +################################################################################ + + +# 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)" + $(INSTALL_PROGRAM) $(executables) "$(installpath)" + $(info ++++ info: executables of lib $(lib.name) installed \ + from $(CURDIR) to $(installpath)) + +install-datafiles: all + $(INSTALL_DIR) -v "$(installpath)" + $(INSTALL_DATA) $(datafiles) "$(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 + +mpdh := $(shell ls "$(pdincludepath)m_pd.h") +mpdh := $(if $(mpdh), $(mpdh), m_pd.h not found. Is Pd(-extended) installed?) + + +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 " $(shell ls "$(pdincludepath)m_pd.h")" + @echo " You may specify your preferred include path as argument to" + @echo " the make command, like 'pdincludepath=path/to/pd/src'." + @echo + @echo " Path for installation of your libdir(s):" + @echo " $(objectsdir)" + @echo " Alternatively you may specify your path for installation as argument" + @echo " to the make command, like 'objectsdir=path/to/pd-externals'." + @echo " For detailed info read the doc sections in Makefile.pdlibbuilder." + @echo + + +#=== dummy target ============================================================== + + +coffee: + @echo "Makefile.pdlibbuilder: Can not make coffee. Sorry." + + +################################################################################ +### the end #################################################################### +################################################################################ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf5b7d8 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ + + +### Makefile.pdlibbuilder ### + +Helper makefile for Pure Data external libraries. +Written by Katja Vetter March-June 2015 for the public domain. +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 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 LICENCE.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, read the documentation sections in Makefile.pdlibbuilder. + + +### examples ### + + +Here is one deployment example of the Makefile.pdlibbuilder approach: + +http://sourceforge.net/p/pure-data/svn/HEAD/tree/trunk/externals/miXed/cyclone/Makefile.cyclone + +More examples will be referenced here when they are available. From 9c7e50126638d7694acc293770d0de15f548a8c8 Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 25 Jun 2015 12:35:26 +0200 Subject: [PATCH 002/150] changed some comments --- Makefile.pdlibbuilder | 13 ++++--------- README.md | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 56674ec..86e89f0 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,7 +1,7 @@ -# Makefile.pdlibbuilder version 0.0.0, dated 2015-06-24 +# Makefile.pdlibbuilder version 0.0.0, dated 2015-06-25 # # Helper makefile for Pure Data external libraries. -# Written by Katja Vetter March-June 2015 for the public domain. +# 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. # @@ -32,7 +32,7 @@ # # class.sources = myclass1.c myclass2.c # -# datafiles = myclass1-help.pd myclass2-help.pd +# datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENCE.txt # # include Makefile.pdlibbuilder # ________________________________________________________________________ @@ -232,11 +232,7 @@ # .lst: make asm/source output file in current working directory # # install: install executables and data files -# dist: make source package for distribution (not yet implemented) -# dpkg-source: make debian source package (not yet implemented) -# # clean: remove build products from source tree -# distclean: not yet implemented # # help: print help text # vars: print makefile variables @@ -286,9 +282,8 @@ # - cygwin support # - android support # - Windows 64 bit support -# - makefile template targets: dpkg-source dist libdir distclean tags # - figure out how to handle '$' in filenames -# +# - add makefile template targets dpkg-source dist libdir distclean tags? # # #=== end of documentation sections ============================================= diff --git a/README.md b/README.md index cf5b7d8..fdf30fe 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ### Makefile.pdlibbuilder ### Helper makefile for Pure Data external libraries. -Written by Katja Vetter March-June 2015 for the public domain. +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. From 3906a92933f7b64e2ac7915defb4c06574e7780f Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 25 Jun 2015 19:43:17 +0200 Subject: [PATCH 003/150] corrected futile typo in comment --- Makefile.pdlibbuilder | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 86e89f0..91fb819 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -32,7 +32,7 @@ # # class.sources = myclass1.c myclass2.c # -# datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENCE.txt +# datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt # # include Makefile.pdlibbuilder # ________________________________________________________________________ diff --git a/README.md b/README.md index fdf30fe..bda994f 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Makefile.pdlibbuilder at the end of the Makefile. Like so: class.sources = myclass1.c myclass2.c - datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENCE.txt + datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt include Makefile.pdlibbuilder From 9e1fa90567f774c8a1f95ce197776fa5296948d0 Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 25 Jun 2015 19:53:17 +0200 Subject: [PATCH 004/150] added vim modeline for syntax highlighting --- Makefile.pdlibbuilder | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 91fb819..bc6cad6 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1128,6 +1128,10 @@ coffee: ################################################################################ -### the end #################################################################### +### end of rules sections ###################################################### ################################################################################ + +# for syntax highlighting in vim and github +# vim: set filetype=make + From b43f7ad2b3f6c10e5d417e72880874ce67a25bb6 Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 25 Jun 2015 19:59:43 +0200 Subject: [PATCH 005/150] another try at syntax highlighting modeline --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index bc6cad6..79f2d51 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1133,5 +1133,5 @@ coffee: # for syntax highlighting in vim and github -# vim: set filetype=make +# vim: set filetype=make: From 84ae43edc872cc46ddd5064a03ad512788a22841 Mon Sep 17 00:00:00 2001 From: katja Date: Mon, 6 Jul 2015 23:30:28 +0200 Subject: [PATCH 006/150] Added reference to helloworld project in README.md. --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bda994f..5e0c2a6 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Makefile.pdlibbuilder at the end of the Makefile. Like so: include Makefile.pdlibbuilder -For files in class.sources it is assumed that class basename == source file +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. @@ -47,7 +47,9 @@ most basic usage, read the documentation sections in Makefile.pdlibbuilder. ### examples ### -Here is one deployment example of the Makefile.pdlibbuilder approach: +Here are two projects using the Makefile.pdlibbuilder approach: + +https://github.com/pure-data/helloworld http://sourceforge.net/p/pure-data/svn/HEAD/tree/trunk/externals/miXed/cyclone/Makefile.cyclone From 0a7d0573419ff1f72aa0d36827a23c0250a08f0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?uml=C3=A4ute?= Date: Thu, 29 Oct 2015 00:31:08 +0100 Subject: [PATCH 007/150] use $(metafile) in version expansion lib.version is only expanded if the file named by $(metafile) exists, but then it uses a hardcoded filename to do the actual expansion. this patch uses $(metafile) to do the expansion instead. --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 79f2d51..31510f1 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -662,7 +662,7 @@ 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' \ - $(lib.name)-meta.pd) + $(metafile)) endif From 9015ba7b9fcb55687fd415029aefe062881c5337 Mon Sep 17 00:00:00 2001 From: katja Date: Sat, 31 Oct 2015 20:56:29 +0100 Subject: [PATCH 008/150] fix expansion of variable lib.version in cflags during compilation --- Makefile.pdlibbuilder | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 31510f1..190938d 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -314,13 +314,27 @@ Makefile.pdlibbuilder = true ################################################################################ -### variables: files ########################################################### +### 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 =================================================================== @@ -652,20 +666,6 @@ else endif -#=== library version =========================================================== - - -# 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 - - ################################################################################ ### rules: special targets ##################################################### ################################################################################ From 974b6174ce1de9546f58e96b4542914488df0dc5 Mon Sep 17 00:00:00 2001 From: katja Date: Sat, 31 Oct 2015 21:04:36 +0100 Subject: [PATCH 009/150] bump version to 0.0.1 --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 190938d..b97e2b5 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,4 +1,4 @@ -# Makefile.pdlibbuilder version 0.0.0, dated 2015-06-25 +# Makefile.pdlibbuilder version 0.0.1, dated 2015-10-31 # # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. From 164d29478877cc589a4206925fe75efbb766f59e Mon Sep 17 00:00:00 2001 From: katja Date: Fri, 4 Dec 2015 15:34:04 +0100 Subject: [PATCH 010/150] Evaluate optional per-system multiline defines --- Makefile.pdlibbuilder | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index b97e2b5..598cda9 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -66,6 +66,13 @@ # - makefiledirs # - externalsdir # +# Optional multiline defines evaluated per operating system: +# +# - forLinux +# - forDarwin +# - forWindows +# +# # Variables avaialable for (re)definition via command arguments: # # - pdbinpath (Windows only) @@ -140,6 +147,13 @@ # is '..', meaning the direct parent. The value is used in search paths for # pd core components (header files, and executable in the case of Windows). # +# 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. @@ -423,20 +437,25 @@ endif # The following systems are defined: Linux, Darwin, Windows. GNU and -# GNU/kFreeBSD are treated as Linux to get the same options. +# GNU/kFreeBSD are treated as Linux to get the same options. System-specific +# multiline defines (optionally set in library makefile) are conditionally +# evaluated here. uname := $(shell uname) ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname)) system = Linux + $(eval $(forLinux)) endif ifeq ($(uname), Darwin) system = Darwin + $(eval $(forDarwin)) endif ifeq ($(findstring MINGW, $(uname)), MINGW) system = Windows + $(eval $(forWindows)) endif # TODO: Cygwin, Android From 589d7fcda6ee17542ab75854ea824970b10248d7 Mon Sep 17 00:00:00 2001 From: katja Date: Sat, 5 Dec 2015 11:31:43 +0100 Subject: [PATCH 011/150] Use CPPFLAGS, CFLAGS and LDFLAGS to override/add build flags This commit reorganizes the accumulation of build flags in such a way that non-obligatory build flags can be overriden or added by specifying CPPFLAGS, CFLAGS and LDFLAGS as arguments from command line or environment. --- Makefile.pdlibbuilder | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index b97e2b5..1c214b7 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -393,29 +393,29 @@ endif #=== flags per architecture ==================================================== -# Set architecture-dependent flags, mainly for Linux. For Mac and Windows, -# arch.flags are overriden below. +# Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, +# arch.c.flags are overriden below. machine := $(shell uname -m) # Raspberry Pi 1st generation ifeq ($(machine), armv6l) - arch.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard + arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard endif # Beagle, Udoo, RPi2 etc. ifeq ($(machine), armv7l) - arch.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard + arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard endif # Intel 32 bit, build with SSE and SSE2 instructions ifeq ($(findstring $(machine), i386 i686), $(machine)) - arch.flags = -march=pentium4 -mfpmath=sse -msse -msse2 + arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 endif # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions ifeq ($(findstring $(machine), ia64 x86_64), $(machine)) - arch.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 + arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 endif @@ -482,7 +482,6 @@ ifeq ($(system), Darwin) /Applications/Pd-extended.app/Contents/Resources/include/pdextended/m_pd.h \ /Applications/Pd.app/Contents/Resources/src/m_pd.h))) extension = pd_darwin - arch.flags = cpp.flags := -DUNIX -DMACOSX -I /sw/include c.flags := c.ldflags := -undefined suppress -flat_namespace -bundle @@ -496,10 +495,12 @@ ifeq ($(system), Darwin) stripflags = -x ifeq ($(machine), i386) cxx.flags := -fcheck-new - arch.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + arch.c.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + arch.ld.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 endif ifeq ($(machine), x86_64) - arch.flags := -arch i386 -arch x86_64 -mmacosx-version-min=10.5 + arch.c.flags := -arch i386 -arch x86_64 -mmacosx-version-min=10.5 + arch.ld.flags := -arch i386 -arch x86_64 -mmacosx-version-min=10.5 endif endif @@ -537,7 +538,7 @@ ifeq ($(system), Windows) extension = dll CC = gcc CXX = g++ - arch.flags := -march=pentium4 -msse -msse2 -mfpmath=sse + arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse cpp.flags := -DMSW -DNT c.flags := c.ldflags := -static-libgcc -shared \ @@ -574,9 +575,9 @@ pdincludepathwithspaces := $(if $(word 2, $(pdincludepath)), $(pdincludepath)) # From GNU make docs: 'Users expect to be able to specify CFLAGS freely -# themselves.' So we use CFLAGS to define platform-independent options which -# are not strictly required for compilation: optimizations and warnings. CFLAGS -# can be safely overriden using a make command argument. +# 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 @@ -587,19 +588,22 @@ ifdef suppress-wunused warn.flags += $(addprefix -Wno-unused-, function parameter value variable) endif -CFLAGS = $(warn.flags) $(optimization.flags) +CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) # preprocessor flags -cpp.flags += -DPD -I "$(pdincludepath)" +cpp.flags += -DPD -I "$(pdincludepath)" $(CPPFLAGS) -# flags for C compiler / linker +# architecture specifications for linker are overridable by LDFLAGS +LDFLAGS := $(arch.ld.flags) + +# accumulated flags for C compiler / linker c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) -c.ldflags := $(c.ldflags) $(ldflags) +c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS) c.ldlibs := $(c.ldlibs) $(ldlibs) -# flags for C++ compiler / linker +# accumulated flags for C++ compiler / linker cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS) -cxx.ldflags := $(cxx.ldflags) $(ldflags) +cxx.ldflags := $(cxx.ldflags) $(ldflags) $(LDFLAGS) cxx.ldlibs := $(cxx.ldlibs) $(ldlibs) @@ -706,7 +710,6 @@ alldebug: all # argument $2 = class basename define link-class $(compile-$1) \ - $(arch.flags) \ $($1.ldflags) $($2.class.ldflags) \ -o $2.$(extension) \ $(addsuffix .o, $(basename $($2.class.sources))) \ @@ -733,7 +736,6 @@ build-lib: $(lib.name).$(extension) # argument $1 = compiler type (c or cxx) define link-lib $(compile-$1) \ - $(arch.flags) \ $($1.ldflags) $(lib.ldflags) \ -o $(lib.name).$(extension) $(all.objects) \ $($1.ldlibs) $(lib.ldlibs) @@ -756,7 +758,6 @@ endif # argument $1 = compiler type (c or cxx) define link-shared $(compile-$1) \ - $(arch.flags) \ $(shared.ldflags) \ -o lib$(lib.name).$(shared.extension) $(shared.objects) \ $($1.ldlibs) $(shared.ldlibs) @@ -780,7 +781,7 @@ define make-object-file $(info ++++ info: making $@ in lib $(lib.name)) $(compile-$1) \ $($1.flags) \ - $(arch.flags) -o $@ -c $< + -o $@ -c $< endef # Three rules to create .o files. These are double colon 'terminal' rules, @@ -904,7 +905,6 @@ define make-assembly-file $(compile-$1) \ -c -Wa,-a,-ad -fverbose-asm \ $($1.flags) \ - $(arch.flags) \ $< > $(notdir $*.lst) endef From 0595e44e9f807a2b7586d6e856797a468e650320 Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 6 Dec 2015 16:18:50 +0100 Subject: [PATCH 012/150] Improve methods for searching Pd include paths. I've also tried to make printed info a bit more helpful. --- Makefile.pdlibbuilder | 78 ++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index b97e2b5..b3bcf6e 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -193,19 +193,19 @@ # Object (.o) files are built in the directory of their source files. # Executables are built in current working directory. # -# Variable 'pdincludepath' stores the location where m_pd.h was found. +# Variable 'pdincludepath' stores a location where m_pd.h is expected to reside. # Locations where Makefile.pdlibbuilder tries to find it, in order of priority: # -# any OS: $(externalsdir)../pd/src/ +# any OS: $(externalsdir)../pd/src # -# Linux: /usr/include/pdextended/ -# /usr/include/pd/ +# Linux: /usr/include/pdextended +# /usr/include/pd # -# OSX: /Applications/Pd-extended.app/Contents/Resources/include/pdextended/ -# /Applications/Pd.app/Contents/Resources/src/ +# OSX: /Applications/Pd-extended.app/Contents/Resources/include/pdextended +# /Applications/Pd.app/Contents/Resources/src # -# Windows: %PROGRAMFILES%/pd/include/pdextended/ -# %PROGRAMFILES%/pd/src/ +# Windows: %PROGRAMFILES%/pd/include/pdextended +# %PROGRAMFILES%/pd/src # # The path for installation of all library components is constructed as: # @@ -449,10 +449,10 @@ ifeq ($(system), Linux) prefix = /usr/local libdir := $(prefix)/lib pkglibdir = $(libdir)/pd-externals - pdincludepath := $(firstword $(dir $(wildcard \ - $(externalsdir)/../pd/src/m_pd.h \ - /usr/include/pdextended/m_pd.h \ - /usr/include/pd/m_pd.h))) + pdincludepath := $(firstword $(wildcard \ + $(externalsdir)/../pd/src \ + /usr/include/pdextended \ + /usr/include/pd)) extension = pd_linux cpp.flags := -DUNIX c.flags := -fpic @@ -477,10 +477,10 @@ endif ifeq ($(system), Darwin) pkglibdir = $(HOME)/Library/Pd - pdincludepath := $(firstword $(dir $(wildcard \ - $(externalsdir)/../pd/src/m_pd.h \ - /Applications/Pd-extended.app/Contents/Resources/include/pdextended/m_pd.h \ - /Applications/Pd.app/Contents/Resources/src/m_pd.h))) + pdincludepath := $(firstword $(wildcard \ + $(externalsdir)/../pd/src \ + /Applications/Pd-extended*.app/Contents/Resources/include/pdextended \ + /Applications/Pd*.app/Contents/Resources/src)) extension = pd_darwin arch.flags = cpp.flags := -DUNIX -DMACOSX -I /sw/include @@ -517,16 +517,16 @@ endif # paths for 32-bit executables on 64-bit Windows aren't yet defined here (TODO) ifeq ($(system), Windows) pkglibdir := $(APPDATA)/Pd - pdbinpath := $(wildcard $(externalsdir)/../pd/bin/) - pdincludepath := $(wildcard $(externalsdir)/../pd/src/) + pdbinpath := $(wildcard $(externalsdir)/../pd/bin) + pdincludepath := $(wildcard $(externalsdir)/../pd/src) ifndef pdbinpath - pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin/") + pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin") endif ifndef pdincludepath - pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/include/pdextended/") + pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/include/pdextended") endif ifndef pdincludepath - pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src/") + pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src") endif endif @@ -541,14 +541,14 @@ ifeq ($(system), Windows) cpp.flags := -DMSW -DNT c.flags := c.ldflags := -static-libgcc -shared \ - -Wl,--enable-auto-import "$(pdbinpath)pd.dll" + -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" c.ldlibs := cxx.flags := -fcheck-new cxx.ldflags := -static-libstdc++ -shared \ - -Wl,--enable-auto-import "$(pdbinpath)pd.dll" + -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" cxx.ldlibs := shared.extension = dll - shared.ldflags := -static-libgcc -shared "$(pdbinpath)pd.dll" + shared.ldflags := -static-libgcc -shared "$(pdbinpath)/pd.dll" stripflags = --strip-unneeded -R .note -R .comment endif @@ -637,10 +637,17 @@ else goals := all endif -# check if m_pd.h is found and print info about it -$(if $(shell ls "$(pdincludepath)m_pd.h"), \ - $(info ++++ info: using Pd API $(pdincludepath)m_pd.h), \ - $(warning Where is your m_pd.h? Do 'make help' for info.)) +# store path to Pd API m_pd.h if it is found +ifdef pdincludepath + mpdh := $(shell ls "$(pdincludepath)/m_pd.h") +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))) @@ -1094,9 +1101,11 @@ depend: # brief info about targets and paths -mpdh := $(shell ls "$(pdincludepath)m_pd.h") -mpdh := $(if $(mpdh), $(mpdh), m_pd.h not found. Is Pd(-extended) installed?) - +ifdef mpdh + mpdhinfo := $(mpdh) +else + mpdhinfo := m_pd.h was not found. Is Pd(-extended) installed? +endif help: @echo @@ -1108,15 +1117,16 @@ help: @echo " help: print this help text" @echo @echo " Pd API m_pd.h:" - @echo " $(shell ls "$(pdincludepath)m_pd.h")" - @echo " You may specify your preferred include path as argument to" + @echo " $(mpdhinfo)" + @echo " You may specify your preferred Pd include path as argument to" @echo " the make command, like 'pdincludepath=path/to/pd/src'." @echo @echo " Path for installation of your libdir(s):" @echo " $(objectsdir)" @echo " Alternatively you may specify your path for installation as argument" @echo " to the make command, like 'objectsdir=path/to/pd-externals'." - @echo " For detailed info read the doc sections in Makefile.pdlibbuilder." + @echo + @echo " Default paths are listed in the doc sections in Makefile.pdlibbuilder." @echo From 15832b5e0793f953c85203169237281e2dd46f8d Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 6 Dec 2015 18:00:01 +0100 Subject: [PATCH 013/150] Small fix: add LDFLAGS to shared.ldflags too. --- Makefile.pdlibbuilder | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 1c214b7..df60884 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -596,6 +596,9 @@ cpp.flags += -DPD -I "$(pdincludepath)" $(CPPFLAGS) # architecture specifications for linker are overridable by LDFLAGS LDFLAGS := $(arch.ld.flags) +# now add the same ld flags to shared dynamic lib +shared.ldflags := $(shared.ldflags) $(LDFLAGS) + # accumulated flags for C compiler / linker c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS) From ed37e6bbb57cb07b91b405b16bdbfcf8151b433b Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 6 Dec 2015 20:52:45 +0100 Subject: [PATCH 014/150] Bumped to version 0.0.2. --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index b3bcf6e..fa507e2 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,4 +1,4 @@ -# Makefile.pdlibbuilder version 0.0.1, dated 2015-10-31 +# Makefile.pdlibbuilder version 0.0.2, dated 2015-12-06 # # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. From e08bab9eaaa731ce2b9c83282620f1c2142b82cd Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 6 Dec 2015 20:57:08 +0100 Subject: [PATCH 015/150] Updated README.md to include reference to xeq. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e0c2a6..a683915 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,12 @@ most basic usage, read the documentation sections in Makefile.pdlibbuilder. ### examples ### -Here are two projects using the Makefile.pdlibbuilder approach: +Here are three projects using the Makefile.pdlibbuilder approach: https://github.com/pure-data/helloworld http://sourceforge.net/p/pure-data/svn/HEAD/tree/trunk/externals/miXed/cyclone/Makefile.cyclone +https://github.com/pure-data/xeq + More examples will be referenced here when they are available. From c42845611fbed81e8f7f57ee46b4c362af7f995b Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 8 Dec 2015 13:04:13 +0100 Subject: [PATCH 016/150] Introduce pre and post targets. Targets pre and post can be defined in the including (library) makefile. They are added to provide extra flexibility. Target all will build pre, $(executable) and post in deterministic order. Built-in documentation is modified to reflect the new situation. --- Makefile.pdlibbuilder | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index fa507e2..52ab025 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -225,7 +225,9 @@ #=== targets =================================================================== # # -# all: build classes (default) or library blob (if make-lib-executable=true) +# all: build $(executables) plus optional pre and post targets +# pre: target to build before $(executables) +# 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 @@ -240,6 +242,11 @@ # depend: print generated prerequisites # 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 ================================================ # @@ -684,7 +691,8 @@ MAKEFLAGS += --no-builtin-rules .PRECIOUS: .SUFFIXES: -.PHONY: all build-classes build-lib $(classes) $(makefiledirs) $(makefiles)\ +.PHONY: all pre post build-classes build-lib \ + $(classes) $(makefiledirs) $(makefiles) \ install install-executables install-datafiles install-datadirs \ force clean vars allvars depend help @@ -694,10 +702,19 @@ MAKEFLAGS += --no-builtin-rules ################################################################################ -# target all builds class executables plus optional shared lib -# or alternatively a single lib executable when make-lib-executable=true -all: $(executables) - $(info ++++ info: $(if $(executables),executables in $(lib.name) completed)) +# Target all forces the build of targets [pre $(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. Targets pre and post are optionally defined by +# library makefile. + +all: post +post: $(executables) +$(executables): pre +pre: + +all: + $(info ++++info: target all in lib $(lib.name) completed) # build all with -g option turned on for debug symbols alldebug: c.flags += -g From a5678ac1e096f7f4e58ec141ce07dd37cb401b5c Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 8 Dec 2015 13:17:54 +0100 Subject: [PATCH 017/150] bump version 0.0.2 > 0.1.0 for added feature (targets pre / post) --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 52ab025..11e42db 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,4 +1,4 @@ -# Makefile.pdlibbuilder version 0.0.2, dated 2015-12-06 +# Makefile.pdlibbuilder version 0.1.0, dated 2015-12-08 # # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. From abeb4dec6e72f1153d9a27f3ede552812edce4fb Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 8 Dec 2015 14:35:12 +0100 Subject: [PATCH 018/150] Remove cruft from .PHONY: --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 11e42db..950286b 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -691,7 +691,7 @@ MAKEFLAGS += --no-builtin-rules .PRECIOUS: .SUFFIXES: -.PHONY: all pre post build-classes build-lib \ +.PHONY: all pre post build-lib \ $(classes) $(makefiledirs) $(makefiles) \ install install-executables install-datafiles install-datadirs \ force clean vars allvars depend help From 8cba158c9a38e5ca44ebe4fe0bbde8930c43620d Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 8 Dec 2015 14:41:30 +0100 Subject: [PATCH 019/150] Remove cruft from a variable definition --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 950286b..4d869a6 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -856,7 +856,7 @@ $(foreach v, $(classes), $(eval $(declare-class-executable-target))) # prerequisites rules so we do not evaluate them in that case. ifndef pdincludepathwithspaces - must-build-everything := $(filter all default lib, $(goals)) + must-build-everything := $(filter all, $(goals)) must-build-class := $(filter $(classes), $(goals)) must-build-sources := $(foreach v, $(must-build-class), $($v.class.sources)) endif From c6fe1832fc6f604b58e7ab696954e0a1bbb77cf2 Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 22 Dec 2015 00:45:26 +0100 Subject: [PATCH 020/150] Document CPPFLAGS, CFLAGS, LDFLAGS --- Makefile.pdlibbuilder | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index df60884..094db78 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -74,7 +74,9 @@ # - prefix # - libdir # - pkglibdir +# - CPPFLAGS # - CFLAGS +# - LDFLAGS # - CC # - CXX # - INSTALL @@ -161,9 +163,18 @@ # Alias of pkglibdir. Can be defined in your makefile to enable project- # dependent relative install locations. # +# CPPFLAGS: +# Preprocessor flags which are not strictly required for building. +# # CFLAGS: -# Compiler (notably optimization) flags which are defined by -# Makefile.pdlibbuilder, but may be overriden via command argument. +# 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. From c8875697b4123704800e41bbd88a22964a0efe5b Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 22 Dec 2015 23:25:03 +0100 Subject: [PATCH 021/150] Replaced outdated link to cyclone repository in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a683915..03d7f0f 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Here are three projects using the Makefile.pdlibbuilder approach: https://github.com/pure-data/helloworld -http://sourceforge.net/p/pure-data/svn/HEAD/tree/trunk/externals/miXed/cyclone/Makefile.cyclone +https://github.com/electrickery/pd-cyclone https://github.com/pure-data/xeq From d94538e1bbe5f02fa3b645504d477ab010ff54d1 Mon Sep 17 00:00:00 2001 From: katja Date: Sat, 26 Mar 2016 14:55:55 +0100 Subject: [PATCH 022/150] Remove target 'pre' from Makefile.pdlibbuilder Phony target 'pre' forces rebuilds. This should not be default behavior of Makefile.pdlibbuilder. If one needs a pre-build target (phony or real file), declare it as prerequisite of $(all.objects) in the library makefile after inclusion of Makefile.pdlibbuilder. A pre-build target can have any name that isn't a target in Makefile.pdlibbuilder. --- Makefile.pdlibbuilder | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 7f5d4bf..6ce5a3b 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -728,7 +728,7 @@ MAKEFLAGS += --no-builtin-rules .PRECIOUS: .SUFFIXES: -.PHONY: all pre post build-lib \ +.PHONY: all post build-lib \ $(classes) $(makefiledirs) $(makefiles) \ install install-executables install-datafiles install-datadirs \ force clean vars allvars depend help @@ -739,16 +739,14 @@ MAKEFLAGS += --no-builtin-rules ################################################################################ -# Target all forces the build of targets [pre $(executables) post] in +# 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. Targets pre and post are optionally defined by +# make-lib-executable=true. Target post is optionally defined by # library makefile. all: post post: $(executables) -$(executables): pre -pre: all: $(info ++++info: target all in lib $(lib.name) completed) From c989c8e0b0ddd9ca4404e5ae206eaadbfc7e7e64 Mon Sep 17 00:00:00 2001 From: katja Date: Sat, 26 Mar 2016 15:39:39 +0100 Subject: [PATCH 023/150] Bump to version 0.2.2 after removal of 'pre' target Also remove associated documentation comments. --- Makefile.pdlibbuilder | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 6ce5a3b..5f61e6f 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,4 +1,4 @@ -# Makefile.pdlibbuilder version 0.2.1, dated 2015-12-27 +# Makefile.pdlibbuilder version 0.2.2, dated 2016-03-28 # # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -250,8 +250,7 @@ #=== targets =================================================================== # # -# all: build $(executables) plus optional pre and post targets -# pre: target to build before $(executables) +# 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 From eb614fdf163889297602813966eb062339b60e05 Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 29 Mar 2016 11:26:52 +0200 Subject: [PATCH 024/150] Disable dep. checking for fat builds on OSX <= 10.5. Version 0.2.3 Multiple arch flags are incompatible with option -MM for preprocessor on (at least) OSX <= 10.5. Non clean builds would stall on this. This commit disables dependency checking for fat builds (current default for OSX) on ppc and i386. Assuming that development is done on newer systems / machines it should rarely hurt. --- Makefile.pdlibbuilder | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 5f61e6f..a91bb39 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,4 +1,4 @@ -# Makefile.pdlibbuilder version 0.2.2, dated 2016-03-28 +# Makefile.pdlibbuilder version 0.2.3, dated 2016-03-29 # # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -884,9 +884,16 @@ $(foreach v, $(classes), $(eval $(declare-class-executable-target))) # which case implicit prerequisites are not checked. # When the Pd include path contains spaces it will mess up the implicit -# prerequisites rules so we do not evaluate them in that case. +# prerequisites rules. Also it is known that multiple arch flags are +# incompatible with preprocessor option -MM on OSX <= 10.5. Dependency +# tracking must be disabled in those cases. -ifndef pdincludepathwithspaces +oldfat := $(and $(filter ppc i386, $(machine)), \ + $(filter-out 0 1, $(words $(filter -arch, $(c.flags))))) + +disable-dependency-tracking := pdincludepathwithspaces oldfat + +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)) From 1d7bb5e15493afdb2ea2a34a983d1188e045dc13 Mon Sep 17 00:00:00 2001 From: katja Date: Sat, 25 Jun 2016 22:26:33 +0200 Subject: [PATCH 025/150] Fix regression bug that disabled all dependency checking The bug was probably introduced with version 0.2.3. Bump version to 0.2.4. --- Makefile.pdlibbuilder | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index a91bb39..eb30f71 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,4 +1,4 @@ -# Makefile.pdlibbuilder version 0.2.3, dated 2016-03-29 +# Makefile.pdlibbuilder version 0.2.4, dated 2016-06-25 # # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -891,7 +891,7 @@ $(foreach v, $(classes), $(eval $(declare-class-executable-target))) oldfat := $(and $(filter ppc i386, $(machine)), \ $(filter-out 0 1, $(words $(filter -arch, $(c.flags))))) -disable-dependency-tracking := pdincludepathwithspaces oldfat +disable-dependency-tracking := $(strip $(pdincludepathwithspaces) $(oldfat)) ifndef disable-dependency-tracking must-build-everything := $(filter all, $(goals)) From b1a4c9b5251814546a2621a1faf3b494791cc419 Mon Sep 17 00:00:00 2001 From: katja Date: Sat, 25 Jun 2016 23:19:32 +0200 Subject: [PATCH 026/150] Print Makefile.pdlibbuilder version --- Makefile.pdlibbuilder | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index eb30f71..9f9990c 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,7 @@ -# Makefile.pdlibbuilder version 0.2.4, dated 2016-06-25 -# +# Makefile.pdlibbuilder dated 2016-06-25 + +version = 0.2.4 + # 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 @@ -685,6 +687,9 @@ ifdef pdincludepath mpdh := $(shell ls "$(pdincludepath)/m_pd.h") endif +# print Makefile.pdlibbuilder version +$(info ++++ info: using Makefile.pdlibbuilder version $(version)) + # when making target all, check if m_pd.h is found and print info about it ifeq ($(goals), all) $(if $(mpdh), \ From f06e550a3ac006737c20bda199f8379354b8d47d Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 26 Jun 2016 11:19:54 +0200 Subject: [PATCH 027/150] Fix dependency checking for object files in other directories And bump version to 0.2.5 --- Makefile.pdlibbuilder | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 9f9990c..bb02fe1 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,6 +1,6 @@ -# Makefile.pdlibbuilder dated 2016-06-25 +# Makefile.pdlibbuilder dated 2016-06-26 -version = 0.2.4 +version = 0.2.5 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -906,8 +906,9 @@ 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 -$(filter %.o: %.h, $(shell $(CPP) $(c.flags) -MM $1)) $(MAKEFILE_LIST) +$(dir $1)$(filter %.o: %.h, $(shell $(CPP) $(c.flags) -MM $1)) $(MAKEFILE_LIST) endef # evaluate implicit prerequisite rules when rebuilding everything From 49a0b2fa5ea07fdf0775d92d5ce5a20cd96f0820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Tue, 28 Jun 2016 11:33:25 +0200 Subject: [PATCH 028/150] allow installed files to contain weirdo characters ...like '$' (e.g. "$arg-help.pd") by installing them one-by-one and using single-quotes (so the shell doesn't expand the dollargs) NOTE: this does not fix compiling such weirdo filenames Closes: https://github.com/pure-data/pd-lib-builder/issues/19 --- Makefile.pdlibbuilder | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index a91bb39..4885a30 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1009,13 +1009,15 @@ install: $(if $(datadirs), install-datadirs) install-executables: all $(INSTALL_DIR) -v "$(installpath)" - $(INSTALL_PROGRAM) $(executables) "$(installpath)" + $(foreach v, $(executables), \ + $(INSTALL_PROGRAM) '$v' "$(installpath)";) $(info ++++ info: executables of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) install-datafiles: all $(INSTALL_DIR) -v "$(installpath)" - $(INSTALL_DATA) $(datafiles) "$(installpath)" + $(foreach v, $(datafiles), \ + $(INSTALL_DATA) '$(v)' "$(installpath)";) $(info ++++ info: data files of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) From 9fd17957c7c6bb11ab9f77c9cc2cbffd0adb9587 Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 20 Sep 2016 12:37:55 +0200 Subject: [PATCH 029/150] Do not pass architecture flags for dependency checking Only pass flags categories which can be expected to hold -I flags to the preprocessor for dependency checking. Omit categories which may contain architecture and tuning flags. This is a small and hopefully reasonable limitation of dependency-checking functionality. The preprocessor will still see predefined macros, amongst which architecture definition. Thus, eventual architecture-dependent include statements in the source code are considered for native architecture during dependency checking. This commit should resolve the rebuild issue on OSX, where some compiler versions can not handle multiple architecture flags during dependency checking. --- Makefile.pdlibbuilder | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index bb02fe1..37179d3 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,6 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-06-26 - -version = 0.2.5 +# Makefile.pdlibbuilder dated 2016-09-20 +version = 0.2.6 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -629,7 +628,10 @@ endif CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) # preprocessor flags -cpp.flags += -DPD -I "$(pdincludepath)" $(CPPFLAGS) +cpp.flags := -DPD -I "$(pdincludepath)" $(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) @@ -908,7 +910,7 @@ endif # argument $1 is input source file(s) # dir is explicitly added because option -MM strips it by default define declare-object-target -$(dir $1)$(filter %.o: %.h, $(shell $(CPP) $(c.flags) -MM $1)) $(MAKEFILE_LIST) +$(dir $1)$(filter %.o: %.h, $(shell $(CPP) $(depcheck.flags) -MM $1)) $(MAKEFILE_LIST) endef # evaluate implicit prerequisite rules when rebuilding everything From 2832db38fd7eba25ba1890f88ae902e33d662f51 Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 20 Sep 2016 13:01:10 +0200 Subject: [PATCH 030/150] Remove old dependency-check workaround for OSX <= 10.5 --- Makefile.pdlibbuilder | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 37179d3..707288d 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -891,14 +891,8 @@ $(foreach v, $(classes), $(eval $(declare-class-executable-target))) # which case implicit prerequisites are not checked. # When the Pd include path contains spaces it will mess up the implicit -# prerequisites rules. Also it is known that multiple arch flags are -# incompatible with preprocessor option -MM on OSX <= 10.5. Dependency -# tracking must be disabled in those cases. - -oldfat := $(and $(filter ppc i386, $(machine)), \ - $(filter-out 0 1, $(words $(filter -arch, $(c.flags))))) - -disable-dependency-tracking := $(strip $(pdincludepathwithspaces) $(oldfat)) +# prerequisites rules. +disable-dependency-tracking := $(strip $(pdincludepathwithspaces)) ifndef disable-dependency-tracking must-build-everything := $(filter all, $(goals)) From 5c9fed10988570b7cf0459920db11dad4fe51bee Mon Sep 17 00:00:00 2001 From: Dan Wilcox Date: Fri, 30 Sep 2016 11:40:21 -0600 Subject: [PATCH 031/150] updated cyclone link --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 03d7f0f..0a61e55 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,6 @@ Here are three projects using the Makefile.pdlibbuilder approach: https://github.com/pure-data/helloworld -https://github.com/electrickery/pd-cyclone - -https://github.com/pure-data/xeq +https://github.com/porres/pd-cyclone More examples will be referenced here when they are available. From dc9a8df02ac805f1d66f5896e55ebef10224214b Mon Sep 17 00:00:00 2001 From: Dan Wilcox Date: Sun, 2 Oct 2016 11:12:11 -0600 Subject: [PATCH 032/150] re-added cyclone link & added contextual info --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0a61e55..7bf6c51 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,12 @@ most basic usage, read the documentation sections in Makefile.pdlibbuilder. ### examples ### -Here are three projects using the Makefile.pdlibbuilder approach: +Here are a few projects using the Makefile.pdlibbuilder approach: https://github.com/pure-data/helloworld -https://github.com/porres/pd-cyclone +https://github.com/electrickery/pd-cyclone (stable) + +https://github.com/porres/pd-cyclone (experimental) More examples will be referenced here when they are available. From a6a89dc021d42fdb5a61de8ca371fed0862009a8 Mon Sep 17 00:00:00 2001 From: katja Date: Tue, 4 Oct 2016 17:33:45 +0200 Subject: [PATCH 033/150] Scrap all default include / bin paths except vanilla's Multiple defaults cause confusion and after discussion vanilla is preferred default because: 1. vanilla is actively maintained 2. currently most pd lib authors develop against vanilla 3. unlike other pd flavors, vanilla is not part of a centralized build system with internal include path --- Makefile.pdlibbuilder | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 707288d..ef49b24 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-09-20 -version = 0.2.6 +# Makefile.pdlibbuilder dated 2016-10-04 +version = 0.2.7 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -220,18 +220,13 @@ version = 0.2.6 # Executables are built in current working directory. # # Variable 'pdincludepath' stores a location where m_pd.h is expected to reside. -# Locations where Makefile.pdlibbuilder tries to find it, in order of priority: +# Location where Makefile.pdlibbuilder tries to find it: # -# any OS: $(externalsdir)../pd/src +# Linux: /usr/include/pd # -# Linux: /usr/include/pdextended -# /usr/include/pd +# OSX: /Applications/Pd*.app/Contents/Resources/src # -# OSX: /Applications/Pd-extended.app/Contents/Resources/include/pdextended -# /Applications/Pd.app/Contents/Resources/src -# -# Windows: %PROGRAMFILES%/pd/include/pdextended -# %PROGRAMFILES%/pd/src +# Windows: %PROGRAMFILES%/pd/src # # The path for installation of all library components is constructed as: # @@ -337,8 +332,7 @@ 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. This variable is used to probe for -# paths. +# defined differently in including makefile. externalsdir ?= .. # variable you can use to check if Makefile.pdlibbuilder is already included @@ -486,10 +480,7 @@ ifeq ($(system), Linux) prefix = /usr/local libdir := $(prefix)/lib pkglibdir = $(libdir)/pd-externals - pdincludepath := $(firstword $(wildcard \ - $(externalsdir)/../pd/src \ - /usr/include/pdextended \ - /usr/include/pd)) + pdincludepath := $(wildcard /usr/include/pd) extension = pd_linux cpp.flags := -DUNIX c.flags := -fpic @@ -515,8 +506,6 @@ endif ifeq ($(system), Darwin) pkglibdir = $(HOME)/Library/Pd pdincludepath := $(firstword $(wildcard \ - $(externalsdir)/../pd/src \ - /Applications/Pd-extended*.app/Contents/Resources/include/pdextended \ /Applications/Pd*.app/Contents/Resources/src)) extension = pd_darwin cpp.flags := -DUNIX -DMACOSX -I /sw/include @@ -555,14 +544,9 @@ endif # paths for 32-bit executables on 64-bit Windows aren't yet defined here (TODO) ifeq ($(system), Windows) pkglibdir := $(APPDATA)/Pd - pdbinpath := $(wildcard $(externalsdir)/../pd/bin) - pdincludepath := $(wildcard $(externalsdir)/../pd/src) ifndef pdbinpath pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin") endif - ifndef pdincludepath - pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/include/pdextended") - endif ifndef pdincludepath pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src") endif @@ -1160,7 +1144,7 @@ depend: ifdef mpdh mpdhinfo := $(mpdh) else - mpdhinfo := m_pd.h was not found. Is Pd(-extended) installed? + mpdhinfo := m_pd.h was not found. Is Pd installed? endif help: From 4815915ae28f18edfc7f887f60001d92a0cfe1ee Mon Sep 17 00:00:00 2001 From: katja Date: Wed, 5 Oct 2016 15:52:47 +0200 Subject: [PATCH 034/150] Add more projects that use pd-lib-builder in README.md --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 7bf6c51..fd7660f 100644 --- a/README.md +++ b/README.md @@ -55,4 +55,16 @@ https://github.com/electrickery/pd-cyclone (stable) https://github.com/porres/pd-cyclone (experimental) +https://git.iem.at/pd/iemguts + +https://git.iem.at/pd/iemnet + +https://git.iem.at/pd/iem_ambi + +https://git.iem.at/pd/mediasettings + +https://git.iem.at/pd-gui/punish + +https://github.com/residuum/PuRestJson + More examples will be referenced here when they are available. From a7d309822db391213ef61cdcfcafdf6902ecea09 Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 9 Oct 2016 11:56:14 +0200 Subject: [PATCH 035/150] Respect flag '-mmacosx-version-min=*' from lib makefile Makefile.pdlibbuilder sets a default minimum OSX version for optimal support of older OSX versions. With this commit, '-mmacosx-version-min=*' in variable 'cflags' from the lib makefile is respected, not overridden. A lib makefile can now determine the minimum OSX version (for example to support C++11, which was the direct motivation for this change). This is a response to pull request #22 'Making minimum Mac OS X version configurable', but note that it is implemented in a different way. --- Makefile.pdlibbuilder | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 724678c..c1512ff 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -503,6 +503,7 @@ endif # LLVM-clang doesn't support -fcheck-new, therefore this flag is omitted for # OSX x86_64. + ifeq ($(system), Darwin) pkglibdir = $(HOME)/Library/Pd pdincludepath := $(firstword $(wildcard \ @@ -519,15 +520,18 @@ ifeq ($(system), Darwin) -install_name @loader_path/$(shared.lib) \ -compatibility_version 1 -current_version 1.0 stripflags = -x + version.flag := $(filter $(cflags), -mmacosx-version-min=%) ifeq ($(machine), i386) cxx.flags := -fcheck-new - arch.c.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 - arch.ld.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + arch := ppc i386 x86_64 + version.flag ?= -mmacosx-version-min=10.4 endif ifeq ($(machine), x86_64) - arch.c.flags := -arch i386 -arch x86_64 -mmacosx-version-min=10.5 - arch.ld.flags := -arch i386 -arch x86_64 -mmacosx-version-min=10.5 + arch := i386 x86_64 + version.flag ?= -mmacosx-version-min=10.5 endif + arch.c.flags := $(addprefix -arch , $(arch)) $(version.flag) + arch.ld.flags := $(arch.c.flags) endif From 5b920b194db4f01a7b16b15858cd1b39680f49dd Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 9 Oct 2016 14:12:31 +0200 Subject: [PATCH 036/150] Set version to 0.2.8 after merging 'install-dollarfiles' Update version number because of previous (merge) commit. The merge was done with github's 'Merge' button. Never again. The merged commit was 49a0b2f from 2016-06-28 allowing installed files to contain weirdo characters, and closing issue #19. --- Makefile.pdlibbuilder | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 724678c..6f68ebb 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-10-04 -version = 0.2.7 +# Makefile.pdlibbuilder dated 2016-10-09 +version = 0.2.8 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. From 41e9743ed5fa0dfd74008e50510543b9a3596d26 Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 9 Oct 2016 22:07:23 +0200 Subject: [PATCH 037/150] Introduce variable 'PD_PATH', bump version to 0.3.0 This variable is useful when building against a 'portable' pd install. Makefile.pdlibbuilder should now be compatible with centralized build systems when PD_PATH is passed as make argument, or set in environment. --- Makefile.pdlibbuilder | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 6f68ebb..a0dbd70 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ # Makefile.pdlibbuilder dated 2016-10-09 -version = 0.2.8 +version = 0.3.0 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -76,6 +76,7 @@ version = 0.2.8 # # Variables avaialable for (re)definition via command arguments: # +# - PD_PATH # - pdbinpath (Windows only) # - pdincludepath # - DESTDIR @@ -161,6 +162,10 @@ version = 0.2.8 # Extra makefiles or directories with makefiles that should be made in sub-make # processes. # +# PD_PATH: +# Root directory of portable pd installation where bin/ and src/ are direct +# subdirs. +# # pdbinpath: # For Windows only. Directory where pd.dll can be found for linking. # @@ -566,11 +571,11 @@ ifeq ($(system), Windows) -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" c.ldlibs := cxx.flags := -fcheck-new - cxx.ldflags := -static-libstdc++ -shared \ + cxx.ldflags = -static-libstdc++ -shared \ -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" cxx.ldlibs := shared.extension = dll - shared.ldflags := -static-libgcc -shared "$(pdbinpath)/pd.dll" + shared.ldflags = -static-libgcc -shared "$(pdbinpath)/pd.dll" stripflags = --strip-unneeded -R .note -R .comment endif @@ -578,6 +583,13 @@ endif #=== paths ===================================================================== +# If PD_PATH is defined as make command argument or in the environment, override +# the earlier platform-dependent default. +ifdef PD_PATH + pdincludepath := $(PD_PATH)/src + pdbinpath := $(PD_PATH)/bin +endif + # Default pkglibdir is specified above per operating system. It is aliased as # 'objectsdir' to retain compatibility with pd-extended template. Assignment # operator '?=' is used to enable a project-relative path definition in the From a0c87bea5e660e78e50fafd3738f266eae0751b1 Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 13 Oct 2016 23:58:13 +0200 Subject: [PATCH 038/150] Defer expansion of $(pdbinpath) to correctly find pd.dll (bugfix) The issue was introduced in version 0.3.0 from the previous commit (41e9743). --- Makefile.pdlibbuilder | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index a0dbd70..f8215b8 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-10-09 -version = 0.3.0 +# Makefile.pdlibbuilder dated 2016-10-13 +version = 0.3.1 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -567,7 +567,7 @@ ifeq ($(system), Windows) arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse cpp.flags := -DMSW -DNT c.flags := - c.ldflags := -static-libgcc -shared \ + c.ldflags = -static-libgcc -shared \ -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" c.ldlibs := cxx.flags := -fcheck-new From b0dab729b9a1fe08ea55eb051298f99b9c779027 Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 13 Oct 2016 23:44:18 +0200 Subject: [PATCH 039/150] Introduce variables PDDIR, PDINCLUDEDIR, PDBINDIR, PDLIBDIR These new path variables are aliases of existing ones that didn't have coherent names. The new variables are all defined such that they are overridable from the environment, as indicated by the upper case syntax. --- Makefile.pdlibbuilder | 46 ++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index f8215b8..184bda5 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-10-13 -version = 0.3.1 +# Makefile.pdlibbuilder dated 2016-10-14 +version = 0.4.0 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -583,25 +583,27 @@ endif #=== paths ===================================================================== -# If PD_PATH is defined as make command argument or in the environment, override -# the earlier platform-dependent default. -ifdef PD_PATH - pdincludepath := $(PD_PATH)/src - pdbinpath := $(PD_PATH)/bin -endif +# 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. 'PD_PATH' and 'objectsdir' are supported for compatibility with +# the build system that pd-l2ork has inherited from pd-extended. + +PDDIR ?= $(PD_PATH) +PDINCLUDEDIR ?= $(pdincludepath) +PDBINDIR ?= $(pdbinpath) +PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) -# Default pkglibdir is specified above per operating system. It is aliased as -# 'objectsdir' to retain compatibility with pd-extended template. Assignment -# operator '?=' is used to enable a project-relative path definition in the -# including makefile. -objectsdir ?= $(pkglibdir) +ifneq ($(PDDIR),) + PDINCLUDEDIR := $(wildcard $(PDDIR)/src) + PDBINDIR := $(wildcard $(PDDIR)/bin) +endif # base path where all components of the lib will be installed by default -installpath := $(DESTDIR)$(objectsdir)/$(lib.name) +installpath := $(DESTDIR)$(PDLIBDIR)/$(lib.name) -# check if pdincludepath contains spaces (as is often the case on Windows) +# 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, $(pdincludepath)), $(pdincludepath)) +pdincludepathwithspaces := $(if $(word 2, $(PDINCLUDEDIR)), $(PDINCLUDEDIR)) #=== accumulated build flags =================================================== @@ -624,7 +626,7 @@ endif CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) # preprocessor flags -cpp.flags := -DPD -I "$(pdincludepath)" $(cpp.flags) $(CPPFLAGS) +cpp.flags := -DPD -I "$(PDINCLUDEDIR)" $(cpp.flags) $(CPPFLAGS) # flags for dependency checking (cflags from makefile may define -I options) depcheck.flags := $(cpp.flags) $(cflags) @@ -682,7 +684,7 @@ endif # store path to Pd API m_pd.h if it is found ifdef pdincludepath - mpdh := $(shell ls "$(pdincludepath)/m_pd.h") + mpdh := $(shell ls "$(PDINCLUDEDIR)/m_pd.h") endif # print Makefile.pdlibbuilder version @@ -1172,13 +1174,13 @@ help: @echo @echo " Pd API m_pd.h:" @echo " $(mpdhinfo)" - @echo " You may specify your preferred Pd include path as argument to" - @echo " the make command, like 'pdincludepath=path/to/pd/src'." + @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 " $(objectsdir)" + @echo " $(PDLIBDIR)" @echo " Alternatively you may specify your path for installation as argument" - @echo " to the make command, like 'objectsdir=path/to/pd-externals'." + @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 From cf04da9b4732733b5fdbd51efb7ca79a5287722f Mon Sep 17 00:00:00 2001 From: katja Date: Fri, 14 Oct 2016 11:50:34 +0200 Subject: [PATCH 040/150] Rewrite variable descriptions after introduction of 'PDDIR' & Co. Variables PDDIR, PDINCLUDEDIR, PDBINDIR and PDLIBDIR were introduced in the previous commit as API replacement for a less coherent set of path variable names, and made these paths settable in the environment. This commit (re)writes variable descriptions accordingly and reorganizes descriptions with the intention to give a more comprehensible overview of the API structure. --- Makefile.pdlibbuilder | 117 ++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 184bda5..f39efb3 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -73,31 +73,34 @@ version = 0.4.0 # - forDarwin # - forWindows # +# Variables available for your makefile or make command line: # -# Variables avaialable for (re)definition via command arguments: +# - 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: # -# - PD_PATH -# - pdbinpath (Windows only) -# - pdincludepath -# - DESTDIR -# - prefix -# - libdir -# - pkglibdir # - CPPFLAGS # - CFLAGS # - LDFLAGS # - CC # - CXX # - INSTALL -# - INSTALL_PROGRAM -# - INSTALL_DATA -# - INSTALL_DIR +# - DESTDIR # -# Variables available for your makefile or as command argument: +# Deprecated path variables: # +# - PD_PATH +# - pdincludepath +# - pdbinpath # - objectsdir -# - make-lib-executable -# - suppress-wunused # # #=== descriptions of Makefile.pdlibbuilder API variables ======================= @@ -145,12 +148,6 @@ version = 0.4.0 # files that should go into your lib rootdir and 'datadirs' for complete # directories you want to copy from source to distribution. # -# externalsdir: -# Relative path to directory 'externals' in the context of pd-extended SVN, or -# any other centralized build layout for multiple libraries. Default value -# is '..', meaning the direct parent. The value is used in search paths for -# pd core components (header files, and executable in the case of Windows). -# # forLinux, forDarwin, forWindows: # Shorthand for 'variable definitions for Linux only' etc. Use like: # define forLinux @@ -162,26 +159,37 @@ version = 0.4.0 # Extra makefiles or directories with makefiles that should be made in sub-make # processes. # -# PD_PATH: -# Root directory of portable pd installation where bin/ and src/ are direct -# subdirs. +# 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 overriden 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. # -# pdbinpath: -# For Windows only. Directory where pd.dll can be found for linking. +# PDDIR: +# Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and +# PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. # -# pdincludepath: -# Directory where Pd API m_pd.h can be found, and other Pd header files. +# PDINCLUDEDIR: +# Directory where Pd API m_pd.h should be found, and other Pd header files. +# Overrides the default search path. # -# DESTDIR, prefix, libdir: -# Components of the path for installation as conventionally used on Linux. +# PDBINDIR: +# Directory where pd.dll should be found for linking (Windows only). Overrides +# the default search path. # -# pkglibdir: -# Base path for installation of Pd library directories. Default is specified -# per OS, see section about paths below. +# PDLIBDIR: +# Root directory for installation of Pd library directories. Overrides the +# default install location. # -# objectsdir: -# Alias of pkglibdir. Can be defined in your makefile to enable project- -# dependent relative install locations. +# DESTDIR: +# Prepended path component for staged install. # # CPPFLAGS: # Preprocessor flags which are not strictly required for building. @@ -199,21 +207,21 @@ version = 0.4.0 # CC and CXX: # C and C++ compiler programs as defined in your build environment. # -# INSTALL, INSTALL_PROGRAM, INSTALL_DATA, INSTALL_DIR: -# Definitions of install program, may be overriden via command argument. +# INSTALL +# Definition of install program. # -# 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 overriden with 'make-lib-executable=no' as command argument -# to build individual class executables (the Makefile.pdlibbuilder default.) +# PD_PATH: +# Equivalent to PDDIR. Supported for compatibility with pd-extended central +# makefile, but deprecated otherwise. # -# 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. +# 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 ===================================================================== @@ -224,8 +232,8 @@ version = 0.4.0 # Object (.o) files are built in the directory of their source files. # Executables are built in current working directory. # -# Variable 'pdincludepath' stores a location where m_pd.h is expected to reside. -# Location where Makefile.pdlibbuilder tries to find it: +# Default search path for m_pd.h and other API header files is platform +# dependent, and overridable by PDINCLUDEDIR: # # Linux: /usr/include/pd # @@ -233,17 +241,14 @@ version = 0.4.0 # # Windows: %PROGRAMFILES%/pd/src # -# The path for installation of all library components is constructed as: -# -# installpath := $(DESTDIR)$(objectsdir)/$(lib.name) -# -# Default for 'objectsdir' is defined per platform and follows this convention: -# https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files +# 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. # From 48c41272973f183f8f25bc8f98f2bdead701db90 Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 27 Oct 2016 00:44:56 +0200 Subject: [PATCH 041/150] Bump version to 0.4.1 after merging 'configurable-minimum-osxversion' --- Makefile.pdlibbuilder | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 4306898..8be6339 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-10-14 -version = 0.4.0 +# Makefile.pdlibbuilder dated 2016-10-27 +version = 0.4.1 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. From 4c680bfe6ff839c272ffc6e1ba9740d88611df1d Mon Sep 17 00:00:00 2001 From: katja Date: Thu, 27 Oct 2016 01:10:53 +0200 Subject: [PATCH 042/150] Add 'path' and 'documentation' sections in README.md --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index fd7660f..c6926b6 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,39 @@ 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. + + +### 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. A tips&tricks page is in the works. + + ### examples ### From 006d9575b52b79a4ac27dd5a345d9f21daa6c31b Mon Sep 17 00:00:00 2001 From: katja Date: Fri, 28 Oct 2016 09:58:47 +0200 Subject: [PATCH 043/150] Add CHANGELOG.txt to the project --- CHANGELOG.txt | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 CHANGELOG.txt diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..1c9607c --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,71 @@ +Changelog for Makefile.pdlibbuilder. + + +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) From 058ba82a4792ebd568b9ab29618c1ecf249dd9d9 Mon Sep 17 00:00:00 2001 From: katja Date: Fri, 28 Oct 2016 14:31:01 +0200 Subject: [PATCH 044/150] Add section 'versioning' in README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index c6926b6..75e070e 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,16 @@ paths, and targets. The internal documentation reflects the exact functionality of the particular version. A tips&tricks page is in the works. +### 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 ### From 2e13d8f7a33ab8ea61868b5bcf2403f41cddbe50 Mon Sep 17 00:00:00 2001 From: katja Date: Sun, 30 Oct 2016 21:50:10 +0100 Subject: [PATCH 045/150] Fix bug where incorrect message about m_pd.h is given And bump to version 0.4.2 --- Makefile.pdlibbuilder | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 8be6339..2cc321c 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-10-27 -version = 0.4.1 +# Makefile.pdlibbuilder dated 2016-10-30 +version = 0.4.2 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -692,7 +692,7 @@ else endif # store path to Pd API m_pd.h if it is found -ifdef pdincludepath +ifdef PDINCLUDEDIR mpdh := $(shell ls "$(PDINCLUDEDIR)/m_pd.h") endif From 426b38bb3543b72ba27149dc96020f099f12830f Mon Sep 17 00:00:00 2001 From: katja Date: Wed, 2 Nov 2016 01:27:43 +0100 Subject: [PATCH 046/150] Replace flags '-fpic' with '-fPIC' Reportedly '-fPIC' should work for all architectures while '-fpic' does not. --- Makefile.pdlibbuilder | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 2cc321c..8aa1cb7 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-10-30 -version = 0.4.2 +# Makefile.pdlibbuilder dated 2016-11-02 +version = 0.4.3 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -493,14 +493,14 @@ ifeq ($(system), Linux) 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.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.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) + shared.ldflags := -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) stripflags = --strip-unneeded -R .note -R .comment endif From 6120db18a56eae468d3665eee8175d74da496db4 Mon Sep 17 00:00:00 2001 From: katja Date: Wed, 2 Nov 2016 01:44:26 +0100 Subject: [PATCH 047/150] Update CHANGELOG.txt --- CHANGELOG.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1c9607c..76e273c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,12 @@ Changelog for Makefile.pdlibbuilder. +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. From cdd3b4397801b8a37035bce6d73958db4605df78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Tue, 22 Nov 2016 09:45:25 -0500 Subject: [PATCH 048/150] removed trailing whitespace --- Makefile.pdlibbuilder | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 8aa1cb7..dfcfb08 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -106,7 +106,7 @@ version = 0.4.3 #=== descriptions of Makefile.pdlibbuilder API variables ======================= # # -# lib.name: +# 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. @@ -116,7 +116,7 @@ version = 0.4.3 # into a single lib binary. # # class.sources: -# All sources files (C or C++) for which the condition holds that +# All sources files (C or C++) for which the condition holds that # class name == source file basename. # # .class.sources: @@ -135,13 +135,13 @@ version = 0.4.3 # link libs) for the whole library. These flags are added to platform-specific # flags defined by Makefile.pdlibbuilder. # -# .class.ldflags and .class.ldlibs: +# .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: +# 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 @@ -155,7 +155,7 @@ version = 0.4.3 # class.sources += linuxthing.c # endef # -# makefiles and makefiledirs: +# makefiles and makefiledirs: # Extra makefiles or directories with makefiles that should be made in sub-make # processes. # @@ -164,7 +164,7 @@ version = 0.4.3 # 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 overriden with 'make-lib-executable=no' as command argument +# this can still be overriden with 'make-lib-executable=no' as command argument # to build individual class executables (the Makefile.pdlibbuilder default.) # # suppress-wunused: @@ -173,7 +173,7 @@ version = 0.4.3 # but the other warnings from -Wall are retained. # # PDDIR: -# Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and +# Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and # PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. # # PDINCLUDEDIR: @@ -230,9 +230,9 @@ version = 0.4.3 # 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. +# Executables are built in current working directory. # -# Default search path for m_pd.h and other API header files is platform +# Default search path for m_pd.h and other API header files is platform # dependent, and overridable by PDINCLUDEDIR: # # Linux: /usr/include/pd @@ -301,7 +301,7 @@ version = 0.4.3 # 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, +# Words in variables expressing a function or command are separated by dashes, # like in 'make-lib-executable'. # # @@ -325,7 +325,7 @@ version = 0.4.3 # #=== end of documentation sections ============================================= # -# +# ################################################################################ ################################################################################ ################################################################################ @@ -340,7 +340,7 @@ 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 +# 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 ?= .. @@ -357,7 +357,7 @@ Makefile.pdlibbuilder = true # strip possibles spaces from lib.name, they mess up calculated file names lib.name := $(strip $(lib.name)) -# if meta file exists, check library version +# if meta file exists, check library version metafile := $(wildcard $(lib.name)-meta.pd) ifdef metafile @@ -429,7 +429,7 @@ endif #=== flags per architecture ==================================================== -# Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, +# Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, # arch.c.flags are overriden below. machine := $(shell uname -m) @@ -451,7 +451,7 @@ endif # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions ifeq ($(findstring $(machine), ia64 x86_64), $(machine)) - arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 + arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 endif @@ -520,7 +520,7 @@ ifeq ($(system), Darwin) /Applications/Pd*.app/Contents/Resources/src)) extension = pd_darwin cpp.flags := -DUNIX -DMACOSX -I /sw/include - c.flags := + c.flags := c.ldflags := -undefined suppress -flat_namespace -bundle c.ldlibs := -lc cxx.ldflags := -undefined suppress -flat_namespace -bundle @@ -566,7 +566,7 @@ ifeq ($(system), Windows) endif endif -# On Windows we build 32 bit by default to match Pd(-extended) binary +# On Windows we build 32 bit by default to match Pd(-extended) binary # distributions. This may change in the future. # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) @@ -620,7 +620,7 @@ pdincludepathwithspaces := $(if $(word 2, $(PDINCLUDEDIR)), $(PDINCLUDEDIR)) # 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 +# 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. @@ -679,7 +679,7 @@ compile-cxx := $(CXX) all: # To avoid unpredictable results, make sure the default target is not redefined -# by including makefile. +# by including makefile. ifneq ($(.DEFAULT_GOAL), all) $(error Default target must be 'all'.) endif @@ -753,8 +753,8 @@ MAKEFLAGS += --no-builtin-rules # 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 +# 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. @@ -960,7 +960,7 @@ endef %.pre:: %.cc force $(call make-preprocessor-file,cxx) -%.pre:: %.cpp force +%.pre:: %.cpp force $(call make-preprocessor-file,cxx) From cb839ed47085c7d2c70a5605d5715d823bbd2674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Tue, 22 Nov 2016 09:48:03 -0500 Subject: [PATCH 049/150] note (within the pd-lib-builder Makefile) how to update the file. --- Makefile.pdlibbuilder | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index dfcfb08..fe9a076 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -6,6 +6,9 @@ version = 0.4.3 # 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. # # From 2c141109471b01896bfc0ff0d59e1b501d07f0b6 Mon Sep 17 00:00:00 2001 From: katjav Date: Tue, 22 Nov 2016 17:40:13 +0100 Subject: [PATCH 050/150] Use variable 'system' when evaluating 'for{Linux,Darwin,Windows} This evaluates correctly in the case where 'system' is defined for the purpose of cross compiling. This commit addresses issue #31. --- Makefile.pdlibbuilder | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index fe9a076..eba47f9 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-11-02 -version = 0.4.3 +# Makefile.pdlibbuilder dated 2016-11-22 +version = 0.4.4 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. @@ -462,27 +462,26 @@ endif # The following systems are defined: Linux, Darwin, Windows. GNU and -# GNU/kFreeBSD are treated as Linux to get the same options. System-specific -# multiline defines (optionally set in library makefile) are conditionally -# evaluated here. +# GNU/kFreeBSD are treated as Linux to get the same options. uname := $(shell uname) ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname)) system = Linux - $(eval $(forLinux)) endif ifeq ($(uname), Darwin) system = Darwin - $(eval $(forDarwin)) endif ifeq ($(findstring MINGW, $(uname)), MINGW) system = Windows - $(eval $(forWindows)) endif +# evaluate possible system-specific multiline defines from library makefile +$(eval $(for$(system))) + + # TODO: Cygwin, Android From 872c34b1d3851937251b45a28ba8a91f34c2e2a6 Mon Sep 17 00:00:00 2001 From: katjav Date: Tue, 22 Nov 2016 17:52:04 +0100 Subject: [PATCH 051/150] Update CHANGELOG.txt for v0.4.4 --- CHANGELOG.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 76e273c..58e8b98 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,9 @@ Changelog for Makefile.pdlibbuilder. +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) From fcf20d15ff01fc15c95c5bb4b978e01e228661db Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Thu, 20 Apr 2017 16:24:57 +0200 Subject: [PATCH 052/150] Fixed Python signal script. Max help file still incorrect --- maxmsp/py.maxhelp | 2 +- scripts/sig.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/maxmsp/py.maxhelp b/maxmsp/py.maxhelp index 05a60d2..e6b5d93 100644 --- a/maxmsp/py.maxhelp +++ b/maxmsp/py.maxhelp @@ -133,7 +133,7 @@ , { "box" : { "maxclass" : "message", - "text" : "gain 0.5", + "text" : "set gain 0.5", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 100.77256, 1262.583496, 53.0, 18.0 ], diff --git a/scripts/sig.py b/scripts/sig.py index 6bebcb3..7009cd8 100644 --- a/scripts/sig.py +++ b/scripts/sig.py @@ -1,6 +1,6 @@ # py/pyext - python script objects for PD and MaxMSP # -# Copyright (c) 2002-2012 Thomas Grill (gr@grrrr.org) +# Copyright (c) 2002-2017 Thomas Grill (gr@grrrr.org) # For information on usage and redistribution, and for a DISCLAIMER OF ALL # WARRANTIES, see the file, "license.txt," in this distribution. # @@ -35,7 +35,8 @@ class gain(pyext._class): """Just a simple gain stage""" - gain = 0 + def __init__(self): + self.gain = 0 def _signal(self): # Multiply input vector by gain and copy to output @@ -48,7 +49,8 @@ def _signal(self): class gain2(pyext._class): """More optimized version""" - gain = 0 + def __init__(self): + self.gain = 0 def _dsp(self): if not self._arraysupport(): From 88fc77ad904d0bc649c83819589414207d570454 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Wed, 10 May 2017 00:47:30 +0200 Subject: [PATCH 053/150] Change to python2.7 by default --- build/config-lnx.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/config-lnx.def b/build/config-lnx.def index 86477fc..09879a3 100644 --- a/build/config-lnx.def +++ b/build/config-lnx.def @@ -2,7 +2,7 @@ PYTHONPREFIX=/usr # which Python version do you want to compile against? -PYTHONVERSION=2.4 +PYTHONVERSION=2.7 # uncomment if numpy/numarray/numeric support should be compiled in # for info see http://numeric.scipy.org From 4be3e99acb661df7da32ef3bfc4b111dbb0a1a89 Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 20 Jan 2018 17:18:34 +0100 Subject: [PATCH 054/150] Swap OS and machine detection so OS comes first This is in preparation for target architecture detection through gcc / g++. --- Makefile.pdlibbuilder | 67 ++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index eba47f9..2c052d2 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -424,6 +424,44 @@ else endif +################################################################################ +### platform detection ######################################################### +################################################################################ + + +#=== operating system ========================================================== + + +# The following systems are defined: Linux, Darwin, Windows. GNU and +# GNU/kFreeBSD are treated as Linux to get the same options. + +uname := $(shell uname) + +ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname)) + system = Linux +endif + +ifeq ($(uname), Darwin) + system = Darwin +endif + +ifeq ($(findstring MINGW, $(uname)), MINGW) + system = Windows +endif + +# evaluate possible system-specific multiline defines from library makefile +$(eval $(for$(system))) + + +# TODO: Cygwin, Android + + +#=== architecture ============================================================== + + +machine := $(shell uname -m) + + ################################################################################ ### variables per platform ##################################################### ################################################################################ @@ -435,8 +473,6 @@ endif # Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, # arch.c.flags are overriden below. -machine := $(shell uname -m) - # Raspberry Pi 1st generation ifeq ($(machine), armv6l) arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard @@ -458,33 +494,6 @@ ifeq ($(findstring $(machine), ia64 x86_64), $(machine)) endif -#=== operating system ========================================================== - - -# The following systems are defined: Linux, Darwin, Windows. GNU and -# GNU/kFreeBSD are treated as Linux to get the same options. - -uname := $(shell uname) - -ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname)) - system = Linux -endif - -ifeq ($(uname), Darwin) - system = Darwin -endif - -ifeq ($(findstring MINGW, $(uname)), MINGW) - system = Windows -endif - -# evaluate possible system-specific multiline defines from library makefile -$(eval $(for$(system))) - - -# TODO: Cygwin, Android - - #=== flags and paths for Linux ================================================= From fa3c2ca71d231c067f07b62b689f930373737973 Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 20 Jan 2018 17:45:31 +0100 Subject: [PATCH 055/150] Introduce variable 'target.arch' It stores the first field of -- triplet as retrieved from command ' -dumpmachine' where is g++ or gcc. --- Makefile.pdlibbuilder | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 2c052d2..d9e67a1 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -449,6 +449,14 @@ ifeq ($(findstring MINGW, $(uname)), MINGW) system = Windows endif +# Unfortunately not all Mingw versions provide a link cc > gcc, therefore +# gcc is hardcoded here (but not if CC is redefined). +ifeq ($(system), Windows) + ifeq ($(origin CC), default) + CC = gcc + endif +endif + # evaluate possible system-specific multiline defines from library makefile $(eval $(for$(system))) @@ -459,7 +467,16 @@ $(eval $(for$(system))) #=== architecture ============================================================== -machine := $(shell uname -m) +# native architecture +machine := $(shell uname --machine) + +# Target architecture as reported by compiler. Give precedence to eventual +# user-defined compiler. The first field of -- is extracted. +ifneq ($(origin CXX), default) + target.arch = $(firstword $(subst -, ,$(shell $(CXX) -dumpmachine))) +else + target.arch = $(firstword $(subst -, ,$(shell $(CC) -dumpmachine))) +endif ################################################################################ @@ -582,8 +599,6 @@ endif # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) extension = dll - CC = gcc - CXX = g++ arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse cpp.flags := -DMSW -DNT c.flags := From ef21a16eb0d8d5f6745a8741e8ca75a5e9caf19f Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 20 Jan 2018 23:11:15 +0100 Subject: [PATCH 056/150] Introduce architecture dependent settings for Windows --- Makefile.pdlibbuilder | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index d9e67a1..66db349 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -594,13 +594,16 @@ ifeq ($(system), Windows) endif endif -# On Windows we build 32 bit by default to match Pd(-extended) binary -# distributions. This may change in the future. # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) + ifeq ($(findstring $(target.arch), ia64 x86_64), $(target.arch)) + cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 + arch.c.flags := -march=core2 -msse -msse2 -mfpmath=sse + else + cpp.flags := -DMSW -DNT + arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse + endif extension = dll - arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse - cpp.flags := -DMSW -DNT c.flags := c.ldflags = -static-libgcc -shared \ -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" From 37d23530c6be7a97e1cd29fee61db6acbe574283 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 21 Jan 2018 11:19:43 +0100 Subject: [PATCH 057/150] Leave out architecture 'ia64' As per suggestion of Johannes Zmoelnig. It is not relevant and also not compatible with x86_64. --- Makefile.pdlibbuilder | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 66db349..8092166 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -506,7 +506,7 @@ ifeq ($(findstring $(machine), i386 i686), $(machine)) endif # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions -ifeq ($(findstring $(machine), ia64 x86_64), $(machine)) +ifeq ($(findstring $(machine), x86_64), $(machine)) arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 endif @@ -596,7 +596,7 @@ endif # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) - ifeq ($(findstring $(target.arch), ia64 x86_64), $(target.arch)) + ifeq ($(findstring $(target.arch), x86_64), $(target.arch)) cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 arch.c.flags := -march=core2 -msse -msse2 -mfpmath=sse else From f83d4293bdf8bd8b33252ac56d30717221eb95ed Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 21 Jan 2018 11:42:55 +0100 Subject: [PATCH 058/150] Introduce remainder architecture category for Windows And explicitly specify Intel 32 bit architectures, where 'mingw32' is included to support MSYS1. --- Makefile.pdlibbuilder | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 8092166..8bf8328 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -596,12 +596,14 @@ endif # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) - ifeq ($(findstring $(target.arch), x86_64), $(target.arch)) + cpp.flags := -DMSW -DNT + ifeq ($(findstring $(target.arch), i%86 mingw32), $(target.arch)) + arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse + else ifeq (x86_64, $(target.arch)) cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 arch.c.flags := -march=core2 -msse -msse2 -mfpmath=sse else - cpp.flags := -DMSW -DNT - arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse + arch.c.flags = endif extension = dll c.flags := From 867ad5e8e87bfa06770ca2f4c2d26beb5133fd6a Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 21 Jan 2018 11:54:01 +0100 Subject: [PATCH 059/150] Introduce general remainder architecture category --- Makefile.pdlibbuilder | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 8bf8328..4fc4e15 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -493,21 +493,22 @@ endif # Raspberry Pi 1st generation ifeq ($(machine), armv6l) arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard -endif # Beagle, Udoo, RPi2 etc. -ifeq ($(machine), armv7l) +else ifeq ($(machine), armv7l) arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard -endif # Intel 32 bit, build with SSE and SSE2 instructions -ifeq ($(findstring $(machine), i386 i686), $(machine)) +else ifeq ($(findstring $(machine), i386 i686), $(machine)) arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 -endif - + # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions -ifeq ($(findstring $(machine), x86_64), $(machine)) +else ifeq ($(findstring $(machine), x86_64), $(machine)) arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 + +# if none of the above architectures detected +else + arch.c.flags = endif From 231e344b440cdf32dcdda9c564a9e67101d32474 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 21 Jan 2018 12:34:45 +0100 Subject: [PATCH 060/150] Use variables 'build.arch' and 'target.arch' consistently --- Makefile.pdlibbuilder | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 4fc4e15..bce69dd 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -467,15 +467,23 @@ $(eval $(for$(system))) #=== architecture ============================================================== -# native architecture -machine := $(shell uname --machine) +# native architecture of the build machine +build.arch := $(shell uname --machine) # Target architecture as reported by compiler. Give precedence to eventual # user-defined compiler. The first field of -- is extracted. ifneq ($(origin CXX), default) - target.arch = $(firstword $(subst -, ,$(shell $(CXX) -dumpmachine))) + dumpmachine.cpu = $(firstword $(subst -, ,$(shell $(CXX) -dumpmachine))) else - target.arch = $(firstword $(subst -, ,$(shell $(CC) -dumpmachine))) + dumpmachine.cpu = $(firstword $(subst -, ,$(shell $(CC) -dumpmachine))) +endif + +# Target architecture as reported by compiler is only used for Windows at the +# moment. For other systems this still has to be tested. +ifeq ($(system), Windows) + target.arch = $(dumpmachine.cpu) +else + target.arch = $(build.arch) endif @@ -491,19 +499,19 @@ endif # arch.c.flags are overriden below. # Raspberry Pi 1st generation -ifeq ($(machine), armv6l) +ifeq ($(target.arch), armv6l) arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard # Beagle, Udoo, RPi2 etc. -else ifeq ($(machine), armv7l) +else ifeq ($(target.arch), armv7l) arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard # Intel 32 bit, build with SSE and SSE2 instructions -else ifeq ($(findstring $(machine), i386 i686), $(machine)) +else ifeq ($(findstring $(target.arch), i386 i686), $(target.arch)) arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions -else ifeq ($(findstring $(machine), x86_64), $(machine)) +else ifeq ($(findstring $(target.arch), x86_64), $(target.arch)) arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 # if none of the above architectures detected @@ -560,12 +568,12 @@ ifeq ($(system), Darwin) -compatibility_version 1 -current_version 1.0 stripflags = -x version.flag := $(filter $(cflags), -mmacosx-version-min=%) - ifeq ($(machine), i386) + ifeq ($(target.arch), i386) cxx.flags := -fcheck-new arch := ppc i386 x86_64 version.flag ?= -mmacosx-version-min=10.4 endif - ifeq ($(machine), x86_64) + ifeq ($(target.arch), x86_64) arch := i386 x86_64 version.flag ?= -mmacosx-version-min=10.5 endif From e4d42f22278d9b5a9f02408d7fab2ac94c6ffed8 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 21 Jan 2018 14:59:38 +0100 Subject: [PATCH 061/150] Assume system is "Windows" when uname says "MSYS" Needed for building with pd-lib-builder on AppVeyor. --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index bce69dd..94c4116 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -445,7 +445,7 @@ ifeq ($(uname), Darwin) system = Darwin endif -ifeq ($(findstring MINGW, $(uname)), MINGW) +ifeq ($(findstring $(uname), MINGW MSYS), $(uname)) system = Windows endif From 77ff876401d991be5af4928e7fed077a19227f6c Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 21 Jan 2018 22:42:47 +0100 Subject: [PATCH 062/150] Fix conditional checks broken in commits e4d42f2 and f83d429 --- Makefile.pdlibbuilder | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 94c4116..ca89077 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -445,7 +445,7 @@ ifeq ($(uname), Darwin) system = Darwin endif -ifeq ($(findstring $(uname), MINGW MSYS), $(uname)) +ifeq ($(filter MINGW% MSYS, $(uname)), $(uname)) system = Windows endif @@ -606,7 +606,7 @@ endif # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) cpp.flags := -DMSW -DNT - ifeq ($(findstring $(target.arch), i%86 mingw32), $(target.arch)) + ifeq ($(filter i%86 mingw32, $(target.arch)), $(target.arch)) arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse else ifeq (x86_64, $(target.arch)) cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 From 13796bfee28884b8b5aff910cca2d3f6e7924f6c Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 21 Jan 2018 22:52:19 +0100 Subject: [PATCH 063/150] Add option '-msse3' for Windows on x86_64 architecture --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index ca89077..f192f02 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -610,7 +610,7 @@ ifeq ($(system), Windows) arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse else ifeq (x86_64, $(target.arch)) cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 - arch.c.flags := -march=core2 -msse -msse2 -mfpmath=sse + arch.c.flags := -march=core2 -msse -msse2 -msse3 -mfpmath=sse else arch.c.flags = endif From a01ee169cd48e4d40f1fc7530a503a1d32fc14c7 Mon Sep 17 00:00:00 2001 From: katjav Date: Mon, 22 Jan 2018 23:19:24 +0100 Subject: [PATCH 064/150] Revert 'uname --machine' to 'uname -m' (bug fix OSX) Long option name '--machine' was introduced in commit fa3c2ca for explicitness, however it is not supported by clang / OSX. --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index f192f02..1a669ab 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -468,7 +468,7 @@ $(eval $(for$(system))) # native architecture of the build machine -build.arch := $(shell uname --machine) +build.arch := $(shell uname -m) # Target architecture as reported by compiler. Give precedence to eventual # user-defined compiler. The first field of -- is extracted. From 80d7dc0a134d6594799a531036a788de2c6d0b2e Mon Sep 17 00:00:00 2001 From: katjav Date: Tue, 23 Jan 2018 21:25:23 +0100 Subject: [PATCH 065/150] Bump version to 0.5.0, ready for Windows 64 bit Update version number after merge commit 215bf3e. This is the first version handling 64 bit builds for Windows. --- CHANGELOG.txt | 5 +++++ Makefile.pdlibbuilder | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 58e8b98..41ac0e2 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,10 @@ Changelog for Makefile.pdlibbuilder. +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) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 1a669ab..1db3f8c 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2016-11-22 -version = 0.4.4 +# Makefile.pdlibbuilder dated 2018-01-23 +version = 0.5.0 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. From 1361dd399993846b75f451b0dfe121a89d0b2ed0 Mon Sep 17 00:00:00 2001 From: katjav Date: Wed, 24 Jan 2018 13:56:36 +0100 Subject: [PATCH 066/150] Remove unuseful variable 'PD_PATH' The variable was introduced in commit 41e9743 for compatibility with centralized build system as inherited from Pd-extended by Pd-L2ork and Purr Data. But it doesn't work in that context because $(PD_PATH)/bin is absent. Therefore better remove 'PD_PATH' and focus on making variables 'PDDIR' & Co. work as expected. --- Makefile.pdlibbuilder | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 1db3f8c..e7b04a8 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -213,10 +213,6 @@ version = 0.5.0 # INSTALL # Definition of install program. # -# PD_PATH: -# Equivalent to PDDIR. Supported for compatibility with pd-extended central -# makefile, but deprecated otherwise. -# # objectsdir: # Root directory for installation of Pd library directories, like PDLIBDIR but # not overridable by environment. Supported for compatibility with pd-extended @@ -634,10 +630,9 @@ endif # 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. 'PD_PATH' and 'objectsdir' are supported for compatibility with +# environment. Variable 'objectsdir' is supported for compatibility with # the build system that pd-l2ork has inherited from pd-extended. -PDDIR ?= $(PD_PATH) PDINCLUDEDIR ?= $(pdincludepath) PDBINDIR ?= $(pdbinpath) PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) From 77401282570da724d399b14f80329f8f0a6c2250 Mon Sep 17 00:00:00 2001 From: katjav Date: Wed, 24 Jan 2018 22:50:20 +0100 Subject: [PATCH 067/150] Fix priority for user path variables 'PDDIR' & Co. The order of variable expansion prevented this for the path to binary 'pd.dll'. --- Makefile.pdlibbuilder | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index e7b04a8..cb9add5 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -591,12 +591,9 @@ endif # paths for 32-bit executables on 64-bit Windows aren't yet defined here (TODO) ifeq ($(system), Windows) pkglibdir := $(APPDATA)/Pd - ifndef pdbinpath - pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin") - endif - ifndef pdincludepath - pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src") - endif + pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin") + pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src") + PDBINDIR ?= $(pdbinpath) endif # TODO: decide whether -mms-bitfields should be specified. @@ -613,14 +610,14 @@ ifeq ($(system), Windows) extension = dll c.flags := c.ldflags = -static-libgcc -shared \ - -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" + -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" c.ldlibs := cxx.flags := -fcheck-new cxx.ldflags = -static-libstdc++ -shared \ - -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" + -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" cxx.ldlibs := shared.extension = dll - shared.ldflags = -static-libgcc -shared "$(pdbinpath)/pd.dll" + shared.ldflags = -static-libgcc -shared "$(PDBINDIR)/pd.dll" stripflags = --strip-unneeded -R .note -R .comment endif @@ -634,7 +631,6 @@ endif # the build system that pd-l2ork has inherited from pd-extended. PDINCLUDEDIR ?= $(pdincludepath) -PDBINDIR ?= $(pdbinpath) PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) ifneq ($(PDDIR),) From 1bcf78f86eac9348e8422365b2c39f8c55f69801 Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 27 Jan 2018 00:07:21 +0100 Subject: [PATCH 068/150] Define default paths for 32 bit build on 64 bit Windows --- Makefile.pdlibbuilder | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index cb9add5..fe72833 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -588,11 +588,16 @@ endif # variables are assembled or re-expanded later, great care must be taken to put # quotes at appropriate points throughout the makefile. Thanks, Bill. -# paths for 32-bit executables on 64-bit Windows aren't yet defined here (TODO) +# default paths in Mingw environments ifeq ($(system), Windows) pkglibdir := $(APPDATA)/Pd - pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin") - pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src") + ifeq ($(MINGW_CHOST), i686-w64-mingw32) + programfiles := ${ProgramFiles(x86)} + else + programfiles := $(PROGRAMFILES) + endif + pdbinpath := $(shell ls -d "$(programfiles)/Pd/bin") + pdincludepath := $(shell ls -d "$(programfiles)/Pd/src") PDBINDIR ?= $(pdbinpath) endif From f3887bbe7d7514e2bdf4b9ee80b4044aadcc7d79 Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 27 Jan 2018 12:40:46 +0100 Subject: [PATCH 069/150] Update Windows search path documentation in makefile --- Makefile.pdlibbuilder | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index fe72833..273d07a 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -238,7 +238,13 @@ version = 0.5.0 # # OSX: /Applications/Pd*.app/Contents/Resources/src # -# Windows: %PROGRAMFILES%/pd/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: From 9240b64eba92aaee1e253b38bff728c69a25949f Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 27 Jan 2018 14:10:12 +0100 Subject: [PATCH 070/150] Evaluate 'PDBINDIR' before ld flags So ld flags can be evaluated as immediate variables. Otherwise it was too confusing, hard to understand why it worked at all. --- Makefile.pdlibbuilder | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 273d07a..1a306db 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -604,6 +604,16 @@ ifeq ($(system), Windows) endif pdbinpath := $(shell ls -d "$(programfiles)/Pd/bin") pdincludepath := $(shell ls -d "$(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 @@ -620,15 +630,15 @@ ifeq ($(system), Windows) endif extension = dll c.flags := - c.ldflags = -static-libgcc -shared \ + c.ldflags := -static-libgcc -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" c.ldlibs := cxx.flags := -fcheck-new - cxx.ldflags = -static-libstdc++ -shared \ + cxx.ldflags := -static-libstdc++ -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" cxx.ldlibs := shared.extension = dll - shared.ldflags = -static-libgcc -shared "$(PDBINDIR)/pd.dll" + shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" stripflags = --strip-unneeded -R .note -R .comment endif @@ -644,9 +654,8 @@ endif PDINCLUDEDIR ?= $(pdincludepath) PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) -ifneq ($(PDDIR),) +ifdef PDDIR PDINCLUDEDIR := $(wildcard $(PDDIR)/src) - PDBINDIR := $(wildcard $(PDDIR)/bin) endif # base path where all components of the lib will be installed by default From fe45bcb376ec301dda21adf8f9bf348a485dae70 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 28 Jan 2018 20:58:12 +0100 Subject: [PATCH 071/150] Avoid ls errors when default paths for Pd on Windows do not exist Such error messages are confusing if you do not intend to use default paths. Therefore the probes with ls are removed. Paths to m_pd.h and pd.dll are probed later in the process when they are possibly overriden by user definitions. --- Makefile.pdlibbuilder | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 1a306db..d1af670 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -602,8 +602,8 @@ ifeq ($(system), Windows) else programfiles := $(PROGRAMFILES) endif - pdbinpath := $(shell ls -d "$(programfiles)/Pd/bin") - pdincludepath := $(shell ls -d "$(programfiles)/Pd/src") + pdbinpath := $(programfiles)/Pd/bin + pdincludepath := $(programfiles)/Pd/src endif # Store default path to pd.dll in PDBINDIR if the latter is not user-defined. @@ -747,6 +747,11 @@ 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 + # print Makefile.pdlibbuilder version $(info ++++ info: using Makefile.pdlibbuilder version $(version)) From 3e974fdf2149a971c78c7be1a4efcbe2d7c51f80 Mon Sep 17 00:00:00 2001 From: katjav Date: Wed, 31 Jan 2018 12:41:26 +0100 Subject: [PATCH 072/150] Update makefile comments related to paths --- Makefile.pdlibbuilder | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index d1af670..fbcb713 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -100,7 +100,6 @@ version = 0.5.0 # # Deprecated path variables: # -# - PD_PATH # - pdincludepath # - pdbinpath # - objectsdir @@ -323,7 +322,6 @@ version = 0.5.0 # - decide whether to use -static-libgcc or shared dll in MinGW # - cygwin support # - android support -# - Windows 64 bit support # - figure out how to handle '$' in filenames # - add makefile template targets dpkg-source dist libdir distclean tags? # @@ -589,12 +587,13 @@ endif # 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, and probe for each standard path individually. -# Using double quotes around paths with spaces is obligatory. Since some path -# variables are assembled or re-expanded later, great care must be taken to put -# quotes at appropriate points throughout the makefile. Thanks, Bill. +# 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 environments +# 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 ($(MINGW_CHOST), i686-w64-mingw32) From f1b0e3c7b6588f31287f237a8158555c1da41643 Mon Sep 17 00:00:00 2001 From: katjav Date: Thu, 1 Feb 2018 21:45:54 +0100 Subject: [PATCH 073/150] Add linker option '-static-libgcc' for C++ code on Windows It seems that standard C libs are needed for C++ externals because of 'extern "C"' functions (setup, Pd API). --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index fbcb713..13c4ef0 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -633,7 +633,7 @@ ifeq ($(system), Windows) -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" c.ldlibs := cxx.flags := -fcheck-new - cxx.ldflags := -static-libstdc++ -shared \ + cxx.ldflags := -static-libgcc -static-libstdc++ -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" cxx.ldlibs := shared.extension = dll From 0493d4a1e81fdfc700bc84d2c06a60aaecc60be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 3 Oct 2016 15:49:36 +0200 Subject: [PATCH 074/150] Started a small tips&tricks page with handy commands to achieve specific goals --- tips-tricks.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tips-tricks.md diff --git a/tips-tricks.md b/tips-tricks.md new file mode 100644 index 0000000..a6728c8 --- /dev/null +++ b/tips-tricks.md @@ -0,0 +1,14 @@ +pd-lib-builder cheatsheet +========================= + + +## cross-compiling W32 binaries from linux + +I'm using the following to cross-compile W32 binaries on my Debian/64bit system, +using `mingw-w64`. + +Assuming you have unzipped a W32 package for Pd into `${WINPDPATH}`, run: + + make system=Windows pdbinpath="${WINPDPATH}/bin/" pdincludepath="${WINPDPATH}/src/" CC=i686-w64-mingw32-gcc + +(if the project uses C++, you might also need to sed `CXX=i686-w64-mingw32-g++`) From b2ce5007092fdd48a4435a604d1f8ab2a630d9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 3 Oct 2016 15:56:05 +0200 Subject: [PATCH 075/150] sections and TODOs --- tips-tricks.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tips-tricks.md b/tips-tricks.md index a6728c8..79b27d8 100644 --- a/tips-tricks.md +++ b/tips-tricks.md @@ -1,6 +1,7 @@ pd-lib-builder cheatsheet ========================= +# Creating special builds ## cross-compiling W32 binaries from linux @@ -12,3 +13,10 @@ Assuming you have unzipped a W32 package for Pd into `${WINPDPATH}`, run: make system=Windows pdbinpath="${WINPDPATH}/bin/" pdincludepath="${WINPDPATH}/src/" CC=i686-w64-mingw32-gcc (if the project uses C++, you might also need to sed `CXX=i686-w64-mingw32-g++`) + + +## TODO universal binaries on OSX + + +# Project management +## TODO Keeping pd-lib-builder uptodate From 07c5e784f3d42ce4441d06a0a36433893248195a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Feb 2018 15:46:22 +0100 Subject: [PATCH 076/150] document `git subtree` and `git submodule` with heavy WARNING signs --- tips-tricks.md | 167 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) diff --git a/tips-tricks.md b/tips-tricks.md index 79b27d8..7d1f8a5 100644 --- a/tips-tricks.md +++ b/tips-tricks.md @@ -19,4 +19,169 @@ Assuming you have unzipped a W32 package for Pd into `${WINPDPATH}`, run: # Project management -## TODO Keeping pd-lib-builder uptodate + +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 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 pd-lib-builder +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 pd-lib-builder 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` (below). + +### `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 pd-lib-builder +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 pd-lib-builder 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 +- ... From e9a67fd0d6518aa6b9e9d6d1069c7f1dd74c8645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Feb 2018 15:49:12 +0100 Subject: [PATCH 077/150] use ~~ for strikethrough --- tips-tricks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips-tricks.md b/tips-tricks.md index 7d1f8a5..8700bc8 100644 --- a/tips-tricks.md +++ b/tips-tricks.md @@ -36,7 +36,7 @@ include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder ## Keeping pd-lib-builder up-to-date -### ++`git submodule`++ [DISCOURAGED] +### ~~`git submodule`~~ [DISCOURAGED] #### Initial setup/check-out From e90da163ac8fd7cd0067c96687e171afeeee33ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Feb 2018 15:51:42 +0100 Subject: [PATCH 078/150] Moved git-submodule down the page --- tips-tricks.md | 123 +++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/tips-tricks.md b/tips-tricks.md index 8700bc8..5b4d799 100644 --- a/tips-tricks.md +++ b/tips-tricks.md @@ -36,6 +36,67 @@ 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 pd-lib-builder +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 pd-lib-builder 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] @@ -123,65 +184,5 @@ git submodule update source code. In general, I would suggest to **avoid** `git submodule`, and instead use the -better `git subtree` (below). +better `git subtree` (above). -### `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 pd-lib-builder -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 pd-lib-builder 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 -- ... From fa7f798c54e4a9f9d2b2888823fd8c820af2ba49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Feb 2018 15:52:58 +0100 Subject: [PATCH 079/150] drop "pd-lib-builder" from headings when there's only general advise --- tips-tricks.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tips-tricks.md b/tips-tricks.md index 5b4d799..913abb4 100644 --- a/tips-tricks.md +++ b/tips-tricks.md @@ -73,7 +73,7 @@ Just clone your repository as always: git clone https://git.example.org/pd/superbonk~.git ~~~ -#### Updating pd-lib-builder +#### 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: @@ -82,7 +82,7 @@ To update your local copy to pd-lib-builder's current `master`, simply run: git subtree pull --prefix pd-lib-builder/ https://github.com/pure-data/pd-lib-builder master ~~~ -#### Pulling the updated pd-lib-builder into existing clones +#### Pulling the updated subtree into existing clones Again, nothing special. Just pull as always: @@ -126,7 +126,7 @@ git submodule init git submodule update ~~~ -#### Updating pd-lib-builder +#### 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: @@ -140,7 +140,7 @@ git status pd-lib-builder git commit pd-lib-builder -m "Updated pd-lib-builder to current master" ~~~ -#### Pulling the updated pd-lib-builder into existing clones +#### 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: From 7e47b9878b70da44af8b7f597d316bc0cb0d9121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Feb 2018 16:02:26 +0100 Subject: [PATCH 080/150] how to build double/W64/double+W64 externals --- tips-tricks.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tips-tricks.md b/tips-tricks.md index 913abb4..7c1f1da 100644 --- a/tips-tricks.md +++ b/tips-tricks.md @@ -14,6 +14,29 @@ Assuming you have unzipped a W32 package for Pd into `${WINPDPATH}`, run: (if the project uses C++, you might also need to sed `CXX=i686-w64-mingw32-g++`) +## 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 From b715b0e2caf36430ba0de49e4275d143c1123e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Feb 2018 16:18:37 +0100 Subject: [PATCH 081/150] sed -e's| sed | set |' --- tips-tricks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tips-tricks.md b/tips-tricks.md index 7c1f1da..084f9ef 100644 --- a/tips-tricks.md +++ b/tips-tricks.md @@ -12,7 +12,7 @@ Assuming you have unzipped a W32 package for Pd into `${WINPDPATH}`, run: make system=Windows pdbinpath="${WINPDPATH}/bin/" pdincludepath="${WINPDPATH}/src/" CC=i686-w64-mingw32-gcc -(if the project uses C++, you might also need to sed `CXX=i686-w64-mingw32-g++`) +(if the project uses C++, you might also need to set `CXX=i686-w64-mingw32-g++`) ## building double-precision externals From 1b9f3d8895f92af25d85ae45a2acf57bae443663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Feb 2018 21:45:58 +0100 Subject: [PATCH 082/150] Do wildcard-search for MSYS when checking Windows platform --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 13c4ef0..5ee3935 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -445,7 +445,7 @@ ifeq ($(uname), Darwin) system = Darwin endif -ifeq ($(filter MINGW% MSYS, $(uname)), $(uname)) +ifeq ($(filter MINGW% MSYS%, $(uname)), $(uname)) system = Windows endif From 44a32fd0094364bc31a7574996653cea8eadef09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Feb 2018 16:23:51 +0100 Subject: [PATCH 083/150] fixed small typo --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 5ee3935..ed084d5 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -166,7 +166,7 @@ version = 0.5.0 # 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 overriden with 'make-lib-executable=no' as command argument +# this can still be overridden with 'make-lib-executable=no' as command argument # to build individual class executables (the Makefile.pdlibbuilder default.) # # suppress-wunused: From 6bfaba6df09afdb501e399c643e4782a36f9ca02 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 18 Feb 2018 14:33:11 +0100 Subject: [PATCH 084/150] Introduce target 'install-strip' in the battle against Mingw-w64 bloat It seems that externals built with Mingw-w64 are ~10 times larger than equivalent builds on other platforms (including original Mingw). Stripping is therefore desirable. As suggested by IOhannes Zmoelnig stripping is not done by default, instead this alternative installation target is provided (like in autotools). --- Makefile.pdlibbuilder | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index ed084d5..8849983 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -268,6 +268,7 @@ version = 0.5.0 # .lst: make asm/source output file in current working directory # # install: install executables and data files +# install-strip: install executables (stripped) and data files # clean: remove build products from source tree # # help: print help text @@ -538,7 +539,6 @@ ifeq ($(system), Linux) cxx.ldlibs := -lc -lm -lstdc++ shared.extension = so shared.ldflags := -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) - stripflags = --strip-unneeded -R .note -R .comment endif @@ -566,7 +566,6 @@ ifeq ($(system), Darwin) shared.ldflags = -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(shared.lib) \ -compatibility_version 1 -current_version 1.0 - stripflags = -x version.flag := $(filter $(cflags), -mmacosx-version-min=%) ifeq ($(target.arch), i386) cxx.flags := -fcheck-new @@ -638,7 +637,6 @@ ifeq ($(system), Windows) cxx.ldlibs := shared.extension = dll shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" - stripflags = --strip-unneeded -R .note -R .comment endif @@ -1055,8 +1053,11 @@ endef # -p = preserve time stamps # -m = set permission mode (as in chmod) # -d = create all components of specified directories + +# Use recursive expansion for INSTALL_PROGRAM because variable 'stripflags' is +# not defined yet, it is target-specific for 'install-strip'. INSTALL = install -INSTALL_PROGRAM := $(INSTALL) -p -m 644 +INSTALL_PROGRAM = $(INSTALL) $(stripflags) -p -m 644 INSTALL_DATA := $(INSTALL) -p -m 644 INSTALL_DIR := $(INSTALL) -m 755 -d @@ -1092,6 +1093,13 @@ install-datadirs: all $(info ++++ info: data directories of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) +# definition of strip command must be overridable from environment +STRIP ?= strip + +# install everything while stripping symbols of executables +install-strip: stripflags := --strip-program=$(STRIP) -s +install-strip: install + ################################################################################ ### rules: distribution targets ################################################ From f334dd4e475dedbc98ee3ef31d56312c18536deb Mon Sep 17 00:00:00 2001 From: katjav Date: Mon, 12 Mar 2018 08:47:08 +0100 Subject: [PATCH 085/150] Revert "Introduce target 'install-strip' in the battle against Mingw-w64 bloat" This reverts commit 6bfaba6. Target 'install-strip' wasn't a good idea. A library makefile may want to define a post install target. Makefile.pdlibbuilder should define only one installation target, that can be defined as prerequisite for other targets. A stripping method is still needed, but not this one. --- Makefile.pdlibbuilder | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 8849983..ed084d5 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -268,7 +268,6 @@ version = 0.5.0 # .lst: make asm/source output file in current working directory # # install: install executables and data files -# install-strip: install executables (stripped) and data files # clean: remove build products from source tree # # help: print help text @@ -539,6 +538,7 @@ ifeq ($(system), Linux) cxx.ldlibs := -lc -lm -lstdc++ shared.extension = so shared.ldflags := -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) + stripflags = --strip-unneeded -R .note -R .comment endif @@ -566,6 +566,7 @@ ifeq ($(system), Darwin) shared.ldflags = -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(shared.lib) \ -compatibility_version 1 -current_version 1.0 + stripflags = -x version.flag := $(filter $(cflags), -mmacosx-version-min=%) ifeq ($(target.arch), i386) cxx.flags := -fcheck-new @@ -637,6 +638,7 @@ ifeq ($(system), Windows) cxx.ldlibs := shared.extension = dll shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" + stripflags = --strip-unneeded -R .note -R .comment endif @@ -1053,11 +1055,8 @@ endef # -p = preserve time stamps # -m = set permission mode (as in chmod) # -d = create all components of specified directories - -# Use recursive expansion for INSTALL_PROGRAM because variable 'stripflags' is -# not defined yet, it is target-specific for 'install-strip'. INSTALL = install -INSTALL_PROGRAM = $(INSTALL) $(stripflags) -p -m 644 +INSTALL_PROGRAM := $(INSTALL) -p -m 644 INSTALL_DATA := $(INSTALL) -p -m 644 INSTALL_DIR := $(INSTALL) -m 755 -d @@ -1093,13 +1092,6 @@ install-datadirs: all $(info ++++ info: data directories of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) -# definition of strip command must be overridable from environment -STRIP ?= strip - -# install everything while stripping symbols of executables -install-strip: stripflags := --strip-program=$(STRIP) -s -install-strip: install - ################################################################################ ### rules: distribution targets ################################################ From 397b72eb9e1f30062c6dc053fda3134454eab4c9 Mon Sep 17 00:00:00 2001 From: katjav Date: Mon, 12 Mar 2018 09:34:57 +0100 Subject: [PATCH 086/150] Strip when 'stripflags' is defined (default for Windows only) Stripping of installed binaries for Windows is done by default because their unstripped size is ridiculously large when built with Mingw-w64. This default behavior can still be overriden by defining 'stripflags' empty during install. --- Makefile.pdlibbuilder | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index ed084d5..f5f7edd 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -538,7 +538,6 @@ ifeq ($(system), Linux) cxx.ldlibs := -lc -lm -lstdc++ shared.extension = so shared.ldflags := -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) - stripflags = --strip-unneeded -R .note -R .comment endif @@ -566,7 +565,6 @@ ifeq ($(system), Darwin) shared.ldflags = -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(shared.lib) \ -compatibility_version 1 -current_version 1.0 - stripflags = -x version.flag := $(filter $(cflags), -mmacosx-version-min=%) ifeq ($(target.arch), i386) cxx.flags := -fcheck-new @@ -638,7 +636,7 @@ ifeq ($(system), Windows) cxx.ldlibs := shared.extension = dll shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" - stripflags = --strip-unneeded -R .note -R .comment + stripflags = --strip-all endif @@ -1048,10 +1046,33 @@ endef ################################################################################ +#=== 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 @@ -1077,6 +1098,7 @@ install-executables: all $(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)" From 5b4f636ed80e1c37cb0b73a0a36fe4c0b3faf23b Mon Sep 17 00:00:00 2001 From: katjav Date: Thu, 15 Mar 2018 09:39:11 +0100 Subject: [PATCH 087/150] Document 'STRIP' variable --- Makefile.pdlibbuilder | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index f5f7edd..3ddddfc 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -96,6 +96,7 @@ version = 0.5.0 # - CC # - CXX # - INSTALL +# - STRIP # - DESTDIR # # Deprecated path variables: @@ -212,6 +213,10 @@ version = 0.5.0 # 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 From b19fe37198aed1f848e5a66bc4d5aad9b1a3f2ee Mon Sep 17 00:00:00 2001 From: katjav Date: Thu, 15 Mar 2018 22:04:08 +0100 Subject: [PATCH 088/150] Bump version to 0.5.1 for several Windows fixes --- CHANGELOG.txt | 10 ++++++++++ Makefile.pdlibbuilder | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 41ac0e2..971cf80 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,15 @@ Changelog for Makefile.pdlibbuilder. +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). diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 3ddddfc..f81edfe 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2018-01-23 -version = 0.5.0 +# Makefile.pdlibbuilder dated 2018-03-15 +version = 0.5.1 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. From 9dd4f36886b13ad0efee37a156531b00f54fafdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 30 May 2018 23:34:25 +0200 Subject: [PATCH 089/150] Removed trailing whitespace --- Makefile.pdlibbuilder | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index f81edfe..aa84935 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -450,7 +450,7 @@ ifeq ($(uname), Darwin) system = Darwin endif -ifeq ($(filter MINGW% MSYS%, $(uname)), $(uname)) +ifeq ($(filter MINGW% MSYS%, $(uname)), $(uname)) system = Windows endif @@ -514,11 +514,11 @@ else ifeq ($(target.arch), armv7l) # Intel 32 bit, build with SSE and SSE2 instructions else ifeq ($(findstring $(target.arch), i386 i686), $(target.arch)) arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 - + # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions else ifeq ($(findstring $(target.arch), x86_64), $(target.arch)) arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 - + # if none of the above architectures detected else arch.c.flags = From ece8e6b8b7faa4ace36d495c76dbcd7b9b23374a Mon Sep 17 00:00:00 2001 From: katjav Date: Wed, 1 Aug 2018 10:32:57 +0200 Subject: [PATCH 090/150] Fix omission of flag for minimum OSX version This commit fixes a regression bug introduced with commit 48c4127 for v0.4.1. If minimum OSX version is not specified the compiler will assume the version of the build machine and the build may not be fully compatible with older OSX versions. --- Makefile.pdlibbuilder | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index aa84935..6b4483b 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -574,11 +574,14 @@ ifeq ($(system), Darwin) ifeq ($(target.arch), i386) cxx.flags := -fcheck-new arch := ppc i386 x86_64 - version.flag ?= -mmacosx-version-min=10.4 + version.flag = -mmacosx-version-min=10.4 endif ifeq ($(target.arch), x86_64) arch := i386 x86_64 - version.flag ?= -mmacosx-version-min=10.5 + version.flag = -mmacosx-version-min=10.5 + endif + ifneq ($(filter -mmacosx-version-min=%, $(cflags)),) + version.flag := $(filter -mmacosx-version-min=%, $(cflags)) endif arch.c.flags := $(addprefix -arch , $(arch)) $(version.flag) arch.ld.flags := $(arch.c.flags) From 1137cca2fadffc1fbb8f0086165ab1076d5100ef Mon Sep 17 00:00:00 2001 From: katjav Date: Wed, 20 Mar 2019 13:53:59 +0100 Subject: [PATCH 091/150] Specify minimum OSX version 10.6 instead of 10.5 OSX 10.14.3 can not build for 10.5 and stalls the build. Specifying 10.6 as minimum solves the issue (#49). For building with OSX on i386 architectures, minimum OSX version remains unchanged (10.4). --- Makefile.pdlibbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 6b4483b..a0194b2 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -578,7 +578,7 @@ ifeq ($(system), Darwin) endif ifeq ($(target.arch), x86_64) arch := i386 x86_64 - version.flag = -mmacosx-version-min=10.5 + version.flag = -mmacosx-version-min=10.6 endif ifneq ($(filter -mmacosx-version-min=%, $(cflags)),) version.flag := $(filter -mmacosx-version-min=%, $(cflags)) From 7764061037fc91b7642bbedae1e5ce48c68709f1 Mon Sep 17 00:00:00 2001 From: Miranda Kastemaa Date: Wed, 7 Aug 2019 17:32:49 +0300 Subject: [PATCH 092/150] support conda python --- build/config-mac.def | 13 +++++---- build/gnumake-mac-gcc.inc | 57 ++++++++++++++++++++++++++++----------- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/build/config-mac.def b/build/config-mac.def index 0a59aa9..9fbc4a2 100644 --- a/build/config-mac.def +++ b/build/config-mac.def @@ -1,6 +1,9 @@ -# set PY_DEFAULT=0 if you manually installed Python on your system -# (overriding the one that came with OS X by default) -PY_DEFAULT=1 +# which kind of Python installation to use +# system - macOS system default +# local - local installation +# conda - conda environment; specify the environment root dir using the +# PY_CONDA_ROOT environment variable +PY_KIND=conda ######################################################################### @@ -11,7 +14,7 @@ PY_DEFAULT=1 # Mac OSX 10.6 -> default Python version (major.minor) = 2.6 PY_MAJOR_VERSION=2 -PY_MINOR_VERSION=6 +PY_MINOR_VERSION=7 ######################################################################### @@ -19,7 +22,7 @@ PY_MINOR_VERSION=6 # for info see http://numeric.scipy.org # numarray and numeric are outdated -# PY_NUMPY=1 +PY_NUMPY=1 # PY_NUMARRAY=1 # PY_NUMERIC=1 diff --git a/build/gnumake-mac-gcc.inc b/build/gnumake-mac-gcc.inc index 8806024..34495a4 100644 --- a/build/gnumake-mac-gcc.inc +++ b/build/gnumake-mac-gcc.inc @@ -1,3 +1,41 @@ +DEFS += -DPY_EXPORTS + +ifdef PY_NUMPY +DEFS += -DPY_NUMPY +endif + +ifdef PY_NUMARRAY +DEFS += -DPY_NUMARRAY +endif + +ifdef PY_NUMERIC +DEFS += -DPY_NUMERIC +endif + +ifdef PY_USE_GIL +DEFS += -DPY_USE_GIL +endif + +ifdef PY_USE_INOFFICIAL +DEFS += -DPY_USE_INOFFICIAL +endif + +ifeq ($(PY_KIND),conda) + +ifndef PY_CONDA_ROOT +$(error PY_CONDA_ROOT is undefined) +endif + +LIBS += $(PY_CONDA_ROOT)/lib/libpython$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION).dylib +INCPATH += -I$(PY_CONDA_ROOT)/include +INCPATH += -I$(PY_CONDA_ROOT)/include/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) + +ifdef PY_NUMPY +INCPATH += -I$(PY_CONDA_ROOT)/lib/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include +endif + +else + # don't use -framework Python, since this will stick to the default system version _LOCAL_FRAMEWORK := /Library/Frameworks/Python.framework/Versions/$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) @@ -5,10 +43,9 @@ _SYSTEM_FRAMEWORK := /System/Library/Frameworks/Python.framework/Versions/$(PY_M _LOCAL_LIBRARY := /Library/Python/$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) _SYSTEM_LIBRARY := /System/Library/Python/$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) -DEFS += -DPY_EXPORTS INCPATH += -F/Library/Frameworks -framework Python -ifeq ($(PY_DEFAULT),1) +ifeq ($(PY_KIND),system) LIBS += $(_SYSTEM_FRAMEWORK)/Python INCPATH += -I$(_SYSTEM_FRAMEWORK)/Headers else @@ -16,27 +53,15 @@ LIBS += $(_LOCAL_FRAMEWORK)/Python INCPATH += -I$(_LOCAL_FRAMEWORK)/Headers endif -ifdef PY_NUMARRAY -DEFS += -DPY_NUMARRAY -endif ifdef PY_NUMPY -DEFS += -DPY_NUMPY INCPATH += -I$(_LOCAL_LIBRARY)/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include -ifeq ($(PY_DEFAULT),1) + +ifeq ($(PY_KIND),system) INCPATH += -I$(_SYSTEM_FRAMEWORK)/lib/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include INCPATH += -I$(_SYSTEM_FRAMEWORK)/Extras/lib/python/numpy/core/include else INCPATH += -I$(_LOCAL_FRAMEWORK)/lib/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include endif endif -ifdef PY_NUMERIC -DEFS += -DPY_NUMERIC -endif -ifdef PY_USE_GIL -DEFS += -DPY_USE_GIL -endif - -ifdef PY_USE_INOFFICIAL -DEFS += -DPY_USE_INOFFICIAL endif From 21e3b3271f7c6a3e4f65660512b04aa2216a3dbc Mon Sep 17 00:00:00 2001 From: Miranda Kastemaa Date: Thu, 8 Aug 2019 14:55:42 +0300 Subject: [PATCH 093/150] add conda lib dir to rpath --- build/gnumake-mac-gcc.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/build/gnumake-mac-gcc.inc b/build/gnumake-mac-gcc.inc index 34495a4..d93ae5f 100644 --- a/build/gnumake-mac-gcc.inc +++ b/build/gnumake-mac-gcc.inc @@ -29,6 +29,7 @@ endif LIBS += $(PY_CONDA_ROOT)/lib/libpython$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION).dylib INCPATH += -I$(PY_CONDA_ROOT)/include INCPATH += -I$(PY_CONDA_ROOT)/include/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) +LDFLAGS += -rpath $(PY_CONDA_ROOT)/lib ifdef PY_NUMPY INCPATH += -I$(PY_CONDA_ROOT)/lib/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include From ac328cdcd85b9fb5ed93ca5bb7427702ca90dc94 Mon Sep 17 00:00:00 2001 From: Miranda Kastemaa Date: Wed, 14 Aug 2019 17:15:32 +0300 Subject: [PATCH 094/150] add dummy StdOut_Flush() method to make absl logging happy --- source/pybase.cpp | 7 +++++++ source/pybase.h | 1 + 2 files changed, 8 insertions(+) diff --git a/source/pybase.cpp b/source/pybase.cpp index 826e6a4..cb3ea97 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -18,6 +18,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. static PyMethodDef StdOut_Methods[] = { { "write", pybase::StdOut_Write, 1 }, + { "flush", pybase::StdOut_Flush, 1 }, { NULL, NULL, } }; @@ -776,6 +777,12 @@ PyObject* pybase::StdOut_Write(PyObject* self, PyObject* args) return Py_None; } +// dummy flush method, since some logging libraries call this +PyObject* pybase::StdOut_Flush(PyObject* self, PyObject* args) +{ + Py_INCREF(Py_None); + return Py_None; +} class work_data { diff --git a/source/pybase.h b/source/pybase.h index 8a3105e..cfda6bf 100644 --- a/source/pybase.h +++ b/source/pybase.h @@ -269,6 +269,7 @@ class pybase }; static PyObject* StdOut_Write(PyObject* Self, PyObject* Args); + static PyObject* StdOut_Flush(PyObject* Self, PyObject* Args); }; #endif From 1f7e520e4147e1c9cbfe480f669b563f4d0a566a Mon Sep 17 00:00:00 2001 From: Miranda Kastemaa Date: Fri, 16 Aug 2019 11:03:20 +0300 Subject: [PATCH 095/150] call Py_SetProgramName() when building for conda env --- build/gnumake-mac-gcc.inc | 1 + source/pybase.cpp | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/build/gnumake-mac-gcc.inc b/build/gnumake-mac-gcc.inc index d93ae5f..bc2ec27 100644 --- a/build/gnumake-mac-gcc.inc +++ b/build/gnumake-mac-gcc.inc @@ -26,6 +26,7 @@ ifndef PY_CONDA_ROOT $(error PY_CONDA_ROOT is undefined) endif +DEFS += -DPY_INTERPRETER=$(PY_CONDA_ROOT)/bin/python LIBS += $(PY_CONDA_ROOT)/lib/libpython$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION).dylib INCPATH += -I$(PY_CONDA_ROOT)/include INCPATH += -I$(PY_CONDA_ROOT)/include/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) diff --git a/source/pybase.cpp b/source/pybase.cpp index cb3ea97..6694d3e 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -15,6 +15,9 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include #endif +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + static PyMethodDef StdOut_Methods[] = { { "write", pybase::StdOut_Write, 1 }, @@ -99,8 +102,17 @@ void initsymbol(); void initsamplebuffer(); void initbundle(); + + void pybase::lib_setup() -{ +{ +#ifdef PY_INTERPRETER + { + static char py_program_name[] = TOSTRING(PY_INTERPRETER); + Py_SetProgramName(py_program_name); + } +#endif + post(""); post("------------------------------------------------"); post("py/pyext %s - python script objects",PY__VERSION); From 8308d8af67fc53a02427dcac9e7209eae5962b7e Mon Sep 17 00:00:00 2001 From: Miranda Kastemaa Date: Tue, 27 Aug 2019 16:52:00 +0300 Subject: [PATCH 096/150] don't include when using conda --- build/gnumake-mac-gcc.inc | 2 ++ source/pybuffer.h | 2 +- source/pybundle.h | 2 +- source/pyprefix.h | 2 +- source/pysymbol.h | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/build/gnumake-mac-gcc.inc b/build/gnumake-mac-gcc.inc index bc2ec27..1ebf47a 100644 --- a/build/gnumake-mac-gcc.inc +++ b/build/gnumake-mac-gcc.inc @@ -38,6 +38,8 @@ endif else +DEFS += -DPY_USE_FRAMEWORK + # don't use -framework Python, since this will stick to the default system version _LOCAL_FRAMEWORK := /Library/Frameworks/Python.framework/Versions/$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) diff --git a/source/pybuffer.h b/source/pybuffer.h index 5869d13..d7ad071 100644 --- a/source/pybuffer.h +++ b/source/pybuffer.h @@ -15,7 +15,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #error You need at least flext version 0.5.0 #endif -#if FLEXT_OS == FLEXT_OS_MAC +#ifdef PY_USE_FRAMEWORK #include #else #include diff --git a/source/pybundle.h b/source/pybundle.h index b397ffb..f862235 100644 --- a/source/pybundle.h +++ b/source/pybundle.h @@ -15,7 +15,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #error You need at least flext version 0.5.0 #endif -#if FLEXT_OS == FLEXT_OS_MAC +#ifdef PY_USE_FRAMEWORK #include #else #include diff --git a/source/pyprefix.h b/source/pyprefix.h index 8b242a4..e9a624c 100644 --- a/source/pyprefix.h +++ b/source/pyprefix.h @@ -16,7 +16,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. // otherwise some functions don't get defined #include -#if FLEXT_OS == FLEXT_OS_MAC +#ifdef PY_USE_FRAMEWORK #include #else #include diff --git a/source/pysymbol.h b/source/pysymbol.h index 0febfde..0b66138 100644 --- a/source/pysymbol.h +++ b/source/pysymbol.h @@ -15,7 +15,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #error You need at least flext version 0.5.0 #endif -#if FLEXT_OS == FLEXT_OS_MAC +#ifdef PY_USE_FRAMEWORK #include #else #include From 0c800aa49caa840650791073e7183b85859afa6d Mon Sep 17 00:00:00 2001 From: Miranda Kastemaa Date: Tue, 27 Aug 2019 16:57:00 +0300 Subject: [PATCH 097/150] more conda fixing --- source/pybuffer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index 4690381..81bb456 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -18,7 +18,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #ifdef PY_ARRAYS #ifdef PY_NUMARRAY -# if FLEXT_OS == FLEXT_OS_MAC +# ifdef PY_USE_FRAMEWORK # include # else # include @@ -31,7 +31,7 @@ inline bool arrsupport() { return numtype != tAny; } # if defined(PY_NUMPY) # include # else -# if FLEXT_OS == FLEXT_OS_MAC +# ifdef PY_USE_FRAMEWORK # include # else # include @@ -60,7 +60,7 @@ PyObject *pybase::py_arraysupport(PyObject *self,PyObject *args) // PD defines a T_OBJECT symbol #undef T_OBJECT -#if FLEXT_OS == FLEXT_OS_MAC +#ifdef PY_USE_FRAMEWORK #include "Python/bufferobject.h" #include "Python/structmember.h" #else From 6d47a2223d4b40951a221712ce16b69fa2a08a03 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Mon, 25 Nov 2019 00:10:17 +0100 Subject: [PATCH 098/150] Fixed argument type --- source/pybase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/pybase.cpp b/source/pybase.cpp index 826e6a4..f6a4b3f 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -483,7 +483,7 @@ static bool getmodulesub(const char *mod,char *dir,int len,const char *ext) return name != NULL; #elif FLEXT_SYS == FLEXT_SYS_MAX short path; - long type; + unsigned int type; char smod[1024]; strcpy(smod,mod); strcat(smod,ext); From 1dc4219bcb3ee359e5385cef84782e9a2eb89fb9 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 13:55:32 +0100 Subject: [PATCH 099/150] Detect target platform consistently with $(CC) -dumpmachine We already used this for Windows, now use it for all platforms to simplify cross compilation in general. --- Makefile.pdlibbuilder | 65 ++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index a0194b2..ab732f1 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -430,38 +430,33 @@ endif ################################################################################ -### platform detection ######################################################### +### target platform detection ################################################## ################################################################################ +# 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. -uname := $(shell uname) - -ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname)) +ifneq ($(filter linux gnu% kfreebsd, $(target.triplet)),) system = Linux endif -ifeq ($(uname), Darwin) +ifneq ($(filter darwin%, $(target.triplet)),) system = Darwin endif -ifeq ($(filter MINGW% MSYS%, $(uname)), $(uname)) +ifneq ($(filter mingw% cygwin%, $(target.triplet)),) system = Windows endif -# Unfortunately not all Mingw versions provide a link cc > gcc, therefore -# gcc is hardcoded here (but not if CC is redefined). -ifeq ($(system), Windows) - ifeq ($(origin CC), default) - CC = gcc - endif -endif - # evaluate possible system-specific multiline defines from library makefile $(eval $(for$(system))) @@ -472,24 +467,13 @@ $(eval $(for$(system))) #=== architecture ============================================================== -# native architecture of the build machine -build.arch := $(shell uname -m) +# 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 architecture as reported by compiler. Give precedence to eventual -# user-defined compiler. The first field of -- is extracted. -ifneq ($(origin CXX), default) - dumpmachine.cpu = $(firstword $(subst -, ,$(shell $(CXX) -dumpmachine))) -else - dumpmachine.cpu = $(firstword $(subst -, ,$(shell $(CC) -dumpmachine))) -endif - -# Target architecture as reported by compiler is only used for Windows at the -# moment. For other systems this still has to be tested. -ifeq ($(system), Windows) - target.arch = $(dumpmachine.cpu) -else - target.arch = $(build.arch) -endif +target.arch := $(firstword $(target.triplet)) ################################################################################ @@ -501,22 +485,27 @@ endif # Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, -# arch.c.flags are overriden below. +# arch.c.flags are overriden below. To see gcc's default architecture flags: +# $ gcc -Q --help=target -# Raspberry Pi 1st generation -ifeq ($(target.arch), armv6l) +# ARMv6: Raspberry Pi 1st gen, not detectable from target.arch +ifeq ($(shell uname), armv6l) arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard -# Beagle, Udoo, RPi2 etc. -else ifeq ($(target.arch), armv7l) +# 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 ifeq ($(findstring $(target.arch), i386 i686), $(target.arch)) +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 ($(findstring $(target.arch), x86_64), $(target.arch)) +else ifeq ($(target.arch), x86_64) arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 # if none of the above architectures detected From a140d2165deb94630a980492a375240a610e4bba Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 15:09:04 +0100 Subject: [PATCH 100/150] Terminate if target triplet remained empty --- Makefile.pdlibbuilder | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index ab732f1..4daae0a 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -720,6 +720,18 @@ compile-cxx := $(CXX) # 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: @@ -746,9 +758,6 @@ ifeq ($(system), Windows) pddll := $(shell ls "$(PDBINDIR)/pd.dll") endif -# print Makefile.pdlibbuilder version -$(info ++++ info: using Makefile.pdlibbuilder version $(version)) - # when making target all, check if m_pd.h is found and print info about it ifeq ($(goals), all) $(if $(mpdh), \ From e13255de2429c0b78ac13089ae0fb1e72838fea7 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 15:19:16 +0100 Subject: [PATCH 101/150] Test target arch more consistently on Windows --- Makefile.pdlibbuilder | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 4daae0a..c881853 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -591,7 +591,7 @@ endif # required because of parentheses in variable name. ifeq ($(system), Windows) pkglibdir := $(APPDATA)/Pd - ifeq ($(MINGW_CHOST), i686-w64-mingw32) + ifeq ($(target.arch), i686) programfiles := ${ProgramFiles(x86)} else programfiles := $(PROGRAMFILES) @@ -614,9 +614,9 @@ endif # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) cpp.flags := -DMSW -DNT - ifeq ($(filter i%86 mingw32, $(target.arch)), $(target.arch)) + ifeq ($(target.arch), i686) arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse - else ifeq (x86_64, $(target.arch)) + else ifeq ($(target.arch), x86_64) cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 arch.c.flags := -march=core2 -msse -msse2 -msse3 -mfpmath=sse else From 53caa9ca78e83c8430de3b8b8a6514aee5050c20 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 15:31:26 +0100 Subject: [PATCH 102/150] Change test to see whether -fcheck-new must be used on Darwin --- Makefile.pdlibbuilder | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index c881853..6539fc4 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -540,8 +540,8 @@ endif # On OSX we try to build fat binaries by default. It is assumed that OSX i386 # can build for ppc and OSX x86_64 can't. TODO: try to refine this condition. -# LLVM-clang doesn't support -fcheck-new, therefore this flag is omitted for -# OSX x86_64. +# LLVM-clang doesn't support -fcheck-new, therefore this flag is only used when +# compiling with g++. ifeq ($(system), Darwin) @@ -559,9 +559,11 @@ ifeq ($(system), Darwin) 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 version.flag := $(filter $(cflags), -mmacosx-version-min=%) ifeq ($(target.arch), i386) - cxx.flags := -fcheck-new arch := ppc i386 x86_64 version.flag = -mmacosx-version-min=10.4 endif From 2cfb2714a81c1851521e012e0479278564eca1f0 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 16:31:21 +0100 Subject: [PATCH 103/150] For Darwin do not build fat binaries by default Now that we detect target arch rather than build arch it seems even less consistent than before to build fat binaries by default. --- Makefile.pdlibbuilder | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 6539fc4..32ac8ee 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -538,12 +538,9 @@ endif #=== flags and paths for Darwin ================================================ -# On OSX we try to build fat binaries by default. It is assumed that OSX i386 -# can build for ppc and OSX x86_64 can't. TODO: try to refine this condition. # 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 \ @@ -563,12 +560,11 @@ ifeq ($(system), Darwin) cxx.flags := -fcheck-new endif version.flag := $(filter $(cflags), -mmacosx-version-min=%) + arch := $(target.arch) ifeq ($(target.arch), i386) - arch := ppc i386 x86_64 version.flag = -mmacosx-version-min=10.4 endif ifeq ($(target.arch), x86_64) - arch := i386 x86_64 version.flag = -mmacosx-version-min=10.6 endif ifneq ($(filter -mmacosx-version-min=%, $(cflags)),) From 69e2002ac856626581789e34c5e7475d6c6aee4f Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 21:08:38 +0100 Subject: [PATCH 104/150] Reorganize definition of -mmacosx-version-min Minimum version 10.4 was previously set for fat binaries built on i386. Since fat-by-default is dropped, minimum version can simply be 10.6 if not specified otherwise in cflags. --- Makefile.pdlibbuilder | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 32ac8ee..56cf441 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -559,16 +559,11 @@ ifeq ($(system), Darwin) ifneq ($(filter %g++, $(CXX)),) cxx.flags := -fcheck-new endif - version.flag := $(filter $(cflags), -mmacosx-version-min=%) arch := $(target.arch) - ifeq ($(target.arch), i386) - version.flag = -mmacosx-version-min=10.4 - endif - ifeq ($(target.arch), x86_64) - version.flag = -mmacosx-version-min=10.6 - 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) From 65e9fc78d7570b8b6ca83a8718a82ac616b72ccd Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 21:30:00 +0100 Subject: [PATCH 105/150] For Darwin build fat binaries when extension=d_fat This gives a convenient and logical approach to still build fat binaries. Only ppc is left out in the cold. --- Makefile.pdlibbuilder | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 56cf441..b9ae1a0 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -559,7 +559,11 @@ ifeq ($(system), Darwin) ifneq ($(filter %g++, $(CXX)),) cxx.flags := -fcheck-new endif - arch := $(target.arch) + 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 From 262143b66d4cf4949b1f925c5500539619ec8446 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 21:40:05 +0100 Subject: [PATCH 106/150] Introduce optional user variable 'PLATFORM' for cross compilation --- Makefile.pdlibbuilder | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index b9ae1a0..73e11ba 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -434,6 +434,28 @@ endif ################################################################################ +#=== 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)) From f2a5b6614cb6ae9231326f4d44a9508af46d27b1 Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 15 Dec 2019 21:47:41 +0100 Subject: [PATCH 107/150] Add target 'dumpmachine' for verification purposes --- Makefile.pdlibbuilder | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index 73e11ba..dbdf120 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1297,6 +1297,16 @@ help: @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 ============================================================== From 099353552e755ca55b819e84140edf97b272641a Mon Sep 17 00:00:00 2001 From: katjav Date: Fri, 20 Dec 2019 23:25:55 +0100 Subject: [PATCH 108/150] Add description of variable 'PLATFORM'and target 'dumpmachine' --- Makefile.pdlibbuilder | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index dbdf120..abcf562 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -99,6 +99,10 @@ version = 0.5.1 # - STRIP # - DESTDIR # +# Optional user variables for make command line or environment: +# +# - PLATFORM +# # Deprecated path variables: # # - pdincludepath @@ -194,6 +198,13 @@ version = 0.5.1 # 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. # @@ -279,6 +290,7 @@ version = 0.5.1 # 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, From db2bcddcb0d28812bda3d5ad83e6198a888f2594 Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 21 Dec 2019 14:04:49 +0100 Subject: [PATCH 109/150] Update version to 0.6.0 after merging 'target-detection' --- Makefile.pdlibbuilder | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder index abcf562..7d6c11c 100644 --- a/Makefile.pdlibbuilder +++ b/Makefile.pdlibbuilder @@ -1,5 +1,5 @@ -# Makefile.pdlibbuilder dated 2018-03-15 -version = 0.5.1 +# 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. From 8a27ffc4bdeadac5cc0d01fb8dca0f845e57bcc6 Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 21 Dec 2019 15:10:13 +0100 Subject: [PATCH 110/150] Update CHANGELOG.txt for version 0.6.0 --- CHANGELOG.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 971cf80..5bdfce6 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,12 @@ 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 @@ -32,7 +39,7 @@ 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 +Introduced path variables PDDIR, PDINCLUDEDIR, PDBINDIR, PDLIBDIR which can also be defined in environment. (feature, issue #27, commit b0dab72) From 2d3b7f4835f2c2052ae83797d926daecb07456e9 Mon Sep 17 00:00:00 2001 From: katjav Date: Sat, 21 Dec 2019 21:59:15 +0100 Subject: [PATCH 111/150] Update section about cross-compiling in tips-tricks.md --- tips-tricks.md | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tips-tricks.md b/tips-tricks.md index 084f9ef..c1795f4 100644 --- a/tips-tricks.md +++ b/tips-tricks.md @@ -3,16 +3,35 @@ pd-lib-builder cheatsheet # Creating special builds -## cross-compiling W32 binaries from linux +## cross-compiling on linux x86_64 for other platforms -I'm using the following to cross-compile W32 binaries on my Debian/64bit system, -using `mingw-w64`. +Using pd-lib-builder >=0.6.0 we can define variable `PLATFORM` to specify a +target triplet for cross-compilation. Example to build W32 binaries (assuming +package `mingw-w64` is installed and a W32 package for Pd is unzipped into a +path `${PDWIN32}`: -Assuming you have unzipped a W32 package for Pd into `${WINPDPATH}`, run: + make PLATFORM=x86_64-w64-mingw32 PDDIR="${PDWIN32}" - make system=Windows pdbinpath="${WINPDPATH}/bin/" pdincludepath="${WINPDPATH}/src/" CC=i686-w64-mingw32-gcc +#### older pd-lib-builder versions -(if the project uses C++, you might also need to set `CXX=i686-w64-mingw32-g++`) +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 + +Cross toolchains for relevant platforms in Debian Buster (install g++ +with dependencies for a given platform to get the whole tool chain): + +- `arm-linux-gnueabihf` +- `aarch64-linux-gnu` +- `i686-linux-gnu` +- `i686-w64-mingw32` and `x86_64-w64-mingw32` (install `mingw-w64`) + +OSX/MacOS cross tool chains are not distributed by Debian. Use project +`osxcross` from Thomas Poechtraeger to create the tools. ## building double-precision externals From d187d4792978ceb4bcc8e68bd347f13fca24f11c Mon Sep 17 00:00:00 2001 From: katjav Date: Sun, 22 Dec 2019 14:18:40 +0100 Subject: [PATCH 112/150] Update README.txt, mainly to list more projects --- README.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 75e070e..187b132 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,10 @@ ### Makefile.pdlibbuilder ### -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. +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. @@ -13,7 +13,7 @@ GNU make version >= 3.81 required. ### characteristics ### -* defines build settings based on autodetected OS and architecture +* 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 @@ -52,7 +52,7 @@ 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 +Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. PDINCLUDEDIR: @@ -74,7 +74,8 @@ default install location. 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. A tips&tricks page is in the works. +of the particular version. For suggestions about project maintenance and +advanced compilation see tips-tricks.md. ### versioning ### @@ -82,32 +83,80 @@ of the particular version. A tips&tricks page is in the works. 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 +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. -Here are a few projects using the Makefile.pdlibbuilder approach: +- 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-cyclone (stable) +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://github.com/porres/pd-cyclone (experimental) +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 -More examples will be referenced here when they are available. +https://github.com/libpd/abl_link + +https://github.com/wbrent/timbreID + +https://github.com/MetaluNet/moonlib + + From 7d70890007645610115c929f1cfeeb7695365aba Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Thu, 5 Mar 2020 13:39:37 +0100 Subject: [PATCH 113/150] const str --- source/pybase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/pybase.cpp b/source/pybase.cpp index f6a4b3f..7311a5a 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -398,7 +398,7 @@ void pybase::OpenEditor() #else // thanks to Tim Blechmann - char *editor = getenv("EDITOR"); + const char *editor = getenv("EDITOR"); if(!editor) { // || !strcmp(editor, "/usr/bin/nano") || !strcmp(editor, "/usr/bin/pico") || !strcmp(editor, "/usr/bin/vi")) { // no environment variable or console text editor found ... use idle instead (should have come with Python) From 8c92c66bb869fb6d410028553eec91f0f492c73a Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Thu, 5 Mar 2020 13:45:04 +0100 Subject: [PATCH 114/150] Use pd-lib-builder for compilation --- Makefile | 12 ++++++++++++ readme.txt | 20 +++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0a5cea5 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +NAME=py +cflags=-DFLEXT_INLINE -DFLEXT_ATTRIBUTES=1 + +# source files +$(NAME).class.sources = $(wildcard source/*.cpp) + +# help files +datafiles = $(wildcard pd/*.pd scripts/*.py) + +# include Makefile.pdlibbuilder from submodule directory 'pd-lib-builder' +PDLIBBUILDER_DIR=./pd-lib-builder/ +include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder diff --git a/readme.txt b/readme.txt index 75d3f73..fa2d42a 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ py/pyext - python script objects for PD and Max/MSP -Copyright ©2002-2012 Thomas Grill (gr@grrrr.org) +Copyright (c)2002-2020 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. @@ -57,8 +57,22 @@ BUILDING from source You will need the flext C++ layer for PD and Max/MSP externals to compile this. See http://grrrr.org/ext/flext -Download, install and compile the package. -Afterwards you can proceed with building this external. +Download and unzip, or git-clone the package. + + +Pure data - any platform supporting gcc-compatible compilers +------------------------------------------------------------ + +The pd-lib-builder project (https://github.com/pure-data/pd-lib-builder) is used to compile the project. +A git subtree of this project is already present. + +The compilation is done using the GNU make tool and it will need additional information about the location of the flext source files, and possibly, Pure data, if a specific version should be used. + +This could be an example: +make CPPFLAGS="-I ../flext/source" PDDIR="../../pure-data" + +For OS X, further flags can be needed: +CFLAGS="-mmacosx-version-min=10.9" LDFLAGS="-mmacosx-version-min=10.9" pd/Max - Windows - Microsoft Visual C, Borland C++, MinGW: From 5488e405f7ac57942eac79a4c9eb00dcc14d56d6 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Thu, 5 Mar 2020 22:30:12 +0000 Subject: [PATCH 115/150] Fix float type --- source/modmeth.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/modmeth.cpp b/source/modmeth.cpp index 7d7497a..2a35b07 100644 --- a/source/modmeth.cpp +++ b/source/modmeth.cpp @@ -235,10 +235,10 @@ PyObject *pybase::py_getvalue(PyObject *self,PyObject *args) PyObject *ret; if( - sz == 1 && + sz == 1 && (sym = pyObject_AsSymbol(PyTuple_GET_ITEM(args,0))) != NULL ) { - float f; + t_float f; if(value_getfloat(const_cast(sym),&f)) { post("py/pyext - Could not get value '%s'",GetString(sym)); Py_INCREF(Py_None); From c0b374ee1e672ef2c14039bdc62cad5f64a95e1b Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 10 Mar 2020 13:23:07 +0200 Subject: [PATCH 116/150] python 3 compatibility fixes --- source/bound.cpp | 4 +- source/clmeth.cpp | 9 +- source/pybase.cpp | 79 +++++++++++++++- source/pybuffer.cpp | 217 +++++++++++++++++++++++++------------------- source/pybundle.cpp | 5 +- source/pydsp.cpp | 20 +++- source/pyext.cpp | 7 +- source/pyext.h | 2 +- source/pymeth.cpp | 4 + source/pysymbol.cpp | 76 ++++++++-------- 10 files changed, 276 insertions(+), 147 deletions(-) diff --git a/source/bound.cpp b/source/bound.cpp index 419760e..01cf681 100644 --- a/source/bound.cpp +++ b/source/bound.cpp @@ -86,7 +86,7 @@ PyObject *pyext::pyext_bind(PyObject *,PyObject *args) PyObject *self,*meth,*name; if(!PyArg_ParseTuple(args, "OOO:pyext_bind", &self,&name,&meth)) // borrowed references post("py/pyext - Wrong arguments!"); - else if(!PyInstance_Check(self) || !PyCallable_Check(meth)) { + else if(!PyCallable_Check(meth)) { post("py/pyext - Wrong argument types!"); } else { @@ -131,7 +131,7 @@ PyObject *pyext::pyext_unbind(PyObject *,PyObject *args) PyObject *self,*meth,*name; if(!PyArg_ParseTuple(args, "OOO:pyext_bind", &self,&name,&meth)) // borrowed references post("py/pyext - Wrong arguments!"); - else if(!PyInstance_Check(self) || !PyCallable_Check(meth)) { + else if(!PyCallable_Check(meth)) { post("py/pyext - Wrong argument types!"); } else { diff --git a/source/clmeth.cpp b/source/clmeth.cpp index a7e6d8d..340dcc4 100644 --- a/source/clmeth.cpp +++ b/source/clmeth.cpp @@ -114,10 +114,7 @@ PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) } */ if(!handled) { - if(PyInstance_Check(self)) - PyDict_SetItem(((PyInstanceObject *)self)->in_dict, name,val); - else - ERRINTERNAL(); + PyDict_SetItem(self, name, val); } Py_INCREF(Py_None); @@ -192,7 +189,7 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) if( sz >= 2 && - (self = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(self) && + (self = PyTuple_GET_ITEM(args,0)) != NULL && (outl = PyTuple_GET_ITEM(args,1)) != NULL && #if PY_MAJOR_VERSION < 3 PyInt_Check(outl) @@ -333,7 +330,7 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) PyObject *self; // borrowed ref if( sz >= 1 && - (self = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(self) + (self = PyTuple_GET_ITEM(args,0)) != NULL ) { pyext *ext = GetThis(self); if(!ext) { diff --git a/source/pybase.cpp b/source/pybase.cpp index 9d887fa..41fa70a 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -17,6 +17,8 @@ WARRANTIES, see the file, "license.txt," in this distribution. #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) +#define WSTRINGIFY(x) L ## #x +#define TOWSTRING(x) WSTRINGIFY(x) static PyMethodDef StdOut_Methods[] = { @@ -108,7 +110,11 @@ void pybase::lib_setup() { #ifdef PY_INTERPRETER { +#if PY_MAJOR_VERSION < 3 static char py_program_name[] = TOSTRING(PY_INTERPRETER); +#else + static wchar_t py_program_name[] = TOWSTRING(PY_INTERPRETER); +#endif Py_SetProgramName(py_program_name); } #endif @@ -163,20 +169,70 @@ void pybase::lib_setup() #endif // sys.argv must be set to empty tuple +#if PY_MAJOR_VERSION < 3 const char *nothing = ""; PySys_SetArgv(0,const_cast(¬hing)); +#else + const wchar_t *nothing = L""; + PySys_SetArgv(0,const_cast(¬hing)); +#endif // register/initialize pyext module only once! +#if PY_MAJOR_VERSION < 3 module_obj = Py_InitModule(const_cast(PYEXT_MODULE), func_tbl); +#else + struct PyModuleDef pyext_module_def = { + PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base + PYEXT_MODULE, // const char *m_name + py_doc, // const char *m_doc + -1, // Py_ssize_t m_size + func_tbl, // PyMethodDef *m_methods + NULL, // PyModuleDef_Slot *m_slots + NULL, // traverseproc m_traverse + NULL, // inquiry m_clear + NULL // freefunc m_free + }; + module_obj = PyModule_Create(&pyext_module_def); +#endif module_dict = PyModule_GetDict(module_obj); // borrowed reference PyModule_AddStringConstant(module_obj,"__doc__",(char *)py_doc); // redirect stdout PyObject* py_out; +#if PY_MAJOR_VERSION < 3 py_out = Py_InitModule(const_cast("stdout"), StdOut_Methods); +#else + struct PyModuleDef stdout_module_def = { + PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base + "stdout", // const char *m_name + "", // const char *m_doc + -1, // Py_ssize_t m_size + func_tbl, // PyMethodDef *m_methods + NULL, // PyModuleDef_Slot *m_slots + NULL, // traverseproc m_traverse + NULL, // inquiry m_clear + NULL // freefunc m_free + }; + py_out = PyModule_Create(&stdout_module_def); +#endif PySys_SetObject(const_cast("stdout"), py_out); +#if PY_MAJOR_VERSION < 3 py_out = Py_InitModule(const_cast("stderr"), StdOut_Methods); +#else + struct PyModuleDef stderr_module_def = { + PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base + "stderr", // const char *m_name + "", // const char *m_doc + -1, // Py_ssize_t m_size + func_tbl, // PyMethodDef *m_methods + NULL, // PyModuleDef_Slot *m_slots + NULL, // traverseproc m_traverse + NULL, // inquiry m_clear + NULL // freefunc m_free + }; + py_out = PyModule_Create(&stdout_module_def); +#endif PySys_SetObject(const_cast("stderr"), py_out); // get garbage collector function @@ -445,13 +501,32 @@ void pybase::SetArgs() // script arguments int argc = args.Count(); const t_atom *argv = args.Atoms(); +#if PY_MAJOR_VERSION < 3 char **sargv = new char *[argc+1]; +#else + wchar_t **sargv = new wchar_t *[argc+1]; +#endif for(int i = 0; i <= argc; ++i) { +#if PY_MAJOR_VERSION < 3 sargv[i] = new char[256]; - if(!i) +#else + sargv[i] = new wchar_t[256]; +#endif + if(!i) { +#if PY_MAJOR_VERSION < 3 strcpy(sargv[i],"py/pyext"); - else +#else + wcscpy(sargv[i],L"py/pyext"); +#endif + } else { +#if PY_MAJOR_VERSION < 3 GetAString(argv[i-1],sargv[i],255); +#else + char *arg = new char[256]; + GetAString(argv[i-1],arg,255); + mbstowcs(sargv[i],arg,255); +#endif + } } // the arguments to the module are only recognized once! (at first use in a patcher) diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index b4c9222..6892d03 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -61,10 +61,8 @@ PyObject *pybase::py_arraysupport(PyObject *self,PyObject *args) #undef T_OBJECT #ifdef PY_USE_FRAMEWORK -#include "Python/bufferobject.h" #include "Python/structmember.h" #else -#include "bufferobject.h" #include "structmember.h" #endif @@ -168,7 +166,8 @@ static PyObject *buffer_dirty(PyObject *obj) static PyObject *buffer_resize(PyObject *obj,PyObject *args,PyObject *kwds) { - flext::buffer *b = ((pySamplebuffer *)obj)->buf; + pySamplebuffer *self = reinterpret_cast(obj); + flext::buffer *b = self->buf; if(b) { int frames,keep = 1,zero = 1; static char const *kwlist[] = {"frames", "keep", "zero", NULL}; @@ -192,47 +191,63 @@ static PyMethodDef buffer_methods[] = { {NULL} /* Sentinel */ }; +// support the buffer protocol +static int buffer_getbuffer(PyObject *obj, Py_buffer *view, int flags) { + if(flags & PyBUF_INDIRECT) { + PyErr_SetString(PyExc_BufferError, "PyBUF_INDIRECT not supported"); + view->obj = NULL; + return -1; + } -// support the buffer protocol + if(flags & PyBUF_STRIDES) { + PyErr_SetString(PyExc_BufferError, "PyBUF_STRIDES not supported"); + view->obj = NULL; + return -1; + } -static Py_ssize_t buffer_readbuffer(PyObject *obj, Py_ssize_t segment, void **ptrptr) -{ - flext::buffer *b = ((pySamplebuffer *)obj)->buf; - ptrptr[0] = b->Data(); - return b->Channels()*b->Frames()*sizeof(t_sample); -} + if(flags & PyBUF_ND) { + PyErr_SetString(PyExc_BufferError, "PyBUF_ND not supported"); + view->obj = NULL; + return -1; + } -static Py_ssize_t buffer_writebuffer(PyObject *obj, Py_ssize_t segment, void **ptrptr) -{ - flext::buffer *b = ((pySamplebuffer *)obj)->buf; - ptrptr[0] = b->Data(); - return b->Channels()*b->Frames()*sizeof(t_sample); -} + if(flags & PyBUF_F_CONTIGUOUS) { + PyErr_SetString(PyExc_BufferError, "PyBUF_F_CONTIGUOUS not supported"); + view->obj = NULL; + return -1; + } -static Py_ssize_t buffer_segcount(PyObject *obj, Py_ssize_t *lenp) -{ - flext::buffer *b = ((pySamplebuffer *)obj)->buf; - if(lenp) lenp[0] = b->Channels()*b->Frames()*sizeof(t_sample); - return 1; + pySamplebuffer *self = reinterpret_cast(obj); + flext::buffer *b = self->buf; + + view->buf = (void *)b->Data(); + Py_INCREF(obj); + view->obj = obj; + view->len = b->Channels()*b->Frames()*sizeof(t_sample); + view->readonly = false; + view->itemsize = 1; + view->format = NULL; + view->ndim = 1; + view->shape = NULL; + view->strides = NULL; + view->suboffsets = NULL; + view->internal = NULL; + + if(flags & PyBUF_FORMAT) { + view->format = "B"; + } + + return 0; } -static Py_ssize_t buffer_charbuffer(PyObject *obj, Py_ssize_t segment, -#if PY_VERSION_HEX < 0x02050000 - const -#endif - char **ptrptr) -{ - flext::buffer *b = ((pySamplebuffer *)obj)->buf; - ptrptr[0] = (char *)b->Data(); - return b->Channels()*b->Frames()*sizeof(t_sample); +static void buffer_releasebuffer(PyObject *obj, Py_buffer *view) { + // nothing to do here } static PyBufferProcs buffer_as_buffer = { - buffer_readbuffer, - buffer_writebuffer, - buffer_segcount, - buffer_charbuffer + buffer_getbuffer, + buffer_releasebuffer }; static Py_ssize_t buffer_length(PyObject *s) @@ -279,16 +294,15 @@ PyObject *arrayfrombuffer(PyObject *buf,int c,int n) #ifdef PY_NUMARRAY arr = (PyObject *)NA_NewAllFromBuffer(c == 1?1:2,shape,numtype,buf,0,0,NA_ByteOrder(),1,1); #else - void *data; - Py_ssize_t len; - int err = PyObject_AsWriteBuffer(buf,&data,&len); + Py_buffer view; + int err = PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE | PyBUF_WRITABLE); if(!err) { - FLEXT_ASSERT(len <= n*c*sizeof(t_sample)); + FLEXT_ASSERT(view->len <= n*c*sizeof(t_sample)); // Py_INCREF(buf); // ATTENTION... this won't be released any more!! # ifdef PY_NUMPY - arr = PyArray_NewFromDescr(&PyArray_Type,PyArray_DescrNewFromType(numtype),c == 1?1:2,shape,0,(char *)data,NPY_WRITEABLE|NPY_C_CONTIGUOUS,NULL); + arr = PyArray_NewFromDescr(&PyArray_Type,PyArray_DescrNewFromType(numtype),c == 1?1:2,shape,0,(char *)view.buf,NPY_WRITEABLE|NPY_C_CONTIGUOUS,NULL); # else - arr = PyArray_FromDimsAndData(c == 1?1:2,shape,numtype,(char *)data); + arr = PyArray_FromDimsAndData(c == 1?1:2,shape,numtype,(char *)view.buf); # endif } else { @@ -462,13 +476,14 @@ static PyObject *buffer_repeat(PyObject *s,Py_ssize_t rep) static PySequenceMethods buffer_as_seq = { - buffer_length, /* inquiry sq_length; __len__ */ - buffer_concat, /* __add__ */ - buffer_repeat, /* __mul__ */ - buffer_item, /* intargfunc sq_item; __getitem__ */ - buffer_slice, /* intintargfunc sq_slice; __getslice__ */ - buffer_ass_item, /* intobjargproc sq_ass_item; __setitem__ */ - buffer_ass_slice, /* intintobjargproc sq_ass_slice; __setslice__ */ + buffer_length, /* lenfunc sq_length __len__ */ + buffer_concat, /* binaryfunc sq_concat __add__ */ + buffer_repeat, /* ssizeargfunc sq_repeat __mul__ */ + buffer_item, /* ssizeargfunc sq_item; __getitem__ */ + NULL, /* ssizeobjargproc sq_ass_item __setitem__ */ + NULL, /* objobjproc sq_contains __contains__ */ + NULL, /* binaryfunc sq_inplace_concat __iadd__ */ + NULL /* ssizeargfunc sq_inplace_repeat __imul */ }; static PyObject *buffer_iter(PyObject *s) @@ -723,6 +738,20 @@ static PyObject *buffer_inplace_divide(PyObject *s,PyObject *op) } #endif +static PyObject *buffer_inplace_true_divide(PyObject *s,PyObject *op) +{ + pySamplebuffer *self = reinterpret_cast(s); + PyObject *nobj = buffer_slice(s); + if(nobj) { + PyObject *ret = PyNumber_InPlaceTrueDivide(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + static PyObject *buffer_inplace_floor_divide(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); @@ -768,57 +797,59 @@ static PyObject *buffer_inplace_power(PyObject *s,PyObject *op1,PyObject *op2) static PyNumberMethods buffer_as_number = { - (binaryfunc)buffer_add, /*nb_add*/ - (binaryfunc)buffer_subtract, /*nb_subtract*/ - (binaryfunc)buffer_multiply, /*nb_multiply*/ + (binaryfunc)buffer_add, // binaryfunc nb_add + (binaryfunc)buffer_subtract, // binaryfunc nb_subtract + (binaryfunc)buffer_multiply, // binaryfunc nb_multiply #if PY_MAJOR_VERSION < 3 - (binaryfunc)buffer_divide, /*nb_divide*/ -#else - 0, /*nb_divide not supported */ + (binaryfunc)buffer_divide, // binaryfunc nb_divide +#endif + (binaryfunc)buffer_remainder, // nb_binaryfunc remainder + (binaryfunc)buffer_divmod, // binaryfunc nb_divmod + (ternaryfunc)buffer_power, // ternaryfunc nb_power + (unaryfunc)buffer_negative, // unaryfunc nb_negative + (unaryfunc)buffer_pos, // unaryfunc nb_pos + (unaryfunc)buffer_absolute, // unaryfunc np_absolute + 0, //(inquiry)buffer_nonzero, // inquiry nb_nonzero + 0, // unaryfunc nb_invert + 0, // binaryfunc nb_lshift + 0, // binaryfunc nb_rshift + 0, // binaryfunc nb_and + 0, // binaryfunc nb_xor + 0, // binaryfunc nb_or +#if PY_MAJOR_VERSION < 3 + (coercion)buffer_coerce, // coercion nb_coerce #endif - (binaryfunc)buffer_remainder, /*nb_remainder*/ - (binaryfunc)buffer_divmod, /*nb_divmod*/ - (ternaryfunc)buffer_power, /*nb_power*/ - (unaryfunc)buffer_negative, - (unaryfunc)buffer_pos, /*nb_pos*/ - (unaryfunc)buffer_absolute, /* (unaryfunc)buffer_abs, */ - 0, //(inquiry)buffer_nonzero, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ - (coercion)buffer_coerce, /*nb_coerce*/ - 0, /*nb_int*/ - 0, /*nb_long*/ - 0, /*nb_float*/ - 0, /*nb_oct*/ - 0, /*nb_hex*/ - (binaryfunc)buffer_inplace_add, /* nb_inplace_add */ - (binaryfunc)buffer_inplace_subtract, /* nb_inplace_subtract */ - (binaryfunc)buffer_inplace_multiply, /* nb_inplace_multiply */ + 0, // unaryfunc nb_int #if PY_MAJOR_VERSION < 3 - (binaryfunc)buffer_inplace_divide, /* nb_inplace_divide */ + 0, // unaryfunc nb_long + 0, // unaryfunc nb_float + 0, // unaryfunc nb_oct + 0, // unaryfunc nb_hex #else - 0, /* nb_inplace_divide not supported */ + 0, // void *nb_reserved + 0, // unaryfunc nb_float #endif - (binaryfunc)buffer_inplace_remainder, /* nb_inplace_remainder */ - (ternaryfunc)buffer_inplace_power, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - (binaryfunc)buffer_floor_divide, /* nb_floor_divide */ - (binaryfunc)buffer_true_divide, /* nb_true_divide */ - (binaryfunc)buffer_inplace_floor_divide, /* nb_inplace_floor_divide */ -// buffer_inplace_div, /* nb_inplace_true_divide */ + (binaryfunc)buffer_inplace_add, // binaryfunc nb_inplace_add + (binaryfunc)buffer_inplace_subtract, // binaryfunc nb_inplace_subtract + (binaryfunc)buffer_inplace_multiply, // binaryfunc nb_inplace_multiply +#if PY_MAJOR_VERSION < 3 + (binaryfunc)buffer_inplace_divide, // binaryfunc nb_inplace_divide +#endif + (binaryfunc)buffer_inplace_remainder, // binaryfunc nb_inplace_remainder + (ternaryfunc)buffer_inplace_power, // ternaryfunc nb_inplace_power + 0, // binaryfunc nb_inplace_lshift + 0, // binaryfunc nb_inplace_rshift + 0, // binaryfunc nb_inplace_and + 0, // binaryfunc nb_inplace_xor + 0, // binaryfunc nb_inplace_or + (binaryfunc)buffer_floor_divide, // binaryfunc nb_floor_divide + (binaryfunc)buffer_true_divide, // binaryfunc nb_true_divide + (binaryfunc)buffer_inplace_floor_divide, // binaryfunc nb_inplace_floor_divide + (binaryfunc)buffer_inplace_true_divide, // binaryfunc nb_inplace_true_divide }; PyTypeObject pySamplebuffer_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "Buffer", /*tp_name*/ sizeof(pySamplebuffer), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -838,6 +869,9 @@ PyTypeObject pySamplebuffer_Type = { 0, /*tp_setattro*/ &buffer_as_buffer, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ +#if PY_MAJOR_VERSION < 3 + | Py_TPFLAGS_HAVE_NEWBUFFER +#endif "Samplebuffer objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -861,13 +895,14 @@ PyTypeObject pySamplebuffer_Type = { // Must have this as a function because the import_array macro in numpy version 1.01 strangely has a return statement included. // Furthermore the import error printout from this macro is ugly, but we accept that for now, waiting for later numpy updates to fix all of this. #ifdef PY_ARRAYS -static void __import_array__() +static int __import_array__() { #ifdef PY_NUMARRAY import_libnumarray(); #else import_array(); #endif + return 0; } #endif diff --git a/source/pybundle.cpp b/source/pybundle.cpp index 8f136ec..b2512d6 100644 --- a/source/pybundle.cpp +++ b/source/pybundle.cpp @@ -108,7 +108,7 @@ static PyObject *bundle_append(PyObject *self,PyObject *args) int o; if(sz > 2 && - (tg = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(tg) && + (tg = PyTuple_GET_ITEM(args,0)) != NULL && (outl = PyTuple_GET_ITEM(args,1)) != NULL && #if PY_MAJOR_VERSION < 3 PyInt_Check(outl) @@ -195,8 +195,7 @@ static PyMethodDef bundle_methods[] = { PyTypeObject pyBundle_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "Bundle", /*tp_name*/ sizeof(pyBundle), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/pydsp.cpp b/source/pydsp.cpp index 49e6aee..7676557 100644 --- a/source/pydsp.cpp +++ b/source/pydsp.cpp @@ -83,7 +83,15 @@ void pydsp::NewBuffers() for(i = 0; i < ins; ++i) { Py_XDECREF(buffers[i]); - PyObject *b = PyBuffer_FromReadWriteMemory(insigs[i],n*sizeof(t_sample)); + PyObject *b = +#if PY_MAJOR_VERSION < 3 + PyBuffer_FromReadWriteMemory(insigs[i],n*sizeof(t_sample)); +#elif PY_MINOR_VERSION >= 3 + PyMemoryView_FromMemory(reinterpret_cast(insigs[i]), n*sizeof(t_sample), PyBUF_WRITE); +#else +#error "TODO" +#endif + buffers[i] = arrayfrombuffer(b,1,n); Py_DECREF(b); } @@ -95,7 +103,15 @@ void pydsp::NewBuffers() Py_XINCREF(buffers[i]); } else { - PyObject *b = PyBuffer_FromReadWriteMemory(outsigs[i],n*sizeof(t_sample)); + PyObject *b = +#if PY_MAJOR_VERSION < 3 + PyBuffer_FromReadWriteMemory(outsigs[i],n*sizeof(t_sample)); +#elif PY_MINOR_VERSION >= 3 + PyMemoryView_FromMemory(reinterpret_cast(outsigs[i]), n*sizeof(t_sample), PyBUF_WRITE); +#else +#error "TODO" +#endif + buffers[ins+i] = arrayfrombuffer(b,1,n); Py_DECREF(b); } diff --git a/source/pyext.cpp b/source/pyext.cpp index 0deb2e9..c96b7b3 100644 --- a/source/pyext.cpp +++ b/source/pyext.cpp @@ -63,13 +63,16 @@ void pyext::Setup(t_classid c) Py_DECREF(func); } - class_obj = PyClass_New(NULL, class_dict, className); + //class_obj = PyClass_New(NULL, class_dict, className); + PyObject *classBases = PyTuple_New(0); + class_obj = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, className, classBases, class_dict, NULL); + Py_DECREF(classBases); Py_DECREF(className); // add methods to class for (def = meth_tbl; def->ml_name != NULL; def++) { PyObject *func = PyCFunction_New(def, NULL); - PyObject *method = PyMethod_New(func, NULL, class_obj); // increases class_obj ref count by 1 + PyObject *method = PyInstanceMethod_New(func); // increases class_obj ref count by 1 PyDict_SetItemString(class_dict, def->ml_name, method); Py_DECREF(func); Py_DECREF(method); diff --git a/source/pyext.h b/source/pyext.h index 61b892a..f27b8f3 100644 --- a/source/pyext.h +++ b/source/pyext.h @@ -65,7 +65,7 @@ class pyext void ms_initargs(const AtomList &a) { m_reload_(a.Count(),a.Atoms()); } void m_dir_() { m__dir(pyobj); } void mg_dir_(AtomList &lst) { GetDir(pyobj,lst); } - void m_doc_() { m__doc(((PyInstanceObject *)pyobj)->in_class->cl_dict); } + void m_doc_() { m__doc(pyobj); } void m_get(const t_symbol *s); void m_set(int argc,const t_atom *argv); diff --git a/source/pymeth.cpp b/source/pymeth.cpp index 0ff87ed..42cbfca 100644 --- a/source/pymeth.cpp +++ b/source/pymeth.cpp @@ -382,7 +382,11 @@ bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) else if(self != objects[0]) { // type hasn't changed, but object has PyObject *f = function; +#if PY_MAJOR_VERSION < 3 function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0],PyMethod_GET_CLASS(f)); +#else + function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0]); +#endif Py_DECREF(f); } } diff --git a/source/pysymbol.cpp b/source/pysymbol.cpp index 743207f..5d2a46c 100644 --- a/source/pysymbol.cpp +++ b/source/pysymbol.cpp @@ -178,13 +178,14 @@ static PyObject *symbol_repeat(PyObject *s,Py_ssize_t rep) } static PySequenceMethods symbol_as_seq = { - symbol_length, /* inquiry sq_length; __len__ */ - symbol_concat, /* __add__ */ - symbol_repeat, /* __mul__ */ - symbol_item, /* intargfunc sq_item; __getitem__ */ - symbol_slice, /* intintargfunc sq_slice; __getslice__ */ - NULL, /* intobjargproc sq_ass_item; __setitem__ */ - NULL, /* intintobjargproc sq_ass_slice; __setslice__ */ + symbol_length, /* lenfunc sq_length __len__ */ + symbol_concat, /* binaryfunc sq_concat __add__ */ + symbol_repeat, /* ssizeargfunc sq_repeat __mul__ */ + symbol_item, /* ssizeargfunc sq_item; __getitem__ */ + NULL, /* ssizeobjargproc sq_ass_item __setitem__ */ + NULL, /* objobjproc sq_contains __contains__ */ + NULL, /* binaryfunc sq_inplace_concat __iadd__ */ + NULL /* ssizeargfunc sq_inplace_repeat __imul */ }; static PyObject *symbol_iter(PyObject *s) @@ -203,45 +204,44 @@ static PyObject *symbol_iter(PyObject *s) PyTypeObject pySymbol_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Symbol", /*tp_name*/ - sizeof(pySymbol), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - symbol_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - &symbol_as_seq, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - symbol_hash, /*tp_hash */ - 0, /*tp_call*/ - symbol_str, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ - "Symbol objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + PyVarObject_HEAD_INIT(NULL, 0) + "Symbol", /* tp_name */ + sizeof(pySymbol), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + symbol_repr, /* tp_repr */ + 0, /* tp_as_number */ + &symbol_as_seq, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + symbol_hash, /* tp_hash */ + 0, /* tp_call */ + symbol_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_BASETYPE*/, /* tp_flags */ + "Symbol objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ symbol_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - symbol_iter, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ + 0, /* tp_weaklistoffset */ + symbol_iter, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - symbol_init, /* tp_init */ + symbol_init, /* tp_init */ 0, /* tp_alloc */ - symbol_new, /* tp_new */ + symbol_new, /* tp_new */ }; pySymbol *pySymbol__; From 99abb6a03dd76e08064f41b411ab193f75c3bca1 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 10 Mar 2020 13:47:23 +0200 Subject: [PATCH 117/150] support pymalloc python build --- build/config-mac.def | 3 +++ build/gnumake-mac-gcc.inc | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/build/config-mac.def b/build/config-mac.def index 8184e69..a86906f 100644 --- a/build/config-mac.def +++ b/build/config-mac.def @@ -33,3 +33,6 @@ PY_USE_GIL=1 # use inofficial (pure data) functionality # PY_USE_INOFFICIAL=1 + +# use python with pymalloc (look for "pythonX.Ym" files) +PY_USE_PYMALLOC=1 diff --git a/build/gnumake-mac-gcc.inc b/build/gnumake-mac-gcc.inc index c224c00..dadf7ce 100644 --- a/build/gnumake-mac-gcc.inc +++ b/build/gnumake-mac-gcc.inc @@ -27,10 +27,14 @@ $(error PY_CONDA_ROOT is undefined) endif DEFS += -DPY_INTERPRETER=$(PY_CONDA_ROOT)/bin/python -LIBS += $(PY_CONDA_ROOT)/lib/libpython$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION).dylib INCPATH += -I$(PY_CONDA_ROOT)/include +ifdef PY_USE_PYMALLOC INCPATH += -I$(PY_CONDA_ROOT)/include/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)m +LIBS += $(PY_CONDA_ROOT)/lib/libpython$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)m.dylib +else INCPATH += -I$(PY_CONDA_ROOT)/include/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) +LIBS += $(PY_CONDA_ROOT)/lib/libpython$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION).dylib +endif LDFLAGS += -rpath $(PY_CONDA_ROOT)/lib ifdef PY_NUMPY From 379ab50e47ed0c34b450ee03fff49f2fb91b582d Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 10 Mar 2020 14:18:51 +0200 Subject: [PATCH 118/150] reorganize module defs & fix builtins import --- source/modmeth.cpp | 14 ++++++++++ source/pybase.cpp | 65 +++++++++++++++++++++------------------------- source/pybase.h | 3 +++ 3 files changed, 47 insertions(+), 35 deletions(-) diff --git a/source/modmeth.cpp b/source/modmeth.cpp index 2a35b07..2325f10 100644 --- a/source/modmeth.cpp +++ b/source/modmeth.cpp @@ -52,6 +52,20 @@ const char *pybase::py_doc = "_tuple(args...): Make a tuple from args\n" ; +#if PY_MAJOR_VERSION >= 3 +PyModuleDef pybase::pyext_module_def = { + PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base + PYEXT_MODULE, // const char *m_name + py_doc, // const char *m_doc + -1, // Py_ssize_t m_size + func_tbl, // PyMethodDef *m_methods + NULL, // PyModuleDef_Slot *m_slots + NULL, // traverseproc m_traverse + NULL, // inquiry m_clear + NULL // freefunc m_free +}; +#endif + #ifdef FLEXT_THREADS void pybase::tick(void *) { diff --git a/source/pybase.cpp b/source/pybase.cpp index 41fa70a..a416a4b 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -27,6 +27,30 @@ static PyMethodDef StdOut_Methods[] = { NULL, NULL, } }; +static PyModuleDef StdOut_ModuleDef = { + PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base + "stdout", // const char *m_name + "pyext standard output", // const char *m_doc + -1, // Py_ssize_t m_size + StdOut_Methods, // PyMethodDef *m_methods + NULL, // PyModuleDef_Slot *m_slots + NULL, // traverseproc m_traverse + NULL, // inquiry m_clear + NULL // freefunc m_free +}; + +static PyModuleDef StdErr_ModuleDef = { + PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base + "pyext standard error", // const char *m_name + "", // const char *m_doc + -1, // Py_ssize_t m_size + StdOut_Methods, // PyMethodDef *m_methods + NULL, // PyModuleDef_Slot *m_slots + NULL, // traverseproc m_traverse + NULL, // inquiry m_clear + NULL // freefunc m_free +}; + static PyObject *gcollect = NULL; #ifdef FLEXT_THREADS @@ -181,17 +205,6 @@ void pybase::lib_setup() #if PY_MAJOR_VERSION < 3 module_obj = Py_InitModule(const_cast(PYEXT_MODULE), func_tbl); #else - struct PyModuleDef pyext_module_def = { - PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base - PYEXT_MODULE, // const char *m_name - py_doc, // const char *m_doc - -1, // Py_ssize_t m_size - func_tbl, // PyMethodDef *m_methods - NULL, // PyModuleDef_Slot *m_slots - NULL, // traverseproc m_traverse - NULL, // inquiry m_clear - NULL // freefunc m_free - }; module_obj = PyModule_Create(&pyext_module_def); #endif module_dict = PyModule_GetDict(module_obj); // borrowed reference @@ -203,35 +216,13 @@ void pybase::lib_setup() #if PY_MAJOR_VERSION < 3 py_out = Py_InitModule(const_cast("stdout"), StdOut_Methods); #else - struct PyModuleDef stdout_module_def = { - PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base - "stdout", // const char *m_name - "", // const char *m_doc - -1, // Py_ssize_t m_size - func_tbl, // PyMethodDef *m_methods - NULL, // PyModuleDef_Slot *m_slots - NULL, // traverseproc m_traverse - NULL, // inquiry m_clear - NULL // freefunc m_free - }; - py_out = PyModule_Create(&stdout_module_def); + py_out = PyModule_Create(&StdOut_ModuleDef); #endif PySys_SetObject(const_cast("stdout"), py_out); #if PY_MAJOR_VERSION < 3 py_out = Py_InitModule(const_cast("stderr"), StdOut_Methods); #else - struct PyModuleDef stderr_module_def = { - PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base - "stderr", // const char *m_name - "", // const char *m_doc - -1, // Py_ssize_t m_size - func_tbl, // PyMethodDef *m_methods - NULL, // PyModuleDef_Slot *m_slots - NULL, // traverseproc m_traverse - NULL, // inquiry m_clear - NULL // freefunc m_free - }; - py_out = PyModule_Create(&stdout_module_def); + py_out = PyModule_Create(&StdErr_ModuleDef); #endif PySys_SetObject(const_cast("stderr"), py_out); @@ -242,7 +233,11 @@ void pybase::lib_setup() Py_DECREF(gcobj); } +#if PY_MAJOR_VERSION < 3 builtins_obj = PyImport_ImportModule("__builtin__"); +#else + builtins_obj = PyImport_ImportModule("builtins"); +#endif builtins_dict = PyModule_GetDict(builtins_obj); // borrowed reference // add symbol type diff --git a/source/pybase.h b/source/pybase.h index cfda6bf..1db827c 100644 --- a/source/pybase.h +++ b/source/pybase.h @@ -111,6 +111,9 @@ class pybase static PyObject *module_obj,*module_dict; static PyObject *builtins_obj,*builtins_dict; static PyMethodDef func_tbl[],attr_tbl[]; +#if PY_MAJOR_VERSION >= 3 + static PyModuleDef pyext_module_def; +#endif static PyObject *py__doc__(PyObject *,PyObject *args); static PyObject *py_send(PyObject *,PyObject *args); From 34c529ed7fdef4d1199398b917102974118d087b Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 10 Mar 2020 16:18:01 +0200 Subject: [PATCH 119/150] fix module init --- scripts/simple.py | 43 ++++++++--------- source/pybase.cpp | 118 +++++++++++++++++++++------------------------- source/pybase.h | 21 +++++++++ 3 files changed, 96 insertions(+), 86 deletions(-) diff --git a/scripts/simple.py b/scripts/simple.py index 1aa211c..b2c40bc 100644 --- a/scripts/simple.py +++ b/scripts/simple.py @@ -1,3 +1,4 @@ +from __future__ import print_function # py/pyext - python script objects for PD and MaxMSP # # Copyright (c) 2002-2007 Thomas Grill (gr@grrrr.org) @@ -68,72 +69,71 @@ try: import pyext except: - print "ERROR: This script must be loaded by the PD/Max pyext external" + print("ERROR: This script must be loaded by the PD/Max pyext external") ################################################################# class ex1(pyext._class): """Example of a simple class which receives messages and prints to the console""" - + # number of inlets and outlets _inlets=3 _outlets=0 - # methods for first inlet def bang_1(self): - print "Bang into first inlet" + print("Bang into first inlet") def int_1(self,f): - print "Integer",f,"into first inlet" + print("Integer",f,"into first inlet") def float_1(self,f): - print "Float",f,"into first inlet" + print("Float",f,"into first inlet") def list_1(self,*s): - print "List",s,"into first inlet" + print("List",s,"into first inlet") # methods for second inlet def hey_2(self): - print "Tag 'hey' into second inlet" + print("Tag 'hey' into second inlet") def ho_2(self): - print "Tag 'ho' into second inlet" + print("Tag 'ho' into second inlet") def lets_2(self): - print "Tag 'lets' into second inlet" + print("Tag 'lets' into second inlet") def go_2(self): - print "Tag 'go' into second inlet" + print("Tag 'go' into second inlet") def _anything_2(self,*args): - print "Some other message into second inlet:",args + print("Some other message into second inlet:",args) # methods for third inlet def onearg_3(self,a): - print "Tag 'onearg' into third inlet:",a + print("Tag 'onearg' into third inlet:",a) def twoargs_3(self,*a): if len(a) == 2: - print "Tag 'twoargs' into third inlet:",a[0],a[1] + print("Tag 'twoargs' into third inlet:",a[0],a[1]) else: - print "Tag 'twoargs': wrong number of arguments" + print("Tag 'twoargs': wrong number of arguments") def threeargs_3(self,*a): if len(a) == 3: - print "Tag 'threeargs' into third inlet",a[0],a[1],a[2] + print("Tag 'threeargs' into third inlet",a[0],a[1],a[2]) else: - print "Tag 'threeargs': wrong number of arguments" + print("Tag 'threeargs': wrong number of arguments") def varargs_3(self,*args): # with *args there can be arguments or not - print "Tag 'varargs' into third inlet",args + print("Tag 'varargs' into third inlet",args) @@ -149,10 +149,10 @@ class ex2(pyext._class): # methods for all inlets def hello_(self,n): - print "Tag 'hello' into inlet",n + print("Tag 'hello' into inlet",n) def _anything_(self,n,*args): - print "Message into inlet",n,":",args + print("Message into inlet",n,":",args) # methods for first inlet @@ -196,7 +196,7 @@ def __init__(self,*args): if isNumber(args[0]): self.tmp = args[0] else: - print "ex3: __init__ has superfluous arguments" + print("ex3: __init__ has superfluous arguments") # methods @@ -212,3 +212,4 @@ def int_1(self,f): def int_2(self,f): self.float_2(f) + diff --git a/source/pybase.cpp b/source/pybase.cpp index a416a4b..c778302 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -27,30 +27,6 @@ static PyMethodDef StdOut_Methods[] = { NULL, NULL, } }; -static PyModuleDef StdOut_ModuleDef = { - PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base - "stdout", // const char *m_name - "pyext standard output", // const char *m_doc - -1, // Py_ssize_t m_size - StdOut_Methods, // PyMethodDef *m_methods - NULL, // PyModuleDef_Slot *m_slots - NULL, // traverseproc m_traverse - NULL, // inquiry m_clear - NULL // freefunc m_free -}; - -static PyModuleDef StdErr_ModuleDef = { - PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base - "pyext standard error", // const char *m_name - "", // const char *m_doc - -1, // Py_ssize_t m_size - StdOut_Methods, // PyMethodDef *m_methods - NULL, // PyModuleDef_Slot *m_slots - NULL, // traverseproc m_traverse - NULL, // inquiry m_clear - NULL // freefunc m_free -}; - static PyObject *gcollect = NULL; #ifdef FLEXT_THREADS @@ -128,7 +104,46 @@ void initsymbol(); void initsamplebuffer(); void initbundle(); +MOD_INIT(pyext) +{ + return MOD_SUCCESS_VAL(pybase::pyext_init()); +} +PyObject *pybase::pyext_init() +{ + if(module_obj == NULL) { + PyObject *m; + + MOD_DEF(m, PYEXT_MODULE, py_doc, func_tbl); + + PyModule_AddStringConstant(m,"__doc__",(char *)py_doc); + + // add symbol type + initsymbol(); + PyModule_AddObject(m,"Symbol",(PyObject *)&pySymbol_Type); + + // pre-defined symbols + PyModule_AddObject(m,"_s_",(PyObject *)pySymbol__); + PyModule_AddObject(m,"_s_bang",(PyObject *)pySymbol_bang); + PyModule_AddObject(m,"_s_list",(PyObject *)pySymbol_list); + PyModule_AddObject(m,"_s_symbol",(PyObject *)pySymbol_symbol); + PyModule_AddObject(m,"_s_float",(PyObject *)pySymbol_float); + PyModule_AddObject(m,"_s_int",(PyObject *)pySymbol_int); + + // add samplebuffer type + initsamplebuffer(); + PyModule_AddObject(m,"Buffer",(PyObject *)&pySamplebuffer_Type); + + // add message bundle type + initbundle(); + PyModule_AddObject(m,"Bundle",(PyObject *)&pyBundle_Type); + + module_obj = m; + module_dict = PyModule_GetDict(m); // borrowed reference + } + + return module_obj; +} void pybase::lib_setup() { @@ -167,6 +182,8 @@ void pybase::lib_setup() // ------------------------------------------------------------- + PyImport_AppendInittab(PYEXT_MODULE, MOD_INIT_NAME(pyext)); + Py_Initialize(); #ifdef FLEXT_DEBUG @@ -201,31 +218,22 @@ void pybase::lib_setup() PySys_SetArgv(0,const_cast(¬hing)); #endif - // register/initialize pyext module only once! -#if PY_MAJOR_VERSION < 3 - module_obj = Py_InitModule(const_cast(PYEXT_MODULE), func_tbl); -#else - module_obj = PyModule_Create(&pyext_module_def); -#endif - module_dict = PyModule_GetDict(module_obj); // borrowed reference - - PyModule_AddStringConstant(module_obj,"__doc__",(char *)py_doc); - + // import the pyext module to ensure init + PyImport_ImportModule(PYEXT_MODULE); + // redirect stdout PyObject* py_out; -#if PY_MAJOR_VERSION < 3 - py_out = Py_InitModule(const_cast("stdout"), StdOut_Methods); -#else - py_out = PyModule_Create(&StdOut_ModuleDef); -#endif + + { + MOD_DEF(py_out, "stdout", "pyext standard output", StdOut_Methods); + } PySys_SetObject(const_cast("stdout"), py_out); -#if PY_MAJOR_VERSION < 3 - py_out = Py_InitModule(const_cast("stderr"), StdOut_Methods); -#else - py_out = PyModule_Create(&StdErr_ModuleDef); -#endif + + { + MOD_DEF(py_out, "stderr", "pyext standard error", StdOut_Methods); + } PySys_SetObject(const_cast("stderr"), py_out); - + // get garbage collector function PyObject *gcobj = PyImport_ImportModule("gc"); if(gcobj) { @@ -240,26 +248,6 @@ void pybase::lib_setup() #endif builtins_dict = PyModule_GetDict(builtins_obj); // borrowed reference - // add symbol type - initsymbol(); - PyModule_AddObject(module_obj,"Symbol",(PyObject *)&pySymbol_Type); - - // pre-defined symbols - PyModule_AddObject(module_obj,"_s_",(PyObject *)pySymbol__); - PyModule_AddObject(module_obj,"_s_bang",(PyObject *)pySymbol_bang); - PyModule_AddObject(module_obj,"_s_list",(PyObject *)pySymbol_list); - PyModule_AddObject(module_obj,"_s_symbol",(PyObject *)pySymbol_symbol); - PyModule_AddObject(module_obj,"_s_float",(PyObject *)pySymbol_float); - PyModule_AddObject(module_obj,"_s_int",(PyObject *)pySymbol_int); - - // add samplebuffer type - initsamplebuffer(); - PyModule_AddObject(module_obj,"Buffer",(PyObject *)&pySamplebuffer_Type); - - // add message bundle type - initbundle(); - PyModule_AddObject(module_obj,"Bundle",(PyObject *)&pyBundle_Type); - // ------------------------------------------------------------- #if FLEXT_SYS == FLEXT_SYS_PD && defined(PD_DEVEL_VERSION) && defined(PY_USE_INOFFICIAL) // add PD paths diff --git a/source/pybase.h b/source/pybase.h index 1db827c..e13d672 100644 --- a/source/pybase.h +++ b/source/pybase.h @@ -24,6 +24,26 @@ WARRANTIES, see the file, "license.txt," in this distribution. typedef int ThrState; // dummy #endif +#if PY_MAJOR_VERSION < 3 +#define MOD_ERROR_VAL +#define MOD_SUCCESS_VAL(val) +#define MOD_INIT_NAME(name) init##name +#define MOD_INIT(name) void MOD_INIT_NAME(name)(void) +#define MOD_DEF(ob, name, doc, methods) \ + ob = Py_InitModule3(name, methods, doc); +#else +#define MOD_ERROR_VAL NULL +#define MOD_SUCCESS_VAL(val) val +#define MOD_INIT_NAME(name) PyInit_##name +#define MOD_INIT(name) PyMODINIT_FUNC MOD_INIT_NAME(name)(void) +#define MOD_DEF(ob, name, doc, methods) \ + static struct PyModuleDef moduledef = { \ + PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \ + ob = PyModule_Create(&moduledef); +#endif + +MOD_INIT(pyext); + class pybase : public flext { @@ -38,6 +58,7 @@ class pybase static const t_symbol *GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0); static const t_symbol *GetPyAtom(AtomList &lst,PyObject *pValue); + static PyObject *pyext_init(); static void lib_setup(); protected: From 22e960149fa5a1df465064b65739fd01267aa035 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 10 Mar 2020 16:56:09 +0200 Subject: [PATCH 120/150] fix python 2 build --- source/pyargs.cpp | 3 ++- source/pybuffer.cpp | 56 +++++++++++++++++++++++++++++++++++++++++---- source/pybuffer.h | 4 ++-- source/pyext.cpp | 14 ++++++++---- source/pysymbol.cpp | 3 ++- source/pysymbol.h | 8 +++---- 6 files changed, 71 insertions(+), 17 deletions(-) diff --git a/source/pyargs.cpp b/source/pyargs.cpp index 6845f98..0dd3c15 100644 --- a/source/pyargs.cpp +++ b/source/pyargs.cpp @@ -162,8 +162,9 @@ const t_symbol *pybase::getone(t_atom &at,PyObject *arg) else if(pySymbol_Check(arg)) { flext::SetSymbol(at,pySymbol_AS_SYMBOL(arg)); return flext::sym_symbol; } #if PY_MAJOR_VERSION < 3 else if(PyString_Check(arg)) { flext::SetString(at,PyString_AS_STRING(arg)); return flext::sym_symbol; } -#endif +#else else if(PyUnicode_Check(arg)) { flext::SetString(at,PyUnicode_AsUTF8(arg)); return flext::sym_symbol; } +#endif else { PyObject *tp = PyObject_Type(arg); PyObject *stp = tp?PyObject_Str(tp):NULL; diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index 6892d03..4bba04e 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -106,9 +106,10 @@ static int buffer_init(PyObject *obj, PyObject *args, PyObject *kwds) #if PY_MAJOR_VERSION < 3 else if(PyString_Check(arg)) self->sym = flext::MakeSymbol(PyString_AS_STRING(arg)); -#endif +#else else if(PyUnicode_Check(arg)) self->sym = flext::MakeSymbol(PyUnicode_AsUTF8(arg)); +#endif else ret = -1; Py_DECREF(arg); @@ -193,6 +194,38 @@ static PyMethodDef buffer_methods[] = { // support the buffer protocol +static Py_ssize_t buffer_readbuffer(PyObject *obj, Py_ssize_t segment, void **ptrptr) +{ + flext::buffer *b = ((pySamplebuffer *)obj)->buf; + ptrptr[0] = b->Data(); + return b->Channels()*b->Frames()*sizeof(t_sample); +} + +static Py_ssize_t buffer_writebuffer(PyObject *obj, Py_ssize_t segment, void **ptrptr) +{ + flext::buffer *b = ((pySamplebuffer *)obj)->buf; + ptrptr[0] = b->Data(); + return b->Channels()*b->Frames()*sizeof(t_sample); +} + +static Py_ssize_t buffer_segcount(PyObject *obj, Py_ssize_t *lenp) +{ + flext::buffer *b = ((pySamplebuffer *)obj)->buf; + if(lenp) lenp[0] = b->Channels()*b->Frames()*sizeof(t_sample); + return 1; +} + +static Py_ssize_t buffer_charbuffer(PyObject *obj, Py_ssize_t segment, +#if PY_VERSION_HEX < 0x02050000 + const +#endif + char **ptrptr) +{ + flext::buffer *b = ((pySamplebuffer *)obj)->buf; + ptrptr[0] = (char *)b->Data(); + return b->Channels()*b->Frames()*sizeof(t_sample); +} + static int buffer_getbuffer(PyObject *obj, Py_buffer *view, int flags) { if(flags & PyBUF_INDIRECT) { PyErr_SetString(PyExc_BufferError, "PyBUF_INDIRECT not supported"); @@ -246,8 +279,15 @@ static void buffer_releasebuffer(PyObject *obj, Py_buffer *view) { } static PyBufferProcs buffer_as_buffer = { +#if PY_MAJOR_VERSION < 3 + buffer_readbuffer, + buffer_writebuffer, + buffer_segcount, + buffer_charbuffer +#else buffer_getbuffer, buffer_releasebuffer +#endif }; static Py_ssize_t buffer_length(PyObject *s) @@ -868,10 +908,11 @@ PyTypeObject pySamplebuffer_Type = { 0, /*tp_getattro*/ 0, /*tp_setattro*/ &buffer_as_buffer, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ + Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/ /*tp_flags*/ #if PY_MAJOR_VERSION < 3 | Py_TPFLAGS_HAVE_NEWBUFFER #endif + , "Samplebuffer objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -894,15 +935,22 @@ PyTypeObject pySamplebuffer_Type = { // Must have this as a function because the import_array macro in numpy version 1.01 strangely has a return statement included. // Furthermore the import error printout from this macro is ugly, but we accept that for now, waiting for later numpy updates to fix all of this. +// The situation is further complicated by Python 3, where numpy's import_array returns NULL... #ifdef PY_ARRAYS -static int __import_array__() +#ifdef PY_NUMARRAY +#define IMPORT_ARRAY_RET_TYPE void +#elif PY_MAJOR_VERSION < 3 +#define IMPORT_ARRAY_RET_TYPE void +#else +#define IMPORT_ARRAY_RET_TYPE void * +#endif +static IMPORT_ARRAY_RET_TYPE __import_array__() { #ifdef PY_NUMARRAY import_libnumarray(); #else import_array(); #endif - return 0; } #endif diff --git a/source/pybuffer.h b/source/pybuffer.h index b14a6e5..8c98255 100644 --- a/source/pybuffer.h +++ b/source/pybuffer.h @@ -60,10 +60,10 @@ inline PyObject *pySamplebuffer_FromString(PyObject *str) #if PY_MAJOR_VERSION < 3 if(PyString_Check(str)) cstr = PyString_AsString(str); - else -#endif +#else if(PyUnicode_Check(str)) cstr = PyUnicode_AsUTF8(str); +#endif else PyErr_SetString(PyExc_TypeError, "Type must be string or unicode"); return pySamplebuffer_FromString(cstr); diff --git a/source/pyext.cpp b/source/pyext.cpp index c96b7b3..d6a2106 100644 --- a/source/pyext.cpp +++ b/source/pyext.cpp @@ -72,7 +72,11 @@ void pyext::Setup(t_classid c) // add methods to class for (def = meth_tbl; def->ml_name != NULL; def++) { PyObject *func = PyCFunction_New(def, NULL); - PyObject *method = PyInstanceMethod_New(func); // increases class_obj ref count by 1 +#if PY_MAJOR_VERSION < 3 + PyObject *method = PyMethod_New(func, NULL, class_obj); // increases class_obj ref count by 1 +#else + PyObject *method = PyInstanceMethod_New(func); +#endif PyDict_SetItemString(class_dict, def->ml_name, method); Py_DECREF(func); Py_DECREF(method); @@ -379,10 +383,10 @@ bool pyext::InitInOut(int &inl,int &outl) #if PY_MAJOR_VERSION < 3 if(PyInt_Check(res)) inl = PyInt_AS_LONG(res); - else -#endif +#else if(PyLong_Check(res)) inl = PyLong_AS_LONG(res); +#endif else PyErr_SetString(PyExc_TypeError, "Type must be integer"); Py_DECREF(res); @@ -403,10 +407,10 @@ bool pyext::InitInOut(int &inl,int &outl) #if PY_MAJOR_VERSION < 3 if(PyInt_Check(res)) outl = PyInt_AS_LONG(res); - else -#endif +#else if(PyLong_Check(res)) outl = PyLong_AS_LONG(res); +#endif else PyErr_SetString(PyExc_TypeError, "Type must be integer"); diff --git a/source/pysymbol.cpp b/source/pysymbol.cpp index 5d2a46c..d03cb2f 100644 --- a/source/pysymbol.cpp +++ b/source/pysymbol.cpp @@ -35,9 +35,10 @@ static int symbol_init(PyObject *self, PyObject *args, PyObject *kwds) #if PY_MAJOR_VERSION < 3 else if(PyString_Check(arg)) ((pySymbol *)self)->sym = flext::MakeSymbol(PyString_AS_STRING(arg)); -#endif +#else else if(PyUnicode_Check(arg)) ((pySymbol *)self)->sym = flext::MakeSymbol(PyUnicode_AsUTF8(arg)); +#endif else { PyErr_SetString(PyExc_TypeError, "string, unicode or symbol argument expected"); ret = -1; diff --git a/source/pysymbol.h b/source/pysymbol.h index 7ecd9cc..5e7353c 100644 --- a/source/pysymbol.h +++ b/source/pysymbol.h @@ -65,10 +65,10 @@ inline PyObject *pySymbol_FromString(PyObject *str) #if PY_MAJOR_VERSION < 3 if(PyString_Check(str)) cstr = PyString_AsString(str); - else -#endif +#else if(PyUnicode_Check(str)) cstr = PyUnicode_AsUTF8(str); +#endif else PyErr_SetString(PyExc_TypeError, "Type must be string or unicode"); @@ -95,10 +95,10 @@ inline const t_symbol *pyObject_AsSymbol(PyObject *op) #if PY_MAJOR_VERSION < 3 if(PyString_Check(op)) return flext::MakeSymbol(PyString_AS_STRING(op)); - else -#endif +#else if(PyUnicode_Check(op)) return flext::MakeSymbol(PyUnicode_AsUTF8(op)); +#endif else return pySymbol_AsSymbol(op); } From 4ec81db4e5ae38079a6c65c1009c04d41ee51217 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 17 Mar 2020 13:45:42 +0200 Subject: [PATCH 121/150] more python 3 fixing... simple-1.pd now works --- source/clmeth.cpp | 137 +++++++++++++++++++++++++++++++++++++++----- source/pybase.cpp | 4 ++ source/pybuffer.cpp | 2 +- source/pyext.cpp | 17 +++++- 4 files changed, 143 insertions(+), 17 deletions(-) diff --git a/source/clmeth.cpp b/source/clmeth.cpp index 340dcc4..1a18eb1 100644 --- a/source/clmeth.cpp +++ b/source/clmeth.cpp @@ -29,17 +29,22 @@ PyMethodDef pyext::meth_tbl[] = #endif { "_invec", pyext::pyext_invec, METH_VARARGS,"Get input vector" }, { "_outvec", pyext::pyext_outvec, METH_VARARGS,"Get output vector" }, +#if PY_MAJOR_VERSION >= 3 + { "__setattr__", pyext::pyext_setattr, METH_VARARGS,"Set class attribute" }, + { "__getattr__", pyext::pyext_getattr, METH_VARARGS,"Get class attribute" }, +#endif {NULL, NULL, 0, NULL} /* Sentinel */ }; PyMethodDef pyext::attr_tbl[] = { +#if PY_MAJOR_VERSION < 3 { "__setattr__", pyext::pyext_setattr, METH_VARARGS,"Set class attribute" }, { "__getattr__", pyext::pyext_getattr, METH_VARARGS,"Get class attribute" }, +#endif { NULL, NULL,0,NULL }, }; - const char *pyext::pyext_doc = "py/pyext - python external object for PD and Max/MSP, (C)2002-2008 Thomas Grill\n" "\n" @@ -76,15 +81,21 @@ PyObject* pyext::pyext__del__(PyObject *,PyObject *args) } */ +#if PY_MAJOR_VERSION < 3 PyObject* pyext::pyext__str__(PyObject *,PyObject *args) +#else +PyObject* pyext::pyext__str__(PyObject *self, PyObject *args) +#endif { +#if PY_MAJOR_VERSION < 3 PyObject *self; if(!PyArg_ParseTuple(args, "O:pyext__str__",&self)) { // handle error ERRINTERNAL(); return NULL; } - +#endif + return #if PY_MAJOR_VERSION < 3 PyString_FromFormat @@ -94,10 +105,20 @@ PyObject* pyext::pyext__str__(PyObject *,PyObject *args) ("", self); } +#if PY_MAJOR_VERSION < 3 PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) +#else +PyObject* pyext::pyext_setattr(PyObject *self, PyObject *args) +#endif { +#if PY_MAJOR_VERSION < 3 PyObject *self,*name,*val; - if(!PyArg_ParseTuple(args, "OOO:pyext_setattr", &self,&name,&val)) { + if(!PyArg_ParseTuple(args, "OOO:pyext_setattr", &self,&name,&val)) +#else + PyObject *name, *val; + if(!PyArg_ParseTuple(args, "OO:pyext_setattr", &name, &val)) +#endif + { // handle error ERRINTERNAL(); return NULL; @@ -121,19 +142,35 @@ PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) return Py_None; } +#if PY_MAJOR_VERSION < 3 PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) +#else +PyObject* pyext::pyext_getattr(PyObject *self, PyObject *args) +#endif { +#if PY_MAJOR_VERSION < 3 PyObject *self, *name, *ret = NULL; - if(!PyArg_ParseTuple(args, "OO:pyext_getattr", &self, &name)) { + if(!PyArg_ParseTuple(args, "OO:pyext_getattr", &self, &name)) +#else + PyObject *name, *ret = NULL; + if(!PyArg_ParseTuple(args, "O:pyext_getattr", &name)) +#endif + { // handle error ERRINTERNAL(); + return NULL; } #if PY_MAJOR_VERSION < 3 - if(PyString_Check(name)) { + if(PyString_Check(name)) +#else + if(PyUnicode_Check(name)) + +#endif + { +#if PY_MAJOR_VERSION < 3 const char *sname = PyString_AS_STRING(name); #else - if(PyUnicode_Check(name)) { const char *sname = PyUnicode_AsUTF8(name); #endif if(sname) { @@ -175,7 +212,11 @@ PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) } //! Send message to outlet +#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) +#else +PyObject *pyext::pyext_outlet(PyObject *self, PyObject *args) +#endif { bool ok = false; @@ -185,11 +226,19 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) int sz = PyTuple_GET_SIZE(args); // borrowed references! +#if PY_MAJOR_VERSION < 3 PyObject *self,*outl; +#else + PyObject *outl; +#endif if( sz >= 2 && - (self = PyTuple_GET_ITEM(args,0)) != NULL && +#if PY_MAJOR_VERSION < 3 + (self = PyTuple_GET_ITEM(args,0)) != NULL && +#else + self != NULL && +#endif (outl = PyTuple_GET_ITEM(args,1)) != NULL && #if PY_MAJOR_VERSION < 3 PyInt_Check(outl) @@ -256,11 +305,23 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) #ifdef FLEXT_THREADS //! Detach threads +#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_detach(PyObject *,PyObject *args) +#else +PyObject *pyext::pyext_detach(PyObject *self, PyObject *args) +#endif { - PyObject *self; +#if PY_MAJOR_VERSION < 3 + PyObject *self; +#endif int val; - if(!PyArg_ParseTuple(args, "Oi:pyext_detach",&self,&val)) { + if( +#if PY_MAJOR_VERSION < 3 + !PyArg_ParseTuple(args, "Oi:pyext_detach",&self,&val) +#else + !PyArg_ParseTuple(args, "i:pyext_detach", &val) +#endif + ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _detach(self,[0/1/2])"); return NULL; @@ -284,11 +345,23 @@ PyObject *pyext::pyext_detach(PyObject *,PyObject *args) } //! Stop running threads +#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_stop(PyObject *,PyObject *args) +#else +PyObject *pyext::pyext_stop(PyObject *self, PyObject *args) +#endif { - PyObject *self; +#if PY_MAJOR_VERSION < 3 + PyObject *self; +#endif int val = -1; - if(!PyArg_ParseTuple(args, "O|i:pyext_stop",&self,&val)) { + if( +#if PY_MAJOR_VERSION < 3 + !PyArg_ParseTuple(args, "O|i:pyext_stop",&self,&val) +#else + !PyArg_ParseTuple(args, "|i:pyext_stop", &val) +#endif + ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _stop(self,{wait time})"); return NULL; @@ -320,17 +393,27 @@ PyObject *pyext::pyext_stop(PyObject *,PyObject *args) #if FLEXT_SYS == FLEXT_SYS_PD //! Send message to canvas +#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) +#else +PyObject *pyext::pyext_tocanvas(PyObject *self, PyObject *args) +#endif { FLEXT_ASSERT(PyTuple_Check(args)); int sz = PyTuple_GET_SIZE(args); bool ok = false; +#if PY_MAJOR_VERSION < 3 PyObject *self; // borrowed ref +#endif if( sz >= 1 && +#if PY_MAJOR_VERSION < 3 (self = PyTuple_GET_ITEM(args,0)) != NULL +#else + self != NULL +#endif ) { pyext *ext = GetThis(self); if(!ext) { @@ -381,11 +464,23 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) } #endif +#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_invec(PyObject *,PyObject *args) +#else +PyObject *pyext::pyext_invec(PyObject *self, PyObject *args) +#endif { - PyObject *self; +#if PY_MAJOR_VERSION < 3 + PyObject *self; +#endif int val = -1; - if(!PyArg_ParseTuple(args, "O|i:pyext_invec",&self,&val)) { + if( +#if PY_MAJOR_VERSION < 3 + !PyArg_ParseTuple(args, "O|i:pyext_invec",&self,&val) +#else + !PyArg_ParseTuple(args, "|i:pyext_invec", &val) +#endif + ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _invec(self,inlet)"); return NULL; @@ -410,11 +505,23 @@ PyObject *pyext::pyext_invec(PyObject *,PyObject *args) return Py_None; } +#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_outvec(PyObject *,PyObject *args) +#else +PyObject *pyext::pyext_outvec(PyObject *self, PyObject *args) +#endif { - PyObject *self; +#if PY_MAJOR_VERSION < 3 + PyObject *self; +#endif int val = -1; - if(!PyArg_ParseTuple(args, "O|i:pyext_outvec",&self,&val)) { + if( +#if PY_MAJOR_VERSION < 3 + !PyArg_ParseTuple(args, "O|i:pyext_outvec",&self,&val) +#else + !PyArg_ParseTuple(args, "|i:pyext_outvec", &val) +#endif + ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _outvec(self,inlet)"); return NULL; diff --git a/source/pybase.cpp b/source/pybase.cpp index c778302..7a5358a 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -1058,7 +1058,11 @@ bool pybase::collect() PyObject *ret = PyObject_CallObject(gcollect,NULL); if(ret) { #ifdef FLEXT_DEBUG +#if PY_MAJOR_VERSION < 3 int refs = PyInt_AsLong(ret); +#else + int refs = PyLong_AsLong(ret); +#endif if(refs) post("py/pyext - Garbage collector reports %i unreachable objects",refs); #endif Py_DECREF(ret); diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index 4bba04e..22eb1c4 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -337,7 +337,7 @@ PyObject *arrayfrombuffer(PyObject *buf,int c,int n) Py_buffer view; int err = PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE | PyBUF_WRITABLE); if(!err) { - FLEXT_ASSERT(view->len <= n*c*sizeof(t_sample)); + FLEXT_ASSERT(view.len <= n*c*sizeof(t_sample)); // Py_INCREF(buf); // ATTENTION... this won't be released any more!! # ifdef PY_NUMPY arr = PyArray_NewFromDescr(&PyArray_Type,PyArray_DescrNewFromType(numtype),c == 1?1:2,shape,0,(char *)view.buf,NPY_WRITEABLE|NPY_C_CONTIGUOUS,NULL); diff --git a/source/pyext.cpp b/source/pyext.cpp index d6a2106..84f805d 100644 --- a/source/pyext.cpp +++ b/source/pyext.cpp @@ -214,7 +214,10 @@ bool pyext::Init() if(methname) { MakeInstance(); - if(pyobj) InitInOut(inlets,outlets); + if(pyobj) { + SetThis(); + InitInOut(inlets,outlets); + } } else inlets = outlets = 0; @@ -366,9 +369,11 @@ bool pyext::InitInOut(int &inl,int &outl) FLEXT_ASSERT(!ret); } +#if PY_MAJOR_VERSION < 3 // __init__ can override the number of inlets and outlets if(!DoInit()) // call __init__ constructor return false; +#endif if(inl < 0) { // get number of inlets @@ -440,6 +445,16 @@ bool pyext::MakeInstance() if(PyObject_IsInstance(pref, (PyObject *)&PyType_Type)) { // pyobj = PyBaseObject_Type.tp_new() // TODO: correctly initialize instance + + PyObject *pargs = MakePyArgs(NULL, initargs.Count(), initargs.Atoms()); + + if(!pargs) { + PyErr_Print(); + } else { + pyobj = PyObject_CallObject(pref, pargs); + + Py_DECREF(pargs); + } #endif if(!pyobj) PyErr_Print(); } From 6e8ea8212d6d9e9b451e30c81787b9f8f08b02eb Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 17 Mar 2020 17:16:42 +0200 Subject: [PATCH 122/150] python 3 - simple-2.pd now working --- source/clmeth.cpp | 98 ++++++----------------------------------------- source/pyext.cpp | 5 ++- 2 files changed, 14 insertions(+), 89 deletions(-) diff --git a/source/clmeth.cpp b/source/clmeth.cpp index 1a18eb1..a28ca1d 100644 --- a/source/clmeth.cpp +++ b/source/clmeth.cpp @@ -81,20 +81,14 @@ PyObject* pyext::pyext__del__(PyObject *,PyObject *args) } */ -#if PY_MAJOR_VERSION < 3 PyObject* pyext::pyext__str__(PyObject *,PyObject *args) -#else -PyObject* pyext::pyext__str__(PyObject *self, PyObject *args) -#endif { -#if PY_MAJOR_VERSION < 3 PyObject *self; if(!PyArg_ParseTuple(args, "O:pyext__str__",&self)) { // handle error ERRINTERNAL(); return NULL; } -#endif return #if PY_MAJOR_VERSION < 3 @@ -105,19 +99,10 @@ PyObject* pyext::pyext__str__(PyObject *self, PyObject *args) ("", self); } -#if PY_MAJOR_VERSION < 3 PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) -#else -PyObject* pyext::pyext_setattr(PyObject *self, PyObject *args) -#endif { -#if PY_MAJOR_VERSION < 3 PyObject *self,*name,*val; if(!PyArg_ParseTuple(args, "OOO:pyext_setattr", &self,&name,&val)) -#else - PyObject *name, *val; - if(!PyArg_ParseTuple(args, "OO:pyext_setattr", &name, &val)) -#endif { // handle error ERRINTERNAL(); @@ -135,26 +120,27 @@ PyObject* pyext::pyext_setattr(PyObject *self, PyObject *args) } */ if(!handled) { - PyDict_SetItem(self, name, val); + if( +#if PY_MAJOR_VERSION < 3 + PyDict_SetItem(self, name, val) +#else + PyObject_SetAttr(self, name, val) +#endif + < 0 + ) { + ERRINTERNAL(); + return NULL; + } } Py_INCREF(Py_None); return Py_None; } -#if PY_MAJOR_VERSION < 3 PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) -#else -PyObject* pyext::pyext_getattr(PyObject *self, PyObject *args) -#endif { -#if PY_MAJOR_VERSION < 3 PyObject *self, *name, *ret = NULL; if(!PyArg_ParseTuple(args, "OO:pyext_getattr", &self, &name)) -#else - PyObject *name, *ret = NULL; - if(!PyArg_ParseTuple(args, "O:pyext_getattr", &name)) -#endif { // handle error ERRINTERNAL(); @@ -212,11 +198,7 @@ PyObject* pyext::pyext_getattr(PyObject *self, PyObject *args) } //! Send message to outlet -#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) -#else -PyObject *pyext::pyext_outlet(PyObject *self, PyObject *args) -#endif { bool ok = false; @@ -226,19 +208,11 @@ PyObject *pyext::pyext_outlet(PyObject *self, PyObject *args) int sz = PyTuple_GET_SIZE(args); // borrowed references! -#if PY_MAJOR_VERSION < 3 PyObject *self,*outl; -#else - PyObject *outl; -#endif if( sz >= 2 && -#if PY_MAJOR_VERSION < 3 (self = PyTuple_GET_ITEM(args,0)) != NULL && -#else - self != NULL && -#endif (outl = PyTuple_GET_ITEM(args,1)) != NULL && #if PY_MAJOR_VERSION < 3 PyInt_Check(outl) @@ -305,22 +279,12 @@ PyObject *pyext::pyext_outlet(PyObject *self, PyObject *args) #ifdef FLEXT_THREADS //! Detach threads -#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_detach(PyObject *,PyObject *args) -#else -PyObject *pyext::pyext_detach(PyObject *self, PyObject *args) -#endif { -#if PY_MAJOR_VERSION < 3 PyObject *self; -#endif int val; if( -#if PY_MAJOR_VERSION < 3 !PyArg_ParseTuple(args, "Oi:pyext_detach",&self,&val) -#else - !PyArg_ParseTuple(args, "i:pyext_detach", &val) -#endif ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _detach(self,[0/1/2])"); @@ -345,22 +309,12 @@ PyObject *pyext::pyext_detach(PyObject *self, PyObject *args) } //! Stop running threads -#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_stop(PyObject *,PyObject *args) -#else -PyObject *pyext::pyext_stop(PyObject *self, PyObject *args) -#endif { -#if PY_MAJOR_VERSION < 3 PyObject *self; -#endif int val = -1; if( -#if PY_MAJOR_VERSION < 3 !PyArg_ParseTuple(args, "O|i:pyext_stop",&self,&val) -#else - !PyArg_ParseTuple(args, "|i:pyext_stop", &val) -#endif ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _stop(self,{wait time})"); @@ -393,27 +347,17 @@ PyObject *pyext::pyext_stop(PyObject *self, PyObject *args) #if FLEXT_SYS == FLEXT_SYS_PD //! Send message to canvas -#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) -#else -PyObject *pyext::pyext_tocanvas(PyObject *self, PyObject *args) -#endif { FLEXT_ASSERT(PyTuple_Check(args)); int sz = PyTuple_GET_SIZE(args); bool ok = false; -#if PY_MAJOR_VERSION < 3 PyObject *self; // borrowed ref -#endif if( sz >= 1 && -#if PY_MAJOR_VERSION < 3 (self = PyTuple_GET_ITEM(args,0)) != NULL -#else - self != NULL -#endif ) { pyext *ext = GetThis(self); if(!ext) { @@ -464,22 +408,12 @@ PyObject *pyext::pyext_tocanvas(PyObject *self, PyObject *args) } #endif -#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_invec(PyObject *,PyObject *args) -#else -PyObject *pyext::pyext_invec(PyObject *self, PyObject *args) -#endif { -#if PY_MAJOR_VERSION < 3 PyObject *self; -#endif int val = -1; if( -#if PY_MAJOR_VERSION < 3 !PyArg_ParseTuple(args, "O|i:pyext_invec",&self,&val) -#else - !PyArg_ParseTuple(args, "|i:pyext_invec", &val) -#endif ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _invec(self,inlet)"); @@ -505,22 +439,12 @@ PyObject *pyext::pyext_invec(PyObject *self, PyObject *args) return Py_None; } -#if PY_MAJOR_VERSION < 3 PyObject *pyext::pyext_outvec(PyObject *,PyObject *args) -#else -PyObject *pyext::pyext_outvec(PyObject *self, PyObject *args) -#endif { -#if PY_MAJOR_VERSION < 3 PyObject *self; -#endif int val = -1; if( -#if PY_MAJOR_VERSION < 3 !PyArg_ParseTuple(args, "O|i:pyext_outvec",&self,&val) -#else - !PyArg_ParseTuple(args, "|i:pyext_outvec", &val) -#endif ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _outvec(self,inlet)"); diff --git a/source/pyext.cpp b/source/pyext.cpp index 84f805d..6e9636b 100644 --- a/source/pyext.cpp +++ b/source/pyext.cpp @@ -74,10 +74,11 @@ void pyext::Setup(t_classid c) PyObject *func = PyCFunction_New(def, NULL); #if PY_MAJOR_VERSION < 3 PyObject *method = PyMethod_New(func, NULL, class_obj); // increases class_obj ref count by 1 + PyDict_SetItemString(class_dict, def->ml_name, method); #else - PyObject *method = PyInstanceMethod_New(func); + PyObject *method = PyMethod_New(func, class_obj); + PyObject_SetAttrString(class_obj, def->ml_name, method); #endif - PyDict_SetItemString(class_dict, def->ml_name, method); Py_DECREF(func); Py_DECREF(method); } From 4408d3d84443dd4743a1ea9edbc0f2711ffd04c2 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 17 Mar 2020 17:21:27 +0200 Subject: [PATCH 123/150] fix script.py for python 3, fix simple.py docstring --- scripts/script.py | 9 ++++++--- scripts/simple.py | 11 ++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/scripts/script.py b/scripts/script.py index ff41730..0ef6492 100644 --- a/scripts/script.py +++ b/scripts/script.py @@ -7,14 +7,17 @@ """Several functions to show the py script functionality""" +from __future__ import print_function + +from functools import reduce import sys -print "Script initialized" +print("Script initialized") try: - print "Script arguments: ",sys.argv + print("Script arguments: ",sys.argv) except: - print + print() def numargs(*args): # variable argument list """Return the number of arguments""" diff --git a/scripts/simple.py b/scripts/simple.py index b2c40bc..4377a16 100644 --- a/scripts/simple.py +++ b/scripts/simple.py @@ -1,4 +1,3 @@ -from __future__ import print_function # py/pyext - python script objects for PD and MaxMSP # # Copyright (c) 2002-2007 Thomas Grill (gr@grrrr.org) @@ -59,13 +58,15 @@ or self._outlet(outlet,arg) ... where arg is a sequence containing only atoms - Do not use _outlet inside __init__, since the outlets have not been created at that time. + Do not use _outlet inside __init__, since the outlets have not been created at that time. - Use pyext functions and methods: See the __doc__ strings of the pyext module and the pyext._class base class. """ +from __future__ import print_function + try: import pyext except: @@ -75,7 +76,7 @@ class ex1(pyext._class): """Example of a simple class which receives messages and prints to the console""" - + # number of inlets and outlets _inlets=3 _outlets=0 @@ -207,9 +208,9 @@ def float_2(self,f): self.tmp = f # handlers for MaxMSP int type - def int_1(self,f): + def int_1(self,f): self.float_1(f) - def int_2(self,f): + def int_2(self,f): self.float_2(f) From a32b6dbbbb1f20485e551c969f1d8078ecd3583f Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 17 Mar 2020 17:40:16 +0200 Subject: [PATCH 124/150] more python 3 compat work on example scripts --- scripts/buffer.py | 6 ++++-- scripts/simple.py | 9 ++++++++- scripts/threads.py | 15 ++++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/scripts/buffer.py b/scripts/buffer.py index b58ea42..401cc6b 100644 --- a/scripts/buffer.py +++ b/scripts/buffer.py @@ -12,18 +12,20 @@ Numeric, numarray and numpy (for all of them see http://numeric.scipy.org) """ +from __future__ import print_function + import sys try: import pyext except: - print "ERROR: This script must be loaded by the PD/Max py/pyext external" + print("ERROR: This script must be loaded by the PD/Max py/pyext external") try: # numpy is assumed here... numeric and numarray are considered deprecated import numpy as N except: - print "Failed importing numpy module:",sys.exc_value + print("Failed importing numpy module:",sys.exc_value) def mul(*args): # create buffer objects diff --git a/scripts/simple.py b/scripts/simple.py index 4377a16..3d749d3 100644 --- a/scripts/simple.py +++ b/scripts/simple.py @@ -72,6 +72,13 @@ except: print("ERROR: This script must be loaded by the PD/Max pyext external") +try: + # Python 2 + _long = long + del _long +except NameError: + long = int + ################################################################# class ex1(pyext._class): @@ -172,7 +179,7 @@ def float_2(self,f): # helper function - determine whether argument is a numeric type def isNumber(value): import types - if type(value) in (types.FloatType, types.IntType, types.LongType): + if type(value) in (float, int, long): return 1 else: return 0 diff --git a/scripts/threads.py b/scripts/threads.py index b029910..769127f 100755 --- a/scripts/threads.py +++ b/scripts/threads.py @@ -16,13 +16,22 @@ """ +from __future__ import print_function + try: import pyext except: - print "ERROR: This script must be loaded by the PD/Max pyext external" + print("ERROR: This script must be loaded by the PD/Max pyext external") from time import sleep +try: + # Python 2 + range = xrange +except NameError: + # Python 3 + pass + ################################################################# class ex1(pyext._class): @@ -37,10 +46,10 @@ class ex1(pyext._class): # method for bang to any inlet def bang_(self,n): - for i in xrange(self.loops): + for i in range(self.loops): # if _shouldexit is true, the thread ought to stop if self._shouldexit: - print "BREAK" + print("BREAK") break self._outlet(n,i) From daa554340acdec6e13cfa7e47a8212f7d6808632 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Mon, 23 Mar 2020 19:04:23 +0200 Subject: [PATCH 125/150] first shot at pybuffer in py3. still buggy... --- source/pybuffer.cpp | 143 ++++++++++++++++++++++++++++++++++++++++++-- source/pycompat.cpp | 93 ++++++++++++++++++++++++++++ source/pycompat.h | 40 +++++++++++++ source/pyprefix.h | 23 +++++++ 4 files changed, 293 insertions(+), 6 deletions(-) create mode 100644 source/pycompat.cpp create mode 100644 source/pycompat.h diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index 22eb1c4..d19e817 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -43,6 +43,7 @@ inline bool arrsupport() { return numtype != tAny; } #endif #endif +#include "pycompat.h" PyObject *pybase::py_arraysupport(PyObject *self,PyObject *args) { @@ -57,7 +58,7 @@ PyObject *pybase::py_arraysupport(PyObject *self,PyObject *args) } -// PD defines a T_OBJECT symbol +// undefine PD's T_OBJECT to avoid conflict with Python's #undef T_OBJECT #ifdef PY_USE_FRAMEWORK @@ -301,6 +302,9 @@ static PyObject *buffer_item(PyObject *s,Py_ssize_t i) pySamplebuffer *self = reinterpret_cast(s); PyObject *ret; if(self->buf) { + if(i < 0) { + i += self->buf->Frames(); + } if (i < 0 || i >= self->buf->Frames()) { PyErr_SetString(PyExc_IndexError,"Index out of range"); ret = NULL; @@ -514,16 +518,139 @@ static PyObject *buffer_repeat(PyObject *s,Py_ssize_t rep) return NULL; } +static PyObject *buffer_subscript(PyObject *s, PyObject *item) +{ + pySamplebuffer *self = reinterpret_cast(s); + PyObject *ret; + +#ifdef PY_ARRAYS + if(arrsupport()) { + if(self->buf) { + const int n = self->buf->Frames(); + const int c = self->buf->Channels(); + + PyObject *nobj = arrayfrombuffer((PyObject *) self, c, n); + ret = PyObject_GetItem(nobj, item); + Py_DECREF(nobj); + } else { + Py_INCREF(Py_None); + ret = Py_None; + } + } + else +#endif + if(PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if(i == -1 && PyErr_Occurred()) { + ret = NULL; + } else { + if(i < 0) + i += PyList_GET_SIZE(self); + + ret = buffer_item(s, i); + } + } else if(PySlice_Check(item)) { + PyErr_SetString(PyExc_RuntimeError, "No array support"); + ret = NULL; + } else { + PyErr_Format( + PyExc_TypeError, + "buffer indices must be integers or slices, not %.200s", + item->ob_type->tp_name + ); + ret = NULL; + } + + return ret; +} + +static int buffer_ass_subscript(PyObject *s, PyObject *item, PyObject *value) +{ + pySamplebuffer *self = reinterpret_cast(s); + int ret; + + if(PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if(i == -1 && PyErr_Occurred()) { + ret = -1; + } else { + ret = buffer_ass_item(s, i, value); + } + } else if(PySlice_Check(item)) { +#ifdef PY_ARRAYS + if(arrsupport()) { + if(self->buf) { + const int n = self->buf->Frames(); + const int c = self->buf->Channels(); + + PyArrayObject *out = (PyArrayObject *) PyArray_ContiguousFromObject(value, numtype, 1, 2); + const t_sample *src = (t_sample *) out->data; + + if(!out) { + // exception already set + ret = -1; + } else if(out->nd != 1) { + PyErr_SetString(PyExc_NotImplementedError, "Multiple dimensions not supported yet"); + ret = -1; + } else { + Py_ssize_t ilow, ihigh, istep; + + if(PySlice_Unpack(item, &ilow, &ihigh, &istep) < 0) { + ret = -1; + } else { + Py_ssize_t dlen = PySlice_AdjustIndices(n, &ilow, &ihigh, istep); + int slen = out->dimensions[0]; + int cnt = slen < dlen ? slen : dlen; + flext::buffer::Element *dst = self->buf->Data() + ilow; + for(int i = 0; i < cnt; i += istep) { + dst[i] = src[i]; + } + + self->dirty = true; + ret = 0; + } + } + + Py_XDECREF(out); + } else { + PyErr_SetString(PyExc_ValueError,"Buffer is not assigned"); + ret = -1; + } + } + else +#endif + { + PyErr_SetString(PyExc_RuntimeError, "No array support"); + ret = -1; + } + } else { + PyErr_Format( + PyExc_TypeError, + "buffer indices must be integers or slices, not %.200s", + item->ob_type->tp_name + ); + ret = -1; + } + + return ret; +} static PySequenceMethods buffer_as_seq = { buffer_length, /* lenfunc sq_length __len__ */ buffer_concat, /* binaryfunc sq_concat __add__ */ buffer_repeat, /* ssizeargfunc sq_repeat __mul__ */ - buffer_item, /* ssizeargfunc sq_item; __getitem__ */ + NULL, /* ssizeargfunc sq_item; __getitem__ */ + NULL, /* intintargfunc sq_slice; __getslice__ */ NULL, /* ssizeobjargproc sq_ass_item __setitem__ */ - NULL, /* objobjproc sq_contains __contains__ */ - NULL, /* binaryfunc sq_inplace_concat __iadd__ */ - NULL /* ssizeargfunc sq_inplace_repeat __imul */ + NULL, /* intintobjargproc sq_ass_slice; __setslice__ */ +}; + +static PyMappingMethods buffer_as_mapping = { + buffer_length, // lenfunc mp_length + buffer_subscript, // binaryfunc mp_subscript + buffer_ass_subscript // objobjargproc mp_ass_subscript }; static PyObject *buffer_iter(PyObject *s) @@ -901,7 +1028,7 @@ PyTypeObject pySamplebuffer_Type = { buffer_repr, /*tp_repr*/ &buffer_as_number, /*tp_as_number*/ &buffer_as_seq, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ + &buffer_as_mapping, /*tp_as_mapping*/ buffer_hash, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ @@ -939,10 +1066,13 @@ PyTypeObject pySamplebuffer_Type = { #ifdef PY_ARRAYS #ifdef PY_NUMARRAY #define IMPORT_ARRAY_RET_TYPE void +#define IMPORT_ARRAY_RET_VALUE #elif PY_MAJOR_VERSION < 3 #define IMPORT_ARRAY_RET_TYPE void +#define IMPORT_ARRAY_RET_VALUE #else #define IMPORT_ARRAY_RET_TYPE void * +#define IMPORT_ARRAY_RET_VALUE NULL #endif static IMPORT_ARRAY_RET_TYPE __import_array__() { @@ -951,6 +1081,7 @@ static IMPORT_ARRAY_RET_TYPE __import_array__() #else import_array(); #endif + return IMPORT_ARRAY_RET_VALUE; } #endif diff --git a/source/pycompat.cpp b/source/pycompat.cpp new file mode 100644 index 0000000..809c830 --- /dev/null +++ b/source/pycompat.cpp @@ -0,0 +1,93 @@ +#include "pycompat.h" + +// copied from Python 3.8.2 for compatibility with pre-3.6.1 versions because +// doing the right thing with the older slice functions seems difficult... + +#if PY_VERSION_HEX < 0x03060100 +int +PySlice_Unpack(PyObject *_r, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) +{ + PySliceObject *r = (PySliceObject*)_r; + /* this is harder to get right than you might think */ + + Py_BUILD_ASSERT(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX); + + if (r->step == Py_None) { + *step = 1; + } + else { + if (!_PyEval_SliceIndex(r->step, step)) return -1; + if (*step == 0) { + PyErr_SetString(PyExc_ValueError, + "slice step cannot be zero"); + return -1; + } + /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it + * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it + * guards against later undefined behaviour resulting from code that + * does "step = -step" as part of a slice reversal. + */ + if (*step < -PY_SSIZE_T_MAX) + *step = -PY_SSIZE_T_MAX; + } + + if (r->start == Py_None) { + *start = *step < 0 ? PY_SSIZE_T_MAX : 0; + } + else { + if (!_PyEval_SliceIndex(r->start, start)) return -1; + } + + if (r->stop == Py_None) { + *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX; + } + else { + if (!_PyEval_SliceIndex(r->stop, stop)) return -1; + } + + return 0; +} + +Py_ssize_t +PySlice_AdjustIndices(Py_ssize_t length, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step) +{ + /* this is harder to get right than you might think */ + + assert(step != 0); + assert(step >= -PY_SSIZE_T_MAX); + + if (*start < 0) { + *start += length; + if (*start < 0) { + *start = (step < 0) ? -1 : 0; + } + } + else if (*start >= length) { + *start = (step < 0) ? length - 1 : length; + } + + if (*stop < 0) { + *stop += length; + if (*stop < 0) { + *stop = (step < 0) ? -1 : 0; + } + } + else if (*stop >= length) { + *stop = (step < 0) ? length - 1 : length; + } + + if (step < 0) { + if (*stop < *start) { + return (*start - *stop - 1) / (-step) + 1; + } + } + else { + if (*start < *stop) { + return (*stop - *start - 1) / step + 1; + } + } + return 0; +} +#endif diff --git a/source/pycompat.h b/source/pycompat.h new file mode 100644 index 0000000..3f5cb26 --- /dev/null +++ b/source/pycompat.h @@ -0,0 +1,40 @@ +#ifndef __PYCOMPAT_H +#define __PYCOMPAT_H + +#ifdef PY_USE_FRAMEWORK +#include +#else +#include +#endif + +// copied from Python 3.8.2 for compatibility with pre-3.6.1 versions because +// doing the right thing with the older slice functions seems difficult... + +#if PY_VERSION_HEX < 0x03060100 +#if PY_MAJOR_VERSION < 3 +/* Assert a build-time dependency, as an expression. + Your compile will fail if the condition isn't true, or can't be evaluated + by the compiler. This can be used in an expression: its value is 0. + Example: + #define foo_to_char(foo) \ + ((char *)(foo) \ + + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0)) + Written by Rusty Russell, public domain, http://ccodearchive.net/ */ +#define Py_BUILD_ASSERT_EXPR(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#define Py_BUILD_ASSERT(cond) do { \ + (void)Py_BUILD_ASSERT_EXPR(cond); \ + } while(0) +#endif + +int +PySlice_Unpack(PyObject *_r, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step); + +Py_ssize_t +PySlice_AdjustIndices(Py_ssize_t length, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step); +#endif + +#endif diff --git a/source/pyprefix.h b/source/pyprefix.h index e9a624c..7da820d 100644 --- a/source/pyprefix.h +++ b/source/pyprefix.h @@ -47,4 +47,27 @@ extern "C" { typedef int Py_ssize_t; #endif +// these are copied from the Python 3.8.2 source because doing the right thing +// with the pre-3.6.1 slice functions seems difficult... + +#if PY_MAJOR_VERSION < 3 +/* Assert a build-time dependency, as an expression. + Your compile will fail if the condition isn't true, or can't be evaluated + by the compiler. This can be used in an expression: its value is 0. + Example: + #define foo_to_char(foo) \ + ((char *)(foo) \ + + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0)) + Written by Rusty Russell, public domain, http://ccodearchive.net/ */ +#define Py_BUILD_ASSERT_EXPR(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#define Py_BUILD_ASSERT(cond) do { \ + (void)Py_BUILD_ASSERT_EXPR(cond); \ + } while(0) +#endif + +#if PY_VERSION_HEX < 0x03060100 +#endif + #endif From e3dfb2e1879f20093cdd24874f519cdaecf8b4df Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Mon, 30 Mar 2020 14:20:32 +0300 Subject: [PATCH 126/150] handle Pd array memory layout using strides --- build/gnumake-mac-gcc.inc | 3 +++ source/pybuffer.cpp | 57 +++++++++++++++------------------------ 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/build/gnumake-mac-gcc.inc b/build/gnumake-mac-gcc.inc index dadf7ce..3bd383e 100644 --- a/build/gnumake-mac-gcc.inc +++ b/build/gnumake-mac-gcc.inc @@ -74,3 +74,6 @@ endif endif endif + +#DEBUG = 1 +#DFLAGS += -DFLEXT_DEBUG diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index d19e817..c0e6499 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -228,55 +228,38 @@ static Py_ssize_t buffer_charbuffer(PyObject *obj, Py_ssize_t segment, } static int buffer_getbuffer(PyObject *obj, Py_buffer *view, int flags) { - if(flags & PyBUF_INDIRECT) { - PyErr_SetString(PyExc_BufferError, "PyBUF_INDIRECT not supported"); - view->obj = NULL; - return -1; - } - - if(flags & PyBUF_STRIDES) { - PyErr_SetString(PyExc_BufferError, "PyBUF_STRIDES not supported"); - view->obj = NULL; - return -1; - } - - if(flags & PyBUF_ND) { - PyErr_SetString(PyExc_BufferError, "PyBUF_ND not supported"); - view->obj = NULL; - return -1; - } + pySamplebuffer *self = reinterpret_cast(obj); + flext::buffer *b = self->buf; + const Py_ssize_t len = b->Channels()*b->Frames()*sizeof(t_sample); - if(flags & PyBUF_F_CONTIGUOUS) { - PyErr_SetString(PyExc_BufferError, "PyBUF_F_CONTIGUOUS not supported"); + if(!(flags & PyBUF_STRIDES)) { view->obj = NULL; + PyErr_SetString(PyExc_BufferError, "Buffer requires support for strides"); return -1; } - pySamplebuffer *self = reinterpret_cast(obj); - flext::buffer *b = self->buf; + std::pair *shape_strides = new std::pair(); + shape_strides->first = b->Channels() * b->Frames(); + shape_strides->second = sizeof(FLEXT_ARRAYTYPE); - view->buf = (void *)b->Data(); - Py_INCREF(obj); + view->buf = (void *) b->Data(); view->obj = obj; - view->len = b->Channels()*b->Frames()*sizeof(t_sample); + view->len = len; view->readonly = false; - view->itemsize = 1; - view->format = NULL; + view->itemsize = sizeof(t_sample); + view->format = (flags & PyBUF_FORMAT) ? (char *) "B" : NULL; view->ndim = 1; - view->shape = NULL; - view->strides = NULL; + view->shape = &shape_strides->first; + view->strides = &shape_strides->second; view->suboffsets = NULL; - view->internal = NULL; - - if(flags & PyBUF_FORMAT) { - view->format = "B"; - } + view->internal = (void *) shape_strides; + Py_INCREF(self); return 0; } static void buffer_releasebuffer(PyObject *obj, Py_buffer *view) { - // nothing to do here + delete (std::pair *) view->internal; } static PyBufferProcs buffer_as_buffer = { @@ -339,12 +322,14 @@ PyObject *arrayfrombuffer(PyObject *buf,int c,int n) arr = (PyObject *)NA_NewAllFromBuffer(c == 1?1:2,shape,numtype,buf,0,0,NA_ByteOrder(),1,1); #else Py_buffer view; - int err = PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE | PyBUF_WRITABLE); + int err = PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE | PyBUF_C_CONTIGUOUS); if(!err) { FLEXT_ASSERT(view.len <= n*c*sizeof(t_sample)); // Py_INCREF(buf); // ATTENTION... this won't be released any more!! # ifdef PY_NUMPY - arr = PyArray_NewFromDescr(&PyArray_Type,PyArray_DescrNewFromType(numtype),c == 1?1:2,shape,0,(char *)view.buf,NPY_WRITEABLE|NPY_C_CONTIGUOUS,NULL); + npy_intp strides[2] = {*view.strides, 0}; + arr = PyArray_NewFromDescr(&PyArray_Type, PyArray_DescrNewFromType(numtype), + c == 1 ? 1 : 2, shape, strides, (char *) view.buf, NPY_ARRAY_WRITEABLE | NPY_ARRAY_C_CONTIGUOUS, NULL); # else arr = PyArray_FromDimsAndData(c == 1?1:2,shape,numtype,(char *)view.buf); # endif From ec04393dc13c5ef283988b90a0729ba00bbc5e71 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Mon, 30 Mar 2020 14:41:20 +0300 Subject: [PATCH 127/150] fix numpy buffer format --- source/pybuffer.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index c0e6499..92770a0 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -30,6 +30,11 @@ inline bool arrsupport() { return numtype != tAny; } #else # if defined(PY_NUMPY) # include +# if _FLEXT_NEED_SAMPLE_CONV +# define PY_NUMPY_BUFFER_FORMAT "f" +# else +# define PY_NUMPY_BUFFER_FORMAT "d" +# endif # else # ifdef PY_USE_FRAMEWORK # include @@ -247,7 +252,7 @@ static int buffer_getbuffer(PyObject *obj, Py_buffer *view, int flags) { view->len = len; view->readonly = false; view->itemsize = sizeof(t_sample); - view->format = (flags & PyBUF_FORMAT) ? (char *) "B" : NULL; + view->format = (flags & PyBUF_FORMAT) ? (char *) PY_NUMPY_BUFFER_FORMAT : NULL; view->ndim = 1; view->shape = &shape_strides->first; view->strides = &shape_strides->second; @@ -571,7 +576,6 @@ static int buffer_ass_subscript(PyObject *s, PyObject *item, PyObject *value) const int c = self->buf->Channels(); PyArrayObject *out = (PyArrayObject *) PyArray_ContiguousFromObject(value, numtype, 1, 2); - const t_sample *src = (t_sample *) out->data; if(!out) { // exception already set @@ -580,6 +584,8 @@ static int buffer_ass_subscript(PyObject *s, PyObject *item, PyObject *value) PyErr_SetString(PyExc_NotImplementedError, "Multiple dimensions not supported yet"); ret = -1; } else { + const t_sample *src = (t_sample *) out->data; + Py_ssize_t ilow, ihigh, istep; if(PySlice_Unpack(item, &ilow, &ihigh, &istep) < 0) { From e6782e7f7ecd38cf46d3c601a66ec19aacf21251 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 31 Mar 2020 14:34:00 +0300 Subject: [PATCH 128/150] port sig.py to python3 and fix dsp buffer handling --- scripts/sig.py | 18 ++++++++++-------- source/pybuffer.cpp | 27 ++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/scripts/sig.py b/scripts/sig.py index 7009cd8..075721f 100644 --- a/scripts/sig.py +++ b/scripts/sig.py @@ -11,15 +11,17 @@ It will probably once be replaced by Numeric(3) """ +from __future__ import print_function + try: import pyext except: - print "ERROR: This script must be loaded by the PD/Max py/pyext external" + print("ERROR: This script must be loaded by the PD/Max py/pyext external") try: import psyco psyco.full() - print "Using JIT compilation" + print("Using JIT compilation") except: # don't care pass @@ -29,7 +31,7 @@ try: import numpy as N except: - print "Failed importing numpy module:",sys.exc_value + print("Failed importing numpy module:",sys.exc_value) class gain(pyext._class): @@ -40,10 +42,10 @@ def __init__(self): def _signal(self): # Multiply input vector by gain and copy to output - try: - self._outvec(0)[:] = self._invec(0)*self.gain - except: - pass + try: + self._outvec(0)[:] = self._invec(0)*self.gain + except: + pass class gain2(pyext._class): @@ -54,7 +56,7 @@ def __init__(self): def _dsp(self): if not self._arraysupport(): - print "No DSP support" + print("No DSP support") return False # cache vectors in this scope diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index 92770a0..463a6fd 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -239,7 +239,13 @@ static int buffer_getbuffer(PyObject *obj, Py_buffer *view, int flags) { if(!(flags & PyBUF_STRIDES)) { view->obj = NULL; - PyErr_SetString(PyExc_BufferError, "Buffer requires support for strides"); + PyErr_SetString(PyExc_BufferError, "PyBUF_STRIDES is required"); + return -1; + } + + if(!(flags & PyBUF_FORMAT)) { + view->obj = NULL; + PyErr_SetString(PyExc_BufferError, "PyBUF_FORMAT is required"); return -1; } @@ -327,12 +333,27 @@ PyObject *arrayfrombuffer(PyObject *buf,int c,int n) arr = (PyObject *)NA_NewAllFromBuffer(c == 1?1:2,shape,numtype,buf,0,0,NA_ByteOrder(),1,1); #else Py_buffer view; - int err = PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE | PyBUF_C_CONTIGUOUS); + int err = PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE | PyBUF_FORMAT | PyBUF_STRIDES); if(!err) { FLEXT_ASSERT(view.len <= n*c*sizeof(t_sample)); // Py_INCREF(buf); // ATTENTION... this won't be released any more!! # ifdef PY_NUMPY - npy_intp strides[2] = {*view.strides, 0}; + // the results of PyObject_GetBuffer() differ a bit depending on + // whether we're dealing with a pySamplebuffer (Pd array) or a numpy + // array (Pd signal). + // + // for pySamplebuffer, we get stride information that must be used + // to correctly deal with float32 Pd. + // + // for numpy arrays, we get strides=1 (due to format="B"), which + // breaks PyArray_NewFromDescr(), so instead we pass strides=NULL. + bool use_strides = pySamplebuffer_Check(buf); + npy_intp strides_arr[2] = {0, 0}; + npy_intp *strides = NULL; + if(use_strides) { + strides_arr[0] = *view.strides; + strides = strides_arr; + } arr = PyArray_NewFromDescr(&PyArray_Type, PyArray_DescrNewFromType(numtype), c == 1 ? 1 : 2, shape, strides, (char *) view.buf, NPY_ARRAY_WRITEABLE | NPY_ARRAY_C_CONTIGUOUS, NULL); # else From aaaf6c1e20cf87dc0258b2b13e9ba91596515153 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 31 Mar 2020 15:20:09 +0300 Subject: [PATCH 129/150] port sendrecv.py to python3 --- scripts/sendrecv.py | 220 ++++++++++++++++++++++---------------------- 1 file changed, 111 insertions(+), 109 deletions(-) diff --git a/scripts/sendrecv.py b/scripts/sendrecv.py index 9d873ba..0c58a5e 100644 --- a/scripts/sendrecv.py +++ b/scripts/sendrecv.py @@ -18,10 +18,12 @@ """ +from __future__ import print_function + try: - import pyext + import pyext except: - print "ERROR: This script must be loaded by the PD/Max pyext external" + print("ERROR: This script must be loaded by the PD/Max pyext external") from time import sleep @@ -29,92 +31,92 @@ ################################################################# def recv_gl(arg): - """This is a global receive function, it has no access to class members.""" - print "GLOBAL",arg + """This is a global receive function, it has no access to class members.""" + print("GLOBAL",arg) class ex1(pyext._class): - """Example of a class which receives and sends messages + """Example of a class which receives and sends messages - It has two creation arguments: a receiver and a sender name. - There are no inlets and outlets. - Python functions (one global function, one class method) are bound to PD's or Max/MSP's receive symbols. - The class method sends the received messages out again. - """ + It has two creation arguments: a receiver and a sender name. + There are no inlets and outlets. + Python functions (one global function, one class method) are bound to PD's or Max/MSP's receive symbols. + The class method sends the received messages out again. + """ - # no inlets and outlets - _inlets=1 - _outlets=0 + # no inlets and outlets + _inlets=1 + _outlets=0 - recvname="" - sendname="" + recvname="" + sendname="" - def recv(self,*arg): - """This is a class-local receive function, which has access to class members.""" + def recv(self,*arg): + """This is a class-local receive function, which has access to class members.""" - # print some stuff - print "CLASS",self.recvname,arg + # print some stuff + print("CLASS",self.recvname,arg) - # send data to specified send address - self._send(self.sendname,arg) + # send data to specified send address + self._send(self.sendname,arg) - def __init__(self,*args): - """Class constructor""" + def __init__(self,*args): + """Class constructor""" - # store sender/receiver names - if len(args) >= 1: self.recvname = args[0] - if len(args) >= 2: self.sendname = args[1] + # store sender/receiver names + if len(args) >= 1: self.recvname = args[0] + if len(args) >= 2: self.sendname = args[1] - self.bind_1() + self.bind_1() - def bind_1(self): - # bind functions to receiver names - # both are called upon message - self._bind(self.recvname,self.recv) - self._bind(self.recvname,recv_gl) + def bind_1(self): + # bind functions to receiver names + # both are called upon message + self._bind(self.recvname,self.recv) + self._bind(self.recvname,recv_gl) - def unbind_1(self): - self._unbind(self.recvname,self.recv) - self._unbind(self.recvname,recv_gl) + def unbind_1(self): + self._unbind(self.recvname,self.recv) + self._unbind(self.recvname,recv_gl) - def __del__(self): - """Class destructor""" + def __del__(self): + """Class destructor""" - # unbinding is automatically done at destruction - pass + # unbinding is automatically done at destruction + pass ################################################################# class ex2(pyext._class): - """Example of a class which receives a message and forwards it to an outlet + """Example of a class which receives a message and forwards it to an outlet - It has one creation argument: the receiver name. - """ + It has one creation argument: the receiver name. + """ - # define inlets and outlets - _inlets=0 - _outlets=1 + # define inlets and outlets + _inlets=0 + _outlets=1 - recvname="" + recvname="" - def recv(self,*arg): - """This is a class-local receive function""" + def recv(self,*arg): + """This is a class-local receive function""" - # send received data to outlet - self._outlet(1,arg) + # send received data to outlet + self._outlet(1,arg) - def __init__(self,rname): - """Class constructor""" + def __init__(self,rname): + """Class constructor""" - # store receiver names - self.recvname = rname + # store receiver names + self.recvname = rname - # bind function to receiver name - self._bind(self.recvname,self.recv) + # bind function to receiver name + self._bind(self.recvname,self.recv) ################################################################# @@ -124,57 +126,57 @@ def __init__(self,rname): from random import random,randint class ex3(pyext._class): - """Example of a class which does some object manipulation by scripting""" - - - # define inlets and outlets - _inlets=1 - _outlets=0 - - def __init__(self): - """Class constructor""" - - # called scripting method should run on its own thread - if self._isthreaded: - print "Threading is on" - self._detach(1) - - def bang_1(self): - """Do some scripting - PD only!""" - - num = 12 # number of objects - ori = complex(150,180) # origin - rad = 100 # radius - l = range(num) # initialize list - - # make flower - self._tocanvas("obj",ori.real,ori.imag,"bng",20,250,50,0,"empty","yeah","empty",0,-6,64,8,-24198,-1,-1) - for i in xrange(num): - l[i] = ori+rad*exp(complex(0,i*2*pi/num)) - self._tocanvas("obj",l[i].real,l[i].imag,"bng",15,250,50,0,"empty","yeah"+str(i),"empty",0,-6,64,8,0,-1,-1) - self._tocanvas("connect",6,0,7+i,0) - - # blink - for i in range(10): - self._send("yeah","bang") - sleep(1./(i+1)) - - # move objects around - for i in xrange(200): - ix = randint(0,num-1) - l[ix] = ori+rad*complex(2*random()-1,2*random()-1) - self._send("yeah"+str(ix),"pos",l[ix].real,l[ix].imag) - sleep(0.02) - - # now delete - # this is not well-done... from time to time an object remains - self._tocanvas("editmode",1) - for i in xrange(num): - self._tocanvas("mouse",l[i].real,l[i].imag,0,0) - self._tocanvas("cut") - - self._tocanvas("mouse",ori.real+1,ori.imag+1,0,0) - self._tocanvas("cut") - - self._tocanvas("editmode",0) + """Example of a class which does some object manipulation by scripting""" + + + # define inlets and outlets + _inlets=1 + _outlets=0 + + def __init__(self): + """Class constructor""" + + # called scripting method should run on its own thread + if self._isthreaded: + print("Threading is on") + self._detach(1) + + def bang_1(self): + """Do some scripting - PD only!""" + + num = 12 # number of objects + ori = complex(150,180) # origin + rad = 100 # radius + l = range(num) # initialize list + + # make flower + self._tocanvas("obj",ori.real,ori.imag,"bng",20,250,50,0,"empty","yeah","empty",0,-6,64,8,-24198,-1,-1) + for i in xrange(num): + l[i] = ori+rad*exp(complex(0,i*2*pi/num)) + self._tocanvas("obj",l[i].real,l[i].imag,"bng",15,250,50,0,"empty","yeah"+str(i),"empty",0,-6,64,8,0,-1,-1) + self._tocanvas("connect",6,0,7+i,0) + + # blink + for i in range(10): + self._send("yeah","bang") + sleep(1./(i+1)) + + # move objects around + for i in xrange(200): + ix = randint(0,num-1) + l[ix] = ori+rad*complex(2*random()-1,2*random()-1) + self._send("yeah"+str(ix),"pos",l[ix].real,l[ix].imag) + sleep(0.02) + + # now delete + # this is not well-done... from time to time an object remains + self._tocanvas("editmode",1) + for i in xrange(num): + self._tocanvas("mouse",l[i].real,l[i].imag,0,0) + self._tocanvas("cut") + + self._tocanvas("mouse",ori.real+1,ori.imag+1,0,0) + self._tocanvas("cut") + + self._tocanvas("editmode",0) From e8a95d75049dec3a359be7b00558d9eb60145264 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 31 Mar 2020 15:36:52 +0300 Subject: [PATCH 130/150] untabify simple.py --- scripts/simple.py | 246 +++++++++++++++++++++++----------------------- 1 file changed, 123 insertions(+), 123 deletions(-) diff --git a/scripts/simple.py b/scripts/simple.py index 3d749d3..9e57f10 100644 --- a/scripts/simple.py +++ b/scripts/simple.py @@ -13,64 +13,64 @@ - Inherit your class from pyext._class - Specfiy the number of inlets and outlets: - Use the class members (variables) _inlets and _outlets - If not given they default to 1 - You can also use class methods with the same names to return the respective number + Use the class members (variables) _inlets and _outlets + If not given they default to 1 + You can also use class methods with the same names to return the respective number - Constructors/Destructors - You can specify an __init__ constructor and/or an __del__ destructor. - The constructor will be called with the object's arguments + You can specify an __init__ constructor and/or an __del__ destructor. + The constructor will be called with the object's arguments - e.g. if your PD or MaxMSP object looks like - [pyext script class arg1 arg2 arg3] + e.g. if your PD or MaxMSP object looks like + [pyext script class arg1 arg2 arg3] - then the __init__(self,*args) function will be called with a tuple argument - args = (arg1,arg2,arg3) - With this syntax, you will have to give at least one argument. - By defining the constructor as __init__(self,*args) you can also initialize - the class without arguments. + then the __init__(self,*args) function will be called with a tuple argument + args = (arg1,arg2,arg3) + With this syntax, you will have to give at least one argument. + By defining the constructor as __init__(self,*args) you can also initialize + the class without arguments. - Methods called by pyext - The general format is 'tag_inlet(self,arg)' resp. 'tag_inlet(self,*args)': - tag is the PD or MaxMSP message header.. either bang, float, list etc. - inlet is the inlet (starting from 1) from which messages are received. - args is a tuple which corresponds to the content of the message. args can be omitted. + The general format is 'tag_inlet(self,arg)' resp. 'tag_inlet(self,*args)': + tag is the PD or MaxMSP message header.. either bang, float, list etc. + inlet is the inlet (starting from 1) from which messages are received. + args is a tuple which corresponds to the content of the message. args can be omitted. - The inlet index can be omitted. The method name then has the format 'tag_(self,inlet,args)'. - Here, the inlet index is a additional parameter to the method + The inlet index can be omitted. The method name then has the format 'tag_(self,inlet,args)'. + Here, the inlet index is a additional parameter to the method - You can also set up methods which react on any message. These have the special forms - _anything_inlet(self,*args) - or - _anything_(self,inlet,*args) + You can also set up methods which react on any message. These have the special forms + _anything_inlet(self,*args) + or + _anything_(self,inlet,*args) - Please see below for examples. + Please see below for examples. - Any return values are ignored - use _outlet (see below). + Any return values are ignored - use _outlet (see below). - Generally, you should avoid method_, method_xx forms for your non-pyext class methods. - Identifiers (variables and functions) with leading underscores are reserved for pyext. + Generally, you should avoid method_, method_xx forms for your non-pyext class methods. + Identifiers (variables and functions) with leading underscores are reserved for pyext. - Send messages to outlets: - Use the inherited _outlet method. - You can either use the form - self._outlet(outlet,arg1,arg2,arg3,arg4) ... where all args are atoms (no sequence types!) - or - self._outlet(outlet,arg) ... where arg is a sequence containing only atoms - - Do not use _outlet inside __init__, since the outlets have not been created at that time. + Use the inherited _outlet method. + You can either use the form + self._outlet(outlet,arg1,arg2,arg3,arg4) ... where all args are atoms (no sequence types!) + or + self._outlet(outlet,arg) ... where arg is a sequence containing only atoms + + Do not use _outlet inside __init__, since the outlets have not been created at that time. - Use pyext functions and methods: - See the __doc__ strings of the pyext module and the pyext._class base class. + See the __doc__ strings of the pyext module and the pyext._class base class. """ from __future__ import print_function try: - import pyext + import pyext except: - print("ERROR: This script must be loaded by the PD/Max pyext external") + print("ERROR: This script must be loaded by the PD/Max pyext external") try: # Python 2 @@ -82,142 +82,142 @@ ################################################################# class ex1(pyext._class): - """Example of a simple class which receives messages and prints to the console""" - - # number of inlets and outlets - _inlets=3 - _outlets=0 + """Example of a simple class which receives messages and prints to the console""" + + # number of inlets and outlets + _inlets=3 + _outlets=0 - # methods for first inlet + # methods for first inlet - def bang_1(self): - print("Bang into first inlet") + def bang_1(self): + print("Bang into first inlet") - def int_1(self,f): - print("Integer",f,"into first inlet") + def int_1(self,f): + print("Integer",f,"into first inlet") - def float_1(self,f): - print("Float",f,"into first inlet") + def float_1(self,f): + print("Float",f,"into first inlet") - def list_1(self,*s): - print("List",s,"into first inlet") + def list_1(self,*s): + print("List",s,"into first inlet") - # methods for second inlet + # methods for second inlet - def hey_2(self): - print("Tag 'hey' into second inlet") + def hey_2(self): + print("Tag 'hey' into second inlet") - def ho_2(self): - print("Tag 'ho' into second inlet") + def ho_2(self): + print("Tag 'ho' into second inlet") - def lets_2(self): - print("Tag 'lets' into second inlet") + def lets_2(self): + print("Tag 'lets' into second inlet") - def go_2(self): - print("Tag 'go' into second inlet") + def go_2(self): + print("Tag 'go' into second inlet") - def _anything_2(self,*args): - print("Some other message into second inlet:",args) + def _anything_2(self,*args): + print("Some other message into second inlet:",args) - # methods for third inlet + # methods for third inlet - def onearg_3(self,a): - print("Tag 'onearg' into third inlet:",a) + def onearg_3(self,a): + print("Tag 'onearg' into third inlet:",a) - def twoargs_3(self,*a): - if len(a) == 2: - print("Tag 'twoargs' into third inlet:",a[0],a[1]) - else: - print("Tag 'twoargs': wrong number of arguments") + def twoargs_3(self,*a): + if len(a) == 2: + print("Tag 'twoargs' into third inlet:",a[0],a[1]) + else: + print("Tag 'twoargs': wrong number of arguments") - def threeargs_3(self,*a): - if len(a) == 3: - print("Tag 'threeargs' into third inlet",a[0],a[1],a[2]) - else: - print("Tag 'threeargs': wrong number of arguments") + def threeargs_3(self,*a): + if len(a) == 3: + print("Tag 'threeargs' into third inlet",a[0],a[1],a[2]) + else: + print("Tag 'threeargs': wrong number of arguments") - def varargs_3(self,*args): - # with *args there can be arguments or not + def varargs_3(self,*args): + # with *args there can be arguments or not - print("Tag 'varargs' into third inlet",args) + print("Tag 'varargs' into third inlet",args) ################################################################# class ex2(pyext._class): - """Example of a simple class which receives messages and writes to outlets""" + """Example of a simple class which receives messages and writes to outlets""" - # number of inlets and outlets - _inlets=3 - _outlets=2 + # number of inlets and outlets + _inlets=3 + _outlets=2 - # methods for all inlets + # methods for all inlets - def hello_(self,n): - print("Tag 'hello' into inlet",n) + def hello_(self,n): + print("Tag 'hello' into inlet",n) - def _anything_(self,n,*args): - print("Message into inlet",n,":",args) + def _anything_(self,n,*args): + print("Message into inlet",n,":",args) - # methods for first inlet + # methods for first inlet - def float_1(self,f): - self._outlet(2,f) + def float_1(self,f): + self._outlet(2,f) - # methods for second inlet + # methods for second inlet - def float_2(self,f): - self._outlet(1,f) + def float_2(self,f): + self._outlet(1,f) ################################################################# # helper function - determine whether argument is a numeric type def isNumber(value): - import types - if type(value) in (float, int, long): - return 1 - else: - return 0 + import types + if type(value) in (float, int, long): + return 1 + else: + return 0 class ex3(pyext._class): - """Example of a simple class doing a typical number addition - - It uses a constructor and a class member as temporary storage. - """ + """Example of a simple class doing a typical number addition + + It uses a constructor and a class member as temporary storage. + """ - # number of inlets and outlets - _inlets=2 - _outlets=1 + # number of inlets and outlets + _inlets=2 + _outlets=1 - # temporary storage - tmp=0 + # temporary storage + tmp=0 - # constructor - def __init__(self,*args): - if len(args) == 1: - if isNumber(args[0]): - self.tmp = args[0] - else: - print("ex3: __init__ has superfluous arguments") + # constructor + def __init__(self,*args): + if len(args) == 1: + if isNumber(args[0]): + self.tmp = args[0] + else: + print("ex3: __init__ has superfluous arguments") - # methods + # methods - def float_1(self,f): - self._outlet(1,self.tmp+f) + def float_1(self,f): + self._outlet(1,self.tmp+f) - def float_2(self,f): - self.tmp = f + def float_2(self,f): + self.tmp = f - # handlers for MaxMSP int type - def int_1(self,f): - self.float_1(f) + # handlers for MaxMSP int type + def int_1(self,f): + self.float_1(f) - def int_2(self,f): - self.float_2(f) + def int_2(self,f): + self.float_2(f) From 36416a5dfc487c39b13bfd51cd1b708fb3dad2ae Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Mon, 6 Apr 2020 19:37:09 +0300 Subject: [PATCH 131/150] define pyext class using PyTypeObject --- source/bound.cpp | 12 ++-- source/clmeth.cpp | 175 +++++++++++++++++++--------------------------- source/pyext.cpp | 103 +++++++++++++++++++++------ source/pyext.h | 43 +++++++----- 4 files changed, 182 insertions(+), 151 deletions(-) diff --git a/source/bound.cpp b/source/bound.cpp index 01cf681..4ba7700 100644 --- a/source/bound.cpp +++ b/source/bound.cpp @@ -81,10 +81,10 @@ bool pyext::boundmeth(flext_base *th,t_symbol *sym,int argc,t_atom *argv,void *d return true; } -PyObject *pyext::pyext_bind(PyObject *,PyObject *args) +PyObject *pyext::pyext_bind(PyObject *self, PyObject *args) { - PyObject *self,*meth,*name; - if(!PyArg_ParseTuple(args, "OOO:pyext_bind", &self,&name,&meth)) // borrowed references + PyObject *meth,*name; + if(!PyArg_ParseTuple(args, "OO:pyext_bind",&name,&meth)) // borrowed references post("py/pyext - Wrong arguments!"); else if(!PyCallable_Check(meth)) { post("py/pyext - Wrong argument types!"); @@ -126,10 +126,10 @@ PyObject *pyext::pyext_bind(PyObject *,PyObject *args) return Py_None; } -PyObject *pyext::pyext_unbind(PyObject *,PyObject *args) +PyObject *pyext::pyext_unbind(PyObject *self, PyObject *args) { - PyObject *self,*meth,*name; - if(!PyArg_ParseTuple(args, "OOO:pyext_bind", &self,&name,&meth)) // borrowed references + PyObject *meth,*name; + if(!PyArg_ParseTuple(args, "OO:pyext_bind",&name,&meth)) // borrowed references post("py/pyext - Wrong arguments!"); else if(!PyCallable_Check(meth)) { post("py/pyext - Wrong argument types!"); diff --git a/source/clmeth.cpp b/source/clmeth.cpp index a28ca1d..f59fb4d 100644 --- a/source/clmeth.cpp +++ b/source/clmeth.cpp @@ -63,33 +63,8 @@ const char *pyext::pyext_doc = #endif ; -/* -PyObject* pyext::pyext__init__(PyObject *,PyObject *args) -{ -// post("pyext.__init__ called"); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* pyext::pyext__del__(PyObject *,PyObject *args) -{ -// post("pyext.__del__ called"); - - Py_INCREF(Py_None); - return Py_None; -} -*/ - -PyObject* pyext::pyext__str__(PyObject *,PyObject *args) -{ - PyObject *self; - if(!PyArg_ParseTuple(args, "O:pyext__str__",&self)) { - // handle error - ERRINTERNAL(); - return NULL; - } - +PyObject* pyext::pyext__str__(PyObject *self, PyObject *args) +{ return #if PY_MAJOR_VERSION < 3 PyString_FromFormat @@ -99,16 +74,17 @@ PyObject* pyext::pyext__str__(PyObject *,PyObject *args) ("", self); } -PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) +PyObject* pyext::pyext_setattr(PyObject *self, PyObject *args) { - PyObject *self,*name,*val; - if(!PyArg_ParseTuple(args, "OOO:pyext_setattr", &self,&name,&val)) + PyObject *name,*val; + if(!PyArg_ParseTuple(args, "OO:pyext_setattr",&name,&val)) { // handle error ERRINTERNAL(); return NULL; } - + post("setattr %s", PyUnicode_AsUTF8(name)); + bool handled = false; /* @@ -124,7 +100,7 @@ PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) #if PY_MAJOR_VERSION < 3 PyDict_SetItem(self, name, val) #else - PyObject_SetAttr(self, name, val) + PyObject_GenericSetAttr(self, name, val) #endif < 0 ) { @@ -137,21 +113,21 @@ PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) return Py_None; } -PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) +PyObject* pyext::pyext_getattr(PyObject *self, PyObject *args) { - PyObject *self, *name, *ret = NULL; - if(!PyArg_ParseTuple(args, "OO:pyext_getattr", &self, &name)) + PyObject *name, *ret = NULL; + if(!PyArg_ParseTuple(args, "O:pyext_getattr", &name)) { // handle error ERRINTERNAL(); return NULL; } + post("getattr %s", PyUnicode_AsUTF8(name)); #if PY_MAJOR_VERSION < 3 if(PyString_Check(name)) #else if(PyUnicode_Check(name)) - #endif { #if PY_MAJOR_VERSION < 3 @@ -198,7 +174,7 @@ PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) } //! Send message to outlet -PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) +PyObject *pyext::pyext_outlet(PyObject *self, PyObject *args) { bool ok = false; @@ -208,12 +184,11 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) int sz = PyTuple_GET_SIZE(args); // borrowed references! - PyObject *self,*outl; + PyObject *outl; if( - sz >= 2 && - (self = PyTuple_GET_ITEM(args,0)) != NULL && - (outl = PyTuple_GET_ITEM(args,1)) != NULL && + sz >= 1 && + (outl = PyTuple_GET_ITEM(args,0)) != NULL && #if PY_MAJOR_VERSION < 3 PyInt_Check(outl) #else @@ -228,8 +203,8 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) PyObject *val; #if 0 - if(sz == 3) { - val = PyTuple_GET_ITEM(args,2); // borrow reference + if(sz == 2) { + val = PyTuple_GET_ITEM(args,1); // borrow reference Py_INCREF(val); tp = PySequence_Check(val); } @@ -237,14 +212,14 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) tp = false; if(!tp) - val = PySequence_GetSlice(args,2,sz); // new ref + val = PySequence_GetSlice(args,1,sz); // new ref #else - if(sz == 3) { - val = PyTuple_GET_ITEM(args,2); // borrow reference + if(sz == 2) { + val = PyTuple_GET_ITEM(args,1); // borrow reference Py_INCREF(val); } else - val = PyTuple_GetSlice(args,2,sz); // new ref + val = PyTuple_GetSlice(args,1,sz); // new ref #endif int o; @@ -279,12 +254,11 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) #ifdef FLEXT_THREADS //! Detach threads -PyObject *pyext::pyext_detach(PyObject *,PyObject *args) +PyObject *pyext::pyext_detach(PyObject *self, PyObject *args) { - PyObject *self; int val; if( - !PyArg_ParseTuple(args, "Oi:pyext_detach",&self,&val) + !PyArg_ParseTuple(args, "i:pyext_detach",&val) ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _detach(self,[0/1/2])"); @@ -309,12 +283,11 @@ PyObject *pyext::pyext_detach(PyObject *,PyObject *args) } //! Stop running threads -PyObject *pyext::pyext_stop(PyObject *,PyObject *args) +PyObject *pyext::pyext_stop(PyObject *self, PyObject *args) { - PyObject *self; int val = -1; if( - !PyArg_ParseTuple(args, "O|i:pyext_stop",&self,&val) + !PyArg_ParseTuple(args, "|i:pyext_stop",&val) ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _stop(self,{wait time})"); @@ -347,73 +320,66 @@ PyObject *pyext::pyext_stop(PyObject *,PyObject *args) #if FLEXT_SYS == FLEXT_SYS_PD //! Send message to canvas -PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) +PyObject *pyext::pyext_tocanvas(PyObject *self, PyObject *args) { FLEXT_ASSERT(PyTuple_Check(args)); int sz = PyTuple_GET_SIZE(args); bool ok = false; - PyObject *self; // borrowed ref - if( - sz >= 1 && - (self = PyTuple_GET_ITEM(args,0)) != NULL - ) { - pyext *ext = GetThis(self); - if(!ext) { - PyErr_SetString(PyExc_RuntimeError,"pyext - _tocanvas: instance not associated with pd object"); - return NULL; - } - - PyObject *val; - - bool tp = - sz == 2 && - PySequence_Check( - val = PyTuple_GET_ITEM(args,1) // borrowed ref - ); - - if(!tp) - val = PyTuple_GetSlice(args,1,sz); // new ref + pyext *ext = GetThis(self); + if(!ext) { + PyErr_SetString(PyExc_RuntimeError,"pyext - _tocanvas: instance not associated with pd object"); + return NULL; + } - flext::AtomListStatic<16> lst; - const t_symbol *sym = GetPyArgs(lst,val); - if(sym) { - t_glist *gl = ext->thisCanvas(); - if(gl) { - // \TODO find a flext-based non-locking method - sys_lock(); - pd_forwardmess((t_class **)gl,lst.Count(),lst.Atoms()); - sys_unlock(); - } + PyObject *val; + + bool tp = + sz == 2 && + PySequence_Check( + val = PyTuple_GET_ITEM(args,0) // borrowed ref + ); + + if(!tp) + val = PyTuple_GetSlice(args,0,sz); // new ref + + flext::AtomListStatic<16> lst; + const t_symbol *sym = GetPyArgs(lst,val); + if(sym) { + t_glist *gl = ext->thisCanvas(); + if(gl) { + // \TODO find a flext-based non-locking method + sys_lock(); + pd_forwardmess((t_class **)gl,lst.Count(),lst.Atoms()); + sys_unlock(); + } #ifdef FLEXT_DEBUG - else - post("pyext - no parent canvas?!"); + else + post("pyext - no parent canvas?!"); #endif - ok = true; - } - else - post("py/pyext - No data to send"); - - if(!tp) Py_DECREF(val); + ok = true; } + else + post("py/pyext - No data to send"); - if(!ok) { - PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _tocanvas(self,args...)"); - return NULL; - } + if(!tp) Py_DECREF(val); - Py_INCREF(Py_None); - return Py_None; +if(!ok) { + PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _tocanvas(self,args...)"); + return NULL; + } + +Py_INCREF(Py_None); +return Py_None; } #endif -PyObject *pyext::pyext_invec(PyObject *,PyObject *args) +PyObject *pyext::pyext_invec(PyObject *self, PyObject *args) { - PyObject *self; int val = -1; if( - !PyArg_ParseTuple(args, "O|i:pyext_invec",&self,&val) + !PyArg_ParseTuple(args, "|i:pyext_invec",&val) ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _invec(self,inlet)"); @@ -439,12 +405,11 @@ PyObject *pyext::pyext_invec(PyObject *,PyObject *args) return Py_None; } -PyObject *pyext::pyext_outvec(PyObject *,PyObject *args) +PyObject *pyext::pyext_outvec(PyObject *self, PyObject *args) { - PyObject *self; int val = -1; if( - !PyArg_ParseTuple(args, "O|i:pyext_outvec",&self,&val) + !PyArg_ParseTuple(args, "|i:pyext_outvec",&val) ) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _outvec(self,inlet)"); diff --git a/source/pyext.cpp b/source/pyext.cpp index 6e9636b..c8756ec 100644 --- a/source/pyext.cpp +++ b/source/pyext.cpp @@ -9,6 +9,14 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "pyext.h" #include +// undefine PD's T_OBJECT to avoid conflict with Python's +#undef T_OBJECT + +#ifdef PY_USE_FRAMEWORK +#include "Python/structmember.h" +#else +#include "structmember.h" +#endif FLEXT_LIB_V("pyext pyext. pyx pyx.",pyext) @@ -47,6 +55,13 @@ void pyext::Setup(t_classid c) // ---------------------------------------------------- // register/initialize pyext base class along with module + + if(PyType_Ready(&pyPyext_Type) < 0) { + PyErr_Print(); + return; + } + + /* class_dict = PyDict_New(); PyObject *className; #if PY_MAJOR_VERSION < 3 @@ -88,8 +103,10 @@ void pyext::Setup(t_classid c) // make pyext functions available in class scope PyDict_Merge(class_dict,module_dict,0); #endif + */ + // after merge so that it's not in class_dict as well... - PyDict_SetItemString(module_dict, PYEXT_CLASS,class_obj); // increases class_obj ref count by 1 + PyDict_SetItemString(module_dict, PYEXT_CLASS, (PyObject *) &pyPyext_Type); // increases class_obj ref count by 1 PyObject *str; #if PY_MAJOR_VERSION < 3 @@ -97,12 +114,13 @@ void pyext::Setup(t_classid c) #else str = PyUnicode_FromString(pyext_doc); #endif - PyDict_SetItemString(class_dict, "__doc__", str); + //PyDict_SetItemString(class_dict, "__doc__", str); } pyext *pyext::GetThis(PyObject *self) { PyObject *th = PyObject_GetAttrString(self,"_this"); + if(th) { pyext *ret = static_cast(PyLong_AsVoidPtr(th)); Py_DECREF(th); @@ -127,9 +145,6 @@ void pyext::ClearThis() FLEXT_ASSERT(ret != -1); } -PyObject *pyext::class_obj = NULL; -PyObject *pyext::class_dict = NULL; - pyext::pyext(int argc,const t_atom *argv,bool sig): methname(NULL), pyobj(NULL), @@ -216,7 +231,6 @@ bool pyext::Init() if(methname) { MakeInstance(); if(pyobj) { - SetThis(); InitInOut(inlets,outlets); } } @@ -287,8 +301,13 @@ bool pyext::DoInit() bool ok = true; SetThis(); + + if(pyobj->ob_type->tp_init(pyobj, pargs, NULL) < 0) { // need subtype + ok = false; + PyErr_Print(); + } - PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref + /*PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref if(init) { if(PyMethod_Check(init)) { PyObject *res = PyObject_CallObject(init,pargs); @@ -305,7 +324,7 @@ bool pyext::DoInit() } else // __init__ has not been found - don't care - PyErr_Clear(); + PyErr_Clear();*/ Py_DECREF(pargs); return ok; @@ -370,11 +389,9 @@ bool pyext::InitInOut(int &inl,int &outl) FLEXT_ASSERT(!ret); } -#if PY_MAJOR_VERSION < 3 // __init__ can override the number of inlets and outlets if(!DoInit()) // call __init__ constructor return false; -#endif if(inl < 0) { // get number of inlets @@ -438,25 +455,17 @@ bool pyext::MakeInstance() if(!pref) PyErr_Print(); else { -#if PY_MAJOR_VERSION < 3 - if(PyClass_Check(pref)) { - // make instance, but don't call __init__ - pyobj = PyInstance_NewRaw(pref, NULL); -#else - if(PyObject_IsInstance(pref, (PyObject *)&PyType_Type)) { - // pyobj = PyBaseObject_Type.tp_new() - // TODO: correctly initialize instance - + if(PyType_Check(pref) && PyType_IsSubtype((PyTypeObject *) pref, &pyPyext_Type)) { + PyTypeObject *pytypeobj = (PyTypeObject *) pref; PyObject *pargs = MakePyArgs(NULL, initargs.Count(), initargs.Atoms()); if(!pargs) { PyErr_Print(); } else { - pyobj = PyObject_CallObject(pref, pargs); - + pyobj = pytypeobj->tp_new(pytypeobj, pargs, NULL); + Py_DECREF(pargs); } -#endif if(!pyobj) PyErr_Print(); } else @@ -503,6 +512,7 @@ void pyext::Unload() void pyext::m_get(const t_symbol *s) { + post("m_get %s", GetString(s)); ThrLockSys lock; PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast(GetString(s))); /* fetch bound method */ @@ -531,6 +541,7 @@ void pyext::m_set(int argc,const t_atom *argv) else if(*GetString(argv[0]) == '_') post("%s - set: variables with leading _ are reserved and can't be set",thisName()); else { + post("m_set %s", GetString(argv[0])); char *ch = const_cast(GetString(argv[0])); if(PyObject_HasAttrString(pyobj,ch)) { PyObject *pval = MakePyArgs(NULL,argc-1,argv+1); @@ -710,3 +721,51 @@ void pyext::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) { ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); } + +static PyObject *pyext_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + post("pyext_new"); + pyPyext *self = (pyPyext *) type->tp_alloc(type, 0); + + self->this_ptr = 0; + + PyObject *ret = (PyObject *) self; + + if(self) { + PyObject *this_long = kwds != NULL + ? PyDict_GetItemString(kwds, "_pyext_this") + : NULL; + + if(this_long) { + if(!PyLong_Check(this_long)) { + self->this_ptr = PyLong_AsLong(this_long); + } else { + Py_DECREF(self); + ret = NULL; + } + + Py_DECREF(this_long); + } + } else { + ret = NULL; + } + + return (PyObject *) ret; +} + +static PyMemberDef pyPyext_members[] = { + {"_this", T_OBJECT_EX, offsetof(pyPyext, this_ptr), 0, "pointer to pyext object"}, + {NULL} +}; + +PyTypeObject pyPyext_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = PYEXT_MODULE "." PYEXT_CLASS, + .tp_doc = pyext::pyext_doc, + .tp_basicsize = sizeof(pyPyext), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_new = pyext_new, + .tp_members = pyPyext_members, + .tp_methods = pyext::meth_tbl +}; diff --git a/source/pyext.h b/source/pyext.h index f27b8f3..9fbb1f2 100644 --- a/source/pyext.h +++ b/source/pyext.h @@ -20,30 +20,32 @@ class pyext public: pyext(int argc,const t_atom *argv,bool sig = false); - static PyObject *pyext__str__(PyObject *,PyObject *args); + static PyObject *pyext__str__(PyObject *self, PyObject *args); - static PyObject *pyext_outlet(PyObject *,PyObject *args); + static PyObject *pyext_outlet(PyObject *self, PyObject *args); #if FLEXT_SYS == FLEXT_SYS_PD - static PyObject *pyext_tocanvas(PyObject *,PyObject *args); + static PyObject *pyext_tocanvas(PyObject *self, PyObject *args); #endif - static PyObject *pyext_setattr(PyObject *,PyObject *args); - static PyObject *pyext_getattr(PyObject *,PyObject *args); + static PyObject *pyext_setattr(PyObject *self, PyObject *args); + static PyObject *pyext_getattr(PyObject *self, PyObject *args); - static PyObject *pyext_detach(PyObject *,PyObject *args); - static PyObject *pyext_stop(PyObject *,PyObject *args); - static PyObject *pyext_isthreaded(PyObject *,PyObject *); + static PyObject *pyext_detach(PyObject *self, PyObject *args); + static PyObject *pyext_stop(PyObject *self, PyObject *args); - static PyObject *pyext_inbuf(PyObject *,PyObject *args); - static PyObject *pyext_invec(PyObject *,PyObject *args); - static PyObject *pyext_outbuf(PyObject *,PyObject *args); - static PyObject *pyext_outvec(PyObject *,PyObject *args); + static PyObject *pyext_inbuf(PyObject *self, PyObject *args); + static PyObject *pyext_invec(PyObject *self, PyObject *args); + static PyObject *pyext_outbuf(PyObject *self, PyObject *args); + static PyObject *pyext_outvec(PyObject *self, PyObject *args); int Inlets() const { return inlets; } int Outlets() const { return outlets; } static pyext *GetThis(PyObject *self); + static PyMethodDef attr_tbl[],meth_tbl[]; + static const char *pyext_doc; + protected: virtual bool Init(); @@ -98,13 +100,9 @@ class pyext bool MakeInstance(); bool InitInOut(int &inlets,int &outlets); - static PyObject *class_obj,*class_dict; - static PyMethodDef attr_tbl[],meth_tbl[]; - static const char *pyext_doc; - // -------- bind stuff ------------------ - static PyObject *pyext_bind(PyObject *,PyObject *args); - static PyObject *pyext_unbind(PyObject *,PyObject *args); + static PyObject *pyext_bind(PyObject *self, PyObject *args); + static PyObject *pyext_unbind(PyObject *self, PyObject *args); // --------------------------- @@ -151,4 +149,13 @@ class pyext #endif }; +typedef struct { + PyObject_HEAD + long this_ptr; +} pyPyext; + +PY_EXPORT extern PyTypeObject pyPyext_Type; + +#define pyPyext_Check(op) PyObject_TypeCheck((op), &pyPyext_Type) + #endif From f0a6ee1e13f059db9d52577fbe7b9f178015b9d6 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 7 Apr 2020 11:28:28 +0300 Subject: [PATCH 132/150] string.swapcase is gone in py3, use capwords as example instead --- pd/methods-1.pd | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/pd/methods-1.pd b/pd/methods-1.pd index 5b85c43..253fa6a 100644 --- a/pd/methods-1.pd +++ b/pd/methods-1.pd @@ -1,24 +1,24 @@ -#N canvas 540 469 734 369 12; -#X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818 --1 0; -#X text 235 32 http://grrrr.org/ext; -#X symbolatom 21 139 10 0 0 0 - - -; -#X symbolatom 25 298 10 0 0 0 - - -; -#X obj 22 179 py .str @py 1; -#X text 145 170 convert the symbol to a Python string; -#X text 35 216 pass it as a true Python object; -#X symbolatom 364 295 10 0 0 0 - - -; -#X text 462 269 use module function; -#X text 23 119 enter some text; -#X text 145 187 using the built-in str function; -#X obj 25 252 pym swapcase; -#X text 63 270 use swapcase method; -#X obj 363 250 py string.swapcase; -#X text 235 16 Python script objects \, (C)2003-2006 Thomas Grill; -#X text 21 73 Py can act on Python objects in an object-oriented manner -; -#X connect 2 0 4 1; -#X connect 4 0 11 1; -#X connect 4 0 13 1; -#X connect 11 0 3 0; -#X connect 13 0 7 0; +#N canvas 540 469 734 369 12; +#X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818 +-1 0; +#X text 235 32 http://grrrr.org/ext; +#X symbolatom 21 139 10 0 0 0 - - -; +#X symbolatom 25 298 10 0 0 0 - - -; +#X obj 22 179 py .str @py 1; +#X text 145 170 convert the symbol to a Python string; +#X text 35 216 pass it as a true Python object; +#X symbolatom 364 295 10 0 0 0 - - -; +#X text 462 269 use module function; +#X text 23 119 enter some text; +#X text 145 187 using the built-in str function; +#X obj 25 252 pym swapcase; +#X text 63 270 use swapcase method; +#X text 235 16 Python script objects \, (C)2003-2006 Thomas Grill; +#X text 21 73 Py can act on Python objects in an object-oriented manner +; +#X obj 363 250 py string.capwords; +#X connect 2 0 4 1; +#X connect 4 0 11 1; +#X connect 4 0 15 1; +#X connect 11 0 3 0; +#X connect 15 0 7 0; From a6e7a7664330278b6e65447d12f6c7ad72cdafb5 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 7 Apr 2020 12:04:04 +0300 Subject: [PATCH 133/150] compat fixes to examples --- scripts/sendrecv.py | 14 +++++++------- scripts/sig.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/sendrecv.py b/scripts/sendrecv.py index 0c58a5e..25596a7 100644 --- a/scripts/sendrecv.py +++ b/scripts/sendrecv.py @@ -58,7 +58,7 @@ def recv(self,*arg): print("CLASS",self.recvname,arg) # send data to specified send address - self._send(self.sendname,arg) + pyext._send(self.sendname,arg) def __init__(self,*args): @@ -147,31 +147,31 @@ def bang_1(self): num = 12 # number of objects ori = complex(150,180) # origin rad = 100 # radius - l = range(num) # initialize list + l = list(range(num)) # initialize list # make flower self._tocanvas("obj",ori.real,ori.imag,"bng",20,250,50,0,"empty","yeah","empty",0,-6,64,8,-24198,-1,-1) - for i in xrange(num): + for i in range(num): l[i] = ori+rad*exp(complex(0,i*2*pi/num)) self._tocanvas("obj",l[i].real,l[i].imag,"bng",15,250,50,0,"empty","yeah"+str(i),"empty",0,-6,64,8,0,-1,-1) self._tocanvas("connect",6,0,7+i,0) # blink for i in range(10): - self._send("yeah","bang") + pyext._send("yeah","bang") sleep(1./(i+1)) # move objects around - for i in xrange(200): + for i in range(200): ix = randint(0,num-1) l[ix] = ori+rad*complex(2*random()-1,2*random()-1) - self._send("yeah"+str(ix),"pos",l[ix].real,l[ix].imag) + pyext._send("yeah"+str(ix),"pos",l[ix].real,l[ix].imag) sleep(0.02) # now delete # this is not well-done... from time to time an object remains self._tocanvas("editmode",1) - for i in xrange(num): + for i in range(num): self._tocanvas("mouse",l[i].real,l[i].imag,0,0) self._tocanvas("cut") diff --git a/scripts/sig.py b/scripts/sig.py index 075721f..a7de91e 100644 --- a/scripts/sig.py +++ b/scripts/sig.py @@ -55,7 +55,7 @@ def __init__(self): self.gain = 0 def _dsp(self): - if not self._arraysupport(): + if not pyext._arraysupport(): print("No DSP support") return False From 27020c42bd216126f047731dff54ed960938d088 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 7 Apr 2020 12:04:17 +0300 Subject: [PATCH 134/150] cleanup --- source/clmeth.cpp | 2 -- source/pyext.cpp | 66 ++--------------------------------------------- 2 files changed, 2 insertions(+), 66 deletions(-) diff --git a/source/clmeth.cpp b/source/clmeth.cpp index f59fb4d..aacacbf 100644 --- a/source/clmeth.cpp +++ b/source/clmeth.cpp @@ -83,7 +83,6 @@ PyObject* pyext::pyext_setattr(PyObject *self, PyObject *args) ERRINTERNAL(); return NULL; } - post("setattr %s", PyUnicode_AsUTF8(name)); bool handled = false; @@ -122,7 +121,6 @@ PyObject* pyext::pyext_getattr(PyObject *self, PyObject *args) ERRINTERNAL(); return NULL; } - post("getattr %s", PyUnicode_AsUTF8(name)); #if PY_MAJOR_VERSION < 3 if(PyString_Check(name)) diff --git a/source/pyext.cpp b/source/pyext.cpp index c8756ec..fd29ab2 100644 --- a/source/pyext.cpp +++ b/source/pyext.cpp @@ -61,51 +61,12 @@ void pyext::Setup(t_classid c) return; } - /* - class_dict = PyDict_New(); - PyObject *className; -#if PY_MAJOR_VERSION < 3 - className = PyString_FromString(PYEXT_CLASS); -#else - className = PyUnicode_FromString(PYEXT_CLASS); -#endif - PyMethodDef *def; - - // add setattr/getattr to class - for(def = attr_tbl; def->ml_name; def++) { - PyObject *func = PyCFunction_New(def, NULL); - PyDict_SetItemString(class_dict, def->ml_name, func); - Py_DECREF(func); - } - - //class_obj = PyClass_New(NULL, class_dict, className); - PyObject *classBases = PyTuple_New(0); - class_obj = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, className, classBases, class_dict, NULL); - Py_DECREF(classBases); - Py_DECREF(className); - - // add methods to class - for (def = meth_tbl; def->ml_name != NULL; def++) { - PyObject *func = PyCFunction_New(def, NULL); -#if PY_MAJOR_VERSION < 3 - PyObject *method = PyMethod_New(func, NULL, class_obj); // increases class_obj ref count by 1 - PyDict_SetItemString(class_dict, def->ml_name, method); -#else - PyObject *method = PyMethod_New(func, class_obj); - PyObject_SetAttrString(class_obj, def->ml_name, method); -#endif - Py_DECREF(func); - Py_DECREF(method); - } - -#if PY_VERSION_HEX >= 0x02020000 +#if 0 && PY_VERSION_HEX >= 0x02020000 // not absolutely necessary, existent in python 2.2 upwards // make pyext functions available in class scope PyDict_Merge(class_dict,module_dict,0); #endif - */ - // after merge so that it's not in class_dict as well... PyDict_SetItemString(module_dict, PYEXT_CLASS, (PyObject *) &pyPyext_Type); // increases class_obj ref count by 1 PyObject *str; @@ -114,7 +75,6 @@ void pyext::Setup(t_classid c) #else str = PyUnicode_FromString(pyext_doc); #endif - //PyDict_SetItemString(class_dict, "__doc__", str); } pyext *pyext::GetThis(PyObject *self) @@ -302,29 +262,10 @@ bool pyext::DoInit() SetThis(); - if(pyobj->ob_type->tp_init(pyobj, pargs, NULL) < 0) { // need subtype + if(pyobj->ob_type->tp_init(pyobj, pargs, NULL) < 0) { ok = false; PyErr_Print(); } - - /*PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref - if(init) { - if(PyMethod_Check(init)) { - PyObject *res = PyObject_CallObject(init,pargs); - if(!res) { - // exception is set - ok = false; - // we want to know why __init__ failed... - PyErr_Print(); - } - else - Py_DECREF(res); - } - Py_DECREF(init); - } - else - // __init__ has not been found - don't care - PyErr_Clear();*/ Py_DECREF(pargs); return ok; @@ -512,7 +453,6 @@ void pyext::Unload() void pyext::m_get(const t_symbol *s) { - post("m_get %s", GetString(s)); ThrLockSys lock; PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast(GetString(s))); /* fetch bound method */ @@ -541,7 +481,6 @@ void pyext::m_set(int argc,const t_atom *argv) else if(*GetString(argv[0]) == '_') post("%s - set: variables with leading _ are reserved and can't be set",thisName()); else { - post("m_set %s", GetString(argv[0])); char *ch = const_cast(GetString(argv[0])); if(PyObject_HasAttrString(pyobj,ch)) { PyObject *pval = MakePyArgs(NULL,argc-1,argv+1); @@ -724,7 +663,6 @@ void pyext::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) static PyObject *pyext_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - post("pyext_new"); pyPyext *self = (pyPyext *) type->tp_alloc(type, 0); self->this_ptr = 0; From 5a2bca73edb9d7d6a78811db1e5fde3494b1015a Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 7 Apr 2020 12:37:37 +0300 Subject: [PATCH 135/150] cleanup --- source/clmeth.cpp | 9 --------- source/pybase.h | 2 +- source/pyext.h | 2 +- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/source/clmeth.cpp b/source/clmeth.cpp index aacacbf..a8778f2 100644 --- a/source/clmeth.cpp +++ b/source/clmeth.cpp @@ -36,15 +36,6 @@ PyMethodDef pyext::meth_tbl[] = {NULL, NULL, 0, NULL} /* Sentinel */ }; -PyMethodDef pyext::attr_tbl[] = -{ -#if PY_MAJOR_VERSION < 3 - { "__setattr__", pyext::pyext_setattr, METH_VARARGS,"Set class attribute" }, - { "__getattr__", pyext::pyext_getattr, METH_VARARGS,"Get class attribute" }, -#endif - { NULL, NULL,0,NULL }, -}; - const char *pyext::pyext_doc = "py/pyext - python external object for PD and Max/MSP, (C)2002-2008 Thomas Grill\n" "\n" diff --git a/source/pybase.h b/source/pybase.h index e13d672..bb12b07 100644 --- a/source/pybase.h +++ b/source/pybase.h @@ -131,7 +131,7 @@ class pybase static PyObject *module_obj,*module_dict; static PyObject *builtins_obj,*builtins_dict; - static PyMethodDef func_tbl[],attr_tbl[]; + static PyMethodDef func_tbl[]; #if PY_MAJOR_VERSION >= 3 static PyModuleDef pyext_module_def; #endif diff --git a/source/pyext.h b/source/pyext.h index 9fbb1f2..92e5649 100644 --- a/source/pyext.h +++ b/source/pyext.h @@ -43,7 +43,7 @@ class pyext static pyext *GetThis(PyObject *self); - static PyMethodDef attr_tbl[],meth_tbl[]; + static PyMethodDef meth_tbl[]; static const char *pyext_doc; protected: From 2737539c32f20d9ab3e41f6382296f70530ce7a6 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 7 Apr 2020 13:51:11 +0300 Subject: [PATCH 136/150] unbreak python 2 --- package.txt | 4 ++-- scripts/tcltk.py | 6 ++++-- source/clmeth.cpp | 12 ++---------- source/pybase.cpp | 3 ++- source/pybuffer.cpp | 11 ++--------- 5 files changed, 12 insertions(+), 24 deletions(-) diff --git a/package.txt b/package.txt index 9002aa8..2a19933 100644 --- a/package.txt +++ b/package.txt @@ -11,6 +11,6 @@ SRCS= \ py.cpp pyext.cpp modmeth.cpp clmeth.cpp \ register.cpp bound.cpp pyargs.cpp \ pysymbol.cpp pybuffer.cpp pybundle.cpp pydsp.cpp \ - pyatom.cpp pybase.cpp pymeth.cpp + pyatom.cpp pybase.cpp pymeth.cpp pycompat.cpp -HDRS= pyprefix.h main.h pyext.h pysymbol.h pybuffer.h pybundle.h pyatom.h pybase.h +HDRS= pyprefix.h main.h pyext.h pysymbol.h pybuffer.h pybundle.h pyatom.h pybase.h pycompat.h diff --git a/scripts/tcltk.py b/scripts/tcltk.py index 0813199..a02b7ef 100644 --- a/scripts/tcltk.py +++ b/scripts/tcltk.py @@ -7,10 +7,12 @@ """This is an example script for showing a nonsense tcl/tk application.""" +from __future__ import print_function + try: import pyext except: - print "ERROR: This script must be loaded by the PD/Max pyext external" + print("ERROR: This script must be loaded by the PD/Max pyext external") from Tkinter import * import random @@ -74,7 +76,7 @@ def __init__(self): self._detach(1) def bang_1(self): - self._priority(-3) + pyext._priority(-3) # display the tcl/tk dialog app = Application(self) app.mainloop() diff --git a/source/clmeth.cpp b/source/clmeth.cpp index a8778f2..312dad8 100644 --- a/source/clmeth.cpp +++ b/source/clmeth.cpp @@ -29,10 +29,8 @@ PyMethodDef pyext::meth_tbl[] = #endif { "_invec", pyext::pyext_invec, METH_VARARGS,"Get input vector" }, { "_outvec", pyext::pyext_outvec, METH_VARARGS,"Get output vector" }, -#if PY_MAJOR_VERSION >= 3 { "__setattr__", pyext::pyext_setattr, METH_VARARGS,"Set class attribute" }, { "__getattr__", pyext::pyext_getattr, METH_VARARGS,"Get class attribute" }, -#endif {NULL, NULL, 0, NULL} /* Sentinel */ }; @@ -75,6 +73,7 @@ PyObject* pyext::pyext_setattr(PyObject *self, PyObject *args) return NULL; } + bool handled = false; /* @@ -86,14 +85,7 @@ PyObject* pyext::pyext_setattr(PyObject *self, PyObject *args) } */ if(!handled) { - if( -#if PY_MAJOR_VERSION < 3 - PyDict_SetItem(self, name, val) -#else - PyObject_GenericSetAttr(self, name, val) -#endif - < 0 - ) { + if(PyObject_GenericSetAttr(self, name, val) < 0) { ERRINTERNAL(); return NULL; } diff --git a/source/pybase.cpp b/source/pybase.cpp index 7a5358a..846d918 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -106,7 +106,8 @@ void initbundle(); MOD_INIT(pyext) { - return MOD_SUCCESS_VAL(pybase::pyext_init()); + PyObject *init_ret = pybase::pyext_init(); + return MOD_SUCCESS_VAL(init_ret); } PyObject *pybase::pyext_init() diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index 463a6fd..9238d02 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -274,15 +274,8 @@ static void buffer_releasebuffer(PyObject *obj, Py_buffer *view) { } static PyBufferProcs buffer_as_buffer = { -#if PY_MAJOR_VERSION < 3 - buffer_readbuffer, - buffer_writebuffer, - buffer_segcount, - buffer_charbuffer -#else - buffer_getbuffer, - buffer_releasebuffer -#endif + .bf_getbuffer = buffer_getbuffer, + .bf_releasebuffer = buffer_releasebuffer }; static Py_ssize_t buffer_length(PyObject *s) From cc2ad778e81ab1ade379f9a94731db3f67eeba96 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Mon, 7 Sep 2020 18:50:33 +0300 Subject: [PATCH 137/150] add _canvas_dir attribute --- source/clmeth.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/clmeth.cpp b/source/clmeth.cpp index 312dad8..77f1a73 100644 --- a/source/clmeth.cpp +++ b/source/clmeth.cpp @@ -139,6 +139,16 @@ PyObject* pyext::pyext_getattr(PyObject *self, PyObject *args) ret = Py_False; #endif } + else if(!strcmp(sname, "_canvas_dir")) { + pyext *ext = GetThis(self); + char dir[1024]; + ext->GetCanvasDir(dir, sizeof(dir)); +#if PY_MAJOR_VERSION < 3 + ret = PyString_InternFromString(dir); +#else + ret = PyUnicode_InternFromString(dir); +#endif + } } } From 0e35ed1baa151aebc6e0c5296d558b1e27aa9e1d Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Mon, 7 Sep 2020 18:50:53 +0300 Subject: [PATCH 138/150] fix(?) "pyext." behavior --- source/pyext.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/pyext.cpp b/source/pyext.cpp index fd29ab2..620424e 100644 --- a/source/pyext.cpp +++ b/source/pyext.cpp @@ -162,7 +162,13 @@ pyext::pyext(int argc,const t_atom *argv,bool sig): PyErr_SetString(PyExc_ValueError,"Invalid module name"); // check for alias creation names - if(dotted) clname = scr; + // ...this seems wrong? + // e.g. "pyext. a.b c" becomes the equivalent of: + // from a.b import a.b + // instead of + // from a.b import c + // so let's disable it for now. + //if(dotted) clname = scr; } Register(GetRegistry(REGNAME)); From 630fcdbbe77c39b745ddc021e0438f5edce34226 Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Tue, 10 Nov 2020 16:27:22 +0200 Subject: [PATCH 139/150] make conda build work on linux --- build/config-lnx.def | 10 +++++++++- build/gnumake-lnx-gcc.inc | 15 +++++++++++++++ source/pyext.cpp | 6 +++--- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/build/config-lnx.def b/build/config-lnx.def index 09879a3..cfdbcd6 100644 --- a/build/config-lnx.def +++ b/build/config-lnx.def @@ -1,8 +1,13 @@ # what is the base prefix of the Python installation? +ifdef PY_CONDA_ROOT +PYTHONPREFIX=$(PY_CONDA_ROOT) +else PYTHONPREFIX=/usr +endif # which Python version do you want to compile against? -PYTHONVERSION=2.7 +PY_MAJOR_VERSION=3 +PY_MINOR_VERSION=7 # uncomment if numpy/numarray/numeric support should be compiled in # for info see http://numeric.scipy.org @@ -15,3 +20,6 @@ PY_USE_GIL=1 # use inofficial (pure data) functionality # PY_USE_INOFFICIAL=1 + +# use python with pymalloc (look for "pythonX.Ym" files) +PY_USE_PYMALLOC=1 diff --git a/build/gnumake-lnx-gcc.inc b/build/gnumake-lnx-gcc.inc index 7bbde1f..e9177b4 100644 --- a/build/gnumake-lnx-gcc.inc +++ b/build/gnumake-lnx-gcc.inc @@ -1,5 +1,19 @@ +ifdef PY_USE_PYMALLOC +PYTHONVERSION=$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)m +else +PYTHONVERSION=$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) +endif + DEFS += -DPY_EXPORTS + INCPATH += -I$(PYTHONPREFIX)/include/python$(PYTHONVERSION) + +ifdef PY_CONDA_ROOT +LIBPATH += -L$(PY_CONDA_ROOT)/lib +LDFLAGS += -Wl,-R$(PY_CONDA_ROOT)/lib +DEFS += -DPY_INTERPRETER=$(PY_CONDA_ROOT)/bin/python +endif + LIBS += -lpython$(PYTHONVERSION) ifdef PY_NUMARRAY @@ -7,6 +21,7 @@ DEFS += -DPY_NUMARRAY endif ifdef PY_NUMPY DEFS += -DPY_NUMPY +INCPATH += -I$(PYTHONPREFIX)/lib/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include endif ifdef PY_NUMERIC DEFS += -DPY_NUMERIC diff --git a/source/pyext.cpp b/source/pyext.cpp index 620424e..9b19bd2 100644 --- a/source/pyext.cpp +++ b/source/pyext.cpp @@ -705,11 +705,11 @@ static PyMemberDef pyPyext_members[] = { PyTypeObject pyPyext_Type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = PYEXT_MODULE "." PYEXT_CLASS, - .tp_doc = pyext::pyext_doc, .tp_basicsize = sizeof(pyPyext), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_new = pyext_new, + .tp_doc = pyext::pyext_doc, + .tp_methods = pyext::meth_tbl, .tp_members = pyPyext_members, - .tp_methods = pyext::meth_tbl + .tp_new = pyext_new }; From bc0708f97d43058446cea0023ea98ccdd9c58fbb Mon Sep 17 00:00:00 2001 From: miranda kastemaa Date: Mon, 30 Nov 2020 17:17:16 +0200 Subject: [PATCH 140/150] fix some uninitialized memory bugs found by valgrind --- source/pybase.cpp | 1 + source/pydsp.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/source/pybase.cpp b/source/pybase.cpp index 846d918..340c920 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -291,6 +291,7 @@ FLEXT_LIB_SETUP(py,pybase::lib_setup) pybase::pybase() : module(NULL) , dict(NULL) + , respond(false) #ifdef FLEXT_THREADS , thrcount(0) , shouldexit(false),stoptick(0) diff --git a/source/pydsp.cpp b/source/pydsp.cpp index 7676557..db8a8ad 100644 --- a/source/pydsp.cpp +++ b/source/pydsp.cpp @@ -38,6 +38,7 @@ FLEXT_LIB_DSP_V("pyext~ pyext.~ pyx~ pyx.~",pydsp) pydsp::pydsp(int argc,const t_atom *argv) : pyext(argc,argv,true) , dspfun(NULL),sigfun(NULL) + , buffers(NULL) {} bool pydsp::DoInit() From 5a8994e3a52248043f4853de9d0d39d390e076c6 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Thu, 29 Jun 2023 16:40:34 +0200 Subject: [PATCH 141/150] build py/pyext for python3 with cmake --- .gitignore | 4 ++ CMakeLists.txt | 100 ++++++++++++++++++++++++++++++++++++++++++++ readme.txt | 19 +++++++++ source/pybuffer.cpp | 6 ++- 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 CMakeLists.txt diff --git a/.gitignore b/.gitignore index 2a5de48..bbf6d82 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,7 @@ *.app config.txt .DS_Store + +# CMake build folder +cmake-build +*__pycache__* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..33ecbae --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,100 @@ +cmake_minimum_required(VERSION 3.0.0) +project(py VERSION 0.1.0 LANGUAGES C CXX) + + +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1) + +# path to pythonX.X.so (e.g python3.10.so) +if(NOT PYTHON_SHARED_LIB_PATH) + set(PYTHON_SHARED_LIB_PATH "/usr/lib64") +endif() + +# path search by puredata for externals (preferences>edit preferences...>paths in new pd versions) +if(NOT PATH_TO_PD_EXTERNALS) + set(PATH_TO_PD_EXTERNALS "~/Documents/Pd/externals") +endif() + +# path to libpd source files +if(NOT PD_SOURCE_PATH) + set(PD_SOURCE_PATH /usr/local/pd/src) +endif() + +# path to flext source files ; default is assumed py/pyext and flext repos have been cloned in a common parent directory +if(NOT FLEXT_SOURCE_PATH) + set(FLEXT_SOURCE_PATH ../flext/source) +endif() + +# path to python source files (can be found by running `sudo find / -iname "Python.h"`) +if(NOT PYTHON_SOURCE_PATH) + set(PYTHON_SOURCE_PATH /usr/include/python3.10) +endif() + +# your python version +if(NOT PYTHON_VERSION) + set(PYTHON_VERSION 3.10) +endif() + +include(CMakePrintHelpers) +cmake_print_variables(PYTHON_SOURCE_PATH) +set(CMAKE_INSTALL_RPATH ${PYTHON_SHARED_LIB_PATH}) +set(CMAKE_BUILD_RPATH ${PYTHON_SHARED_LIB_PATH}) +# ---------------------------------------------- # +# BUILDING OBJECT FILES + +add_library(objects OBJECT + source/bound.cpp + source/clmeth.cpp + source/main.cpp + source/modmeth.cpp + source/py.cpp + source/pyargs.cpp + source/pyatom.cpp + source/pybase.cpp + source/pybuffer.cpp + source/pybundle.cpp + source/pycompat.cpp + source/pydsp.cpp + source/pyext.cpp + source/pymeth.cpp + source/pysymbol.cpp + source/register.cpp) + +target_compile_options(objects PRIVATE -DPD -DUNIX -O3 -Wl,--trace -fPIC -fcheck-new -DFLEXT_INLINE -DFLEXT_ATTRIBUTES=1 -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing -ffast-math -funroll-loops -fomit-frame-pointer -march=core2 -mfpmath=sse -msse -msse2 -msse3) + +target_include_directories(objects PRIVATE + ${PD_SOURCE_PATH} + ${FLEXT_SOURCE_PATH} + ${PYTHON_SOURCE_PATH}) + +target_link_libraries(objects PRIVATE -lpython${PYTHON_VERSION}) + +# ---------------------------------------------- # +# BUILDING PD EXTERNAL PY/PYEXT + +add_library(py SHARED $) + +target_compile_options(py PRIVATE -rdynamic -shared -fPIC -Wl,-rpath,"\$ORIGIN",--enable-new-dtags) + +target_link_libraries(py + PRIVATE -lc + PRIVATE -lm + PRIVATE -lstdc++ + PRIVATE -lpython${PYTHON_VERSION}) + +set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") + +set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".pd_linux") + +# stripping file to make it lighter +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD +COMMAND strip --strip-unneeded cmake-build/${PROJECT_NAME}.pd_linux + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Stripping file..." +) + +# copying file to Pd externals directory +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD +COMMAND mkdir -p ${PATH_TO_PD_EXTERNALS}/${PROJECT_NAME} && cp cmake-build/${PROJECT_NAME}.pd_linux ${PATH_TO_PD_EXTERNALS}/${PROJECT_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Copying file to Pd externals directory..." +) \ No newline at end of file diff --git a/readme.txt b/readme.txt index fa2d42a..fc8bf6e 100644 --- a/readme.txt +++ b/readme.txt @@ -63,6 +63,25 @@ Download and unzip, or git-clone the package. Pure data - any platform supporting gcc-compatible compilers ------------------------------------------------------------ + --> Build with cmake for Python3 support <-- + +A lot of variables can be set to redirect paths for puredata, flext and python, according to your environment. It is suggested to have a look at the CMakeLists.txt to better understand which variables are used where and what they correspond to. + +To build with cmake, run the following commands, replacing the paths and values according to your current environment: +mkdir cmake-build +cd cmake-build +cmake .. \ +-GNinja \ # optional, builds faster +-DPYTHON_SHARED_LIB_PATH=/path/to/pythonx.x.so \ +-DPATH_TO_PD_EXTERNALS=/path/to/pd/externals \ +-DPD_SOURCE_PATH=/path/to/pd/sources \ +-DFLEXT_SOURCE_PATH=/path/to/flext/sources \ +-DPYTHON_SOURCE_PATH=/path/to/python/sources \ +-DPYTHON_VERSION=pythoncurrent.version + +------------------------------------------------------------ + + The pd-lib-builder project (https://github.com/pure-data/pd-lib-builder) is used to compile the project. A git subtree of this project is already present. diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index 9238d02..709b5bd 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -7,7 +7,6 @@ WARRANTIES, see the file, "license.txt," in this distribution. */ #include "pybase.h" - #undef PY_ARRAYS @@ -258,7 +257,12 @@ static int buffer_getbuffer(PyObject *obj, Py_buffer *view, int flags) { view->len = len; view->readonly = false; view->itemsize = sizeof(t_sample); + // adapt to newer versions of numpy (PY_NUMPY_BUFFER_FORMAT is deleted in versions >= 1.7.0) + #ifndef PY_NUMPY_BUFFER_FORMAT + view->format = (flags & PyBUF_FORMAT) ? ((Py_buffer*)view)->format : NULL; + #else view->format = (flags & PyBUF_FORMAT) ? (char *) PY_NUMPY_BUFFER_FORMAT : NULL; + #endif // !1 view->ndim = 1; view->shape = &shape_strides->first; view->strides = &shape_strides->second; From 6f4c52b1505d06f7c3bee8a08d60012dcb631aa4 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Wed, 5 Jul 2023 16:34:05 +0200 Subject: [PATCH 142/150] some other numpy deprecated macros --- source/pybuffer.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/pybuffer.cpp b/source/pybuffer.cpp index 709b5bd..86c975f 100644 --- a/source/pybuffer.cpp +++ b/source/pybuffer.cpp @@ -9,9 +9,14 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "pybase.h" #undef PY_ARRAYS - -#if defined(PY_NUMERIC) || defined(PY_NUMPY) || defined(PY_NUMARRAY) - #define PY_ARRAYS 1 +#if PY_MAJOR_VERSION >= 3 + #include + #define PY_ARRAYS defined(NUMPY_CORE_INCLUDE_NUMPY_ARRAYOBJECT_H_) + #define PY_NUMPY PY_ARRAYS +#else + #if defined(PY_NUMERIC) || defined(PY_NUMPY) || defined(PY_NUMARRAY) + #define PY_ARRAYS 1 + #endif #endif #ifdef PY_ARRAYS From be1bd98cbccc7a436faee0b0880820086dc6645d Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Thu, 6 Jul 2023 12:04:56 +0200 Subject: [PATCH 143/150] enable python 3 & multithreaded flext --- .gitignore | 2 +- CMakeLists.txt | 30 +++++++++++++++++++++++++----- source/pybase.cpp | 11 ++++++++++- source/pybase.h | 8 ++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index bbf6d82..d3ecec4 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,5 @@ config.txt .DS_Store # CMake build folder -cmake-build +*-build *__pycache__* diff --git a/CMakeLists.txt b/CMakeLists.txt index 33ecbae..c4e735d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,11 @@ if(NOT PYTHON_VERSION) set(PYTHON_VERSION 3.10) endif() +# flext build +if(NOT FLEXT_BUILD_TYPE) + set(FLEXT_BUILD_TYPE SINGLE) +endif() + include(CMakePrintHelpers) cmake_print_variables(PYTHON_SOURCE_PATH) set(CMAKE_INSTALL_RPATH ${PYTHON_SHARED_LIB_PATH}) @@ -61,6 +66,14 @@ add_library(objects OBJECT target_compile_options(objects PRIVATE -DPD -DUNIX -O3 -Wl,--trace -fPIC -fcheck-new -DFLEXT_INLINE -DFLEXT_ATTRIBUTES=1 -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing -ffast-math -funroll-loops -fomit-frame-pointer -march=core2 -mfpmath=sse -msse -msse2 -msse3) +# add flext flag depending on chosen build type +if(FLEXT_BUILD_TYPE STREQUAL MULTI) + message("setting threads") + target_compile_options(objects PRIVATE -DFLEXT_THREADS) +elseif(FLEXT_BUILD_TYPE STREQUAL SHARED) + target_compile_options(objects PRIVATE -DFLEXT_SHARED) +endif() + target_include_directories(objects PRIVATE ${PD_SOURCE_PATH} ${FLEXT_SOURCE_PATH} @@ -71,30 +84,37 @@ target_link_libraries(objects PRIVATE -lpython${PYTHON_VERSION}) # ---------------------------------------------- # # BUILDING PD EXTERNAL PY/PYEXT -add_library(py SHARED $) +add_library(${PROJECT_NAME} SHARED $) -target_compile_options(py PRIVATE -rdynamic -shared -fPIC -Wl,-rpath,"\$ORIGIN",--enable-new-dtags) +target_compile_options(${PROJECT_NAME} PRIVATE -rdynamic -shared -fPIC -Wl,-rpath,"\$ORIGIN",--enable-new-dtags) -target_link_libraries(py +target_link_directories(${PROJECT_NAME} PRIVATE /usr/local/lib) +target_link_directories(${PROJECT_NAME} PRIVATE ${PYTHON_SHARED_LIB_PATH}) + +target_link_libraries(${PROJECT_NAME} PRIVATE -lc PRIVATE -lm PRIVATE -lstdc++ PRIVATE -lpython${PYTHON_VERSION}) +if(FLEXT_BUILD_TYPE STREQUAL SHARED) + target_compile_options(${PROJECT_NAME} PRIVATE lflext-pd) +endif() + set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".pd_linux") # stripping file to make it lighter add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD -COMMAND strip --strip-unneeded cmake-build/${PROJECT_NAME}.pd_linux +COMMAND strip --strip-unneeded ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pd_linux WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Stripping file..." ) # copying file to Pd externals directory add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD -COMMAND mkdir -p ${PATH_TO_PD_EXTERNALS}/${PROJECT_NAME} && cp cmake-build/${PROJECT_NAME}.pd_linux ${PATH_TO_PD_EXTERNALS}/${PROJECT_NAME} +COMMAND mkdir -p ${PATH_TO_PD_EXTERNALS}/${PROJECT_NAME} && cp ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pd_linux ${PATH_TO_PD_EXTERNALS}/${PROJECT_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Copying file to Pd externals directory..." ) \ No newline at end of file diff --git a/source/pybase.cpp b/source/pybase.cpp index 340c920..e05905f 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -8,7 +8,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "pybase.h" #include - +#include #if FLEXT_OS == FLEXT_OS_WIN #include #elif FLEXT_OS == FLEXT_OS_MAC @@ -157,6 +157,7 @@ void pybase::lib_setup() #endif Py_SetProgramName(py_program_name); } + #endif post(""); @@ -165,6 +166,14 @@ void pybase::lib_setup() post("(C)2002-2019 Thomas Grill - http://grrrr.org/ext"); post(""); post("using Python %s",Py_GetVersion()); + #ifdef FLEXT_THREADS + post(""); + post("Built with multithreaded flext"); + #endif + + #ifdef PY_USE_GIL + post("Using Python GIL"); + #endif #ifdef FLEXT_DEBUG post(""); diff --git a/source/pybase.h b/source/pybase.h index bb12b07..aa0d79f 100644 --- a/source/pybase.h +++ b/source/pybase.h @@ -13,6 +13,14 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "pysymbol.h" #include "pybuffer.h" #include "pybundle.h" +#include "ceval.h" +#include + +#if PY_MAJOR_VERSION >= 3 + #ifdef Py_BEGIN_ALLOW_THREADS + #define PY_USE_GIL + #endif // Py_BEGIN_ALLOW_THREADS +#endif #ifdef FLEXT_THREADS # ifdef PY_USE_GIL From 8c02920959aa59a2e11cbc75e2c38a0ceb82c199 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Wed, 12 Jul 2023 14:39:46 +0200 Subject: [PATCH 144/150] Solved hang on close with threaded build of py/pyext --- source/pybase.cpp | 5 +++-- source/pybase.h | 4 ++++ source/thrctrl.h | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 source/thrctrl.h diff --git a/source/pybase.cpp b/source/pybase.cpp index e05905f..59b6a04 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -85,6 +85,8 @@ void pybase::FreeThreadState() PyFifo pybase::qufifo; flext::ThrCond pybase::qucond; +bool pybase::qurunning; +ThrCtrl pybase::qucondctrl {&pybase::qucond, &pybase::qurunning}; // attaching the qucond to the controller to send a signal when closing pd #endif @@ -1018,7 +1020,7 @@ void pybase::quworker(thr_params *) FifoEl *el; ThrState my = FindThreadState(); - for(;;) { + while(qurunning) { while((el = qufifo.Get())) { ++el->th->thrcount; // \todo this should be atomic { @@ -1032,7 +1034,6 @@ void pybase::quworker(thr_params *) } qucond.Wait(); } - // we never end if(false) { ThrLock lock(my); diff --git a/source/pybase.h b/source/pybase.h index aa0d79f..716fb60 100644 --- a/source/pybase.h +++ b/source/pybase.h @@ -14,6 +14,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "pybuffer.h" #include "pybundle.h" #include "ceval.h" +#include "thrctrl.h" #include #if PY_MAJOR_VERSION >= 3 @@ -221,6 +222,9 @@ class pybase static PyFifo qufifo; static ThrCond qucond; + /* The two following variables provide means of shutting the thread system down. */ + static bool qurunning; + static ThrCtrl qucondctrl; #ifndef PY_USE_GIL static ThrState pythrsys; diff --git a/source/thrctrl.h b/source/thrctrl.h new file mode 100644 index 0000000..8278610 --- /dev/null +++ b/source/thrctrl.h @@ -0,0 +1,33 @@ +#ifndef __THRCTRL_H +#define __THRCTRL_H + +#include +#include "flsupport.h" + +#ifdef FLEXT_THREADS +class ThrCtrl +{ +public: + explicit ThrCtrl(flext::ThrCond * thr, bool * ctrlbool, bool init = true) + : _attached_boolean { ctrlbool } + , _attached_thrcond { thr } + { + *_attached_boolean = init; + } + + ~ThrCtrl() + { + *_attached_boolean = !*_attached_boolean; + if(!*_attached_boolean) + { + _attached_thrcond->Signal(); + fprintf(stderr, "Shutting down py/pyext thread pool.\n"); + } + } + +private: + bool * _attached_boolean; + flext::ThrCond * _attached_thrcond; +}; +#endif +#endif // !__THRCTRL_H \ No newline at end of file From 2d5708e2c134e6e49326a830b7770ed226a8464c Mon Sep 17 00:00:00 2001 From: Federico Ferri Date: Tue, 11 Jul 2023 19:40:23 +0200 Subject: [PATCH 145/150] several improvements to CMake build system: - define cache variables instead of plain variable for user-configurable options; those will display nicely in any CMake gui and are self-documenting; - use Python3 module instead of hardcoded paths to python/numpy; - try to automatically determine the shared library suffix (e.g.: .pd_darwin) using Python's `platform` module (note: I tested this only on Darwin); - add a STRIP_TARGET option to make `strip` optional; strip fails on Darwin, probably because some GNU-specific switch has been used; - removed some architecture-specific options which caused build to fail on arm64; those options should anyway not be hardcoded via target_compile_options() but rather set into the specific CMAKE_* variable (e.g. `CMAKE_CXX_FLAGS`, or `CMAKE_CXX_FLAGS_RELEASE`); - refactored some cpp options into the proper CMake commands; - removed the POST_BUILD `mkdir` && `cp` command, and used the more appropriate CMake `install(...)` command. --- CMakeLists.txt | 130 +++++++++++++++++++++---------------------------- 1 file changed, 56 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4e735d..d289143 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,52 +1,45 @@ -cmake_minimum_required(VERSION 3.0.0) +cmake_minimum_required(VERSION 3.26) project(py VERSION 0.1.0 LANGUAGES C CXX) +include(CMakePrintHelpers) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1) -# path to pythonX.X.so (e.g python3.10.so) -if(NOT PYTHON_SHARED_LIB_PATH) - set(PYTHON_SHARED_LIB_PATH "/usr/lib64") -endif() - -# path search by puredata for externals (preferences>edit preferences...>paths in new pd versions) -if(NOT PATH_TO_PD_EXTERNALS) - set(PATH_TO_PD_EXTERNALS "~/Documents/Pd/externals") +find_package(Python3 REQUIRED COMPONENTS Interpreter Development NumPy) +if(VERBOSE) + cmake_print_variables(Python3_INCLUDE_DIRS) + cmake_print_variables(Python3_NumPy_INCLUDE_DIRS) endif() -# path to libpd source files -if(NOT PD_SOURCE_PATH) - set(PD_SOURCE_PATH /usr/local/pd/src) -endif() +# TODO: make a FindPd.cmake find module to address the following PD_* items: -# path to flext source files ; default is assumed py/pyext and flext repos have been cloned in a common parent directory -if(NOT FLEXT_SOURCE_PATH) - set(FLEXT_SOURCE_PATH ../flext/source) +execute_process( + COMMAND "${Python3_EXECUTABLE}" -c "import platform; print('.pd_' + platform.system().lower())" + OUTPUT_VARIABLE PD_EXTERNAL_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE +) +if(VERBOSE) + cmake_print_variables(PD_EXTERNAL_SUFFIX) endif() -# path to python source files (can be found by running `sudo find / -iname "Python.h"`) -if(NOT PYTHON_SOURCE_PATH) - set(PYTHON_SOURCE_PATH /usr/include/python3.10) -endif() +set(PD_EXTERNALS_PATH "~/Documents/Pd/externals" CACHE PATH "Pd externals path") -# your python version -if(NOT PYTHON_VERSION) - set(PYTHON_VERSION 3.10) +if(UNIX AND NOT APPLE) + set(PD_SOURCE_PATH_DEFAULT /usr/local/pd/src) +elseif(UNIX AND APPLE) + set(PD_SOURCE_PATH_DEFAULT /Applications/Pd-0.54-0.app/Contents/Resources/src) +elseif(WIN32) + set(PD_SOURCE_PATH_DEFAULT c:/pd/src) endif() +set(PD_SOURCE_PATH ${PD_SOURCE_PATH_DEFAULT} CACHE PATH "Pd src path") -# flext build -if(NOT FLEXT_BUILD_TYPE) - set(FLEXT_BUILD_TYPE SINGLE) -endif() +set(STRIP_TARGET OFF CACHE BOOL "Strip unneeded symbols from compiled library (saves some disk space)") -include(CMakePrintHelpers) -cmake_print_variables(PYTHON_SOURCE_PATH) -set(CMAKE_INSTALL_RPATH ${PYTHON_SHARED_LIB_PATH}) -set(CMAKE_BUILD_RPATH ${PYTHON_SHARED_LIB_PATH}) -# ---------------------------------------------- # -# BUILDING OBJECT FILES +set(FLEXT_SOURCE_PATH ../flext/source CACHE PATH "Flext source path") +set(FLEXT_BUILD_TYPE SINGLE CACHE STRING "Flext build type") +set_property(CACHE FLEXT_BUILD_TYPE PROPERTY STRINGS "SINGLE" "SHARED" "MULTI") -add_library(objects OBJECT +add_library(objects OBJECT source/bound.cpp source/clmeth.cpp source/main.cpp @@ -64,57 +57,46 @@ add_library(objects OBJECT source/pysymbol.cpp source/register.cpp) -target_compile_options(objects PRIVATE -DPD -DUNIX -O3 -Wl,--trace -fPIC -fcheck-new -DFLEXT_INLINE -DFLEXT_ATTRIBUTES=1 -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing -ffast-math -funroll-loops -fomit-frame-pointer -march=core2 -mfpmath=sse -msse -msse2 -msse3) - -# add flext flag depending on chosen build type +target_compile_definitions(objects PRIVATE PD) +target_compile_definitions(objects PRIVATE FLEXT_INLINE) +target_compile_definitions(objects PRIVATE FLEXT_ATTRIBUTES=1) if(FLEXT_BUILD_TYPE STREQUAL MULTI) - message("setting threads") - target_compile_options(objects PRIVATE -DFLEXT_THREADS) -elseif(FLEXT_BUILD_TYPE STREQUAL SHARED) - target_compile_options(objects PRIVATE -DFLEXT_SHARED) + target_compile_definitions(objects PRIVATE FLEXT_THREADS) +elseif(FLEXT_BUILD_TYPE STREQUAL SHARED) + target_compile_definitions(objects PRIVATE FLEXT_SHARED) endif() - -target_include_directories(objects PRIVATE - ${PD_SOURCE_PATH} - ${FLEXT_SOURCE_PATH} - ${PYTHON_SOURCE_PATH}) - -target_link_libraries(objects PRIVATE -lpython${PYTHON_VERSION}) +if(UNIX) + target_compile_definitions(objects PRIVATE UNIX) +endif() +target_compile_options(objects PRIVATE -O3 -Wl,--trace -fPIC -fcheck-new -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing -ffast-math -funroll-loops -fomit-frame-pointer) +target_include_directories(objects PRIVATE ${PD_SOURCE_PATH}) +target_include_directories(objects PRIVATE ${FLEXT_SOURCE_PATH}) +target_link_libraries(objects PRIVATE Python3::Python Python3::NumPy) # ---------------------------------------------- # # BUILDING PD EXTERNAL PY/PYEXT add_library(${PROJECT_NAME} SHARED $) - target_compile_options(${PROJECT_NAME} PRIVATE -rdynamic -shared -fPIC -Wl,-rpath,"\$ORIGIN",--enable-new-dtags) - -target_link_directories(${PROJECT_NAME} PRIVATE /usr/local/lib) -target_link_directories(${PROJECT_NAME} PRIVATE ${PYTHON_SHARED_LIB_PATH}) - target_link_libraries(${PROJECT_NAME} - PRIVATE -lc - PRIVATE -lm + PRIVATE -lc + PRIVATE -lm PRIVATE -lstdc++ - PRIVATE -lpython${PYTHON_VERSION}) - -if(FLEXT_BUILD_TYPE STREQUAL SHARED) +) +target_link_libraries(${PROJECT_NAME} PRIVATE Python3::Python Python3::NumPy) +if(FLEXT_BUILD_TYPE STREQUAL SHARED) target_compile_options(${PROJECT_NAME} PRIVATE lflext-pd) endif() - set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") +set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX "${PD_EXTERNAL_SUFFIX}") + +if(STRIP_TARGET) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND strip --strip-unneeded ${CMAKE_BINARY_DIR}/${PROJECT_NAME}${PD_EXTERNAL_SUFFIX} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Stripping file..." + ) +endif() -set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".pd_linux") - -# stripping file to make it lighter -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD -COMMAND strip --strip-unneeded ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pd_linux - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Stripping file..." -) - -# copying file to Pd externals directory -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD -COMMAND mkdir -p ${PATH_TO_PD_EXTERNALS}/${PROJECT_NAME} && cp ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pd_linux ${PATH_TO_PD_EXTERNALS}/${PROJECT_NAME} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Copying file to Pd externals directory..." -) \ No newline at end of file +# install to Pd externals directory (run `cmake --install ` to install) +install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}${PD_EXTERNAL_SUFFIX} DESTINATION ${PD_EXTERNALS_PATH}/${PROJECT_NAME}) From f8a6307fd4a75ee1da1f154d98cf84f3b150756d Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Wed, 12 Jul 2023 15:52:37 +0200 Subject: [PATCH 146/150] README for py/pyext with python 3 --- README.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.txt | 17 ----------------- 2 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..5ea5964 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# py/pyext for Python 3 + +## Credits + +### py/pyext - python script objects for PD and Max/MSP + +Copyright (c)2002-2020 Thomas Grill (gr@grrrr.org) + +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +Donations for further development of the package are highly appreciated. +Visit https://www.paypal.com/xclick/business=gr%40grrrr.org&item_name=pyext&no_note=1&tax=0¤cy_code=EUR + +More info in the previous `readme.txt`. +## Installation + +### Pre-requisite +* A python3 environment; +* An installation of [flext](https://github.com/grrrr/flext/); +* cmake ; +* ninja (optional). +### Build with cmake + +Thanks to the work of @fferri, the `CMakeLists.txt` has been largely purified. +The library can be build with wathever python3 environment ; to build with a conda environment for example, first activate that environment before running the following commands: +```bash +mkdir cmake-build +cd cmake-build +cmake .. \ +-GNinja \ # optional, builds faster +-DFLEXT_BUILD_TYPE=[SINGLE | MULTI | SHARED] # SINGLE is default +``` + +The variable `FLEXT_BUILD_TYPE` allows the user to choose which version of flext to use for the build. `MULTI` and `SHARED` enable thread usage. + +### Build with pd-lib-builder + +See `readme.txt`. +## Pd configuration & usage + +### Configuration + +You should create a folder to hold your python scripts - we'll call it the pd script folder; ideally, place it alongside the folder that natively contains the pd externals (for example at `~/Documents/Pd/externals`). + +* Open puredata and go to `File > Preferences > Edit Preferences` (*might be something along the lines of `Paths` for older pd versions*); +* Add the script folder to your search path. + +If you want to work with scripts that are located somewhere else on your machine, you can create a link to that file in the pd script folder. That way, you can modify your file in place and the changes will be taken into account in puredata without having to move your file over and over again. + +### Usage + +There are plenty examples of patches the `pd` folder of this repo. Try them out ! \ No newline at end of file diff --git a/readme.txt b/readme.txt index fc8bf6e..dd272a0 100644 --- a/readme.txt +++ b/readme.txt @@ -61,23 +61,6 @@ Download and unzip, or git-clone the package. Pure data - any platform supporting gcc-compatible compilers ------------------------------------------------------------- - - --> Build with cmake for Python3 support <-- - -A lot of variables can be set to redirect paths for puredata, flext and python, according to your environment. It is suggested to have a look at the CMakeLists.txt to better understand which variables are used where and what they correspond to. - -To build with cmake, run the following commands, replacing the paths and values according to your current environment: -mkdir cmake-build -cd cmake-build -cmake .. \ --GNinja \ # optional, builds faster --DPYTHON_SHARED_LIB_PATH=/path/to/pythonx.x.so \ --DPATH_TO_PD_EXTERNALS=/path/to/pd/externals \ --DPD_SOURCE_PATH=/path/to/pd/sources \ --DFLEXT_SOURCE_PATH=/path/to/flext/sources \ --DPYTHON_SOURCE_PATH=/path/to/python/sources \ --DPYTHON_VERSION=pythoncurrent.version ------------------------------------------------------------ From 5d7ed566691524bfd3b2148ac52a4eac361ce455 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Mon, 17 Jul 2023 16:45:30 +0200 Subject: [PATCH 147/150] ingoring notes for now --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d3ecec4..81d3280 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ config.txt # CMake build folder *-build *__pycache__* + +notes* From b49ad2e5a085e4a8b474afaf122a22617c3b8653 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Thu, 3 Aug 2023 15:10:52 +0200 Subject: [PATCH 148/150] adapt to new flext install --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d289143..09d64c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ set(PD_SOURCE_PATH ${PD_SOURCE_PATH_DEFAULT} CACHE PATH "Pd src path") set(STRIP_TARGET OFF CACHE BOOL "Strip unneeded symbols from compiled library (saves some disk space)") -set(FLEXT_SOURCE_PATH ../flext/source CACHE PATH "Flext source path") +set(FLEXT_SOURCE_PATH /usr/local/include/flext CACHE PATH "Flext source path") set(FLEXT_BUILD_TYPE SINGLE CACHE STRING "Flext build type") set_property(CACHE FLEXT_BUILD_TYPE PROPERTY STRINGS "SINGLE" "SHARED" "MULTI") From cbcd5979bedf547f663bff317836ee420312afb0 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Wed, 9 Aug 2023 11:00:11 +0200 Subject: [PATCH 149/150] added support for pd instance --- CMakeLists.txt | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09d64c9..9d28be0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,23 +1,24 @@ -cmake_minimum_required(VERSION 3.26) +cmake_minimum_required(VERSION 3.24) project(py VERSION 0.1.0 LANGUAGES C CXX) include(CMakePrintHelpers) -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1) +# set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1) find_package(Python3 REQUIRED COMPONENTS Interpreter Development NumPy) + if(VERBOSE) cmake_print_variables(Python3_INCLUDE_DIRS) cmake_print_variables(Python3_NumPy_INCLUDE_DIRS) endif() # TODO: make a FindPd.cmake find module to address the following PD_* items: - execute_process( COMMAND "${Python3_EXECUTABLE}" -c "import platform; print('.pd_' + platform.system().lower())" OUTPUT_VARIABLE PD_EXTERNAL_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE ) + if(VERBOSE) cmake_print_variables(PD_EXTERNAL_SUFFIX) endif() @@ -31,12 +32,14 @@ elseif(UNIX AND APPLE) elseif(WIN32) set(PD_SOURCE_PATH_DEFAULT c:/pd/src) endif() + set(PD_SOURCE_PATH ${PD_SOURCE_PATH_DEFAULT} CACHE PATH "Pd src path") +set(PD_INSTANCE OFF CACHE BOOL "Builds with PDINSTANCE defined") set(STRIP_TARGET OFF CACHE BOOL "Strip unneeded symbols from compiled library (saves some disk space)") set(FLEXT_SOURCE_PATH /usr/local/include/flext CACHE PATH "Flext source path") -set(FLEXT_BUILD_TYPE SINGLE CACHE STRING "Flext build type") +set(FLEXT_BUILD_TYPE SHARED CACHE STRING "Flext build type") set_property(CACHE FLEXT_BUILD_TYPE PROPERTY STRINGS "SINGLE" "SHARED" "MULTI") add_library(objects OBJECT @@ -60,14 +63,22 @@ add_library(objects OBJECT target_compile_definitions(objects PRIVATE PD) target_compile_definitions(objects PRIVATE FLEXT_INLINE) target_compile_definitions(objects PRIVATE FLEXT_ATTRIBUTES=1) + if(FLEXT_BUILD_TYPE STREQUAL MULTI) target_compile_definitions(objects PRIVATE FLEXT_THREADS) elseif(FLEXT_BUILD_TYPE STREQUAL SHARED) target_compile_definitions(objects PRIVATE FLEXT_SHARED) endif() + +if(${PD_INSTANCE}) + target_compile_definitions(objects PRIVATE PDINSTANCE) + target_compile_definitions(objects PRIVATE PDTHREAD) +endif() + if(UNIX) target_compile_definitions(objects PRIVATE UNIX) endif() + target_compile_options(objects PRIVATE -O3 -Wl,--trace -fPIC -fcheck-new -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing -ffast-math -funroll-loops -fomit-frame-pointer) target_include_directories(objects PRIVATE ${PD_SOURCE_PATH}) target_include_directories(objects PRIVATE ${FLEXT_SOURCE_PATH}) @@ -75,7 +86,6 @@ target_link_libraries(objects PRIVATE Python3::Python Python3::NumPy) # ---------------------------------------------- # # BUILDING PD EXTERNAL PY/PYEXT - add_library(${PROJECT_NAME} SHARED $) target_compile_options(${PROJECT_NAME} PRIVATE -rdynamic -shared -fPIC -Wl,-rpath,"\$ORIGIN",--enable-new-dtags) target_link_libraries(${PROJECT_NAME} @@ -84,19 +94,31 @@ target_link_libraries(${PROJECT_NAME} PRIVATE -lstdc++ ) target_link_libraries(${PROJECT_NAME} PRIVATE Python3::Python Python3::NumPy) -if(FLEXT_BUILD_TYPE STREQUAL SHARED) - target_compile_options(${PROJECT_NAME} PRIVATE lflext-pd) + +if(FLEXT_BUILD_TYPE STREQUAL MULTI) + target_compile_definitions(${PROJECT_NAME} PRIVATE FLEXT_THREADS) +elseif(FLEXT_BUILD_TYPE STREQUAL SHARED) + target_compile_definitions(${PROJECT_NAME} PRIVATE FLEXT_SHARED) +endif() +if(${PD_INSTANCE}) + target_compile_definitions(${PROJECT_NAME} PRIVATE PDINSTANCE) + target_compile_definitions(${PROJECT_NAME} PRIVATE PDTHREAD) endif() + set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX "${PD_EXTERNAL_SUFFIX}") if(STRIP_TARGET) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND strip --strip-unneeded ${CMAKE_BINARY_DIR}/${PROJECT_NAME}${PD_EXTERNAL_SUFFIX} + COMMAND strip --strip-unneeded ${CMAKE_BINARY_DIR}/${PROJECT_NAME}${PD_EXTERNAL_SUFFIX} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Stripping file..." ) endif() # install to Pd externals directory (run `cmake --install ` to install) -install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}${PD_EXTERNAL_SUFFIX} DESTINATION ${PD_EXTERNALS_PATH}/${PROJECT_NAME}) +if(NOT ${PD_INSTANCE}) + install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}${PD_EXTERNAL_SUFFIX} DESTINATION ${PD_EXTERNALS_PATH}/${PROJECT_NAME}) +else() + install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}${PD_EXTERNAL_SUFFIX} DESTINATION ${PD_EXTERNALS_PATH}instance/${PROJECT_NAME}) +endif() From 41b58a2c1c75808adc0299c138954ee1930fff7b Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Wed, 9 Aug 2023 11:08:40 +0200 Subject: [PATCH 150/150] made boolean atomic for thread safety --- source/pybase.cpp | 2 +- source/pybase.h | 5 +++-- source/thrctrl.h | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/source/pybase.cpp b/source/pybase.cpp index 59b6a04..961fe34 100644 --- a/source/pybase.cpp +++ b/source/pybase.cpp @@ -85,7 +85,7 @@ void pybase::FreeThreadState() PyFifo pybase::qufifo; flext::ThrCond pybase::qucond; -bool pybase::qurunning; +std::atomic pybase::qurunning; ThrCtrl pybase::qucondctrl {&pybase::qucond, &pybase::qurunning}; // attaching the qucond to the controller to send a signal when closing pd #endif diff --git a/source/pybase.h b/source/pybase.h index 716fb60..9716bf7 100644 --- a/source/pybase.h +++ b/source/pybase.h @@ -16,6 +16,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "ceval.h" #include "thrctrl.h" #include +#include #if PY_MAJOR_VERSION >= 3 #ifdef Py_BEGIN_ALLOW_THREADS @@ -223,8 +224,8 @@ class pybase static PyFifo qufifo; static ThrCond qucond; /* The two following variables provide means of shutting the thread system down. */ - static bool qurunning; - static ThrCtrl qucondctrl; + static std::atomic qurunning; + static ThrCtrl qucondctrl; #ifndef PY_USE_GIL static ThrState pythrsys; diff --git a/source/thrctrl.h b/source/thrctrl.h index 8278610..edbd978 100644 --- a/source/thrctrl.h +++ b/source/thrctrl.h @@ -2,13 +2,14 @@ #define __THRCTRL_H #include +#include #include "flsupport.h" #ifdef FLEXT_THREADS class ThrCtrl { public: - explicit ThrCtrl(flext::ThrCond * thr, bool * ctrlbool, bool init = true) + explicit ThrCtrl(flext::ThrCond * thr, std::atomic * ctrlbool, bool init = true) : _attached_boolean { ctrlbool } , _attached_thrcond { thr } { @@ -26,7 +27,7 @@ class ThrCtrl } private: - bool * _attached_boolean; + std::atomic * _attached_boolean; flext::ThrCond * _attached_thrcond; }; #endif