1#! /bin/sh
2set -e
3
4# Convert templates into Makefile and config.c, based on the module
5# definitions found in the file Setup.
6#
7# Usage: makesetup [-s dir] [-c file] [-m file] [Setup] ... [-n [Setup] ...]
8#
9# Options:
10# -s directory: alternative source directory (default .)
11# -l directory: library source directory (default derived from $0)
12# -c file:      alternative config.c template (default $libdir/config.c.in)
13# -c -:         don't write config.c
14# -m file:      alternative Makefile template (default ./Makefile.pre)
15# -m -:         don't write Makefile
16#
17# Remaining arguments are one or more Setup files (default ./Setup).
18# Setup files after a -n option are used for their variables, modules
19# and libraries but not for their .o files.
20#
21# See Setup for a description of the format of the Setup file.
22#
23# The following edits are made:
24#
25# Copying config.c.in to config.c:
26# - insert an identifying comment at the start
27# - for each <module> mentioned in Setup before *noconfig*:
28#   + insert 'extern PyObject* PyInit_<module>(void);' before MARKER 1
29#   + insert '{"<module>", PyInit_<module>},' before MARKER 2
30#
31# Copying Makefile.pre to Makefile:
32# - insert an identifying comment at the start
33# - replace _MODBUILT_NAMES_ by the list of *static* and *shared* modules
34#   from Setup
35# - replace _MODBSHARED_NAMES_ by the list of *shared* modules from Setup
36# - replace _MODDISABLED_NAMES_ by the list of *disabled* modules from Setup
37# - replace _MODOBJS_ by the list of objects from Setup (except for
38#   Setup files after a -n option)
39# - replace _MODLIBS_ by the list of libraries from Setup
40# - for each object file mentioned in Setup, append a rule
41#   '<file>.o: <file>.c; <build commands>' to the end of the Makefile
42# - for each module mentioned in Setup, append a rule
43#   which creates a shared library version to the end of the Makefile
44# - for each variable definition found in Setup, insert the definition
45#   before the comment 'Definitions added by makesetup'
46
47# Loop over command line options
48usage='
49usage: makesetup [-s srcdir] [-l libdir] [-c config.c.in] [-m Makefile.pre]
50                 [Setup] ... [-n [Setup] ...]'
51srcdir='.'
52libdir=''
53config=''
54makepre=''
55noobjects=''
56doconfig=yes
57while :
58do
59	case $1 in
60	-s)	shift; srcdir=$1; shift;;
61	-l)	shift; libdir=$1; shift;;
62	-c)	shift; config=$1; shift;;
63	-m)	shift; makepre=$1; shift;;
64	--)	shift; break;;
65	-n)	noobjects=yes;;
66	-*)	echo "$usage" 1>&2; exit 2;;
67	*)	break;;
68	esac
69done
70
71# Set default libdir and config if not set by command line
72# (Not all systems have dirname)
73case $libdir in
74'')	case $0 in
75	*/*)	libdir=`echo $0 | sed 's,/[^/]*$,,'`;;
76	*)	libdir=.;;
77	esac;;
78esac
79case $config in
80'')	config=$libdir/config.c.in;;
81esac
82case $makepre in
83'')	makepre=Makefile.pre;;
84esac
85
86# Newline for sed i and a commands
87NL='\
88'
89
90# Setup to link with extra libraries when making shared extensions.
91# Currently, only Cygwin needs this baggage.
92case `uname -s` in
93CYGWIN*) if test $libdir = .
94	 then
95	 	ExtraLibDir=.
96	 else
97	 	ExtraLibDir='$(LIBPL)'
98	 fi
99	 ExtraLibs="-L$ExtraLibDir -lpython\$(LDVERSION)";;
100esac
101
102# Main loop
103for i in ${*-Setup}
104do
105	case $i in
106	-n)	echo '*noobjects*';;
107	*)	echo '*doconfig*'; cat "$i";;
108	esac
109done |
110sed -e 's/[ 	]*#.*//' -e '/^[ 	]*$/d' |
111(
112	rulesf="@rules.$$"
113	trap 'rm -f $rulesf' 0 1 2 3
114	echo "
115# Rules appended by makesetup
116" >$rulesf
117	DEFS=
118	BUILT=
119	BUILT_SHARED=
120	DISABLED=
121	CONFIGURED=
122	MODS=
123	SHAREDMODS=
124	OBJS=
125	LIBS=
126	LOCALLIBS=
127	BASELIBS=
128	while read line
129	do
130		# to handle backslashes for sh's that don't automatically
131		# continue a read when the last char is a backslash
132		while echo $line | grep '\\$' > /dev/null
133		do
134			read extraline
135			line=`echo $line| sed s/.$//`$extraline
136		done
137
138		# Output DEFS in reverse order so first definition overrides
139		case $line in
140		*=*)	DEFS="$line$NL$DEFS"; continue;;
141		'include '*)	DEFS="$line$NL$DEFS"; continue;;
142		'*noobjects*')
143			case $noobjects in
144			yes)	;;
145			*)	LOCALLIBS=$LIBS; LIBS=;;
146			esac
147			noobjects=yes;
148			continue;;
149		'*doconfig*')	doconfig=yes; continue;;
150		'*static*')	doconfig=yes; continue;;
151		'*noconfig*')	doconfig=no; continue;;
152		'*shared*')	doconfig=no; continue;;
153		'*disabled*')	doconfig=disabled; continue;;
154		esac
155		srcs=
156		cpps=
157		libs=
158		mods=
159		mods_upper=
160		skip=
161		for arg in $line
162		do
163			case $skip in
164			libs)	libs="$libs $arg"; skip=; continue;;
165			cpps)	cpps="$cpps $arg"; skip=; continue;;
166			srcs)	srcs="$srcs $arg"; skip=; continue;;
167			esac
168			case $arg in
169			-framework)	libs="$libs $arg"; skip=libs;
170				        # OSX/OSXS/Darwin framework link cmd
171					;;
172			-[IDUCfF]*)	cpps="$cpps $arg";;
173			-Xcompiler)	skip=cpps;;
174			-Xlinker)	libs="$libs $arg"; skip=libs;;
175			-rpath)		libs="$libs $arg"; skip=libs;;
176			--rpath)	libs="$libs $arg"; skip=libs;;
177			-[A-Zl]*)	libs="$libs $arg";;
178			*.a)		libs="$libs $arg";;
179			*.so)		libs="$libs $arg";;
180			*.sl)		libs="$libs $arg";;
181			/*.o)		libs="$libs $arg";;
182			*.def)		libs="$libs $arg";;
183			*.o)		srcs="$srcs `basename $arg .o`.c";;
184			*.[cC])		srcs="$srcs $arg";;
185			*.m)		srcs="$srcs $arg";; # Objective-C src
186			*.cc)		srcs="$srcs $arg";;
187			*.c++)		srcs="$srcs $arg";;
188			*.cxx)		srcs="$srcs $arg";;
189			*.cpp)		srcs="$srcs $arg";;
190			\$\(*_CFLAGS\))		cpps="$cpps $arg";;
191			\$\(*_INCLUDES\))	cpps="$cpps $arg";;
192			\$\(*_LIBS\))		libs="$libs $arg";;
193			\$\(*_LDFLAGS\))	libs="$libs $arg";;
194			\$\(*_RPATH\))		libs="$libs $arg";;
195			\$*)		libs="$libs $arg"
196					cpps="$cpps $arg";;
197			*.*)		echo 1>&2 "bad word $arg in $line"
198					exit 1;;
199			-u)		skip=libs; libs="$libs -u";;
200			[a-zA-Z_]*)
201					mods="$mods $arg"
202					mods_upper=$(echo $mods | tr '[a-z]' '[A-Z]');;
203			*)		echo 1>&2 "bad word $arg in $line"
204					exit 1;;
205			esac
206		done
207		if test -z "$cpps" -a -z "$libs"; then
208			cpps="\$(MODULE_${mods_upper}_CFLAGS)"
209			libs="\$(MODULE_${mods_upper}_LDFLAGS)"
210		fi
211		for mod in $mods
212		do
213			case $CONFIGURED in
214			*,${mod},*)
215				# Detected multiple rules for a module, first rule wins. This
216				# allows users to disable modules in Setup.local.
217				echo 1>&2 "maksetup: '$mod' was handled by previous rule."
218				continue 2;;
219			esac
220			CONFIGURED="$CONFIGURED,${mod},"
221		done
222		case $doconfig in
223		yes)
224			LIBS="$LIBS $libs"
225			MODS="$MODS $mods"
226			BUILT="$BUILT $mods"
227			;;
228		no)
229			BUILT="$BUILT $mods"
230			;;
231		disabled)
232			DISABLED="$DISABLED $mods"
233			continue
234			;;
235		esac
236		case $noobjects in
237		yes)	continue;;
238		esac
239		objs=''
240		for src in $srcs
241		do
242			case $src in
243			*.c)   obj=`basename $src .c`.o; cc='$(CC)';;
244			*.cc)  obj=`basename $src .cc`.o; cc='$(CXX)';;
245			*.c++) obj=`basename $src .c++`.o; cc='$(CXX)';;
246			*.C)   obj=`basename $src .C`.o; cc='$(CXX)';;
247			*.cxx) obj=`basename $src .cxx`.o; cc='$(CXX)';;
248			*.cpp) obj=`basename $src .cpp`.o; cc='$(CXX)';;
249			*.m)   obj=`basename $src .m`.o; cc='$(CC)';; # Obj-C
250			*)     continue;;
251			esac
252			case $src in
253			*/*) obj="$srcdir/`dirname $src`/$obj";;
254			*)   obj="$srcdir/$obj";;
255			esac
256			objs="$objs $obj"
257			case $src in
258			glmodule.c) ;;
259			/*) ;;
260			\$*) ;;
261			*) src='$(srcdir)/'"$srcdir/$src";;
262			esac
263			# custom flags first, PY_STDMODULE_CFLAGS may contain -I with system libmpdec
264			case $doconfig in
265			no)	cc="$cc $cpps \$(PY_STDMODULE_CFLAGS) \$(CCSHARED)";;
266			*)
267				cc="$cc $cpps \$(PY_BUILTIN_MODULE_CFLAGS)";;
268			esac
269			# force rebuild when header file or module build flavor (static/shared) is changed
270			rule="$obj: $src \$(MODULE_${mods_upper}_DEPS) \$(PYTHON_HEADERS) Modules/config.c; $cc -c $src -o $obj"
271			echo "$rule" >>$rulesf
272		done
273		case $doconfig in
274		yes)	OBJS="$OBJS $objs";;
275		esac
276		for mod in $mods
277		do
278			file="$srcdir/$mod\$(EXT_SUFFIX)"
279			case $doconfig in
280			no)
281				SHAREDMODS="$SHAREDMODS $file"
282				BUILT_SHARED="$BUILT_SHARED $mod"
283				;;
284			esac
285			rule="$file: $objs"
286			rule="$rule; \$(BLDSHARED) $objs $libs $ExtraLibs -o $file"
287			echo "$rule" >>$rulesf
288		done
289	done
290
291	case $SHAREDMODS in
292	'')	;;
293	*)	DEFS="SHAREDMODS=$SHAREDMODS$NL$DEFS";;
294	esac
295
296	case $noobjects in
297	yes)	BASELIBS=$LIBS;;
298	*)	LOCALLIBS=$LIBS;;
299	esac
300	LIBS='$(LOCALMODLIBS) $(BASEMODLIBS)'
301	DEFS="BASEMODLIBS=$BASELIBS$NL$DEFS"
302	DEFS="LOCALMODLIBS=$LOCALLIBS$NL$DEFS"
303
304	EXTDECLS=
305	INITBITS=
306	for mod in $MODS
307	do
308		EXTDECLS="${EXTDECLS}extern PyObject* PyInit_$mod(void);$NL"
309		INITBITS="${INITBITS}    {\"$mod\", PyInit_$mod},$NL"
310	done
311
312
313	case $config in
314	-)  ;;
315	*)  sed -e "
316		1i$NL/* Generated automatically from $config by makesetup. */
317		/MARKER 1/i$NL$EXTDECLS
318
319		/MARKER 2/i$NL$INITBITS
320
321		" $config >config.c
322	    ;;
323	esac
324
325	case $makepre in
326	-)	;;
327	*)
328		# macOS' sed has issues with 'a' command. Use 'r' command with an
329		# external replacement file instead.
330		sedf="@sed.in.$$"
331		sedr="@sed.replace.$$"
332		trap 'rm -f $sedf $sedr' 0 1 2 3
333		echo "$NL$NL$DEFS" | sed 's/\\$//' > $sedr
334		echo "1i\\" >$sedf
335		str="# Generated automatically from $makepre by makesetup."
336		echo "$str" >>$sedf
337		echo "s%_MODBUILT_NAMES_%$BUILT%" >>$sedf
338		echo "s%_MODSHARED_NAMES_%$BUILT_SHARED%" >>$sedf
339		echo "s%_MODDISABLED_NAMES_%$DISABLED%" >>$sedf
340		echo "s%_MODOBJS_%$OBJS%" >>$sedf
341		echo "s%_MODLIBS_%$LIBS%" >>$sedf
342		echo "/Definitions added by makesetup/r $sedr" >>$sedf
343		sed -f $sedf $makepre >Makefile
344		cat $rulesf >>Makefile
345		rm -f $sedf $sedr
346	    ;;
347	esac
348
349	rm -f $rulesf
350)
351