Skip to content

Commit 09e404e

Browse files
committed
shim layering
we need our shims to massage our build variables on linux properly (otherwise, we have to recreate logic every time we use gcc). this adds proper layered fallback to included tooling. obviously envvars can still override.
1 parent e9087dd commit 09e404e

3 files changed

Lines changed: 81 additions & 52 deletions

File tree

build/build.ts

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -161,46 +161,84 @@ if (ghout) {
161161

162162
///////////////////////////////////////////////////////////////////
163163
function make_toolchain() {
164-
const deps = new Set(config.deps.dry.build.concat(config.deps.dry.runtime).map(x => x.project))
164+
if (host().platform == "darwin") return
165165

166-
if (deps.has('llvm.org') || deps.has('gnu.org/gcc')) {
166+
if (yml?.build?.skip === 'shims' || yml?.build?.skip?.includes?.('shims')) {
167167
return
168168
}
169169

170-
if (host().platform != "darwin") {
171-
// rm ∵ // https://github.com/pkgxdev/brewkit/issues/303
172-
const d = config.path.home.join('toolchain').rm({ recursive: true }).mkdir('p')
173-
174-
const symlink = (names: string[], {to}: {to: string}) => {
175-
for (const name of names) {
176-
const path = d.join(name)
177-
if (path.exists()) continue
178-
const target = useConfig().prefix.join('llvm.org/v*/bin', to)
179-
path.ln('s', { target })
180-
}
170+
const deps = new Set(config.deps.dry.build.concat(config.deps.dry.runtime).map(x => x.project))
171+
const has_gcc = deps.has('gnu.org/gcc')
172+
const has_llvm = deps.has('llvm.org')
173+
const has_binutils = deps.has('gnu.org/binutils')
174+
175+
// rm ∵ // https://github.com/pkgxdev/brewkit/issues/303
176+
const d = config.path.home.join('toolchain').rm({ recursive: true }).mkdir('p')
177+
const prefix = useConfig().prefix
178+
179+
const llvm = (bin: string) => prefix.join('llvm.org/v*/bin', bin)
180+
const gcc = (bin: string) => prefix.join('gnu.org/gcc/v*/bin', bin)
181+
const binutils = (bin: string) => prefix.join('gnu.org/binutils/v*/bin', bin)
182+
183+
const symlink = (names: string[], target: Path) => {
184+
for (const name of names) {
185+
const path = d.join(name)
186+
if (path.exists()) continue
187+
path.ln('s', { target })
181188
}
189+
}
190+
191+
// compilers
192+
if (has_gcc && has_llvm) {
193+
symlink(["cc", "gcc"], gcc("gcc"))
194+
symlink(["c++", "g++"], gcc("g++"))
195+
symlink(["clang"], llvm("clang"))
196+
symlink(["clang++"], llvm("clang++"))
197+
symlink(["cpp"], gcc("cpp"))
198+
} else if (has_gcc) {
199+
symlink(["cc", "gcc"], gcc("gcc"))
200+
symlink(["c++", "g++"], gcc("g++"))
201+
symlink(["cpp"], gcc("cpp"))
202+
} else {
203+
// llvm is default; build-script.ts adds +llvm.org to env if not already a dep
204+
symlink(["cc", "gcc", "clang"], llvm("clang"))
205+
symlink(["c++", "g++", "clang++"], llvm("clang++"))
206+
symlink(["cpp"], llvm("clang-cpp"))
207+
}
182208

183-
symlink(["cc", "gcc", "clang"], {to: "clang"})
184-
symlink(["c++", "g++", "clang++"], {to: "clang++"})
185-
symlink(["cpp"], {to: "clang-cpp"})
209+
// linker
210+
if (has_binutils) {
211+
symlink(["ld"], binutils("ld"))
212+
} else if (host().platform == "linux") {
213+
symlink(["ld"], llvm("ld.lld"))
214+
} else if (host().platform == "windows") {
215+
symlink(["ld"], llvm("lld-link"))
216+
}
186217

187-
if (host().platform == "linux") {
188-
symlink(["ld"], {to: "ld.lld"})
189-
} else if (host().platform == "windows") {
190-
symlink(["ld"], {to: "lld-link"})
191-
}
218+
if (has_llvm || !has_gcc) {
219+
symlink(["ld.lld"], llvm("ld.lld"))
220+
symlink(["lld-link"], llvm("lld-link"))
221+
}
192222

193-
symlink(["ld.lld"], {to: "ld.lld"})
194-
symlink(["lld-link"], {to: "lld-link"})
195-
196-
symlink(["ar"], {to: "llvm-ar"})
197-
symlink(["as"], {to: "llvm-as"})
198-
symlink(["nm"], {to: "llvm-nm"})
199-
symlink(["objcopy"], {to: "llvm-objcopy"})
200-
symlink(["ranlib"], {to: "llvm-ranlib"})
201-
symlink(["readelf"], {to: "llvm-readelf"})
202-
symlink(["strings"], {to: "llvm-strings"})
203-
symlink(["strip"], {to: "llvm-strip"})
223+
// utilities
224+
if (has_binutils) {
225+
symlink(["ar"], binutils("ar"))
226+
symlink(["as"], binutils("as"))
227+
symlink(["nm"], binutils("nm"))
228+
symlink(["objcopy"], binutils("objcopy"))
229+
symlink(["ranlib"], binutils("ranlib"))
230+
symlink(["readelf"], binutils("readelf"))
231+
symlink(["strings"], binutils("strings"))
232+
symlink(["strip"], binutils("strip"))
233+
} else {
234+
symlink(["ar"], llvm("llvm-ar"))
235+
symlink(["as"], llvm("llvm-as"))
236+
symlink(["nm"], llvm("llvm-nm"))
237+
symlink(["objcopy"], llvm("llvm-objcopy"))
238+
symlink(["ranlib"], llvm("llvm-ranlib"))
239+
symlink(["readelf"], llvm("llvm-readelf"))
240+
symlink(["strings"], llvm("llvm-strings"))
241+
symlink(["strip"], llvm("llvm-strip"))
204242
}
205243

206244
return new Path(new URL(import.meta.url).pathname).join("../../share/toolchain/bin")

lib/porcelain/build-script.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ const { host } = utils
99
export default async function(config: Config, PATH?: Path): Promise<string> {
1010
const depset = new Set(config.deps.gas.map(x => x.pkg.project))
1111
const depstr = (deps: PackageRequirement[]) => deps.map(x => `"+${utils.pkg.str(x)}"`).join(' ')
12-
const env_plus = `${depstr(config.deps.dry.runtime)} ${depstr(config.deps.dry.build)}`.trim()
12+
let env_plus = `${depstr(config.deps.dry.runtime)} ${depstr(config.deps.dry.build)}`.trim()
13+
14+
// if no compiler is an explicit dep, add llvm as default (was previously done per-invocation in the shim)
15+
if (host().platform != 'darwin' && !depset.has('llvm.org') && !depset.has('gnu.org/gcc')) {
16+
env_plus = `${env_plus} "+llvm.org"`.trim()
17+
}
1318
const user_script = await usePantry().getScript(config.pkg, 'build', config.deps.gas, config)
1419

1520
const pkgx = find_in_PATH('pkgx')
@@ -51,10 +56,10 @@ export default async function(config: Config, PATH?: Path): Promise<string> {
5156
5257
${gum} format "## env"
5358
export PKGX_HOME="$HOME"
59+
export PATH="${brewkit_PATHs}:$PATH"
5460
set -a
5561
${env_plus ? `eval "$(CLICOLOR_FORCE=1 ${pkgx} ${env_plus})"` : ''}
5662
set +a
57-
export PATH="${brewkit_PATHs}:$PATH"
5863
5964
export PKGX="${pkgx}"
6065
export HOME=${config.path.home.string}

share/toolchain/shim

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,18 @@
33
tool=$(basename "$0")
44

55
if [ "$(uname)" != Darwin ]; then
6-
if [ -x /usr/local/bin/pkgx ]; then
7-
# removed from PATH deliberately
8-
#TODO like, probs we should set PKGX or something before removing it from PATH
9-
pkgx=/usr/local/bin/pkgx
10-
else
11-
# if not the above probs this is running in pkgx CI/CD
12-
pkgx="${PKGX_DIR:-$HOME/.pkgx}/pkgx.sh/v*/bin/pkgx"
13-
fi
14-
# prevent fork bombs (shouldn't be possible but who knows)
15-
export PATH="/usr/bin:/bin:/usr/sbin:/sbin"
16-
17-
# NOTE this slows down configure scripts a shit tonne
18-
# 1. a fix is speeding up pkgx resolution by caching the pantry
19-
# 2. or do this once and store the env to a file that we can then source
20-
set -a
21-
eval "$("$pkgx" +llvm.org)"
6+
# ensure $HOME/toolchain (real binaries) is found before shim dir to prevent recursion
7+
export PATH="$HOME/toolchain:$PATH"
228

239
if printf "%s\n" "$@" | grep -qxF -- '-shared'; then
24-
has_shared=1
10+
has_shared=1
2511
fi
2612

2713
filtered_args=()
2814
for arg in "$@"; do
2915
# -shared and -pie conflict. libs aren't executables, so accept the -shared
3016
if [ "$arg" = "-pie" ] && [ "$has_shared" = "1" ]; then
31-
continue
17+
continue
3218
fi
3319

3420
if [ "$arg" != -Werror ]; then

0 commit comments

Comments
 (0)