Skip to content

Commit 9ecf16f

Browse files
committed
fix(openssl): declare xim:make on macosx, and print the log tail on failure
The macOS workspace job failed on both new members ~43s after the tarball landed — far too early for a compile, and with nothing to go on: install() writes everything to an on-disk log (xim's interface mode swallows subprocess stdout) and xlings surfaces the failure as a bare `E_INTERNAL: [openssl] failed:`. Two changes, one for the likely cause and one so the next failure says what it was. macosx now declares `deps = { "xim:make@latest" }`. The previous comment claimed it was unnecessary because "macOS ships GNU Make at /usr/bin/make" — it ships GNU Make **3.81**, the last GPLv2 release, frozen in 2006, and OpenSSL 3.x's generated Makefile does not build with it. That matches the timing exactly: ~30s of Perl Configure, then make failing on sight. compat.openblas already declares this dep on macosx. Each build step now runs through a helper that, on failure, names the step and prints the last 40 lines of the log. The log also opens with `make --version`, because 3.81-vs-4.x is precisely the distinction that is invisible after the fact. The tail is passed as one pre-formatted argument rather than a format string — build output contains `%` often enough that formatting it is its own failure mode. Verified on linux (cold): log opens with "GNU Make 4.3", openssl and asio-ssl members both pass.
1 parent 97e67b1 commit 9ecf16f

1 file changed

Lines changed: 54 additions & 8 deletions

File tree

pkgs/c/compat.openssl.lua

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ package = {
4141
},
4242
},
4343
macosx = {
44-
-- No xim:make dep: macOS ships GNU Make at /usr/bin/make;
45-
-- resolve_make() falls back to PATH when the build dep is absent.
44+
-- xim:make is declared here for the same reason as linux, and NOT
45+
-- left to PATH: macOS does ship a /usr/bin/make, but it is GNU Make
46+
-- 3.81 (the last GPLv2 release, frozen in 2006), and OpenSSL 3.x's
47+
-- generated Makefile does not build with it. compat.openblas
48+
-- declares the same dep on macosx.
49+
deps = { "xim:make@latest" },
4650
["3.5.1"] = {
4751
url = {
4852
GLOBAL = "https://github.com/openssl/openssl/releases/download/openssl-3.5.1/openssl-3.5.1.tar.gz",
@@ -118,6 +122,35 @@ local function have(tool)
118122
end)
119123
end
120124

125+
-- Last `n` lines of the build log, or nil if it cannot be read.
126+
local function tail_lines(file, n)
127+
local ok, content = pcall(io.readfile, file)
128+
if not ok or not content then return nil end
129+
local lines = {}
130+
for line in (tostring(content) .. "\n"):gmatch("(.-)\n") do
131+
lines[#lines + 1] = line
132+
end
133+
if #lines == 0 then return nil end
134+
return table.concat(lines, "\n", math.max(1, #lines - n + 1), #lines)
135+
end
136+
137+
-- Run one build step, and on failure print the tail of the log with it.
138+
--
139+
-- Everything the build says goes to an on-disk log (xim's interface mode
140+
-- swallows subprocess stdout), and xlings surfaces a failed install() as a
141+
-- bare `E_INTERNAL: [openssl] failed:` — so without this the only signal a CI
142+
-- run gives is that something, somewhere, went wrong. The message is passed as
143+
-- a single pre-formatted argument: log output contains `%` often enough that
144+
-- handing it to a format string is its own failure mode.
145+
local function run(step, logf, cmd)
146+
local ok, err = pcall(os.exec, string.format("bash -c %s", sh_quote(cmd)))
147+
if ok then return true end
148+
local tail = tail_lines(logf, 40) or "<log unreadable at " .. tostring(logf) .. ">"
149+
log.error("%s", "compat.openssl: " .. step .. " failed (" .. tostring(err)
150+
.. ")\n--- last 40 lines of " .. tostring(logf) .. " ---\n" .. tail)
151+
return false
152+
end
153+
121154
local function _install_impl()
122155
if not have("perl") then
123156
log.error("compat.openssl: `perl` not found on PATH. OpenSSL's "
@@ -165,22 +198,35 @@ local function _install_impl()
165198
local make = resolve_make()
166199
local jobs = (os.default_njob and os.default_njob()) or 4
167200
local flags = "no-shared no-dso no-tests no-apps no-engine"
168-
os.exec(string.format("bash -c %s", sh_quote(string.format(
201+
202+
-- Record which make is in play: "3.81 vs 4.x" is the difference between a
203+
-- build and a wall of Makefile syntax errors, and it is invisible after
204+
-- the fact otherwise.
205+
run("make --version", logf, string.format(
206+
"%s --version >> %s 2>&1 || true", make, sh_quote(logf)))
207+
208+
if not run("./config", logf, string.format(
169209
"cd %s && ./config --prefix=%s --libdir=lib %s >> %s 2>&1",
170-
sh_quote(srcroot), sh_quote(prefix), flags, sh_quote(logf)))))
171-
os.exec(string.format("bash -c %s", sh_quote(string.format(
210+
sh_quote(srcroot), sh_quote(prefix), flags, sh_quote(logf))) then
211+
return false
212+
end
213+
if not run("make", logf, string.format(
172214
"cd %s && %s -j%d >> %s 2>&1",
173-
sh_quote(srcroot), make, jobs, sh_quote(logf)))))
215+
sh_quote(srcroot), make, jobs, sh_quote(logf))) then
216+
return false
217+
end
174218

175219
-- macOS only: `make install_dev` runs `$(RANLIB) -c`, and the toolchain
176220
-- puts llvm-ranlib (which rejects -c) ahead of the system one on PATH.
177221
-- Pinning an absolute /usr/bin/ranlib is itself a host assumption, so it
178222
-- is confined to the platform that needs it — a Linux container without
179223
-- /usr/bin/ranlib would otherwise fail install_sw for no reason.
180224
local ranlib = (os.host() == "macosx") and "RANLIB=/usr/bin/ranlib " or ""
181-
os.exec(string.format("bash -c %s", sh_quote(string.format(
225+
if not run("make install_sw", logf, string.format(
182226
"cd %s && %s%s install_sw >> %s 2>&1",
183-
sh_quote(srcroot), ranlib, make, sh_quote(logf)))))
227+
sh_quote(srcroot), ranlib, make, sh_quote(logf))) then
228+
return false
229+
end
184230

185231
-- Verify the build produced the expected archives.
186232
local libdir = path.join(prefix, "lib")

0 commit comments

Comments
 (0)