--- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -236,11 +236,19 @@ def _parse_makefile(filename, vars=None) done[n] = v # do variable interpolation here - while notdone: - for name in notdone.keys(): + variables = list(notdone.keys()) + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + while len(variables) > 0: + for name in tuple(variables): value = notdone[name] m = _findvar1_rx.search(value) or _findvar2_rx.search(value) - if m: + if m is not None: n = m.group(1) found = True if n in done: @@ -251,23 +259,48 @@ def _parse_makefile(filename, vars=None) elif n in os.environ: # do it like make: fall back to environment item = os.environ[n] + + elif n in renamed_variables: + if name.startswith('PY_') and name[3:] in renamed_variables: + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + else: done[n] = item = "" + if found: after = value[m.end():] value = value[:m.start()] + item + after if "$" in after: notdone[name] = value else: - try: value = int(value) + try: + value = int(value) except ValueError: done[name] = value.strip() else: done[name] = value - del notdone[name] + variables.remove(name) + + if name.startswith('PY_') \ + and name[3:] in renamed_variables: + + name = name[3:] + if name not in done: + done[name] = value + + else: - # bogus variable reference; just drop it since we can't deal - del notdone[name] + # bogus variable reference (e.g. "prefix=$/opt/python"); + # just drop it since we can't deal + done[name] = value + variables.remove(name) + # strip spurious spaces for k, v in done.items(): if isinstance(v, str): --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -72,12 +72,18 @@ MAKESETUP= $(srcdir)/Modules/makese # Compiler options OPT= @OPT@ BASECFLAGS= @BASECFLAGS@ -CFLAGS= $(BASECFLAGS) @CFLAGS@ $(OPT) $(EXTRA_CFLAGS) +CONFIGURE_CFLAGS= @CFLAGS@ +CONFIGURE_CPPFLAGS= @CPPFLAGS@ +CONFIGURE_LDFLAGS= @LDFLAGS@ +# Avoid assigning CFLAGS, LDFLAGS, etc. so users can use them on the +# command line to append to these values without stomping the pre-set +# values. +PY_CFLAGS= $(BASECFLAGS) $(OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) # Both CPPFLAGS and LDFLAGS need to contain the shell's value for setup.py to # be able to build extension modules using the directories specified in the # environment variables -CPPFLAGS= -I. -IInclude -I$(srcdir)/Include @CPPFLAGS@ -LDFLAGS= @LDFLAGS@ +PY_CPPFLAGS= -I. -IInclude -I$(srcdir)/Include $(CONFIGURE_CPPFLAGS) $(CPPFLAGS) +PY_LDFLAGS= $(CONFIGURE_LDFLAGS) $(LDFLAGS) LDLAST= @LDLAST@ SGI_ABI= @SGI_ABI@ CCSHARED= @CCSHARED@ @@ -86,7 +92,7 @@ ARFLAGS= @ARFLAGS@ # Extra C flags added for building the interpreter object files. CFLAGSFORSHARED=@CFLAGSFORSHARED@ # C flags used for building the interpreter object files -PY_CFLAGS= $(CFLAGS) $(CPPFLAGS) $(CFLAGSFORSHARED) -DPy_BUILD_CORE +PY_CORE_CFLAGS= $(PY_CFLAGS) $(PY_CPPFLAGS) $(CFLAGSFORSHARED) -DPy_BUILD_CORE # Machine-dependent subdirectories @@ -487,7 +493,7 @@ coverage-report: regen-grammar # Build the interpreter $(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY) - $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \ + $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ \ Modules/python.o \ $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) @@ -512,7 +518,7 @@ pybuilddir.txt: $(BUILDPYTHON) # This is shared by the math and cmath modules Modules/_math.o: Modules/_math.c Modules/_math.h - $(CC) -c $(CCSHARED) $(PY_CFLAGS) -o $@ $< + $(CC) -c $(CCSHARED) $(PY_CORE_CFLAGS) -o $@ $< # Build the shared modules # Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for @@ -523,7 +529,7 @@ sharedmods: $(BUILDPYTHON) pybuilddir.tx *\ -s*|s*) quiet="-q";; \ *) quiet="";; \ esac; \ - $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' LDFLAGS='$(PY_LDFLAGS)' OPT='$(OPT)' \ _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build @@ -541,18 +547,18 @@ $(LIBRARY): $(LIBRARY_OBJS) libpython$(VERSION).so: $(LIBRARY_OBJS) if test $(INSTSONAME) != $(LDLIBRARY); then \ - $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + $(BLDSHARED) $(PY_LDFLAGS) $(CCSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ $(LN) -f $(INSTSONAME) $@; \ else \ - $(BLDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + $(BLDSHARED) $(PY_LDFLAGS) $(CCSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ fi libpython$(VERSION).dylib: $(LIBRARY_OBJS) - $(CC) -dynamiclib -Wl,-single_module $(LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(VERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ + $(CC) -dynamiclib -Wl,-single_module $(PY_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(VERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ libpython$(VERSION).sl: $(LIBRARY_OBJS) - $(LDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST) + $(LDSHARED) $(PY_LDFLAGS) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST) # Copy up the gdb python hooks into a position where they can be automatically # loaded by gdb during Lib/test/test_gdb.py @@ -591,7 +597,7 @@ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION # for a shared core library; otherwise, this rule is a noop. $(DLLLIBRARY) libpython$(VERSION).dll.a: $(LIBRARY_OBJS) if test -n "$(DLLLIBRARY)"; then \ - $(LDSHARED) -Wl,--out-implib=$@ -o $(DLLLIBRARY) $^ \ + $(LDSHARED) $(PY_LDFLAGS) -Wl,--out-implib=$@ -o $(DLLLIBRARY) $^ \ $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST); \ else true; \ fi @@ -641,14 +647,14 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \ $(SIGNAL_OBJS) \ $(MODOBJS) \ $(srcdir)/Modules/getbuildinfo.c - $(CC) -c $(PY_CFLAGS) \ + $(CC) -c $(PY_CORE_CFLAGS) \ -DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \ -DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \ -DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \ -o $@ $(srcdir)/Modules/getbuildinfo.c Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile - $(CC) -c $(PY_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ + $(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ -DPREFIX='"$(prefix)"' \ -DEXEC_PREFIX='"$(exec_prefix)"' \ -DVERSION='"$(VERSION)"' \ @@ -656,7 +662,7 @@ Modules/getpath.o: $(srcdir)/Modules/get -o $@ $(srcdir)/Modules/getpath.c Modules/python.o: $(srcdir)/Modules/python.c - $(MAINCC) -c $(PY_CFLAGS) -o $@ $(srcdir)/Modules/python.c + $(MAINCC) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Modules/python.c Modules/posixmodule.o: $(srcdir)/Modules/posixmodule.c $(srcdir)/Modules/posixmodule.h @@ -665,7 +671,7 @@ Modules/grpmodule.o: $(srcdir)/Modules/g Modules/pwdmodule.o: $(srcdir)/Modules/pwdmodule.c $(srcdir)/Modules/posixmodule.h $(PGEN): $(PGENOBJS) - $(CC) $(OPT) $(LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN) + $(CC) $(OPT) $(PY_LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN) .PHONY: regen-grammar regen-grammar: $(PGEN) @@ -701,10 +707,10 @@ regen-ast: Python/compile.o Python/symtable.o Python/ast.o: $(srcdir)/Include/graminit.h $(srcdir)/Include/Python-ast.h Python/getplatform.o: $(srcdir)/Python/getplatform.c - $(CC) -c $(PY_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c + $(CC) -c $(PY_CORE_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c Python/importdl.o: $(srcdir)/Python/importdl.c - $(CC) -c $(PY_CFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c + $(CC) -c $(PY_CORE_CFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c Objects/unicodectype.o: $(srcdir)/Objects/unicodectype.c \ $(srcdir)/Objects/unicodetype_db.h @@ -1362,7 +1368,7 @@ config.status: $(srcdir)/configure # Some make's put the object file in the current directory .c.o: - $(CC) -c $(PY_CFLAGS) -o $@ $< + $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< # Run reindent on the library reindent: --- a/Modules/makesetup +++ b/Modules/makesetup @@ -219,7 +219,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | case $doconfig in no) cc="$cc \$(CCSHARED) \$(CFLAGS) \$(CPPFLAGS)";; *) - cc="$cc \$(PY_CFLAGS)";; + cc="$cc \$(PY_CORE_CFLAGS)";; esac rule="$obj: $src; $cc $cpps -c $src -o $obj" echo "$rule" >>$rulesf --- a/configure.ac +++ b/configure.ac @@ -647,14 +647,13 @@ if test "$MACHDEP" = "irix6" && test "$C fi fi -# If the user set CFLAGS, use this instead of the automatically -# determined setting -preset_cflags="$CFLAGS" -AC_PROG_CC -if test ! -z "$preset_cflags" -then - CFLAGS=$preset_cflags +# Don't let AC_PROG_CC set the default CFLAGS. It normally sets -g -O2 +# when the compiler supports them, but we don't always want -O2, and +# we set -g later. +if test -z "$CFLAGS"; then + CFLAGS= fi +AC_PROG_CC AC_SUBST(CXX) AC_SUBST(MAINCC) --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -330,11 +330,19 @@ def parse_makefile(fn, g=None): done[n] = v # do variable interpolation here - while notdone: - for name in notdone.keys(): + variables = list(notdone.keys()) + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + while len(variables) > 0: + for name in tuple(variables): value = notdone[name] m = _findvar1_rx.search(value) or _findvar2_rx.search(value) - if m: + if m is not None: n = m.group(1) found = True if n in done: @@ -345,25 +353,47 @@ def parse_makefile(fn, g=None): elif n in os.environ: # do it like make: fall back to environment item = os.environ[n] + + elif n in renamed_variables: + if name.startswith('PY_') and name[3:] in renamed_variables: + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + else: done[n] = item = "" + if found: after = value[m.end():] value = value[:m.start()] + item + after if "$" in after: notdone[name] = value else: - try: value = int(value) + try: + value = int(value) except ValueError: done[name] = value.strip() else: done[name] = value - del notdone[name] - else: - # bogus variable reference; just drop it since we can't deal - del notdone[name] + variables.remove(name) + + if name.startswith('PY_') \ + and name[3:] in renamed_variables: - fp.close() + name = name[3:] + if name not in done: + done[name] = value + + + else: + # bogus variable reference (e.g. "prefix=$/opt/python"); + # just drop it since we can't deal + done[name] = value + variables.remove(name) # strip spurious spaces for k, v in done.items(): --- a/Lib/distutils/tests/test_sysconfig.py +++ b/Lib/distutils/tests/test_sysconfig.py @@ -60,7 +60,7 @@ def test_parse_makefile_base(self): fd.close() d = sysconfig.parse_makefile(self.makefile) self.assertEqual(d, {'CONFIG_ARGS': "'--arg1=optarg1' 'ENV=LIB'", - 'OTHER': 'foo'}) + 'OTHER': 'foo', 'VAR': '$OTHER'}) def test_parse_makefile_literal_dollar(self): self.makefile = test.test_support.TESTFN @@ -72,7 +72,7 @@ def test_parse_makefile_literal_dollar(self): fd.close() d = sysconfig.parse_makefile(self.makefile) self.assertEqual(d, {'CONFIG_ARGS': r"'--arg1=optarg1' 'ENV=\$LIB'", - 'OTHER': 'foo'}) + 'OTHER': 'foo', 'VAR': '$OTHER'}) def test_sysconfig_module(self):