1313-- toolchain needs spelled out (macOS SDK, ranlib) has to be handed to it
1414-- explicitly; see cc_override() and the install_sw step.
1515--
16- -- HOST REQUIREMENT — perl. `./config` IS a Perl script, and there is no
17- -- `xim:perl` to declare as a build dep, so this is the one thing the package
18- -- cannot bring itself. CI runners and every mainstream distro ship it; a
19- -- stripped container may not. install() probes for it up front and fails with
20- -- that sentence rather than letting `./config` die with a shell error nobody
21- -- can read. (This is also why mbun's OpenSSL package chose a vendored prebuilt
22- -- over a source build; here a source build is the only option that covers both
23- -- linux and macOS.)
16+ -- PERL. `./config` execs `Configure`, which is `#!/usr/bin/env perl` and opens
17+ -- with `use Config; use FindBin;`. So what this build needs is not "a perl
18+ -- binary on PATH" but "a perl whose CORE MODULES are present" — and those are
19+ -- different things on a distro that splits perl into sub-packages or in a
20+ -- trimmed container image. Probing with `command -v perl` accepts such a host
21+ -- and the build then dies fifteen lines into Configure with
22+ -- `Can't locate FindBin.pm in @INC`, which reads like an OpenSSL problem
23+ -- (#140).
24+ --
25+ -- Two changes follow from that. The package now DECLARES `xim:perl@latest` as
26+ -- a build dep on both platforms and puts that perl's bindir at the front of
27+ -- PATH for the build, so it brings its own known-complete interpreter instead
28+ -- of auditing the host's. And the probe now RUNS perl with the modules
29+ -- Configure needs rather than looking it up, so a host perl reached through
30+ -- the fallback path is checked for the property that actually matters.
31+ --
32+ -- (xim:perl ships linux x86_64/aarch64 as fully static musl builds and
33+ -- macosx x86_64/arm64 as relocatable-perl. Unlike xim:make it HAS a macosx
34+ -- entry, so declaring it there resolves — see the macosx block below for what
35+ -- goes wrong when it doesn't.)
2436--
2537-- Platforms:
2638-- * linux/macosx — build a fully static libcrypto.a + libssl.a from source
@@ -37,7 +49,7 @@ package = {
3749
3850 xpm = {
3951 linux = {
40- deps = { " xim:make@latest" },
52+ deps = { " xim:make@latest" , " xim:perl@latest " },
4153 [" 3.5.1" ] = {
4254 url = {
4355 GLOBAL = " https://github.com/openssl/openssl/releases/download/openssl-3.5.1/openssl-3.5.1.tar.gz" ,
@@ -55,6 +67,11 @@ package = {
5567 -- is broken the same way; it goes unnoticed because that package
5668 -- is Windows-only in the test suite, so its macOS path is never
5769 -- taken. resolve_make() therefore falls back to PATH here.
70+ --
71+ -- xim:perl IS declared: it ships a macosx x86_64/arm64 build, so
72+ -- it resolves here and the platform gets the same
73+ -- known-complete interpreter linux does.
74+ deps = { " xim:perl@latest" },
5875 [" 3.5.1" ] = {
5976 url = {
6077 GLOBAL = " https://github.com/openssl/openssl/releases/download/openssl-3.5.1/openssl-3.5.1.tar.gz" ,
@@ -143,13 +160,45 @@ local function cc_override()
143160 return " "
144161end
145162
146- local function have (tool )
163+ -- Does this perl actually RUN, with the core modules Configure opens with?
164+ --
165+ -- `command -v perl` answers a different question, and the difference is the
166+ -- whole of #140: a host can have /usr/bin/perl and no FindBin.pm, and then the
167+ -- failure lands inside OpenSSL's Configure where it reads as an OpenSSL bug.
168+ -- The module list is Configure's own opening lines (Config, FindBin,
169+ -- File::Basename/File::Spec/File::Path), plus POSIX, which the Makefile's
170+ -- perl helpers use.
171+ local function perl_usable (perl )
147172 return pcall (function ()
148173 os .exec (string.format (" bash -c %s" ,
149- sh_quote (" command -v " .. tool .. " >/dev/null 2>&1" )))
174+ sh_quote (sh_quote (perl )
175+ .. " -MConfig -MFindBin -MFile::Path -MFile::Spec"
176+ .. " -MFile::Basename -MPOSIX -e exit"
177+ .. " >/dev/null 2>&1" )))
150178 end )
151179end
152180
181+ -- Returns the perl to build with and the bindir to put in front of PATH, or
182+ -- nil. The bindir matters as much as the binary: `./config` is a shell script
183+ -- that execs `Configure`, whose shebang is `#!/usr/bin/env perl` — so it takes
184+ -- whatever PATH resolves, not whatever we invoke. Handing it the right PATH is
185+ -- the only way to steer it, and Configure then records that same interpreter
186+ -- as `$config{PERL}` (from `$^X`) for the rest of the build.
187+ local function resolve_perl ()
188+ local p = pkginfo .build_dep (" xim:perl" ) or pkginfo .build_dep (" perl" )
189+ if p and p .bin then
190+ local cand = path .join (p .bin , " perl" )
191+ if os .isfile (cand ) and perl_usable (cand ) then
192+ return cand , p .bin
193+ end
194+ end
195+ -- Fallback: whatever PATH already has, but only if it passes the same
196+ -- check. An engine that cannot resolve the build dep should still build on
197+ -- a host whose own perl is complete.
198+ if perl_usable (" perl" ) then return " perl" , nil end
199+ return nil , nil
200+ end
201+
153202-- Last `n` lines of the build log, or nil if it cannot be read.
154203local function tail_lines (file , n )
155204 local ok , content = pcall (io .readfile , file )
@@ -180,13 +229,28 @@ local function run(step, logf, cmd)
180229end
181230
182231local function _install_impl ()
183- if not have (" perl" ) then
184- log .error (" compat.openssl: `perl` not found on PATH. OpenSSL's "
185- .. " ./config is a Perl script and there is no xim:perl build "
186- .. " dep to fall back on — install perl and retry." )
232+ local perl , perlbin = resolve_perl ()
233+ if not perl then
234+ log .error (" compat.openssl: no usable perl. OpenSSL's ./config execs "
235+ .. " Configure, which needs a perl WITH its core modules "
236+ .. " (Config, FindBin, File::Path, POSIX) — a perl binary alone "
237+ .. " is not enough, and a perl missing them fails inside "
238+ .. " Configure with `Can't locate FindBin.pm in @INC`. The "
239+ .. " xim:perl build dep should have supplied one; if it could "
240+ .. " not be resolved, install a complete perl (e.g. Debian "
241+ .. " perl-modules, Fedora perl-core) and retry." )
187242 return false
188243 end
189244
245+ -- Put the resolved perl FIRST on PATH for every build step. Configure's
246+ -- shebang is `#!/usr/bin/env perl`, so this — not the command we type — is
247+ -- what decides which interpreter runs it. Empty when the fallback picked
248+ -- up the host's own perl, which is already on PATH by definition.
249+ local perl_path = " "
250+ if perlbin then
251+ perl_path = " export PATH=" .. sh_quote (perlbin ) .. ' :"$PATH"; '
252+ end
253+
190254 -- The fetched tarball unpacks to openssl-<ver>/ beside the archive. Every
191255 -- command below cd's into srcroot itself, so the process cwd is left alone
192256 -- (an os.cd here would break the relative-path fallback on the next line).
@@ -229,20 +293,24 @@ local function _install_impl()
229293
230294 -- Record which make is in play: "3.81 vs 4.x" is the difference between a
231295 -- build and a wall of Makefile syntax errors, and it is invisible after
232- -- the fact otherwise.
296+ -- the fact otherwise. `command -v perl` is logged under the same PATH the
297+ -- build will use, so the log says which interpreter Configure got rather
298+ -- than which one we hoped it would get.
233299 run (" build environment" , logf , string.format (
234- " { %s --version; echo \" cc: $(command -v cc)\" ; cc --version; " ..
235- " perl --version; } >> %s 2>&1 || true" , make , sh_quote (logf )))
300+ " %s{ %s --version; echo \" cc: $(command -v cc)\" ; cc --version; " ..
301+ " echo \" perl: $(command -v perl)\" ; perl --version; } >> %s 2>&1 || true" ,
302+ perl_path , make , sh_quote (logf )))
236303
237304 local cc = cc_override ()
238305 if not run (" ./config" , logf , string.format (
239- " cd %s && %s./config --prefix=%s --libdir=lib %s >> %s 2>&1" ,
240- sh_quote (srcroot ), cc , sh_quote (prefix ), flags , sh_quote (logf ))) then
306+ " %scd %s && %s./config --prefix=%s --libdir=lib %s >> %s 2>&1" ,
307+ perl_path , sh_quote (srcroot ), cc , sh_quote (prefix ), flags ,
308+ sh_quote (logf ))) then
241309 return false
242310 end
243311 if not run (" make" , logf , string.format (
244- " cd %s && %s -j%d >> %s 2>&1" ,
245- sh_quote (srcroot ), make , jobs , sh_quote (logf ))) then
312+ " %scd %s && %s -j%d >> %s 2>&1" ,
313+ perl_path , sh_quote (srcroot ), make , jobs , sh_quote (logf ))) then
246314 return false
247315 end
248316
@@ -261,8 +329,8 @@ local function _install_impl()
261329 -- were not there.
262330 local ranlib = (os .host () == " macosx" ) and " RANLIB=/usr/bin/ranlib" or " "
263331 if not run (" make install_sw" , logf , string.format (
264- " cd %s && %s%s install_sw >> %s 2>&1" ,
265- sh_quote (srcroot ), make , ranlib , sh_quote (logf ))) then
332+ " %scd %s && %s%s install_sw >> %s 2>&1" ,
333+ perl_path , sh_quote (srcroot ), make , ranlib , sh_quote (logf ))) then
266334 return false
267335 end
268336
0 commit comments