Skip to content

Commit 890ecca

Browse files
committed
Fix cross-platform configure comparison: CONFIG_ARGS, OpenSSL paths, blank lines.
Three issues found during cross-platform testing (Ubuntu, FreeBSD, OpenBSD, NetBSD, WASI): 1. CONFIG_ARGS missing precious env vars and build/host aliases (WASI): - pyconf.py init_args(): reorder built-in precious vars to match configure.ac's ac_precious_vars order (PKG_CONFIG before CC); remove CXX/CXXFLAGS which configure.ac does not declare as precious. - pyconf.py canonical_host(): insert build_alias/host_alias before the first NAME=VALUE env-var entry, matching autoconf's arg ordering. - pyconf.awk pyconf_env_var(): accumulate env vars in _pyconf_env_args (separate from command-line flags) so ordering can be enforced. - pyconf.awk pyconf_parse_args(): register built-in precious vars after the arg loop (matching Python's init_args behaviour); use ordered split to match ac_precious_vars sequence. - pyconf.awk _pyconf_resolve_exports(): combine flags + aliases + env vars in the correct order when building CONFIG_ARGS. - pyconf.awk pyconf_canonical_host(): record build_alias/host_alias in a separate _pyconf_alias_args accumulator. - configure.awk: regenerated. 2. OpenSSL fallback paths wrong (NetBSD): - conf_security.py: replace ad-hoc include-dir search with the ssldirs list from AX_CHECK_OPENSSL (/usr/local/ssl, /usr/lib/ssl, /usr/ssl, /usr/pkg, /usr/local, /usr) and set OPENSSL_INCLUDES/LDFLAGS properly. 3. Spurious blank lines in Makefile.pre (OpenBSD, diff -B unavailable): - compare-conf.sh: strip blank lines from Makefile.pre before diffing to work around the m4/_AS_QUOTE expansion artifact that adds extra newlines to MODULE_BLOCK entries when values are shell variable references. Assisted-by: Claude
1 parent cac3f31 commit 890ecca

File tree

5 files changed

+214
-60
lines changed

5 files changed

+214
-60
lines changed

Tools/configure/conf_security.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -146,26 +146,32 @@ def check_openssl(v):
146146
)
147147
pyconf.result("no")
148148
else:
149-
# Try default system paths
150-
ssl_h_paths = [
151-
"/usr/include",
152-
"/usr/local/include",
153-
"/usr/include/openssl",
154-
"/usr/local/include/openssl",
149+
# No pkg-config: search default ssldirs (matching AX_CHECK_OPENSSL).
150+
# For each candidate root, check $ssldir/include/openssl/ssl.h and
151+
# set OPENSSL_INCLUDES / OPENSSL_LDFLAGS accordingly.
152+
ssl_dirs = [
153+
"/usr/local/ssl",
154+
"/usr/lib/ssl",
155+
"/usr/ssl",
156+
"/usr/pkg",
157+
"/usr/local",
158+
"/usr",
155159
]
156160
found_ssl = False
157-
for p in ssl_h_paths:
158-
if pyconf.path_exists(pyconf.path_join([p, "openssl/ssl.h"])):
161+
for ssldir in ssl_dirs:
162+
if pyconf.path_exists(
163+
pyconf.path_join([ssldir, "include/openssl/ssl.h"])
164+
):
165+
v.OPENSSL_INCLUDES = f"-I{ssldir}/include"
166+
v.OPENSSL_LDFLAGS = f"-L{ssldir}/lib"
167+
v.OPENSSL_LIBS = "-lssl -lcrypto"
168+
v.have_openssl = True
159169
found_ssl = True
160170
break
161171
pyconf.checking(
162172
"whether compiling and linking against OpenSSL works"
163173
)
164174
if found_ssl:
165-
v.OPENSSL_INCLUDES = ""
166-
v.OPENSSL_LIBS = "-lssl -lcrypto"
167-
v.OPENSSL_LDFLAGS = ""
168-
v.have_openssl = True
169175
pyconf.result("yes")
170176
else:
171177
pyconf.result("no")

Tools/configure/configure.awk

Lines changed: 81 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,24 @@ function pyconf_env_var(name, help_text) {
15481548
# Python's Vars.__getattr__ fallback to os.environ.
15491549
if (!(name in V) && name in ENV)
15501550
V[name] = ENV[name]
1551+
# Record in _pyconf_env_args if the variable is in the environment
1552+
# and not already recorded (matching autoconf precious-variable behaviour).
1553+
# Kept separate from _pyconf_config_args (command-line flags) so that
1554+
# _pyconf_resolve_exports() can combine them in the correct order:
1555+
# flags, then aliases (build_alias/host_alias), then env vars.
1556+
if (name in ENV && !_pyconf_config_args_has_var(name, _pyconf_env_args))
1557+
_pyconf_env_args = _pyconf_env_args \
1558+
(_pyconf_env_args != "" ? " " : "") \
1559+
_shell_quote(name "=" ENV[name])
1560+
}
1561+
1562+
function _pyconf_config_args_has_var(name, haystack) {
1563+
# Return 1 if haystack (or _pyconf_config_args) already contains a
1564+
# "name=..." entry. _shell_quote wraps entries in single quotes, so
1565+
# each entry starts with "'name=". Checking _pyconf_config_args as well
1566+
# prevents duplicates when a var is both an env var and a positional arg.
1567+
return index(haystack, "'" name "=") > 0 || \
1568+
index(_pyconf_config_args, "'" name "=") > 0
15511569
}
15521570

15531571
function pyconf_option_value(key) {
@@ -1689,7 +1707,7 @@ function _pyconf_arg_takes_value(key) {
16891707
key == "host" || key == "build" || key == "target")
16901708
}
16911709

1692-
function pyconf_parse_args( i, arg, key, val, opt_key, eq_pos, config_args) {
1710+
function pyconf_parse_args( i, arg, key, val, opt_key, eq_pos, config_args, bp, n_bp) {
16931711
config_args = ""
16941712
for (i = 1; i < ARGC; i++) {
16951713
arg = ARGV[i]
@@ -1770,6 +1788,13 @@ function pyconf_parse_args( i, arg, key, val, opt_key, eq_pos, config_args) {
17701788
ARGV[i] = ""
17711789
}
17721790
_pyconf_config_args = config_args
1791+
# Register built-in autoconf precious variables in the same order as
1792+
# configure.ac's ac_precious_vars. Done after the arg loop so that
1793+
# positional VAR=VALUE args (already in _pyconf_config_args) prevent
1794+
# duplicates via _pyconf_config_args_has_var().
1795+
n_bp = split("PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP", bp, " ")
1796+
for (i = 1; i <= n_bp; i++)
1797+
pyconf_env_var(bp[i])
17731798
}
17741799

17751800
function pyconf_check_help() {
@@ -1884,10 +1909,18 @@ function _pyconf_build_module_block( i, key, uname, state, block) {
18841909
SUBST["MODULE_BLOCK"] = block
18851910
}
18861911

1887-
function _pyconf_resolve_exports( k) {
1888-
# Finalize CONFIG_ARGS from parsed command-line arguments
1889-
if (_pyconf_config_args != "")
1890-
V["CONFIG_ARGS"] = _pyconf_config_args
1912+
function _pyconf_resolve_exports( k, all_args, sep) {
1913+
# Build CONFIG_ARGS in the same order as autoconf's ac_configure_args:
1914+
# 1. explicit command-line flags (_pyconf_config_args)
1915+
# 2. build_alias / host_alias (_pyconf_alias_args)
1916+
# 3. precious env vars (CC, PKG_CONFIG_PATH, …) (_pyconf_env_args)
1917+
all_args = _pyconf_config_args
1918+
if (_pyconf_alias_args != "")
1919+
all_args = all_args (all_args != "" ? " " : "") _pyconf_alias_args
1920+
if (_pyconf_env_args != "")
1921+
all_args = all_args (all_args != "" ? " " : "") _pyconf_env_args
1922+
if (all_args != "")
1923+
V["CONFIG_ARGS"] = all_args
18911924
for (k in V) {
18921925
if (!(k in SUBST))
18931926
SUBST[k] = V[k]
@@ -2292,6 +2325,19 @@ function pyconf_canonical_host( result, guess, csub, parts, n, host_arg, buil
22922325
pyconf_host_cpu = parts[1]
22932326
pyconf_cross_compiling = "no"
22942327
}
2328+
2329+
# Record build_alias / host_alias when --build/--host were given
2330+
# (matching autoconf's precious-variable behaviour). Use a separate
2331+
# accumulator so _pyconf_resolve_exports() can order them after the
2332+
# explicit flags but before the env-var entries.
2333+
if (build_arg != "" && !_pyconf_config_args_has_var("build_alias", _pyconf_alias_args))
2334+
_pyconf_alias_args = _pyconf_alias_args \
2335+
(_pyconf_alias_args != "" ? " " : "") \
2336+
_shell_quote("build_alias=" build_arg)
2337+
if (host_arg != "" && !_pyconf_config_args_has_var("host_alias", _pyconf_alias_args))
2338+
_pyconf_alias_args = _pyconf_alias_args \
2339+
(_pyconf_alias_args != "" ? " " : "") \
2340+
_shell_quote("host_alias=" host_arg)
22952341
}
22962342

22972343
function pyconf_find_compiler(user_cc, user_cpp, cc, cpp, ver) {
@@ -3494,7 +3540,7 @@ function u_setup_expat( _opt_result, with_system_expat) {
34943540
v_export("LIBEXPAT_INTERNAL")
34953541
}
34963542

3497-
function u_detect_libffi( ac_cv_ffi_complex_double_supported, ctypes_malloc_closure, ffi_h, found_ffi_h, output, parts, pkg, sdkroot, status, _ar_4, _ar_5) {
3543+
function u_detect_libffi( ac_cv_ffi_complex_double_supported, ctypes_malloc_closure, ffi_inc, found_ffi_h, output, parts, pkg, sdkroot, status, _ar_4, _ar_5) {
34983544
delete _ar_4
34993545
delete _ar_5
35003546
V["have_libffi"] = "missing"
@@ -3503,12 +3549,17 @@ function u_detect_libffi( ac_cv_ffi_complex_double_supported, ctypes_malloc_c
35033549
V["MODULE__CTYPES_MALLOC_CLOSURE"] = ""
35043550
if ((V["ac_sys_system"] == "Darwin")) {
35053551
sdkroot = V["SDKROOT"]
3506-
ffi_h = (((sdkroot != "") && (sdkroot != "no")) ? sdkroot "/usr/include/ffi/ffi.h" : "/usr/include/ffi/ffi.h")
3507-
if (pyconf_path_is_file(ffi_h)) {
3508-
V["have_libffi"] = "yes"
3509-
V["LIBFFI_CFLAGS"] = "-I" sdkroot "/usr/include/ffi -DUSING_APPLE_OS_LIBFFI=1"
3510-
V["LIBFFI_LIBS"] = "-lffi"
3552+
ffi_inc = (((sdkroot != "") && (sdkroot != "no")) ? sdkroot "/usr/include/ffi" : "/usr/include/ffi")
3553+
pyconf_save_env()
3554+
V["CFLAGS"] = _str_strip("-I" ffi_inc " " V["CFLAGS"])
3555+
if (pyconf_check_header("ffi.h")) {
3556+
if (pyconf_check_lib("ffi", "ffi_call", "", "")) {
3557+
V["have_libffi"] = "yes"
3558+
V["LIBFFI_CFLAGS"] = "-I" ffi_inc " -DUSING_APPLE_OS_LIBFFI=1"
3559+
V["LIBFFI_LIBS"] = "-lffi"
3560+
}
35113561
}
3562+
pyconf_restore_env()
35123563
}
35133564
if ((V["have_libffi"] == "missing")) {
35143565
pkg = pyconf_find_prog("pkg-config")
@@ -3744,7 +3795,7 @@ function u_detect_tcltk( _i_q, output, parts, pkg, q, status, x11_cflags, x11
37443795
v_export("TCLTK_LIBS")
37453796
}
37463797

3747-
function u_detect_uuid( LIBUUID_CFLAGS, LIBUUID_LIBS, ac_cv_have_uuid_generate_time_safe, ac_cv_have_uuid_h, ac_cv_have_uuid_uuid_h, found, has_create, has_enc_be, have_uuid, node1, node2, pkg, save_CPPFLAGS, save_LIBS, uuid_node_src) {
3798+
function u_detect_uuid( LIBUUID_CFLAGS, LIBUUID_LIBS, ac_cv_have_uuid_generate_time_safe, ac_cv_have_uuid_h, ac_cv_have_uuid_uuid_h, found, has_create, has_enc_be, have_uuid, node1, node2, pkg, uuid_node_src) {
37483799
ac_cv_have_uuid_h = "no"
37493800
ac_cv_have_uuid_uuid_h = "no"
37503801
ac_cv_have_uuid_generate_time_safe = "no"
@@ -3775,8 +3826,7 @@ function u_detect_uuid( LIBUUID_CFLAGS, LIBUUID_LIBS, ac_cv_have_uuid_generat
37753826
LIBUUID_CFLAGS = V["LIBUUID_CFLAGS"]
37763827
LIBUUID_LIBS = V["LIBUUID_LIBS"]
37773828
} else {
3778-
save_CPPFLAGS = V["CPPFLAGS"]
3779-
save_LIBS = V["LIBS"]
3829+
pyconf_save_env()
37803830
V["CPPFLAGS"] = _str_strip(V["CPPFLAGS"] " " LIBUUID_CFLAGS)
37813831
V["LIBS"] = _str_strip(V["LIBS"] " " LIBUUID_LIBS)
37823832
delete _va22
@@ -3795,8 +3845,7 @@ function u_detect_uuid( LIBUUID_CFLAGS, LIBUUID_LIBS, ac_cv_have_uuid_generat
37953845
if ((have_uuid == "yes")) {
37963846
LIBUUID_LIBS = ((LIBUUID_LIBS != "") ? LIBUUID_LIBS : "-luuid")
37973847
}
3798-
V["CPPFLAGS"] = save_CPPFLAGS
3799-
V["LIBS"] = save_LIBS
3848+
pyconf_restore_env()
38003849
}
38013850
}
38023851
if ((have_uuid == "missing")) {
@@ -6242,10 +6291,12 @@ function u_generate_output( cc, host, srcdir_rel) {
62426291
pyconf_config_files_x(_va57)
62436292
pyconf_output()
62446293
if ((!((pyconf_no_create != "") && (pyconf_no_create != "no")))) {
6294+
pyconf_notice("creating Modules/Setup.local")
62456295
if ((!pyconf_path_exists("Modules/Setup.local"))) {
62466296
pyconf_write_file("Modules/Setup.local", "# Edit this file for local setup changes\n")
62476297
}
62486298
srcdir_rel = ((V["srcdir"] != "") ? V["srcdir"] : ".")
6299+
pyconf_notice("creating Makefile")
62496300
delete _va58
62506301
_va58[1] = "/bin/sh"
62516302
_va58[2] = srcdir_rel "/Modules/makesetup"
@@ -6264,18 +6315,18 @@ function u_generate_output( cc, host, srcdir_rel) {
62646315
pyconf_rename_file("config.c", "Modules/config.c")
62656316
}
62666317
if ((!((V["PKG_CONFIG"] != "") && (V["PKG_CONFIG"] != "no")))) {
6267-
print "pkg-config is missing. Some dependencies may not be detected correctly." > "/dev/stderr"
6318+
pyconf_warn("pkg-config is missing. Some dependencies may not be detected correctly.")
62686319
}
62696320
if (((V["Py_OPT"] != "yes") && (V["Py_DEBUG"] != "yes"))) {
62706321
pyconf_notice("\nIf you want a release build with all stable optimizations active (PGO, etc),\nplease run ./configure --enable-optimizations\n")
62716322
}
62726323
if ((V["PY_SUPPORT_TIER"] == 0)) {
62736324
cc = V["ac_cv_cc_name"]
62746325
host = V["host"]
6275-
print "Platform \"" host "\" with compiler \"" cc "\" is not supported by the CPython core team, see https://peps.python.org/pep-0011/ for more information." > "/dev/stderr"
6326+
pyconf_warn("Platform \"" host "\" with compiler \"" cc "\" is not supported by the CPython core team, see https://peps.python.org/pep-0011/ for more information.")
62766327
}
62776328
if ((!((V["ac_cv_header_stdatomic_h"] != "") && (V["ac_cv_header_stdatomic_h"] != "no")))) {
6278-
print "Your compiler or platform does not have a working C11 stdatomic.h. A future version of Python may require stdatomic.h."
6329+
pyconf_notice("Your compiler or platform does not have a working C11 stdatomic.h. A future version of Python may require stdatomic.h.")
62796330
}
62806331
}
62816332

@@ -7247,7 +7298,7 @@ function u_check_getrandom() {
72477298
}
72487299
}
72497300

7250-
function u_check_openssl( LIBCRYPTO_LIBS_len, _i_arg, _i_f, _i_p, _n_arg, _n_f, _n_p, arg, f, found_ssl, inc_flags, inc_parts_len, lib_flags, lib_parts_len, libname, new_ssl_libs_len, openssl_rpath_opt, p, pc_cflags, pc_ldflags, pc_libs, pkg_config, rpath_arg, s1, s2, s3, ssl_dir, ssl_h_paths, with_openssl, working_hashlib, working_ssl, LIBCRYPTO_LIBS, _ar_33, _ar_34, _ar_35, _as_36, _as_37, _as_38, _as_39, _as_40, _as_41, inc_parts, lib_parts, new_ssl_libs) {
7301+
function u_check_openssl( LIBCRYPTO_LIBS_len, _i_arg, _i_f, _i_ssldir, _n_arg, _n_f, _n_ssldir, arg, f, found_ssl, inc_flags, inc_parts_len, lib_flags, lib_parts_len, libname, new_ssl_libs_len, openssl_rpath_opt, pc_cflags, pc_ldflags, pc_libs, pkg_config, rpath_arg, s1, s2, s3, ssl_dir, ssl_dirs, ssldir, with_openssl, working_hashlib, working_ssl, LIBCRYPTO_LIBS, _ar_33, _ar_34, _ar_35, _as_36, _as_37, _as_38, _as_39, _as_40, _as_41, inc_parts, lib_parts, new_ssl_libs) {
72517302
delete LIBCRYPTO_LIBS
72527303
delete _ar_33
72537304
delete _ar_34
@@ -7333,26 +7384,26 @@ function u_check_openssl( LIBCRYPTO_LIBS_len, _i_arg, _i_f, _i_p, _n_arg, _n_
73337384
pyconf_result("no")
73347385
}
73357386
} else {
7336-
ssl_h_paths = "/usr/include" " " "/usr/local/include" " " "/usr/include/openssl" " " "/usr/local/include/openssl"
7387+
ssl_dirs = "/usr/local/ssl" " " "/usr/lib/ssl" " " "/usr/ssl" " " "/usr/pkg" " " "/usr/local" " " "/usr"
73377388
found_ssl = "no"
7338-
_n_p = split(ssl_h_paths, _as_38, " ")
7339-
for (_i_p = 1; (_i_p <= _n_p); _i_p = (_i_p + 1)) {
7340-
p = _as_38[_i_p]
7389+
_n_ssldir = split(ssl_dirs, _as_38, " ")
7390+
for (_i_ssldir = 1; (_i_ssldir <= _n_ssldir); _i_ssldir = (_i_ssldir + 1)) {
7391+
ssldir = _as_38[_i_ssldir]
73417392
delete _va76
7342-
_va76[1] = p
7343-
_va76[2] = "openssl/ssl.h"
7393+
_va76[1] = ssldir
7394+
_va76[2] = "include/openssl/ssl.h"
73447395
_va76[0] = 2
73457396
if (pyconf_path_exists(pyconf_path_join(_va76))) {
7397+
V["OPENSSL_INCLUDES"] = "-I" ssldir "/include"
7398+
V["OPENSSL_LDFLAGS"] = "-L" ssldir "/lib"
7399+
V["OPENSSL_LIBS"] = "-lssl -lcrypto"
7400+
V["have_openssl"] = "yes"
73467401
found_ssl = "yes"
73477402
break
73487403
}
73497404
}
73507405
pyconf_checking("whether compiling and linking against OpenSSL works")
73517406
if (((found_ssl != "") && (found_ssl != "no"))) {
7352-
V["OPENSSL_INCLUDES"] = ""
7353-
V["OPENSSL_LIBS"] = "-lssl -lcrypto"
7354-
V["OPENSSL_LDFLAGS"] = ""
7355-
V["have_openssl"] = "yes"
73567407
pyconf_result("yes")
73577408
} else {
73587409
pyconf_result("no")

Tools/configure/pyconf.py

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -261,21 +261,21 @@ def init_args() -> None:
261261
_original_config_args = [
262262
a for a in sys.argv[1:] if not a.startswith("--srcdir")
263263
]
264-
# Register built-in autoconf precious variables. User-level precious
265-
# variables (MACHDEP, PROFILE_TASK, GDBM_CFLAGS, …) are registered via
266-
# env_var() calls in the configure_*.py files instead.
264+
# Register built-in autoconf precious variables in the same order as
265+
# configure.ac's ac_precious_vars list (PKG_CONFIG before CC, no CXX/CXXFLAGS
266+
# since configure.ac does not call AC_ARG_VAR for those). User-level
267+
# precious variables (MACHDEP, PROFILE_TASK, GDBM_CFLAGS, …) are registered
268+
# via env_var() calls in the configure_*.py files instead.
267269
for pvar in [
270+
"PKG_CONFIG",
271+
"PKG_CONFIG_PATH",
272+
"PKG_CONFIG_LIBDIR",
268273
"CC",
269274
"CFLAGS",
270-
"CXX",
271-
"CXXFLAGS",
272-
"CPP",
273-
"CPPFLAGS",
274275
"LDFLAGS",
275276
"LIBS",
276-
"PKG_CONFIG",
277-
"PKG_CONFIG_LIBDIR",
278-
"PKG_CONFIG_PATH",
277+
"CPPFLAGS",
278+
"CPP",
279279
]:
280280
env_var(pvar)
281281

@@ -1705,6 +1705,40 @@ def _canonicalize(triplet: str) -> str:
17051705
host_cpu = build_cpu
17061706
cross_compiling = False
17071707

1708+
# Record build_alias / host_alias in CONFIG_ARGS when --build/--host were
1709+
# given on the command line (matching autoconf's precious-variable behaviour).
1710+
# Insert before the first VAR=VALUE env-var entry so the order matches
1711+
# autoconf: flags first, then aliases, then env vars.
1712+
present = {
1713+
a.split("=", 1)[0]
1714+
for a in _original_config_args
1715+
if "=" in a and not a.startswith("-")
1716+
}
1717+
if build_arg and "build_alias" not in present:
1718+
# Find insertion point: just before the first NAME=VALUE entry.
1719+
insert_pos = next(
1720+
(
1721+
i
1722+
for i, a in enumerate(_original_config_args)
1723+
if "=" in a and not a.startswith("-")
1724+
),
1725+
len(_original_config_args),
1726+
)
1727+
_original_config_args.insert(insert_pos, f"build_alias={build_arg}")
1728+
insert_pos += 1
1729+
if host_arg and "host_alias" not in present:
1730+
_original_config_args.insert(insert_pos, f"host_alias={host_arg}")
1731+
elif host_arg and "host_alias" not in present:
1732+
insert_pos = next(
1733+
(
1734+
i
1735+
for i, a in enumerate(_original_config_args)
1736+
if "=" in a and not a.startswith("-")
1737+
),
1738+
len(_original_config_args),
1739+
)
1740+
_original_config_args.insert(insert_pos, f"host_alias={host_arg}")
1741+
17081742

17091743
def _fallback_triplet() -> str:
17101744
"""Construct a host triplet from Python's platform module (fallback)."""

0 commit comments

Comments
 (0)