AtlatestRepositorycore-channel
core-channel / tree / src / core / packagespython.sgl
1
;;; CPython, packaged as a BUILD TOOL for this channel and nothing else.2
;;;3
;;; WHY A CHANNEL WITH NO PYTHON PROGRAMS IN IT NEEDS PYTHON. Three4
;;; independent consumers, and no choice of build system removes the first:5
;;;6
;;; 1. foot's own `meson.build` runs `python3` in three UNCONDITIONAL7
;;; custom_targets -- scripts/generate-builtin-terminfo.py,8
;;; scripts/generate-emoji-variation-sequences.py and the srgb generator.9
;;; They emit headers that foot then compiles. No option turns them off.10
;;; 2. meson is CPython.11
;;; 3. fontconfig's configure.ac is `AM_PATH_PYTHON([3])`.12
;;;13
;;; That is why muon -- the C reimplementation of meson -- was considered and14
;;; rejected. It removes consumer 2 and leaves 1 and 3.15
(define-library (core packages python)16
(import (sigil core)17
(core build-environments)18
(core packages compression)19
(sigil env package)20
(sigil build external))21
(export python)22
(begin23
(define python24
(package25
name: "python"26
version: "3.13.7"27
source: (external-source28
location: "https://www.python.org/ftp/python/3.13.7/Python-3.13.7.tar.xz"29
sha256: "5462f9099dfd30e238def83c71d91897d8caa5ff6ebc7a50f14d4802cdaaa79a")30
buildenv: core-buildenv31
;; zlib is the one optional module worth having: `zipfile`, `shutil`'s32
;; archive support and `gzip` all reach for it, and it is already in33
;; the channel. Every other optional module -- ssl, readline, curses,34
;; sqlite3, ctypes, bz2, lzma -- is left to fail its probe, and in this35
;; sandbox that is an HONEST absence: there is no host filesystem for a36
;; probe to find something in, so nothing can be silently absorbed.37
dependencies: (list zlib)38
env: (list39
;; ---------------------------------------------------------40
;; STATIC MODULES. Everything this channel builds is linked41
;; statically and a static binary cannot dlopen. CPython's42
;; default is to build each stdlib extension as a shared object43
;; and load it at import, so left alone the interpreter starts44
;; and then dies on `import re` -- at RUN time, inside some45
;; other package's build, a very long way from here.46
;;47
;; Both switches are read from the ENVIRONMENT by configure,48
;; which is what makes this expressible without patching49
;; CPython:50
;;51
;; configure.ac:7684 MODULE_BUILDTYPE=${MODULE_BUILDTYPE:-shared}52
;; configure.ac:5156 if test -z "$DYNLOADFILE" ...53
;;54
;; Neither name is builder-owned, so neither is refused.55
(cons "MODULE_BUILDTYPE" "static")56
(cons "DYNLOADFILE" "dynload_stub.o")57
;; ---------------------------------------------------------58
;; THE -O2 / __DATE__ COLLISION, WHICH IS A PROPERTY OF THIS59
;; CHANNEL AND NOT OF CPYTHON. The builder hands every compile60
;; a response file whose first line is `-O2`, and zig cc turns61
;; ON -Werror=date-time whenever it optimizes. So ANY package62
;; here whose sources expand __DATE__ or __TIME__ fails to63
;; compile. CPython is merely the first one that does64
;; (Modules/getbuildinfo.c:14,22).65
;;66
;; Narrowed by elimination against this toolchain rather than67
;; guessed: `-g0`, `-ffile-prefix-map` and `-fdebug-prefix-map`68
;; each produce 0 date-time diagnostics; `-O2` alone produces 2,69
;; on the command line and inside a response file alike.70
;;71
;; Suppressing the guard is safe HERE, and the reason is72
;; measured: zig cc expands __DATE__ to "Jan 1 1970" and73
;; __TIME__ to "00:00:00" UNCONDITIONALLY. It does not honour74
;; SOURCE_DATE_EPOCH -- set to 1000000000 it still emits75
;; Jan 1 1970 -- and two independent compiles produced76
;; byte-identical executables. The macros are already77
;; deterministic and the diagnostic is a false positive. It78
;; exists for compilers where they are not.79
;;80
;; CFLAGS is builder-owned but APPENDABLE, and the package's81
;; value is emitted after the builder's, so this beats the82
;; response file's -O2 rather than replacing the dependency83
;; include flags.84
(cons "CFLAGS" "-Wno-error=date-time")85
;; LDFLAGS, same append rule. Static because the sandbox binds86
;; no loader for a build input.87
(cons "LDFLAGS" "-static"))88
phases: (list89
;; THE SUPPRESSION ABOVE IS PAIRED WITH A CHECK THAT ASSERTS90
;; THE PROPERTY IT RELIES ON. Turning off a reproducibility91
;; diagnostic on the strength of "the toolchain pins those92
;; macros" is only honest if something notices when it stops.93
;; If a future toolchain emits the real date, this fails94
;; loudly and prints what it saw, rather than quietly95
;; producing an unreproducible interpreter -- which is96
;; exactly the failure -Wdate-time exists to prevent.97
(external-phase98
kind: 'run99
args: (list "sh" "-c"100
(string-append101
"set -eu\n"102
"echo '#include <stdio.h>' > dtcheck.c\n"103
"echo 'int main(void){ printf(\"%s|%s\", __DATE__, __TIME__); return 0; }' >> dtcheck.c\n"104
;; ARM 1 -- COMPILED WITH $CFLAGS, which is the105
;; whole point. An earlier version of this gate106
;; ran a bare `$CC`, so it carried no107
;; `@compiler.flags` response file and therefore108
;; no `-O2` -- it vouched for a configuration109
;; CPython is not built in, while the comment110
;; above names `-O2` as the trigger. A gate that111
;; compiles under different flags than the code it112
;; certifies is asserting its author's113
;; expectations rather than the product.114
"$CC $CFLAGS -Wno-error=date-time dtcheck.c -o dtcheck\n"115
"v=$(./dtcheck)\n"116
"echo \"TOOLCHAIN-DATE-MACROS=[$v]\"\n"117
"test \"$v\" = \"Jan 1 1970|00:00:00\"\n"118
;; ARM 2 -- THE ARM THAT SEPARATES THE TWO119
;; EXPLANATIONS. The builder sets120
;; SOURCE_DATE_EPOCH=0, and epoch 0 renders as121
;; exactly "Jan 1 1970" / "00:00:00" -- the122
;; literal arm 1 compares against. So arm 1 alone123
;; is green under BOTH hypotheses: "the toolchain124
;; pins these macros unconditionally" (which is125
;; what licenses the -Wno-error above) and "clang126
;; is honouring the builder's epoch" (which would127
;; not license it, because the guarantee would128
;; then belong to a variable a future builder129
;; could stop setting).130
;;131
;; Overriding the epoch to a DIFFERENT instant132
;; discriminates: if the output moves, the macros133
;; track SOURCE_DATE_EPOCH and this package's134
;; justification is wrong.135
"w=$(SOURCE_DATE_EPOCH=1000000000 ./dtcheck)\n"136
"printf 'DATE-MACROS-UNDER-EPOCH-1000000000=[%s]\\n' \"$w\"\n"137
"e=$(SOURCE_DATE_EPOCH=1000000000 $CC $CFLAGS -Wno-error=date-time dtcheck.c -o dtcheck2 && ./dtcheck2)\n"138
"echo \"DATE-MACROS-RECOMPILED-UNDER-EPOCH=[$e]\"\n"139
"test \"$e\" = \"Jan 1 1970|00:00:00\"\n"140
"rm -f dtcheck dtcheck2 dtcheck.c\n"141
"echo DATE-MACRO-PINNING-CONFIRMED\n")))142
(external-phase143
kind: 'configure144
args: (list "--prefix=${out}"145
"--disable-shared"146
"--disable-test-modules"147
"--with-ensurepip=no"))148
(external-phase kind: 'make)149
(external-phase kind: 'install))))))