Skip to content

Commit eb8c67a

Browse files
committed
Refactor static / dynamic linking into build options
1 parent 2a9167e commit eb8c67a

File tree

5 files changed

+66
-33
lines changed

5 files changed

+66
-33
lines changed

ci-targets.yaml

+12-12
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,9 @@ linux:
257257
- "3.12"
258258
- "3.13"
259259
build_options:
260-
- debug
261-
- noopt
262-
- lto
260+
- debug+static
261+
- noopt+static
262+
- lto+static
263263
run: true
264264

265265
x86_64_v2-unknown-linux-musl:
@@ -273,9 +273,9 @@ linux:
273273
- "3.12"
274274
- "3.13"
275275
build_options:
276-
- debug
277-
- noopt
278-
- lto
276+
- debug+static
277+
- noopt+static
278+
- lto+static
279279
run: true
280280

281281
x86_64_v3-unknown-linux-musl:
@@ -289,9 +289,9 @@ linux:
289289
- "3.12"
290290
- "3.13"
291291
build_options:
292-
- debug
293-
- noopt
294-
- lto
292+
- debug+static
293+
- noopt+static
294+
- lto+static
295295
run: true
296296

297297
x86_64_v4-unknown-linux-musl:
@@ -305,9 +305,9 @@ linux:
305305
- "3.12"
306306
- "3.13"
307307
build_options:
308-
- debug
309-
- noopt
310-
- lto
308+
- debug+static
309+
- noopt+static
310+
- lto+static
311311
run: true
312312

313313
windows:

cpython-unix/build-cpython.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ CONFIGURE_FLAGS="
381381
--without-ensurepip
382382
${EXTRA_CONFIGURE_FLAGS}"
383383

384-
if [ "${CC}" = "musl-clang" ]; then
384+
if [ -n "${CPYTHON_STATIC}" ]; then
385385
CFLAGS="${CFLAGS} -static"
386386
CPPFLAGS="${CPPFLAGS} -static"
387387
LDFLAGS="${LDFLAGS} -static"

cpython-unix/build-main.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def main():
4545
print("Unsupported build platform: %s" % sys.platform)
4646
return 1
4747

48+
# Note these arguments must be synced with `build.py`
4849
parser = argparse.ArgumentParser()
4950

5051
parser.add_argument(
@@ -54,10 +55,17 @@ def main():
5455
help="Target host triple to build for",
5556
)
5657

57-
optimizations = {"debug", "noopt", "pgo", "lto", "pgo+lto"}
58+
# Construct possible options, we use a set here for canonical ordering
59+
options = set()
60+
options.update({"debug", "noopt", "pgo", "lto", "pgo+lto"})
61+
options.update({f"freethreaded+{option}" for option in options})
62+
link_modes = {"static", "shared"}
63+
options.update(
64+
{f"{option}+{link_mode}" for link_mode in link_modes for option in options}
65+
)
5866
parser.add_argument(
5967
"--options",
60-
choices=optimizations.union({f"freethreaded+{o}" for o in optimizations}),
68+
choices=options,
6169
default="noopt",
6270
help="Build options to apply when compiling Python",
6371
)
@@ -138,6 +146,10 @@ def main():
138146

139147
env = dict(os.environ)
140148

149+
# Default to dynamic linking if no link mode is specified
150+
if not any(link_mode in args.options for link_mode in link_modes):
151+
args.options += "+shared"
152+
141153
env["PYBUILD_HOST_PLATFORM"] = host_platform
142154
env["PYBUILD_TARGET_TRIPLE"] = target_triple
143155
env["PYBUILD_BUILD_OPTIONS"] = args.options

cpython-unix/build.py

+38-12
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ def python_build_info(
488488
target_triple,
489489
musl,
490490
lto,
491+
static,
491492
extensions,
492493
extra_metadata,
493494
):
@@ -506,7 +507,7 @@ def python_build_info(
506507
)
507508
)
508509

509-
if not musl:
510+
if not static:
510511
bi["core"]["shared_lib"] = "install/lib/libpython%s%s.so.1.0" % (
511512
version,
512513
binary_suffix,
@@ -825,6 +826,8 @@ def build_cpython(
825826
env["CPYTHON_OPTIMIZED"] = "1"
826827
if "lto" in parsed_build_options:
827828
env["CPYTHON_LTO"] = "1"
829+
if "static" in parsed_build_options:
830+
env["CPYTHON_STATIC"] = "1"
828831

829832
add_target_env(env, host_platform, target_triple, build_env)
830833

@@ -834,19 +837,26 @@ def build_cpython(
834837
crt_features = []
835838

836839
if host_platform == "linux64":
837-
if "musl" in target_triple:
840+
if "static" in parsed_build_options:
838841
crt_features.append("static")
839842
else:
840843
extension_module_loading.append("shared-library")
841-
crt_features.append("glibc-dynamic")
842844

843-
glibc_max_version = build_env.get_file("glibc_version.txt").strip()
844-
if not glibc_max_version:
845-
raise Exception("failed to retrieve glibc max symbol version")
845+
if "musl" in target_triple:
846+
crt_features.append("musl-dynamic")
847+
# TODO: Determine the dynamic musl libc version
846848

847-
crt_features.append(
848-
"glibc-max-symbol-version:%s" % glibc_max_version.decode("ascii")
849-
)
849+
else:
850+
crt_features.append("glibc-dynamic")
851+
852+
glibc_max_version = build_env.get_file("glibc_version.txt").strip()
853+
if not glibc_max_version:
854+
raise Exception("failed to retrieve glibc max symbol version")
855+
856+
crt_features.append(
857+
"glibc-max-symbol-version:%s"
858+
% glibc_max_version.decode("ascii")
859+
)
850860

851861
python_symbol_visibility = "global-default"
852862

@@ -874,7 +884,9 @@ def build_cpython(
874884
"python_stdlib_test_packages": sorted(STDLIB_TEST_PACKAGES),
875885
"python_symbol_visibility": python_symbol_visibility,
876886
"python_extension_module_loading": extension_module_loading,
877-
"libpython_link_mode": "static" if "musl" in target_triple else "shared",
887+
"libpython_link_mode": "static"
888+
if "static" in parsed_build_options
889+
else "shared",
878890
"crt_features": crt_features,
879891
"run_tests": "build/run_tests.py",
880892
"build_info": python_build_info(
@@ -884,6 +896,7 @@ def build_cpython(
884896
target_triple,
885897
"musl" in target_triple,
886898
"lto" in parsed_build_options,
899+
"static" in parsed_build_options,
887900
enabled_extensions,
888901
extra_metadata,
889902
),
@@ -946,6 +959,7 @@ def main():
946959
print("unable to connect to Docker: %s" % e, file=sys.stderr)
947960
return 1
948961

962+
# Note these arguments must be synced with `build-main.py`
949963
parser = argparse.ArgumentParser()
950964
parser.add_argument(
951965
"--host-platform", required=True, help="Platform we are building from"
@@ -955,13 +969,25 @@ def main():
955969
required=True,
956970
help="Host triple that we are building Python for",
957971
)
958-
optimizations = {"debug", "noopt", "pgo", "lto", "pgo+lto"}
972+
973+
# Construct possible options
974+
options = set()
975+
options.update({"debug", "noopt", "pgo", "lto", "pgo+lto"})
976+
options.update({f"freethreaded+{option}" for option in options})
977+
options.update(
978+
{
979+
f"{option}+{link_mode}"
980+
for link_mode in {"static", "shared"}
981+
for option in options
982+
}
983+
)
959984
parser.add_argument(
960985
"--options",
961-
choices=optimizations.union({f"freethreaded+{o}" for o in optimizations}),
986+
choices=options,
962987
default="noopt",
963988
help="Build options to apply when compiling Python",
964989
)
990+
965991
parser.add_argument(
966992
"--toolchain",
967993
action="store_true",

pythonbuild/cpython.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -466,12 +466,7 @@ def derive_setup_local(
466466
enabled_extensions[name]["setup_line"] = name.encode("ascii")
467467
continue
468468

469-
# musl is static only. Ignore build-mode override.
470-
if "musl" in target_triple:
471-
section = "static"
472-
else:
473-
section = info.get("build-mode", "static")
474-
469+
section = info.get("build-mode", "static")
475470
enabled_extensions[name]["build-mode"] = section
476471

477472
# Presumably this means the extension comes from the distribution's

0 commit comments

Comments
 (0)