Skip to content

Commit

Permalink
add toolchain shims here (#175)
Browse files Browse the repository at this point in the history
* add toolchain shims here

* only added if no other toolchain is added
* on linux shim through to llvm
* on mac shim through to system

rationale
* reduces hacks in our infra
* these are only used with pantry builds
* brewkit controls that
* everyone expects a C compiler, builds either will work with this or they need to be more specifiuc
* for end users removes the surprise of `cc` being some weird hack
* end users have to control rpaths themselves and if they are going that low-level then they know what to do
* magic is bad
  • Loading branch information
mxcl committed Sep 29, 2023
1 parent 97fae5a commit d4e020f
Show file tree
Hide file tree
Showing 47 changed files with 162 additions and 17 deletions.
22 changes: 12 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ jobs:
- catb.org/wumpus
- c-ares.org
- vim.org
- tea.xyz/gx/cc
# FIXME? requires a darwin platform to run, and needs
# macOS 12 to test. That'll require a more complex matrix
# using get-platform.
Expand All @@ -29,32 +28,35 @@ jobs:
- uses: actions/checkout@v3
- uses: teaxyz/setup@v0

- name: configure PATH
run: echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
- run: |
find ~/.tea/tea.xyz/var/pantry -name 'package.yml' -exec sed -i '/tea\.xyz\/gx\/cc: c99/d' {} \;
- uses: actions/cache@v3
with:
path: ${{ env.HOME }}/.cache/deno
key: deno-get-platform-${{ hashFiles('deno.jsonc')}}
# prefetch dneo deps to make the output from the build step more legible
- run: deno cache **/*.ts

- name: prefetch deno deps
# this makes the output from the build step more legible
run: deno cache **/*.ts
- name: install brewkit
run: |
mkdir -p "$HOME/.tea/tea.xyz/brewkit/v*"
mv * "$HOME/.tea/tea.xyz/brewkit/v*"
echo "$HOME/.tea/tea.xyz/brewkit/v*/bin" >> $GITHUB_PATH
- run: pkg build ${{matrix.pkgs}}
id: build

- run: test -n '${{ steps.build.outputs.pkgs }}'
- run: test -n '${{ steps.build.outputs.relative-paths }}'

- run: |
if pkg query ${{ steps.build.outputs.pkgs }} --src 2>&1 | grep -E '^warn: pkg has no srcs:'; then
echo "srcs=false" >> $GITHUB_OUTPUT
else
echo "srcs=true" >> $GITHUB_OUTPUT
fi
id: srcs
- run: test -n '${{ steps.build.outputs.srcs }}'
if: steps.srcs.outputs.srcs == 'true'

- run: test -n '${{ steps.build.outputs.srcs-relative-paths }}'
if: steps.srcs.outputs.srcs == 'true'

Expand Down
4 changes: 4 additions & 0 deletions lib/usePantry.getScript.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import useConfig from "libtea/hooks/useConfig.ts"
import { SupportedPlatforms } from "https://raw.githubusercontent.com/teaxyz/lib/v0.4.2/src/utils/host.ts"
import { isArray, isString, isPlainObject, PlainObject } from "is-what"
import { Package, Installation, hooks, utils, semver } from "libtea"
Expand All @@ -13,6 +14,9 @@ export const getScript = async (pkg: Package, key: 'build' | 'test', deps: Insta
const mm = useMoustaches()
const script = (input: unknown) => {
const tokens = mm.tokenize.all(pkg, deps)
tokens.push({
from: "build.root", to: useConfig().prefix.string
})
if (isArray(input)) input = input.map(obj => {
if (isPlainObject(obj)) {

Expand Down
5 changes: 5 additions & 0 deletions libexec/stage-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ if (!yml.test) throw "no `test` node in package.yml"
env['PATH'] ??= []
env['PATH'].push("/usr/bin:/bin")

if (!deps.find(({pkg}) => pkg.project == 'llvm.org' || pkg.project == 'gnu.org/gcc')) {
/// add our helper cc toolchain unless the package has picked its own toolchain
env['PATH'].unshift(new Path(new URL(import.meta.url).pathname).parent().parent().join("share/toolchain/bin").string)
}

let text = undent`
#!/usr/bin/env bash
Expand Down
9 changes: 7 additions & 2 deletions libexec/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ const pkg = await pantry.resolve(parse(pkgname))

/// assemble build script
const pantry_sh = await pantry.getScript(pkg, 'build', deps)
const brewkit = new Path(new URL(import.meta.url).pathname).parent().parent().join("share/brewkit")
const sup_PATH = [new Path(new URL(import.meta.url).pathname).parent().parent().join("share/brewkit")]

if (!deps.find(({pkg}) => pkg.project == 'llvm.org' || pkg.project == 'gnu.org/gcc')) {
/// add our helper cc toolchain unless the package has picked its own toolchain
sup_PATH.push(new Path(new URL(import.meta.url).pathname).parent().parent().join("share/toolchain/bin"))
}

/// calc env
const sh = useShellEnv()
Expand Down Expand Up @@ -86,7 +91,7 @@ const text = undent`
mkdir -p "$HOME"
export PATH=${brewkit}:"$PATH"
export PATH=${sup_PATH.map(x => x.string).join(':')}:"$PATH"
export CFLAGS="-w $CFLAGS" # warnings are noise
${pantry_sh}
Expand Down
Binary file added share/.DS_Store
Binary file not shown.
9 changes: 4 additions & 5 deletions share/TEMPLATE.pkg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,13 @@ dependencies:

build:
dependencies:
tea.xyz/gx/cc: c99
tea.xyz/gx/make: '*'
# ^^ often packages need dependencies to build, it is very common for
# packages to need a C compiler and make, the above provide those
cmake.org: ^3
# ^^ we provide a c compiler and make by default, other deps you’ll need to add yourself

script: |
./configure $ARGS
make --jobs {{ hw.concurrency }} install
# it’s extremely common for packages to require the above
# ^^ it’s extremely common for packages to require the above

# script also supports a list of commands, which is useful for complex builds
# or if you want to run a command in a different directory
Expand Down
Binary file added share/toolchain/.DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions share/toolchain/bin/ar
1 change: 1 addition & 0 deletions share/toolchain/bin/as
1 change: 1 addition & 0 deletions share/toolchain/bin/c++
1 change: 1 addition & 0 deletions share/toolchain/bin/cc
1 change: 1 addition & 0 deletions share/toolchain/bin/clang
1 change: 1 addition & 0 deletions share/toolchain/bin/clang++
1 change: 1 addition & 0 deletions share/toolchain/bin/cpp
1 change: 1 addition & 0 deletions share/toolchain/bin/g++
1 change: 1 addition & 0 deletions share/toolchain/bin/gcc
1 change: 1 addition & 0 deletions share/toolchain/bin/ld
1 change: 1 addition & 0 deletions share/toolchain/bin/ld64.lld
1 change: 1 addition & 0 deletions share/toolchain/bin/lld
1 change: 1 addition & 0 deletions share/toolchain/bin/lld-link
7 changes: 7 additions & 0 deletions share/toolchain/bin/make
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

if [ $(uname) = Darwin ]; then
exec /usr/bin/make "$@"
else
exec tea +gnu.org/make make "$@"
fi
1 change: 1 addition & 0 deletions share/toolchain/bin/nm
1 change: 1 addition & 0 deletions share/toolchain/bin/objcopy
1 change: 1 addition & 0 deletions share/toolchain/bin/ranlib
1 change: 1 addition & 0 deletions share/toolchain/bin/readelf
1 change: 1 addition & 0 deletions share/toolchain/bin/strings
1 change: 1 addition & 0 deletions share/toolchain/bin/strip
85 changes: 85 additions & 0 deletions share/toolchain/shim
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/sh

tool=$(basename $0)

if [ $(uname) != Darwin ]; then
d="$(cd "$(dirname "$0")/.." && pwd)"
exec "$TEA_PREFIX/tea.xyz/v*/bin/tea" +llvm.org $d/symlinks/$tool "$@"
fi

case $tool in
cc|gcc|clang|c++|g++|clang++)
exec ruby $0 "$@"
;;
ld|lld|lld-link|ld64.lld)
for word in "$@"; do
if test "$word" = -r; then
exec /usr/bin/"$tool" "$@"
fi
done

exec /usr/bin/$tool "$@" -rpath "${TEA_PREFIX:-$HOME/.tea}"
;;
*)
exec /usr/bin/$tool "$@"
;;
esac


#!/usr/bin/ruby

# - we inject our rpath to ensure our libs our found
# - for bottles we replace that in fix-machos.rb with a relocatable prefix
# - in general usage we don’t, so if the user needs to distribute their artifacts,
# they will need to fix them first, but that's typical anyway.

$tea_prefix = ENV['TEA_PREFIX'] || (ENV['HOME'] + "/.tea")
exe = File.basename($0)

# remove duplicates since this in fact embeds the rpath multiple times
# and omit -nodefaultrpaths since it is not a valid flag for clang
args = ARGV.map do |arg|
arg unless arg == "-Wl,-rpath,#$tea_prefix" or arg == "-nodefaultrpaths"
end.compact

def is_tea? path
path = File.realpath path while File.symlink? path
return File.basename(path) == "tea"
end

# find next example of ourselves
# this will either pick the Apple provided clang or the tea one
exe_path = ENV['PATH'].split(":").filter { |path|
if path == File.dirname(__FILE__)
false
elsif path == File.join($tea_prefix, ".local/bin")
false
elsif is_tea?(path)
false
else
true
end
}.map { |path|
"#{path}/#{exe}"
}.reject { |path|
# if the user created a symlink of `cc` to `tea` don’t use it
File.symlink? path and File.basename(File.readlink(path)) == "tea"
}.find { |path|
File.exist?(path)
}

abort "couldn’t find #{exe} in `PATH`" unless exe_path

for arg in args do
# figuring out what “mode” we are operating in is hard
# we don’t want to add this linker command always because it causes a warning to be
# output if we are not outputing executables/dylibs and this warning can break
# configure scripts, however the below is not fully encompassing
# we aren't sure what the rules are TBH, possibly it is as simple as if the output (`-o`)
# is a .o then we don’t add the rpath
if arg.start_with? '-l' or arg.end_with? '.dylib'
exec exe_path, *args, "-Wl,-rpath,#$tea_prefix"
end
end

exec exe_path, *args
1 change: 1 addition & 0 deletions share/toolchain/symlinks/ar
1 change: 1 addition & 0 deletions share/toolchain/symlinks/as
1 change: 1 addition & 0 deletions share/toolchain/symlinks/c++
1 change: 1 addition & 0 deletions share/toolchain/symlinks/cc
1 change: 1 addition & 0 deletions share/toolchain/symlinks/clang
1 change: 1 addition & 0 deletions share/toolchain/symlinks/clang++
1 change: 1 addition & 0 deletions share/toolchain/symlinks/cpp
1 change: 1 addition & 0 deletions share/toolchain/symlinks/g++
1 change: 1 addition & 0 deletions share/toolchain/symlinks/gcc
1 change: 1 addition & 0 deletions share/toolchain/symlinks/ld
1 change: 1 addition & 0 deletions share/toolchain/symlinks/ld64.lld
1 change: 1 addition & 0 deletions share/toolchain/symlinks/lld
1 change: 1 addition & 0 deletions share/toolchain/symlinks/lld-link
1 change: 1 addition & 0 deletions share/toolchain/symlinks/nm
1 change: 1 addition & 0 deletions share/toolchain/symlinks/objcopy
1 change: 1 addition & 0 deletions share/toolchain/symlinks/ranlib
1 change: 1 addition & 0 deletions share/toolchain/symlinks/readelf
1 change: 1 addition & 0 deletions share/toolchain/symlinks/strings
1 change: 1 addition & 0 deletions share/toolchain/symlinks/strip

0 comments on commit d4e020f

Please sign in to comment.