From e7916a13623087b487ec627c6e1bc7a0d98b6621 Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Mon, 10 Aug 2026 11:43:14 +0000 Subject: [PATCH] fix(build): make tap unit_tests wait for the tap library directory CI-unit-tests-asan-coverage failed its BUILD step with: /usr/bin/ld: error: /opt/proxysql/test/tap/tap/libcurl.so: file too short collect2: error: ld returned 1 exit status make[2]: *** [Makefile:794: genai_fts_string_unit-t] Error 1 Not a corrupt dependency -- a build race. In test/tap/Makefile the `all` and `debug` targets fan out to `tests tests_with_deps unit_tests`, and `unit_tests` was the only one of the four sibling targets without the `tap test_deps` prerequisites (tests, tests_no_infra and tests_with_deps all declare them). Under parallel make it therefore ran CONCURRENTLY with `tap`. The unit tests link -lcurl with -L$(TAP_LDIR), i.e. test/tap/tap, and the `tap` recipe populates that directory by copying the vendored library in: libcurl$(SHLIB_EXT): $(DEPS_PATH)/curl/curl/lib/.libs/libcurl$(SHLIB_EXT) cp -a $(DEPS_PATH)/curl/curl/lib/.libs/libcurl$(SHLIB_EXT)* . libcurl.so and libcurl.so.4 are symlinks onto libcurl.so.4.8.0, ~700 KB of real payload. A unit test's linker following that chain while cp is still writing the payload reads a truncated ELF, which is what "file too short" reports. The CI log catches the overlap directly -- the cp line, unrelated cmake output from another job, and the ld error are consecutive, followed by `make[2]: *** Waiting for unfinished jobs....`. Adding the prerequisites serialises the two, matching the siblings. Intermittent by nature: it needs a copy and a link to overlap, so it hits some runs and not others. The same workflow passed on the immediately preceding commit of the same branch, which is why this reads as a random infrastructure failure rather than a build-order bug. It is not specific to ASAN or to genai -- that job just happens to build the unit tests under a slower toolchain, widening the window. Verified: `make -C test/tap -n unit_tests` now descends into ../deps and tap before tests/unit (previously it went straight to tests/unit), and a parallel `make -C test/tap unit_tests -j$(nproc)` with test/tap/tap/libcurl.so* deleted beforehand completes cleanly and restores the symlink chain. --- test/tap/Makefile | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/test/tap/Makefile b/test/tap/Makefile index 6591ebdf04..061a6bc3b2 100644 --- a/test/tap/Makefile +++ b/test/tap/Makefile @@ -29,8 +29,24 @@ tests_with_deps: tap test_deps cd tests_with_deps && CC=${CC} CXX=${CXX} ${MAKE} $(MAKECMDGOALS) +# `tap test_deps` is NOT optional here, even though nothing under tests/unit is +# built by those targets. The unit tests link -lcurl with -L$(TAP_LDIR), i.e. +# test/tap/tap, and the `tap` recipe populates that directory by copying the +# vendored library into it: +# +# libcurl$(SHLIB_EXT): $(DEPS_PATH)/curl/curl/lib/.libs/libcurl$(SHLIB_EXT) +# cp -a $(DEPS_PATH)/curl/curl/lib/.libs/libcurl$(SHLIB_EXT)* . +# +# Without this prerequisite `unit_tests` runs CONCURRENTLY with `tap` under the +# `all`/`debug` targets above, so a unit test's linker can open libcurl.so while +# that cp is still writing it and fail with `file too short`. Intermittent by +# nature -- it needs the copy and a link to overlap -- and it presents as a +# corrupt library rather than a build-order problem, which makes it easy to +# misread as a real toolchain or dependency failure. Every sibling target here +# (tests, tests_no_infra, tests_with_deps) already declares these prerequisites; +# unit_tests was the only one that did not. .PHONY: unit_tests -unit_tests: +unit_tests: tap test_deps cd tests/unit && CC=${CC} CXX=${CXX} ${MAKE} $(MAKECMDGOALS)