From 81aed170586a25347135ec6fcc648d28018ff739 Mon Sep 17 00:00:00 2001 From: Jacob Heider Date: Fri, 6 Feb 2026 13:01:20 -0500 Subject: [PATCH 1/5] remove .la files they're fully unrelocatable, and we remove them explicitly from dozens of packages to prevent build failures. --- lib/porcelain/fix-up.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/porcelain/fix-up.ts b/lib/porcelain/fix-up.ts index bd1d646f..b487d894 100644 --- a/lib/porcelain/fix-up.ts +++ b/lib/porcelain/fix-up.ts @@ -8,6 +8,7 @@ export default async function finish(config: Config) { await fix_rpaths(prefix, config.pkg, config.path.cache, config.deps.gas) await fix_pc_files(prefix, config.path.build_install) await fix_cmake_files(prefix, config.path.build_install) + await remove_la_files(prefix) } ////////////////////////////////////////////////////////////////////////////////////// @@ -100,3 +101,15 @@ async function fix_cmake_files(pkg_prefix: Path, build_prefix: Path) { } } } + +async function remove_la_files(pkg_prefix: Path) { + // libtool .la files contain hardcoded paths and cause more problems than they solve + const lib = pkg_prefix.join("lib").isDirectory() + if (!lib) return + for await (const [path, { isFile }] of lib.walk()) { + if (isFile && path.extname() == ".la") { + console.log({ removing: path }) + Deno.removeSync(path.string) + } + } +} From 782d770a650f24fe7fc1e3b1f02b561561cf7137 Mon Sep 17 00:00:00 2001 From: Jacob Heider Date: Fri, 6 Feb 2026 13:05:59 -0500 Subject: [PATCH 2/5] add header flattening we use a symlink to preserve header path, while flattening to improve compatibility. --- lib/porcelain/fix-up.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/porcelain/fix-up.ts b/lib/porcelain/fix-up.ts index b487d894..9cc499a7 100644 --- a/lib/porcelain/fix-up.ts +++ b/lib/porcelain/fix-up.ts @@ -9,6 +9,7 @@ export default async function finish(config: Config) { await fix_pc_files(prefix, config.path.build_install) await fix_cmake_files(prefix, config.path.build_install) await remove_la_files(prefix) + await flatten_headers(prefix) } ////////////////////////////////////////////////////////////////////////////////////// @@ -113,3 +114,32 @@ async function remove_la_files(pkg_prefix: Path) { } } } + +async function flatten_headers(pkg_prefix: Path) { + // if include/ contains exactly one subdirectory and no loose files, flatten it + // eg. include/foo/*.h → include/*.h with include/foo → symlink to . + const include = pkg_prefix.join("include").isDirectory() + if (!include) return + + const entries: Path[] = [] + const subdirs: Path[] = [] + + for await (const [path, { isDirectory }] of include.ls()) { + entries.push(path) + if (isDirectory) subdirs.push(path) + } + + if (subdirs.length == 1 && entries.length == 1) { + const subdir = subdirs[0] + const name = subdir.basename() + + // move all contents up + for await (const [path] of subdir.ls()) { + Deno.renameSync(path.string, include.join(path.basename()).string) + } + + Deno.removeSync(subdir.string, { recursive: true }) + Deno.symlinkSync(".", include.join(name).string) + console.log({ flattened_headers: name }) + } +} From 5de3bafea483c1fbaca33935cf353b4d845fbd16 Mon Sep 17 00:00:00 2001 From: Jacob Heider Date: Fri, 6 Feb 2026 13:16:10 -0500 Subject: [PATCH 3/5] merge lib64 into lib automatically this is an artifact of 32-bit linux, which we don't support, anywhere, and which is basically long dead outside of specialized environment.s --- lib/porcelain/fix-up.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/porcelain/fix-up.ts b/lib/porcelain/fix-up.ts index 9cc499a7..4a7e5c86 100644 --- a/lib/porcelain/fix-up.ts +++ b/lib/porcelain/fix-up.ts @@ -9,6 +9,9 @@ export default async function finish(config: Config) { await fix_pc_files(prefix, config.path.build_install) await fix_cmake_files(prefix, config.path.build_install) await remove_la_files(prefix) + if (host().platform == 'linux') { + await consolidate_lib64(prefix) + } await flatten_headers(prefix) } @@ -115,6 +118,25 @@ async function remove_la_files(pkg_prefix: Path) { } } +async function consolidate_lib64(pkg_prefix: Path) { + // some build systems install to lib64 on x86-64 Linux; we standardize on lib + const lib64 = pkg_prefix.join("lib64") + if (!lib64.isDirectory()) return + + const lib = pkg_prefix.join("lib") + lib.mkpath() + + for await (const [path, { isFile, isSymlink }] of lib64.ls()) { + const dest = lib.join(path.basename()) + if (isFile || isSymlink) { + Deno.renameSync(path.string, dest.string) + } + } + + Deno.removeSync(lib64.string, { recursive: true }) + Deno.symlinkSync("lib", lib64.string) +} + async function flatten_headers(pkg_prefix: Path) { // if include/ contains exactly one subdirectory and no loose files, flatten it // eg. include/foo/*.h → include/*.h with include/foo → symlink to . From caa86d51e8f5794b7f76c45a93bee4d800f2237b Mon Sep 17 00:00:00 2001 From: Jacob Heider Date: Fri, 6 Feb 2026 13:17:08 -0500 Subject: [PATCH 4/5] disallow -pie + -shared in the same invocation this is the big one. we have a wrapper-based workaround, spread across numerous files. -pie is for executables, and -shared is for libraries, so you can see why this breaks. --- share/toolchain/shim | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/share/toolchain/shim b/share/toolchain/shim index a0c444b4..95d83f7c 100755 --- a/share/toolchain/shim +++ b/share/toolchain/shim @@ -20,8 +20,17 @@ if [ "$(uname)" != Darwin ]; then set -a eval "$("$pkgx" +llvm.org)" + if printf "%s\n" "$@" | grep -qxF -- '-shared'; then + has_shared=1 + fi + filtered_args=() for arg in "$@"; do + # -shared and -pie conflict. libs aren't executables, so accept the -shared + if [ "$arg" = "-pie" ] && [ "$has_shared" = "1" ]; then + continue + fi + if [ "$arg" != -Werror ]; then filtered_args+=("$arg") fi From ea999ba9eb3e3552f718a468db8483b00e2a5688 Mon Sep 17 00:00:00 2001 From: Jacob Heider Date: Fri, 6 Feb 2026 13:53:16 -0500 Subject: [PATCH 5/5] update CI deps --- .github/workflows/ci.cli.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.cli.yml b/.github/workflows/ci.cli.yml index bc4f5411..563b3ba2 100644 --- a/.github/workflows/ci.cli.yml +++ b/.github/workflows/ci.cli.yml @@ -14,7 +14,7 @@ jobs: matrix: platform: - os: ubuntu-latest - img: debian:buster-slim + img: debian:bullseye-slim tag: linux - os: macos-latest tag: mac @@ -35,6 +35,9 @@ jobs: - uses: actions/checkout@v4 - uses: pkgxdev/setup@v2 + # otherwise, we're getting some weird race conditions on CI + - run: pkgx --sync + - run: bin/bk build ${{matrix.pkg}} - run: bin/bk test ${{matrix.pkg}} - run: bin/bk audit ${{matrix.pkg}} @@ -53,14 +56,13 @@ jobs: # check build can run twice, see https://github.com/pkgxdev/brewkit/issues/303 - run: bin/bk build - unit-tests: runs-on: ubuntu-latest env: PKGX_PANTRY_PATH: null steps: - uses: actions/checkout@v4 - - uses: pkgxdev/dev@v0 + - uses: pkgxdev/dev@v1 - run: deno test --allow-env --allow-net --ignore=.data working-directory: lib @@ -69,7 +71,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: pkgxdev/setup@v2 - - run: pkgx --sync # FIXME PKGX_PANTRY_PATH causes auto sync to fail + - run: pkgx --sync # FIXME PKGX_PANTRY_PATH causes auto sync to fail - name: build run: | set +e