attempt to install as little as possible with apt (#173)

This commit is contained in:
Max Howell 2022-10-03 11:30:12 -04:00 committed by GitHub
parent 3b32634cee
commit 286947912d
8 changed files with 134 additions and 50 deletions

View file

@ -61,8 +61,8 @@ jobs:
run: |
case ${{ matrix.os }} in
ubuntu-latest)
apt update
apt --yes install libc-dev libstdc++-8-dev libgcc-8-dev bzip2 xz-utils patchelf file
apt-get update
apt-get --yes install libc-dev libstdc++-8-dev libgcc-8-dev
;;
macos-11)
# screws up a lot of build scripts
@ -136,7 +136,7 @@ jobs:
- run: |
apt-get update
apt --yes install libc-dev libstdc++-8-dev libgcc-8-dev bzip2 xz-utils patchelf file
apt-get --yes install libc-dev libstdc++-8-dev libgcc-8-dev
if: ${{ matrix.container != '' }}
- uses: teaxyz/setup@v0

View file

@ -0,0 +1,25 @@
distributable:
url: https://astron.com/pub/file/file-{{version.raw}}.tar.gz
#TODO url: ftp://ftp.astron.com/pub/file/file-{{version.raw}}.tar.gz
strip-components: 1
versions:
- 5.43
#TODO github: file/file/tags (has an awful format :/)
dependencies:
zlib.net: 1 #FIXME this is actually an optional dep
build:
dependencies:
tea.xyz/gx/cc: c99
tea.xyz/gx/make: '*'
git-scm.org: 2
script: |
git apply props/relocatable.diff
./configure --prefix={{prefix}}
make --jobs {{hw.concurrency}} install
test: |
file {{prefix}}/bin/file
#TODO check output, we dont since it varies by platform annoyingly

View file

@ -0,0 +1,55 @@
diff --git a/src/file.h b/src/file.h
index 85675df..8d0f058 100644
--- a/src/file.h
+++ b/src/file.h
@@ -95,9 +95,10 @@
#define ENABLE_CONDITIONALS
-#ifndef MAGIC
-#define MAGIC "/etc/magic"
-#endif
+const char *tea_get_lib_dir(void);
+
+#undef MAGIC
+#define MAGIC tea_get_lib_dir()
#if defined(__EMX__) || defined (WIN32)
#define PATHSEP ';'
diff --git a/src/magic.c b/src/magic.c
index 7768497..84e8ba7 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -257,7 +257,7 @@ magic_getpath(const char *magicfile, int action)
return magicfile;
magicfile = getenv("MAGIC");
- if (magicfile != NULL)
+ if (magicfile != NULL && magicfile[0] == '/')
return magicfile;
return action == FILE_LOAD ? get_default_magic() : MAGIC;
@@ -678,3 +678,23 @@ magic_getparam(struct magic_set *ms, int param, void *val)
return -1;
}
}
+
+
+#include <libgen.h>
+
+/// returns the library dir of our relocatable installation
+protected const char *tea_get_lib_dir(void) {
+ char path[MAXPATHLEN + 1] = {0};
+ uint32_t len = sizeof(path) - 1;
+#if __APPLE__
+ int rv = _NSGetExecutablePath(path, &len);
+#else
+ int rv = readlink("/proc/self/exe", path, len - 1);
+#endif
+ if (rv != -1) {
+ sprintf(path, "%s/%s", dirname(dirname(path)), "share/misc/magic");
+ return strdup(path) ?: "/etc/magic";
+ } else {
+ return "/etc/magic";
+ }
+}

View file

@ -1,11 +1,32 @@
#!/usr/bin/env -S tea -E
/*---
args:
- deno
- run
- --allow-run
- --allow-env
- --allow-read
- --allow-write={{tea.prefix}}
- --import-map={{ srcroot }}/import-map.json
dependencies:
nixos.org/patchelf: '*'
darwinsys.com/file: 5
---*/
import { useCellar } from "hooks"
import { PackageRequirement, Installation } from "types"
import { backticks, run, host } from "utils"
import { PackageRequirement, Installation, Package } from "types"
import { backticks, run, host, pkg as pkgutils } from "utils"
import Path from "path"
if (import.meta.main) {
console.log(await get_rpaths(new Path(Deno.args[0])))
const cellar = useCellar()
const [installation, ...pkgs] = Deno.args
await fix_rpaths(
await cellar.resolve(new Path(installation)),
pkgs.map(pkgutils.parse)
)
}
@ -13,7 +34,7 @@ if (import.meta.main) {
//NOTE solution is to have the rpath reference major version (or more specific if poss)
/// fix rpaths or install names for executables and dynamic libraries
export default async function fix_rpaths(installation: Installation, pkgs: PackageRequirement[]) {
export default async function fix_rpaths(installation: Installation, pkgs: (Package | PackageRequirement)[]) {
const skip_rpaths = [
"go.dev", // skipping because for some reason patchelf breaks the go binary resulting in the only output being: `Segmentation Fault`
"tea.xyz", // this causes tea to pass -E/--version (and everything else?) directly to deno, making it _too_ much of a wrapper.
@ -33,7 +54,7 @@ export default async function fix_rpaths(installation: Installation, pkgs: Packa
//NOTE we should have a `safety-inspector` step before bottling to check for this sort of thing
// and then have virtual env manager be more specific via (DY)?LD_LIBRARY_PATH
//FIXME somewhat inefficient for eg. git since git is mostly hardlinks to the same file
async function set_rpaths(exename: Path, pkgs: PackageRequirement[], installation: Installation) {
async function set_rpaths(exename: Path, pkgs: (Package | PackageRequirement)[], installation: Installation) {
if (host().platform != 'linux') throw new Error()
const cellar = useCellar()
@ -80,32 +101,11 @@ async function set_rpaths(exename: Path, pkgs: PackageRequirement[], installatio
}
}
async function prefix(pkg: PackageRequirement) {
async function prefix(pkg: Package | PackageRequirement) {
return (await cellar.resolve(pkg)).path.join("lib").string
}
}
async function get_rpaths(exename: Path): Promise<string[]> {
//GOOD_1ST_ISSUE better tokenizer for the output
const lines = (await backticks({
cmd: ["otool", "-l", exename]
}))
.trim()
.split("\n")
const it = lines.values()
const rv: string[] = []
for (const line of it) {
if (line.trim().match(/^cmd\s+LC_RPATH$/)) {
it.next()
rv.push(it.next().value.trim().match(/^path\s+(.+)$/)[1])
console.debug(rv.at(-1))
}
}
return rv
}
//FIXME pretty slow since we execute `file` for every file
// eg. perl has hundreds of `.pm` files in its `lib`
async function* exefiles(prefix: Path): AsyncGenerator<[Path, 'exe' | 'lib']> {

View file

@ -4,7 +4,6 @@
args:
- deno
- run
- --allow-net
- --allow-run
- --allow-env
- --allow-read

View file

@ -3,10 +3,9 @@ import { link, hydrate } from "prefab"
import { Installation, Package } from "types"
import useShellEnv, { expand } from "hooks/useShellEnv.ts"
import { run, undent, host, tuplize } from "utils"
import { str as pkgstr } from "utils/pkg.ts"
import fix_pkg_config_files from "./fix-pkg-config-files.ts"
import fix_linux_rpaths from "./fix-linux-rpaths.ts"
import Path from "path"
import * as semver from "semver"
const cellar = useCellar()
const pantry = usePantry()
@ -109,14 +108,30 @@ async function __build(pkg: Package) {
}
async function fix_binaries(installation: Installation) {
const prefix = usePrefix().join("tea.xyz/var/pantry/scripts/brewkit")
const env = {
TEA_PREFIX: usePrefix().string,
}
switch (host().platform) {
case 'darwin':
await fix_macho(installation)
break
case 'linux': {
const self = {project: pkg.project, constraint: new semver.Range(pkg.version.toString())}
await fix_linux_rpaths(installation, [...deps.runtime, self])
}}
return await run({
cmd: [
prefix.join('fix-machos.rb'),
installation.path,
...['bin', 'lib', 'libexec'].map(x => installation.path.join(x)).filter(x => x.isDirectory())
],
env
})
case 'linux':
return await run({
cmd: [
prefix.join('fix-elf.ts'),
installation.path,
...[...deps.runtime, pkg].map(pkgstr)
],
env
})
}
}
}
@ -127,14 +142,3 @@ async function fetch_src(pkg: Package): Promise<Path> {
await useSourceUnarchiver().unarchive({ dstdir, zipfile, stripComponents })
return dstdir
}
async function fix_macho(installation: Installation) {
const d = new Path(new URL(import.meta.url).pathname).parent()
const walk = ['bin', 'lib', 'libexec'].map(x => installation.path.join(x)).filter(x => x.isDirectory())
await run({
cmd: [d.join('fix-machos.rb'), installation.path, ...walk],
env: {
TEA_PREFIX: usePrefix().string,
}
})
}

View file

@ -1,5 +1,6 @@
import { Installation } from "types"
import Path from "path"
import "utils"
export default async function fix_pkg_config_files(installation: Installation) {
for await (const pcfile of find_pkg_config_files(installation)) {