Skip to content

Commit 464e661

Browse files
authored
bpo-45800: Move pyexpat build setup into configure (GH-29547)
Settings for :mod:`pyexpat` C extension are now detected by ``configure``. The bundled ``expat`` library is built in ``Makefile``. Signed-off-by: Christian Heimes <[email protected]>
1 parent 25835c5 commit 464e661

File tree

6 files changed

+177
-58
lines changed

6 files changed

+177
-58
lines changed

Makefile.pre.in

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,33 @@ LIBMPDEC_HEADERS= \
537537

538538
LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a
539539

540+
##########################################################################
541+
# pyexpat's expat library
542+
543+
LIBEXPAT_OBJS= \
544+
Modules/expat/xmlparse.o \
545+
Modules/expat/xmlrole.o \
546+
Modules/expat/xmltok.o
547+
548+
LIBEXPAT_HEADERS= \
549+
Modules/expat/ascii.h \
550+
Modules/expat/asciitab.h \
551+
Modules/expat/expat.h \
552+
Modules/expat/expat_config.h \
553+
Modules/expat/expat_external.h \
554+
Modules/expat/iasciitab.h \
555+
Modules/expat/internal.h \
556+
Modules/expat/latin1tab.h \
557+
Modules/expat/nametab.h \
558+
Modules/expat/pyexpatns.h \
559+
Modules/expat/siphash.h \
560+
Modules/expat/utf8tab.h \
561+
Modules/expat/xmlrole.h \
562+
Modules/expat/xmltok.h \
563+
Modules/expat/xmltok_impl.h
564+
565+
LIBEXPAT_A= Modules/expat/libexpat.a
566+
540567
#########################################################################
541568
# Rules
542569

@@ -688,7 +715,7 @@ $(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl
688715
# -s, --silent or --quiet is always the first char.
689716
# Under BSD make, MAKEFLAGS might be " -s -v x=y".
690717
# Ignore macros passed by GNU make, passed after --
691-
sharedmods: $(BUILDPYTHON) pybuilddir.txt @LIBMPDEC_INTERNAL@
718+
sharedmods: $(BUILDPYTHON) pybuilddir.txt @LIBMPDEC_INTERNAL@ @LIBEXPAT_INTERNAL@
692719
@case "`echo X $$MAKEFLAGS | sed 's/^X //;s/ -- .*//'`" in \
693720
*\ -s*|s*) quiet="-q";; \
694721
*) quiet="";; \
@@ -828,6 +855,27 @@ $(LIBMPDEC_A): $(LIBMPDEC_OBJS)
828855
-rm -f $@
829856
$(AR) $(ARFLAGS) $@ $(LIBMPDEC_OBJS)
830857

858+
##########################################################################
859+
# Build static libexpat.a
860+
LIBEXPAT_CFLAGS=$(PY_STDMODULE_CFLAGS) $(CCSHARED) @LIBEXPAT_CFLAGS@
861+
862+
# for setup.py
863+
EXPAT_CFLAGS=@LIBEXPAT_CFLAGS@
864+
EXPAT_LDFLAGS=@LIBEXPAT_LDFLAGS@
865+
866+
Modules/expat/xmlparse.o: $(srcdir)/Modules/expat/xmlparse.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS)
867+
$(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlparse.c
868+
869+
Modules/expat/xmlrole.o: $(srcdir)/Modules/expat/xmlrole.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS)
870+
$(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlrole.c
871+
872+
Modules/expat/xmltok.o: $(srcdir)/Modules/expat/xmltok.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS)
873+
$(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmltok.c
874+
875+
$(LIBEXPAT_A): $(LIBEXPAT_OBJS)
876+
-rm -f $@
877+
$(AR) $(ARFLAGS) $@ $(LIBEXPAT_OBJS)
878+
831879
# create relative links from build/lib.platform/egg.so to Modules/egg.so
832880
# pybuilddir.txt is created too late. We cannot use it in Makefile
833881
# targets. ln --relative is not portable.
@@ -2407,12 +2455,12 @@ Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h
24072455

24082456
MODULE_CMATH_DEPS=$(srcdir)/Modules/_math.h
24092457
MODULE_MATH_DEPS=$(srcdir)/Modules/_math.h
2410-
MODULE_PYEXPAT_DEPS=$(srcdir)/Modules/expat/ascii.h $(srcdir)/Modules/expat/asciitab.h $(srcdir)/Modules/expat/expat.h $(srcdir)/Modules/expat/expat_config.h $(srcdir)/Modules/expat/expat_external.h $(srcdir)/Modules/expat/internal.h $(srcdir)/Modules/expat/latin1tab.h $(srcdir)/Modules/expat/utf8tab.h $(srcdir)/Modules/expat/xmlrole.h $(srcdir)/Modules/expat/xmltok.h $(srcdir)/Modules/expat/xmltok_impl.h
2458+
MODULE_PYEXPAT_DEPS=$(LIBEXPAT_HEADERS) @LIBEXPAT_INTERNAL@
24112459
MODULE_UNICODEDATA_DEPS=$(srcdir)/Modules/unicodedata_db.h $(srcdir)/Modules/unicodename_db.h
24122460
MODULE__BLAKE2_DEPS=$(srcdir)/Modules/_blake2/impl/blake2-config.h $(srcdir)/Modules/_blake2/impl/blake2-dispatch.c $(srcdir)/Modules/_blake2/impl/blake2-impl.h $(srcdir)/Modules/_blake2/impl/blake2-kat.h $(srcdir)/Modules/_blake2/impl/blake2.h $(srcdir)/Modules/_blake2/impl/blake2b-load-sse2.h $(srcdir)/Modules/_blake2/impl/blake2b-load-sse41.h $(srcdir)/Modules/_blake2/impl/blake2b-ref.c $(srcdir)/Modules/_blake2/impl/blake2b-round.h $(srcdir)/Modules/_blake2/impl/blake2b-test.c $(srcdir)/Modules/_blake2/impl/blake2b.c $(srcdir)/Modules/_blake2/impl/blake2bp-test.c $(srcdir)/Modules/_blake2/impl/blake2bp.c $(srcdir)/Modules/_blake2/impl/blake2s-load-sse2.h $(srcdir)/Modules/_blake2/impl/blake2s-load-sse41.h $(srcdir)/Modules/_blake2/impl/blake2s-load-xop.h $(srcdir)/Modules/_blake2/impl/blake2s-ref.c $(srcdir)/Modules/_blake2/impl/blake2s-round.h $(srcdir)/Modules/_blake2/impl/blake2s-test.c $(srcdir)/Modules/_blake2/impl/blake2s.c $(srcdir)/Modules/_blake2/impl/blake2sp-test.c $(srcdir)/Modules/_blake2/impl/blake2sp.c $(srcdir)/Modules/hashlib.h
24132461
MODULE__CTYPES_DEPS=$(srcdir)/Modules/_ctypes/ctypes.h
24142462
MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h $(LIBMPDEC_HEADERS) @LIBMPDEC_INTERNAL@
2415-
MODULE__ELEMENTTREE_DEPS=$(srcdir)/Modules/expat/ascii.h $(srcdir)/Modules/expat/asciitab.h $(srcdir)/Modules/expat/expat.h $(srcdir)/Modules/expat/expat_config.h $(srcdir)/Modules/expat/expat_external.h $(srcdir)/Modules/expat/internal.h $(srcdir)/Modules/expat/latin1tab.h $(srcdir)/Modules/expat/utf8tab.h $(srcdir)/Modules/expat/xmlparse.c $(srcdir)/Modules/expat/xmlrole.c $(srcdir)/Modules/expat/xmlrole.h $(srcdir)/Modules/expat/xmltok.c $(srcdir)/Modules/expat/xmltok.h $(srcdir)/Modules/expat/xmltok_impl.h $(srcdir)/Modules/pyexpat.c
2463+
MODULE__ELEMENTTREE_DEPS=$(LIBEXPAT_HEADERS) @LIBEXPAT_INTERNAL@
24162464
MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h
24172465
MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h
24182466
MODULE__MD5_DEPS=$(srcdir)/Modules/hashlib.h
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Settings for :mod:`pyexpat` C extension are now detected by ``configure``.
2+
The bundled ``expat`` library is built in ``Makefile``.

Modules/Setup

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ time timemodule.c
172172
#select selectmodule.c
173173

174174
# XML
175-
#_elementtree -I$(srcdir)/Modules/expat _elementtree.c
176-
#pyexpat -I$(srcdir)/Modules/expat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c
175+
#_elementtree _elementtree.c $(EXPAT_CFLAGS)
176+
#pyexpat pyexpat.c $(EXPAT_CFLAGS) $(EXPAT_LDFLAGS)
177177

178178
# hashing builtins
179179
#_blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c

configure

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,9 @@ LIBMPDEC_INTERNAL
664664
LIBMPDEC_LDFLAGS
665665
LIBMPDEC_CFLAGS
666666
LIBFFI_INCLUDEDIR
667+
LIBEXPAT_INTERNAL
668+
LIBEXPAT_LDFLAGS
669+
LIBEXPAT_CFLAGS
667670
TZPATH
668671
SHLIBS
669672
CFLAGSFORSHARED
@@ -10715,6 +10718,24 @@ fi
1071510718
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_system_expat" >&5
1071610719
$as_echo "$with_system_expat" >&6; }
1071710720

10721+
if test "x$with_system_expat" = xyes; then :
10722+
10723+
LIBEXPAT_CFLAGS=""
10724+
LIBEXPAT_LDFLAGS="-lexpat"
10725+
LIBEXPAT_INTERNAL=
10726+
10727+
else
10728+
10729+
LIBEXPAT_CFLAGS="-I\$(srcdir)/Modules/expat"
10730+
LIBEXPAT_LDFLAGS="-lm \$(LIBEXPAT_A)"
10731+
LIBEXPAT_INTERNAL="\$(LIBEXPAT_A)"
10732+
10733+
fi
10734+
10735+
10736+
10737+
10738+
1071810739
# Check for use of the system libffi library
1071910740
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-system-ffi" >&5
1072010741
$as_echo_n "checking for --with-system-ffi... " >&6; }

configure.ac

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3017,6 +3017,20 @@ AC_ARG_WITH(system_expat,
30173017

30183018
AC_MSG_RESULT($with_system_expat)
30193019

3020+
AS_VAR_IF([with_system_expat], [yes], [
3021+
LIBEXPAT_CFLAGS=""
3022+
LIBEXPAT_LDFLAGS="-lexpat"
3023+
LIBEXPAT_INTERNAL=
3024+
], [
3025+
LIBEXPAT_CFLAGS="-I\$(srcdir)/Modules/expat"
3026+
LIBEXPAT_LDFLAGS="-lm \$(LIBEXPAT_A)"
3027+
LIBEXPAT_INTERNAL="\$(LIBEXPAT_A)"
3028+
])
3029+
3030+
AC_SUBST([LIBEXPAT_CFLAGS])
3031+
AC_SUBST([LIBEXPAT_LDFLAGS])
3032+
AC_SUBST([LIBEXPAT_INTERNAL])
3033+
30203034
# Check for use of the system libffi library
30213035
AC_MSG_CHECKING(for --with-system-ffi)
30223036
AC_ARG_WITH(system_ffi,

setup.py

Lines changed: 87 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,57 @@ def find_module_file(module, dirlist):
364364
return os.path.join(dirs[0], module)
365365

366366

367+
def parse_cflags(flags):
368+
"""Parse a string with compiler flags (-I, -D, -U, extra)
369+
370+
Distutils appends extra args to the compiler arguments. Some flags like
371+
-I must appear earlier. Otherwise the pre-processor picks up files
372+
from system inclue directories.
373+
"""
374+
include_dirs = []
375+
define_macros = []
376+
undef_macros = []
377+
extra_compile_args = []
378+
if flags is not None:
379+
# shlex.split(None) reads from stdin
380+
for token in shlex.split(flags):
381+
switch = token[0:2]
382+
value = token[2:]
383+
if switch == '-I':
384+
include_dirs.append(value)
385+
elif switch == '-D':
386+
key, _, val = value.partition("=")
387+
if not val:
388+
val = None
389+
define_macros.append((key, val))
390+
elif switch == '-U':
391+
undef_macros.append(value)
392+
else:
393+
extra_compile_args.append(token)
394+
395+
return include_dirs, define_macros, undef_macros, extra_compile_args
396+
397+
398+
def parse_ldflags(flags):
399+
"""Parse a string with linker flags (-L, -l, extra)"""
400+
library_dirs = []
401+
libraries = []
402+
extra_link_args = []
403+
if flags is not None:
404+
# shlex.split(None) reads from stdin
405+
for token in shlex.split(flags):
406+
switch = token[0:2]
407+
value = token[2:]
408+
if switch == '-L':
409+
library_dirs.append(value)
410+
elif switch == '-l':
411+
libraries.append(value)
412+
else:
413+
extra_link_args.append(token)
414+
415+
return library_dirs, libraries, extra_link_args
416+
417+
367418
class PyBuildExt(build_ext):
368419

369420
def __init__(self, dist):
@@ -1469,59 +1520,39 @@ def detect_expat_elementtree(self):
14691520
#
14701521
# More information on Expat can be found at www.libexpat.org.
14711522
#
1472-
if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"):
1473-
expat_inc = []
1474-
extra_compile_args = []
1475-
expat_lib = ['expat']
1476-
expat_sources = []
1477-
expat_depends = []
1478-
else:
1479-
expat_inc = [os.path.join(self.srcdir, 'Modules', 'expat')]
1480-
extra_compile_args = []
1481-
# bpo-44394: libexpat uses isnan() of math.h and needs linkage
1482-
# against the libm
1483-
expat_lib = ['m']
1484-
expat_sources = ['expat/xmlparse.c',
1485-
'expat/xmlrole.c',
1486-
'expat/xmltok.c']
1487-
expat_depends = ['expat/ascii.h',
1488-
'expat/asciitab.h',
1489-
'expat/expat.h',
1490-
'expat/expat_config.h',
1491-
'expat/expat_external.h',
1492-
'expat/internal.h',
1493-
'expat/latin1tab.h',
1494-
'expat/utf8tab.h',
1495-
'expat/xmlrole.h',
1496-
'expat/xmltok.h',
1497-
'expat/xmltok_impl.h'
1498-
]
1499-
1500-
cc = sysconfig.get_config_var('CC').split()[0]
1501-
ret = run_command(
1502-
'"%s" -Werror -Wno-unreachable-code -E -xc /dev/null >/dev/null 2>&1' % cc)
1503-
if ret == 0:
1504-
extra_compile_args.append('-Wno-unreachable-code')
1523+
cflags = parse_cflags(sysconfig.get_config_var("EXPAT_CFLAGS"))
1524+
include_dirs, define_macros, undef_macros, extra_compile_args = cflags
1525+
# ldflags includes either system libexpat or full path to
1526+
# our static libexpat.a.
1527+
ldflags = parse_ldflags(sysconfig.get_config_var("EXPAT_LDFLAGS"))
1528+
library_dirs, libraries, extra_link_args = ldflags
1529+
1530+
expat_depends = []
1531+
libexpat_a = sysconfig.get_config_var("LIBEXPAT_A")
1532+
if libexpat_a:
1533+
expat_depends.append(libexpat_a)
15051534

15061535
self.add(Extension('pyexpat',
1536+
include_dirs=include_dirs,
1537+
define_macros=define_macros,
1538+
undef_macros=undef_macros,
15071539
extra_compile_args=extra_compile_args,
1508-
include_dirs=expat_inc,
1509-
libraries=expat_lib,
1510-
sources=['pyexpat.c'] + expat_sources,
1540+
library_dirs=library_dirs,
1541+
libraries=libraries,
1542+
extra_link_args=extra_link_args,
1543+
sources=['pyexpat.c'],
15111544
depends=expat_depends))
15121545

15131546
# Fredrik Lundh's cElementTree module. Note that this also
15141547
# uses expat (via the CAPI hook in pyexpat).
1515-
1516-
if os.path.isfile(os.path.join(self.srcdir, 'Modules', '_elementtree.c')):
1517-
self.add(Extension('_elementtree',
1518-
include_dirs=expat_inc,
1519-
libraries=expat_lib,
1520-
sources=['_elementtree.c'],
1521-
depends=['pyexpat.c', *expat_sources,
1522-
*expat_depends]))
1523-
else:
1524-
self.missing.append('_elementtree')
1548+
self.add(Extension('_elementtree',
1549+
include_dirs=include_dirs,
1550+
define_macros=define_macros,
1551+
undef_macros=undef_macros,
1552+
extra_compile_args=extra_compile_args,
1553+
# no EXPAT_LDFLAGS
1554+
sources=['_elementtree.c'],
1555+
depends=['pyexpat.c', *expat_depends]))
15251556

15261557
def detect_multibytecodecs(self):
15271558
# Hye-Shik Chang's CJKCodecs modules.
@@ -2019,24 +2050,27 @@ def detect_decimal(self):
20192050
# Stefan Krah's _decimal module
20202051
sources = ['_decimal/_decimal.c']
20212052
depends = ['_decimal/docstrings.h']
2022-
define_macros = []
2023-
2024-
cflags = sysconfig.get_config_var("DECIMAL_CFLAGS")
2025-
extra_compile_args = shlex.split(cflags) if cflags else None
2053+
2054+
cflags = parse_cflags(sysconfig.get_config_var("DECIMAL_CFLAGS"))
2055+
include_dirs, define_macros, undef_macros, extra_compile_args = cflags
20262056
# ldflags includes either system libmpdec or full path to
20272057
# our static libmpdec.a.
2028-
ldflags = sysconfig.get_config_var("DECIMAL_LDFLAGS")
2029-
extra_link_args = shlex.split(ldflags) if ldflags else None
2030-
2058+
ldflags = parse_ldflags(sysconfig.get_config_var("DECIMAL_LDFLAGS"))
2059+
library_dirs, libraries, extra_link_args = ldflags
2060+
20312061
libmpdec_a = sysconfig.get_config_var("LIBMPDEC_A")
20322062
if libmpdec_a:
20332063
depends.append(libmpdec_a)
20342064

20352065
# Uncomment for extra functionality:
20362066
#define_macros.append(('EXTRA_FUNCTIONALITY', 1))
20372067
self.add(Extension('_decimal',
2068+
include_dirs=include_dirs,
20382069
define_macros=define_macros,
2070+
undef_macros=undef_macros,
20392071
extra_compile_args=extra_compile_args,
2072+
library_dirs=library_dirs,
2073+
libraries=libraries,
20402074
extra_link_args=extra_link_args,
20412075
sources=sources,
20422076
depends=depends))

0 commit comments

Comments
 (0)