Skip to content

Commit b2980da

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 b2980da

File tree

3 files changed

+71
-41
lines changed

3 files changed

+71
-41
lines changed

build/build.ts

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -161,47 +161,86 @@ 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))
165-
166-
if (deps.has('llvm.org') || deps.has('gnu.org/gcc')) {
164+
if (yml?.build?.skip === 'shims' || yml?.build?.skip?.includes?.('shims')) {
167165
return
168166
}
169167

170168
if (host().platform != "darwin") {
169+
const deps = new Set(config.deps.dry.build.concat(config.deps.dry.runtime).map(x => x.project))
170+
const has_gcc = deps.has('gnu.org/gcc')
171+
const has_llvm = deps.has('llvm.org')
172+
const has_binutils = deps.has('gnu.org/binutils')
173+
171174
// rm ∵ // https://github.com/pkgxdev/brewkit/issues/303
172175
const d = config.path.home.join('toolchain').rm({ recursive: true }).mkdir('p')
176+
const prefix = useConfig().prefix
173177

174-
const symlink = (names: string[], {to}: {to: string}) => {
178+
const llvm = (bin: string) => prefix.join('llvm.org/v*/bin', bin)
179+
const gcc = (bin: string) => prefix.join('gnu.org/gcc/v*/bin', bin)
180+
const binutils = (bin: string) => prefix.join('gnu.org/binutils/v*/bin', bin)
181+
182+
const symlink = (names: string[], target: Path) => {
175183
for (const name of names) {
176184
const path = d.join(name)
177185
if (path.exists()) continue
178-
const target = useConfig().prefix.join('llvm.org/v*/bin', to)
179186
path.ln('s', { target })
180187
}
181188
}
182189

183-
symlink(["cc", "gcc", "clang"], {to: "clang"})
184-
symlink(["c++", "g++", "clang++"], {to: "clang++"})
185-
symlink(["cpp"], {to: "clang-cpp"})
190+
// compilers
191+
if (has_gcc && has_llvm) {
192+
symlink(["cc", "gcc"], gcc("gcc"))
193+
symlink(["c++", "g++"], gcc("g++"))
194+
symlink(["clang"], llvm("clang"))
195+
symlink(["clang++"], llvm("clang++"))
196+
symlink(["cpp"], gcc("cpp"))
197+
} else if (has_gcc) {
198+
symlink(["cc", "gcc"], gcc("gcc"))
199+
symlink(["c++", "g++"], gcc("g++"))
200+
symlink(["cpp"], gcc("cpp"))
201+
} else {
202+
// llvm is default; build-script.ts adds +llvm.org to env if not already a dep
203+
symlink(["cc", "gcc", "clang"], llvm("clang"))
204+
symlink(["c++", "g++", "clang++"], llvm("clang++"))
205+
symlink(["cpp"], llvm("clang-cpp"))
206+
}
186207

187-
if (host().platform == "linux") {
188-
symlink(["ld"], {to: "ld.lld"})
208+
// linker
209+
if (has_binutils) {
210+
symlink(["ld"], binutils("ld"))
211+
} else if (host().platform == "linux") {
212+
symlink(["ld"], llvm("ld.lld"))
189213
} else if (host().platform == "windows") {
190-
symlink(["ld"], {to: "lld-link"})
214+
symlink(["ld"], llvm("lld-link"))
191215
}
192216

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"})
217+
if (has_llvm || !has_gcc) {
218+
symlink(["ld.lld"], llvm("ld.lld"))
219+
symlink(["lld-link"], llvm("lld-link"))
220+
}
221+
222+
// utilities
223+
if (has_binutils) {
224+
symlink(["ar"], binutils("ar"))
225+
symlink(["as"], binutils("as"))
226+
symlink(["nm"], binutils("nm"))
227+
symlink(["objcopy"], binutils("objcopy"))
228+
symlink(["ranlib"], binutils("ranlib"))
229+
symlink(["readelf"], binutils("readelf"))
230+
symlink(["strings"], binutils("strings"))
231+
symlink(["strip"], binutils("strip"))
232+
} else {
233+
symlink(["ar"], llvm("llvm-ar"))
234+
symlink(["as"], llvm("llvm-as"))
235+
symlink(["nm"], llvm("llvm-nm"))
236+
symlink(["objcopy"], llvm("llvm-objcopy"))
237+
symlink(["ranlib"], llvm("llvm-ranlib"))
238+
symlink(["readelf"], llvm("llvm-readelf"))
239+
symlink(["strings"], llvm("llvm-strings"))
240+
symlink(["strip"], llvm("llvm-strip"))
241+
}
204242
}
205243

244+
// always return shim path — on Darwin the shim handles -Werror filtering and rpath injection via ruby
206245
return new Path(new URL(import.meta.url).pathname).join("../../share/toolchain/bin")
207246
}

lib/porcelain/build-script.ts

Lines changed: 6 additions & 1 deletion
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')

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)