From 4f849103c7240cae78a2218943ce800e25bdb51e Mon Sep 17 00:00:00 2001 From: Ben Lovy Date: Mon, 13 Jan 2025 18:17:38 -0500 Subject: [PATCH] fix: rollup (#140) --- packages/binutils/tangram.ts | 2 +- packages/cmake/tangram.ts | 4 +- packages/curl/tangram.ts | 3 +- packages/git/tangram.ts | 2 +- packages/mold/tangram.ts | 4 +- packages/patch/tangram.ts | 3 +- packages/python/tangram.ts | 18 ++ packages/rust/build.tg.ts | 12 +- packages/rust/cargo.tg.ts | 2 +- packages/rust/proxy.tg.ts | 4 +- packages/rust/proxy/Cargo.lock | 81 ++++----- packages/rust/proxy/Cargo.toml | 2 +- packages/rust/tangram.ts | 10 +- packages/std/Cargo.lock | 70 ++++---- packages/std/Cargo.toml | 2 +- packages/std/dollar.tg.ts | 83 +++++++-- packages/std/packages/ld_proxy/src/main.rs | 54 +++++- packages/std/packages/std/manifest.rs | 42 ++++- packages/std/packages/wrapper/src/main.rs | 8 +- packages/std/sdk/cmake.tg.ts | 4 +- packages/std/sdk/mold.tg.ts | 4 +- packages/std/tangram.ts | 12 +- packages/std/wrap.tg.ts | 195 +++++++++++++++++---- packages/vim/tangram.ts | 2 +- packages/wget/tangram.ts | 3 +- packages/xz/tangram.ts | 2 +- 26 files changed, 456 insertions(+), 172 deletions(-) diff --git a/packages/binutils/tangram.ts b/packages/binutils/tangram.ts index fe94f6c3..21dabc7e 100644 --- a/packages/binutils/tangram.ts +++ b/packages/binutils/tangram.ts @@ -139,7 +139,7 @@ export const test = tg.target(async () => { "size", "strings", "strip", - ]; + ]; await std.assert.pkg({ buildFn: default_, binaries, metadata }); return true; diff --git a/packages/cmake/tangram.ts b/packages/cmake/tangram.ts index e8505c8b..857a62e1 100644 --- a/packages/cmake/tangram.ts +++ b/packages/cmake/tangram.ts @@ -17,13 +17,13 @@ export const metadata = { license: "BSD-3-Clause", name: "cmake", repository: "https://gitlab.kitware.com/cmake/cmake", - version: "3.31.3", + version: "3.31.4", }; export const source = tg.target(() => { const { version } = metadata; const checksum = - "sha256:fac45bc6d410b49b3113ab866074888d6c9e9dc81a141874446eb239ac38cb87"; + "sha256:a6130bfe75f5ba5c73e672e34359f7c0a1931521957e8393a5c2922c8b0f7f25"; const owner = "Kitware"; const repo = "CMake"; const tag = `v${version}`; diff --git a/packages/curl/tangram.ts b/packages/curl/tangram.ts index 03cf9702..771f6f79 100644 --- a/packages/curl/tangram.ts +++ b/packages/curl/tangram.ts @@ -110,7 +110,8 @@ export const test = tg.target(async () => { curl -o $OUTPUT/tangram.svg https://www.tangram.dev/tangram.svg ` .env(default_()) - .checksum("unsafe"); + .checksum("unsafe") + .then(tg.Directory.expect); const exampleContents = await result .get("example") diff --git a/packages/git/tangram.ts b/packages/git/tangram.ts index 8391d920..8dcb9e74 100644 --- a/packages/git/tangram.ts +++ b/packages/git/tangram.ts @@ -59,7 +59,7 @@ export const default_ = tg.target(async (...args: std.Args) => { } = await std.args.apply(...args); const os = std.triple.os(host); - + const sourceDir = source_ ?? source(); const configure = { diff --git a/packages/mold/tangram.ts b/packages/mold/tangram.ts index 4339be69..a412e695 100644 --- a/packages/mold/tangram.ts +++ b/packages/mold/tangram.ts @@ -9,13 +9,13 @@ export const metadata = { license: "MIT", name: "mold", repository: "https://github.com/rui314/mold", - version: "2.35.1", + version: "2.36.0", }; export const source = tg.target(() => { const { name, version } = metadata; const checksum = - "sha256:912b90afe7fde03e53db08d85a62c7b03a57417e54afc72c08e2fa07cab421ff"; + "sha256:3f57fe75535500ecce7a80fa1ba33675830b7d7deb1e5ee9a737e2bc43cdb1c7"; const owner = "rui314"; const repo = name; const tag = `v${version}`; diff --git a/packages/patch/tangram.ts b/packages/patch/tangram.ts index df018631..05b6299e 100644 --- a/packages/patch/tangram.ts +++ b/packages/patch/tangram.ts @@ -14,7 +14,8 @@ export const source = tg.target(async () => { const { name, version } = metadata; const checksum = "sha256:8cf86e00ad3aaa6d26aca30640e86b0e3e1f395ed99f189b06d4c9f74bc58a4e"; - return std.download.fromGnu({ name, version, checksum }) + return std.download + .fromGnu({ name, version, checksum }) .then((source) => std.patch(source, patches)); }); diff --git a/packages/python/tangram.ts b/packages/python/tangram.ts index c0d83328..3dac8ce5 100644 --- a/packages/python/tangram.ts +++ b/packages/python/tangram.ts @@ -75,6 +75,9 @@ export type Arg = { /** The system to build python upon. */ build?: string; + /** Build with --enable-optimizations? Not supported on macOS at the moment, enabled by default on Linux. */ + enableOptimizations?: boolean; + /** The system to use python. Currently must be the same as build. */ host?: string; @@ -101,6 +104,7 @@ export const toolchain = tg.target(async (...args: std.Args) => { sqlite: sqliteArg = {}, zlib: zlibArg = {}, } = {}, + enableOptimizations: enableOptimizations_, env: env_, host, requirements: requirementsArg, @@ -110,6 +114,11 @@ export const toolchain = tg.target(async (...args: std.Args) => { const os = std.triple.os(host); + if (os === "darwin" && enableOptimizations_ === true) { + throw new Error("enableOptimizations is not supported on macOS."); + } + const enableOptimizations = enableOptimizations_ ?? false; + // Set up build dependencies. const buildDependencies = []; const bisonForBuild = bison.default_({ build, host: build }).then((d) => { @@ -208,10 +217,19 @@ export const toolchain = tg.target(async (...args: std.Args) => { env.push({ MACOSX_DEPLOYMENT_TARGET: "15.2" }); } + const configureArgs = []; + if (enableOptimizations) { + configureArgs.push("--enable-optimizations"); + } + + const configure = { args: configureArgs }; + const phases = { configure }; + const output = await std.autotools.build( { ...(await std.triple.rotate({ build, host })), env: std.env.arg(env), + phases, opt: "3", sdk, setRuntimeLibraryPath: true, diff --git a/packages/rust/build.tg.ts b/packages/rust/build.tg.ts index d3a9847f..928c737b 100644 --- a/packages/rust/build.tg.ts +++ b/packages/rust/build.tg.ts @@ -93,7 +93,7 @@ export const build = tg.target(async (...args: std.Args) => { const rustTarget = rustTriple(target); // Determine crate name. - const crateName = crateName_ ?? (await source.id()); + const crateName = crateName_ ?? "main"; // Collect environments. const envs = []; @@ -378,6 +378,7 @@ export const testConditionalCompilation = tg.target(async () => { }); import * as curl from "curl" with { path: "../curl" }; +import * as libpsl from "libpsl" with { path: "../libpsl" }; import * as openssl from "openssl" with { path: "../openssl" }; import * as zlib from "zlib" with { path: "../zlib" }; import * as zstd from "zstd" with { path: "../zstd" }; @@ -386,10 +387,17 @@ export const testLinkLibcurl = tg.target(async () => { // Obtain dependencies. Libcurl transitively requires libssl, libz, and libzstd. const libcurl = curl.default_(); + const libpslArtifact = libpsl.default_(); const sslArtifact = openssl.default_(); const zlibArtifact = zlib.default_(); const zstdArtifact = zstd.default_(); - const deps = [libcurl, sslArtifact, zlibArtifact, zstdArtifact]; + const deps = [ + libcurl, + libpslArtifact, + sslArtifact, + zlibArtifact, + zstdArtifact, + ]; // Build the test. const exe = await build({ diff --git a/packages/rust/cargo.tg.ts b/packages/rust/cargo.tg.ts index 082471fb..6fa927e8 100644 --- a/packages/rust/cargo.tg.ts +++ b/packages/rust/cargo.tg.ts @@ -427,7 +427,7 @@ export const testUnproxiedWorkspace = tg.target(async () => { }, pre: "set -x", proxy: false, - verbose: true + verbose: true, }); const helloOutput = await $` diff --git a/packages/rust/proxy.tg.ts b/packages/rust/proxy.tg.ts index 26d99e55..72fa0a4f 100644 --- a/packages/rust/proxy.tg.ts +++ b/packages/rust/proxy.tg.ts @@ -1,7 +1,7 @@ import * as std from "std" with { path: "../std" }; import { $ } from "std" with { path: "../std" }; -import { cargo, toolchain } from "./tangram.ts"; +import { cargo, toolchain, VERSION } from "./tangram.ts"; import cargoToml from "./proxy/Cargo.toml" with { type: "file" }; import cargoLock from "./proxy/Cargo.lock" with { type: "file" }; @@ -43,7 +43,7 @@ export const test = tg.target(async () => { .env(proxy(), toolchain()) .then(tg.File.expect); const versionText = await version.text(); - tg.assert(versionText.trim().includes("nightly")); + tg.assert(versionText.trim().includes(VERSION)); // Build the basic proxy test. const helloWorld = await cargo.build({ diff --git a/packages/rust/proxy/Cargo.lock b/packages/rust/proxy/Cargo.lock index 0dafd416..82ea0066 100644 --- a/packages/rust/proxy/Cargo.lock +++ b/packages/rust/proxy/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" +checksum = "9fb65153674e51d3a42c8f27b05b9508cea85edfaade8aa46bc8fc18cecdfef3" dependencies = [ "borsh-derive", "cfg_aliases", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" +checksum = "a396e17ad94059c650db3d253bb6e25927f1eb462eede7e7a153bb6e75dce0a7" dependencies = [ "once_cell", "proc-macro-crate", @@ -222,9 +222,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.7" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "shlex", ] @@ -937,9 +937,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -1221,9 +1221,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1391,6 +1391,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" version = "1.0.18" @@ -1608,7 +1614,7 @@ dependencies = [ [[package]] name = "tangram_client" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "blake3", "byte-unit", @@ -1640,7 +1646,6 @@ dependencies = [ "tangram_version", "time", "tokio", - "tokio-stream", "tokio-util", "tracing", "url", @@ -1652,7 +1657,7 @@ dependencies = [ [[package]] name = "tangram_either" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "serde", ] @@ -1660,20 +1665,19 @@ dependencies = [ [[package]] name = "tangram_futures" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "dashmap", "futures", "itertools", "pin-project", "tokio", - "tokio-util", ] [[package]] name = "tangram_http" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "bytes", "erased-serde", @@ -1682,7 +1686,6 @@ dependencies = [ "http-body", "http-body-util", "hyper", - "hyper-util", "pin-project", "serde", "serde_json", @@ -1709,7 +1712,7 @@ dependencies = [ [[package]] name = "tangram_uri" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "derive_more", "once_cell", @@ -1720,7 +1723,7 @@ dependencies = [ [[package]] name = "tangram_version" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "derive_more", "winnow", @@ -1828,18 +1831,6 @@ dependencies = [ "syn 2.0.96", ] -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - [[package]] name = "tokio-util" version = "0.7.13" @@ -2054,20 +2045,21 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", @@ -2079,9 +2071,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2089,9 +2081,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -2102,9 +2094,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "winapi" @@ -2212,9 +2207,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.22" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] diff --git a/packages/rust/proxy/Cargo.toml b/packages/rust/proxy/Cargo.toml index f11c492d..90ca93b6 100644 --- a/packages/rust/proxy/Cargo.toml +++ b/packages/rust/proxy/Cargo.toml @@ -20,7 +20,7 @@ futures = "0.3" itertools = "0.14" serde = { version = "1", features = ["derive"] } serde_json = "1" -tangram_client = { default-features = false, git = "https://github.com/tangramdotdev/tangram", rev = "aacfa4701ecc4ba4eae4a26112a6d9654eddb677" } +tangram_client = { default-features = false, git = "https://github.com/tangramdotdev/tangram", rev = "9e450cf72a4a05d122267814c77ec78c7e14e2c9" } tokio = { version = "1", default-features = false, features = [ "rt", "fs", diff --git a/packages/rust/tangram.ts b/packages/rust/tangram.ts index 922288c4..9e196d42 100644 --- a/packages/rust/tangram.ts +++ b/packages/rust/tangram.ts @@ -20,7 +20,7 @@ export const metadata = { }; const PROFILE = "minimal" as const; -const VERSION = "1.84.0" as const; +export const VERSION = "1.84.0" as const; export type ToolchainArg = { host?: string; @@ -47,7 +47,8 @@ export const toolchain = tg.target(async (arg?: ToolchainArg) => { // Download the Rust manifest for the selected version. const manifestArtifact = await std.download({ url: `https://static.rust-lang.org/dist/channel-rust-${VERSION}.toml`, - checksum: "sha256:94c2c0ba9c6783815df45d680f0f20c7ea80d11b85ee8bbbc61354f3082cd0f5", + checksum: + "sha256:94c2c0ba9c6783815df45d680f0f20c7ea80d11b85ee8bbbc61354f3082cd0f5", decompress: false, extract: false, }); @@ -241,10 +242,9 @@ export const test = tg.target(async () => { const tests = []; tests.push(testHostToolchain()); - // tests.push(testCrossToolchain()); tests.push(testCargo()); - // tests.push(testCargoProxy()); - // tests.push(testNativeBuild()); + tests.push(testCargoProxy()); + tests.push(testNativeBuild()); const results = await Promise.all(tests); // tg.assert(results.every((r) => r === true)); diff --git a/packages/std/Cargo.lock b/packages/std/Cargo.lock index f0afb4e0..695cbb22 100644 --- a/packages/std/Cargo.lock +++ b/packages/std/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" +checksum = "9fb65153674e51d3a42c8f27b05b9508cea85edfaade8aa46bc8fc18cecdfef3" dependencies = [ "borsh-derive", "cfg_aliases", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" +checksum = "a396e17ad94059c650db3d253bb6e25927f1eb462eede7e7a153bb6e75dce0a7" dependencies = [ "once_cell", "proc-macro-crate", @@ -222,9 +222,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.7" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "shlex", ] @@ -964,9 +964,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -1260,9 +1260,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1443,6 +1443,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" version = "1.0.18" @@ -1693,7 +1699,7 @@ dependencies = [ [[package]] name = "tangram_client" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "blake3", "byte-unit", @@ -1725,7 +1731,6 @@ dependencies = [ "tangram_version", "time", "tokio", - "tokio-stream", "tokio-util", "tracing", "url", @@ -1737,7 +1742,7 @@ dependencies = [ [[package]] name = "tangram_either" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "serde", ] @@ -1745,20 +1750,19 @@ dependencies = [ [[package]] name = "tangram_futures" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "dashmap", "futures", "itertools", "pin-project", "tokio", - "tokio-util", ] [[package]] name = "tangram_http" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "bytes", "erased-serde", @@ -1767,7 +1771,6 @@ dependencies = [ "http-body", "http-body-util", "hyper", - "hyper-util", "pin-project", "serde", "serde_json", @@ -1823,7 +1826,7 @@ dependencies = [ [[package]] name = "tangram_uri" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "derive_more", "once_cell", @@ -1834,7 +1837,7 @@ dependencies = [ [[package]] name = "tangram_version" version = "0.0.0" -source = "git+https://github.com/tangramdotdev/tangram?rev=aacfa4701ecc4ba4eae4a26112a6d9654eddb677#aacfa4701ecc4ba4eae4a26112a6d9654eddb677" +source = "git+https://github.com/tangramdotdev/tangram?rev=9e450cf72a4a05d122267814c77ec78c7e14e2c9#9e450cf72a4a05d122267814c77ec78c7e14e2c9" dependencies = [ "derive_more", "winnow", @@ -1979,7 +1982,6 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", - "tokio-util", ] [[package]] @@ -2197,20 +2199,21 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", @@ -2222,9 +2225,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2232,9 +2235,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -2245,9 +2248,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "winapi" @@ -2364,9 +2370,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.22" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] diff --git a/packages/std/Cargo.toml b/packages/std/Cargo.toml index b644cecf..b04a8bdb 100644 --- a/packages/std/Cargo.toml +++ b/packages/std/Cargo.toml @@ -33,7 +33,7 @@ itertools = "0.14" libc = "0.2" serde = { version = "1", features = ["derive"] } serde_json = "1" -tangram_client = { default-features = false, git = "https://github.com/tangramdotdev/tangram", rev = "aacfa4701ecc4ba4eae4a26112a6d9654eddb677" } +tangram_client = { default-features = false, git = "https://github.com/tangramdotdev/tangram", rev = "9e450cf72a4a05d122267814c77ec78c7e14e2c9" } tempfile = "3" tokio = { version = "1", default-features = false, features = [ "rt", diff --git a/packages/std/dollar.tg.ts b/packages/std/dollar.tg.ts index 0fdea249..fc74bebb 100644 --- a/packages/std/dollar.tg.ts +++ b/packages/std/dollar.tg.ts @@ -8,13 +8,17 @@ export function $( } class Dollar { - #strings: TemplateStringsArray; - #placeholders: std.args.UnresolvedArgs; - #host?: string; - #executable?: tg.Artifact | undefined; #args?: Array; - #env?: std.args.UnresolvedArgs; #checksum?: tg.Checksum | undefined; + #disallowUnset: boolean; + #env?: std.args.UnresolvedArgs; + #executable?: tg.Artifact | undefined; + #exitOnErr: boolean; + #includeUtils: boolean; + #host?: string; + #pipefail: boolean; + #placeholders: std.args.UnresolvedArgs; + #strings: TemplateStringsArray; constructor( strings: TemplateStringsArray, @@ -22,6 +26,10 @@ class Dollar { ) { this.#strings = strings; this.#placeholders = placeholders; + this.#disallowUnset = true; + this.#exitOnErr = true; + this.#includeUtils = true; + this.#pipefail = true; } checksum(checksum: tg.Checksum | undefined): Dollar { @@ -29,6 +37,11 @@ class Dollar { return this; } + disallowUnset(bool: boolean): Dollar { + this.#disallowUnset = bool; + return this; + } + env(...envArgs: std.args.UnresolvedArgs): Dollar { this.#env = std.flatten([this.#env, ...envArgs]); return this; @@ -38,23 +51,37 @@ class Dollar { this.#executable = executable; return this; } + + exitOnErr(bool: boolean): Dollar { + this.#exitOnErr = bool; + return this; + } host(host: string): Dollar { this.#host = host; return this; } + includeUtils(bool: boolean): Dollar { + this.#includeUtils = bool; + return this; + } + async output(): Promise { return await (await this.target()).output(); } + + pipefail(bool: boolean): Dollar { + this.#pipefail = bool; + return this; + } async target(): Promise { const arg: tg.Target.ArgObject = {}; - if (this.#host !== undefined) { - arg.host = this.#host; - } - // If the user specified a custom executable, use that. + + // Construct the executable. if (this.#executable !== undefined) { + // If the user specified a custom executable, use that. arg.executable = this.#executable; } else { // Otherwise, use the default bash executable from the standard utils. @@ -63,20 +90,40 @@ class Dollar { .then((dir) => dir.get("bin/bash")) .then(tg.File.expect); } - arg.args = [ - "-c", - await tg(this.#strings, ...std.flatten(this.#placeholders)), - ]; + + // Construct the args. + arg.args = []; + if (this.#disallowUnset) { + arg.args.push("-u"); + } + if (this.#exitOnErr) { + arg.args.push("-e"); + } + if (this.#pipefail) { + arg.args.push("-o"); + arg.args.push("pipefail"); + } + arg.args.push("-c"); + arg.args.push(await tg(this.#strings, ...std.flatten(this.#placeholders))); if (this.#args !== undefined) { arg.args.push(...this.#args); } - // Ensure the standard utils are provided in the env. - const env_ = std.utils.env({ sdk: false, env: std.sdk(), host: arg.host }); - if (this.#env !== undefined) { - arg.env = await std.env.arg(env_, this.#env); + + // Construct the env. + if (this.#includeUtils) { + const utilsEnv = std.utils.env({ sdk: false, env: std.sdk(), host: arg.host }); + if (this.#env !== undefined) { + arg.env = await std.env.arg(utilsEnv, this.#env); + } else { + arg.env = await utilsEnv; + } } else { - arg.env = await env_; + if (this.#env !== undefined) { + arg.env = std.env.arg(this.#env); + } } + + // Set remaining fields. if (this.#checksum !== undefined) { arg.checksum = this.#checksum; } diff --git a/packages/std/packages/ld_proxy/src/main.rs b/packages/std/packages/ld_proxy/src/main.rs index 5296b369..baecc839 100644 --- a/packages/std/packages/ld_proxy/src/main.rs +++ b/packages/std/packages/ld_proxy/src/main.rs @@ -82,6 +82,9 @@ struct Options { /// If any NEEDED libraries are missing at the end, should we still produce a wrapper?. Will warn if false, error if true. Default: false. disallow_missing: bool, + /// The identity to use for the resulting wrapper. If not specified, dynamically-linked executables will use the `Executable` identity, and statically-linked executables will use `Wrapper`. + identity: Option, + /// The interpreter used by the output executable. interpreter_path: Option, @@ -126,6 +129,13 @@ fn read_options() -> tg::Result { // Get the allow_missing flag. let mut disallow_missing = std::env::var("TANGRAM_LINKER_DISALLOW_MISSING").is_ok(); + // Get the identity. + let mut identity = std::env::var("TANGRAM_LINKER_IDENTITY") + .ok() + .map(|s| s.parse()) + .transpose() + .map_err(|source| tg::error!(!source, "invalid identity in TANGRAM_LINKER_IDENTITY"))?; + // Get the interpreter path. let interpreter_path = std::env::var("TANGRAM_LINKER_INTERPRETER_PATH") .ok() @@ -181,6 +191,13 @@ fn read_options() -> tg::Result { } else { tracing::warn!("Invalid max depth argument {option}. Using default."); } + } else if arg.starts_with("--tg-identity=") { + if let Some(current_identity) = identity { + tracing::warn!(?current_identity, "The --tg-identity argument is overwriting the identity set by TANGRAM_LINKER_IDENTITY."); + } + identity = Some(arg.strip_prefix("--tg-identity").unwrap().parse().map_err( + |source| tg::error!(!source, "invalid identity in --tg-identity argument"), + )?); } else if arg.starts_with("--tg-passthrough") { passthrough = true; } else if arg.starts_with("--tg-disallow-missing") { @@ -232,6 +249,7 @@ fn read_options() -> tg::Result { command_path, command_args, disallow_missing, + identity, interpreter_path, interpreter_args, injection_path, @@ -697,17 +715,35 @@ async fn create_manifest( let env = None; let args = None; - // Set the identity. If the interpreter flavor is Dyld, LdLinux, or LdMusl, use `Executable`, and otherwise use `Wrapper`. - let identity = match interpreter { - Some(ref interpreter) => match interpreter { - tangram_std::manifest::Interpreter::LdLinux(_) - | tangram_std::manifest::Interpreter::LdMusl(_) - | tangram_std::manifest::Interpreter::DyLd(_) => tangram_std::manifest::Identity::Executable, - tangram_std::manifest::Interpreter::Normal(_) => { - tangram_std::manifest::Identity::Wrapper + let identity = match options.identity { + // If identity is explicitly set + Some(identity) => { + match identity { + tangram_std::manifest::Identity::Executable + | tangram_std::manifest::Identity::Interpreter => { + // Both Executable and Interpreter require dynamic linking + if let Some(interpreter) = &interpreter { + if !interpreter.is_dynamic() { + return Err(tg::error!("cannot set the Interpreter identity for non-dynamically linked executables")); + } + } + + if matches!(identity, tangram_std::manifest::Identity::Interpreter) { + tracing::warn!("Using the requested Interpreter identity, which may not be what you intended."); + } + + identity + }, + tangram_std::manifest::Identity::Wrapper => identity, + } + }, + // Default identity based on interpreter type + None => match &interpreter { + Some(interpreter) if interpreter.is_dynamic() => { + tangram_std::manifest::Identity::Executable }, + _ => tangram_std::manifest::Identity::Wrapper, }, - None => tangram_std::manifest::Identity::Wrapper, }; // Create the manifest. diff --git a/packages/std/packages/std/manifest.rs b/packages/std/packages/std/manifest.rs index 27fc061f..c010c6e2 100644 --- a/packages/std/packages/std/manifest.rs +++ b/packages/std/packages/std/manifest.rs @@ -35,12 +35,38 @@ pub struct Manifest { pub args: Option>, } -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub enum Identity { - Wrapper, - Interpreter, Executable, + Interpreter, + Wrapper, +} + +impl std::str::FromStr for Identity { + type Err = std::io::Error; + + fn from_str(s: &str) -> Result { + match s.to_ascii_lowercase().as_str() { + "executable" => Ok(Identity::Executable), + "interpreter" => Ok(Identity::Interpreter), + "wrapper" => Ok(Identity::Wrapper), + _ => Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!("unrecognized identity: ${s}"), + )), + } + } +} + +impl std::fmt::Display for Identity { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Identity::Executable => write!(f, "executable"), + Identity::Interpreter => write!(f, "interpreter"), + Identity::Wrapper => write!(f, "wrapper"), + } + } } /// An interpreter is another program that is used to launch the executable. @@ -64,6 +90,16 @@ pub enum Interpreter { DyLd(DyLdInterpreter), } +impl Interpreter { + #[must_use] + pub fn is_dynamic(&self) -> bool { + matches!( + self, + Interpreter::LdLinux(_) | Interpreter::LdMusl(_) | Interpreter::DyLd(_) + ) + } +} + #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct NormalInterpreter { /// The path to the file to exec. diff --git a/packages/std/packages/wrapper/src/main.rs b/packages/std/packages/wrapper/src/main.rs index 1e25023b..1158c18e 100644 --- a/packages/std/packages/wrapper/src/main.rs +++ b/packages/std/packages/wrapper/src/main.rs @@ -66,8 +66,6 @@ fn main_inner() -> std::io::Result<()> { content_executable(&tangram_std::render_template_data(template)?)? }, }; - #[cfg(feature = "tracing")] - tracing::debug!(?executable_path); // Choose the identity path. let identity_path = match &manifest.identity { @@ -141,7 +139,6 @@ fn main_inner() -> std::io::Result<()> { tracing::trace!(?wrapper_args); command.args(wrapper_args); - // Exec the command. #[cfg(feature = "tracing")] tracing::trace!(?command); Err(command.exec()) @@ -154,6 +151,7 @@ fn clear_env() { /// Create a temporary file with the given contents and return the path to the file. fn content_executable(contents: &str) -> std::io::Result { + tracing::trace!("producing content executable."); let fd = unsafe { // Create a temporary file. let temp_path = c"/tmp/XXXXXX".to_owned(); @@ -197,11 +195,13 @@ fn content_executable(contents: &str) -> std::io::Result { ); return Err(std::io::Error::last_os_error()); } + fd }; // Create a path to the temporary file. - Ok(PathBuf::from(format!("/dev/fd/{fd}"))) + let path = PathBuf::from(format!("/dev/fd/{fd}")); + Ok(path) } #[allow(clippy::too_many_lines)] diff --git a/packages/std/sdk/cmake.tg.ts b/packages/std/sdk/cmake.tg.ts index 74c05c4d..ed5f2d14 100644 --- a/packages/std/sdk/cmake.tg.ts +++ b/packages/std/sdk/cmake.tg.ts @@ -7,13 +7,13 @@ export const metadata = { license: "BSD-3-Clause", name: "cmake", repository: "https://gitlab.kitware.com/cmake/cmake", - version: "3.31.3", + version: "3.31.4", }; export const source = tg.target(() => { const { version } = metadata; const checksum = - "sha256:fac45bc6d410b49b3113ab866074888d6c9e9dc81a141874446eb239ac38cb87"; + "sha256:a6130bfe75f5ba5c73e672e34359f7c0a1931521957e8393a5c2922c8b0f7f25"; const owner = "Kitware"; const repo = "CMake"; const tag = `v${version}`; diff --git a/packages/std/sdk/mold.tg.ts b/packages/std/sdk/mold.tg.ts index f650cfa6..e001d7dc 100644 --- a/packages/std/sdk/mold.tg.ts +++ b/packages/std/sdk/mold.tg.ts @@ -11,13 +11,13 @@ export const metadata = { license: "MIT", name: "mold", repository: "https://github.com/rui314/mold", - version: "2.35.1", + version: "2.36.0", }; export const source = tg.target(() => { const { name, version } = metadata; const checksum = - "sha256:912b90afe7fde03e53db08d85a62c7b03a57417e54afc72c08e2fa07cab421ff"; + "sha256:3f57fe75535500ecce7a80fa1ba33675830b7d7deb1e5ee9a737e2bc43cdb1c7"; const owner = "rui314"; const repo = name; const tag = `v${version}`; diff --git a/packages/std/tangram.ts b/packages/std/tangram.ts index 54332d25..4f72ccc6 100644 --- a/packages/std/tangram.ts +++ b/packages/std/tangram.ts @@ -72,6 +72,8 @@ const testActions = (): Record Promise> => { bootstrapMusl: bootstrap.musl.build, wrapArgAndEnvDump: wrap.argAndEnvDump, wrapBasic: wrap.testSingleArgObjectNoMutations, + wrapContent: wrap.testContentExecutable, + wrapContentVariadic: wrap.testContentExecutableVariadic, wrap: wrap.test, env: env.test, proxyBasic: sdk.proxy.testBasic, @@ -163,7 +165,15 @@ const testActions = (): Record Promise> => { }; /** A subset of all defined tests to run in the correct order. */ -const defaultTests = ["hostSystem", "triple", "certificates", "sdkDefault"]; +const defaultTests = [ + "hostSystem", + "triple", + "certificates", + "proxy", + "wrap", + "sdkDefault", + "dollar", +]; /** With no arguments, runs a set of default tests. Pass test names to run individual component tests. */ export const test = tg.target(async (...testNames: Array) => { diff --git a/packages/std/wrap.tg.ts b/packages/std/wrap.tg.ts index da5dbdc5..99bc88a0 100644 --- a/packages/std/wrap.tg.ts +++ b/packages/std/wrap.tg.ts @@ -130,10 +130,10 @@ export namespace wrap { identity?: Identity; /** The interpreter to run the executable with. If not provided, a default is detected. */ - interpreter?: tg.File | tg.Symlink | Interpreter; + interpreter?: tg.File | tg.Symlink | tg.Template | Interpreter; /** Library paths to include. If the executable is wrapped, they will be merged. */ - libraryPaths?: Array; + libraryPaths?: Array; /** Specify how to handle executables that are already Tangram wrappers. When `merge` is true, retain the original executable in the resulting manifest. When `merge` is set to false, produce a manifest pointing to the original wrapper. This option is ignored if the executable being wrapped is not a Tangram wrapper. Default: true. */ merge?: boolean; @@ -216,10 +216,9 @@ export namespace wrap { return { executable: arg }; } else if (typeof arg === "string" || arg instanceof tg.Template) { // This is a "content" executable. - const defaultShell = await defaultShellInterpreter(); return { - identity: "executable" as const, - interpreter: defaultShell, + identity: "wrapper" as const, + interpreter: await wrap.defaultShell(), executable: arg, }; } else if (isArgObject(arg)) { @@ -249,6 +248,8 @@ export namespace wrap { libraryPaths, } = await std.args.applyMutations(mutationArgs); + tg.assert(executable !== undefined); + // If the executable arg is a wrapper, obtain its manifest. const existingManifest = await wrap.existingManifestFromExecutableArg(executable); @@ -284,6 +285,21 @@ export namespace wrap { const env = await std.env.arg(...env_); + // If the executable is a content executable, make sure there is a normal interpreter for it and sensible identity. + if (executable instanceof tg.Template || typeof executable === "string") { + if (interpreter === undefined) { + interpreter = await wrap.defaultShell(); + } + if (identity === undefined) { + identity = "interpreter" as const; + } + if (identity === "executable") { + throw new Error( + "cannot use the executable identity with content executables, select interpreter or wrapper", + ); + } + } + return { args: args_, buildToolchain, @@ -297,6 +313,81 @@ export namespace wrap { }; }; + export type DefaultShellArg = { + /** The toolchain to use to build constituent components. Default: `std.sdk()`. */ + buildToolchain?: std.env.Arg; + /** Should scripts treat unset variables as errors? Equivalent to setting `-u`. Default: true. */ + disallowUnset?: boolean; + /** Should scripts exit on errors? Equivalent to setting `-e`. Default: true. */ + exitOnErr?: boolean; + /** Which identity should we use for the shell? Default: "wrapper". */ + identity?: "interpreter" | "wrapper"; + /** Whether to incldue the complete `std.utils()` environment. Default: true. */ + includeUtils?: boolean; + /** Should failures inside pipelines cause the whole pipeline to fail? Equivalent to setting `-o pipefail`. Default: true. */ + pipefail?: boolean; + }; + + /** Helper to configure a `bash` executable to use as the interpreter for content executables. */ + export const defaultShell = async (arg?: DefaultShellArg) => { + const { + buildToolchain: buildToolchain_, + disallowUnset = true, + exitOnErr = true, + identity = "wrapper", + includeUtils = true, + pipefail = true, + } = arg ?? {}; + + // Provide bash for the detected host system. + let buildArg: + | undefined + | { sdk: boolean; env: tg.Unresolved } = undefined; + if (buildToolchain_) { + buildArg = { sdk: false, env: buildToolchain_ }; + } else { + buildArg = { sdk: false, env: std.sdk() }; + } + const shellExecutable = await std.utils.bash + .build(buildArg) + .then((artifact) => artifact.get("bin/bash")) + .then(tg.File.expect); + + const wrapArgs: Array = [ + { + executable: shellExecutable, + identity, + }, + ]; + if (buildToolchain_ !== undefined) { + wrapArgs.push({ buildToolchain: buildToolchain_ }); + } + + // Set up args. + const args: Array = []; + if (disallowUnset) { + args.push("-u"); + } + if (exitOnErr) { + args.push("-e"); + } + if (pipefail) { + args.push("-o"); + args.push("pipefail"); + } + if (args.length > 0) { + wrapArgs.push({ args }); + } + + // Add utils. + if (includeUtils) { + wrapArgs.push({ env: await std.utils.env(buildArg) }); + } + + // Produce wrapped shell. + return wrap(...wrapArgs); + }; + export const envArgFromManifestEnv = async ( mutation: wrap.Manifest.Mutation | undefined, ): Promise => { @@ -708,6 +799,7 @@ const isArgObject = (arg: unknown): arg is wrap.ArgObject => { ); }; +/** The magic number is `tangram\0`. */ const MANIFEST_MAGIC_NUMBER: Uint8Array = new Uint8Array([ 116, 97, 110, 103, 114, 97, 109, 0, ]); @@ -749,7 +841,12 @@ const isManifestExecutable = ( }; const manifestInterpreterFromArg = async ( - arg: tg.File | tg.Symlink | wrap.Interpreter | wrap.Manifest.Interpreter, + arg: + | tg.File + | tg.Symlink + | tg.Template + | wrap.Interpreter + | wrap.Manifest.Interpreter, buildToolchainArg?: std.env.Arg, ): Promise => { if (isManifestInterpreter(arg)) { @@ -757,7 +854,11 @@ const manifestInterpreterFromArg = async ( } // If the arg is an executable, then wrap it and create a normal interpreter. - if (arg instanceof tg.File || arg instanceof tg.Symlink) { + if ( + arg instanceof tg.File || + arg instanceof tg.Symlink || + arg instanceof tg.Template + ) { const interpreter = await std.wrap({ buildToolchain: buildToolchainArg, executable: arg, @@ -1003,7 +1104,7 @@ const manifestInterpreterFromExecutableArg = async ( case "shebang": { if (metadata.interpreter === undefined) { return manifestInterpreterFromArg( - await defaultShellInterpreter(buildToolchainArg), + await wrap.defaultShell({ buildToolchain: buildToolchainArg }), buildToolchainArg, ); } else { @@ -1078,33 +1179,6 @@ const manifestInterpreterFromElf = async ( } }; -export const defaultShellInterpreter = async ( - buildToolchainArg?: std.env.Arg, -) => { - // Provide bash for the detected host system. - let buildArg: undefined | { sdk: boolean; env: tg.Unresolved } = - undefined; - if (buildToolchainArg) { - buildArg = { sdk: false, env: buildToolchainArg }; - } else { - buildArg = { sdk: false, env: std.sdk() }; - } - const shellArtifact = await std.utils.bash.build(buildArg); - const shellExecutable = tg.File.expect(await shellArtifact.get("bin/bash")); - - // Add the standard utils. - const env = await std.utils.env(buildArg); - - const bash = wrap({ - buildToolchain: buildToolchainArg, - executable: shellExecutable, - identity: "wrapper", - args: ["-euo", "pipefail"], - env, - }); - return bash; -}; - const valueIsTemplateLike = ( value: tg.Value, ): value is string | tg.Template | tg.Artifact => { @@ -1622,6 +1696,8 @@ export const test = tg.target(async () => { testSingleArgObjectNoMutations(), testDependencies(), testDylibPath(), + testContentExecutable(), + testContentExecutableVariadic(), ]); return true; }); @@ -1711,6 +1787,55 @@ export const testSingleArgObjectNoMutations = tg.target(async () => { return wrapper; }); +export const testContentExecutable = tg.target(async () => { + const buildToolchain = bootstrap.sdk(); + const wrapper = await std.wrap({ + buildToolchain, + executable: `echo $NAME`, + env: { + NAME: "Tangram", + }, + }); + + console.log("wrapper", await wrapper.id()); + // Check the output matches the expected output. + const output = await tg + .target(tg`set -x; ${wrapper} > $OUTPUT`, { + env: { TANGRAM_WRAPPER_TRACING: "tangram=trace" }, + }) + .then((target) => target.output()) + .then(tg.File.expect); + const text = await output.text().then((t) => t.trim()); + console.log("text", text); + tg.assert(text.includes("Tangram")); + + return true; +}); + +export const testContentExecutableVariadic = tg.target(async () => { + const buildToolchain = bootstrap.sdk(); + const wrapper = await std.wrap( + `echo "$NAME"`, + { env: { NAME: "Tangram" } }, + { + buildToolchain, + }, + ); + console.log("wrapper", await wrapper.id()); + // Check the output matches the expected output. + const output = await tg + .target(tg`set -x; ${wrapper} > $OUTPUT`, { + env: { TANGRAM_WRAPPER_TRACING: "tangram=trace" }, + }) + .then((target) => target.output()) + .then(tg.File.expect); + const text = await output.text().then((t) => t.trim()); + console.log("text", text); + tg.assert(text.includes("Tangram")); + + return true; +}); + export const testDependencies = tg.target(async () => { const buildToolchain = await bootstrap.sdk.env(); const transitiveDependency = await tg.file("I'm a transitive reference"); diff --git a/packages/vim/tangram.ts b/packages/vim/tangram.ts index dff7dd85..9fe82b63 100644 --- a/packages/vim/tangram.ts +++ b/packages/vim/tangram.ts @@ -71,7 +71,7 @@ export const default_ = tg.target(async (...args: std.Args) => { export default default_; export const test = tg.target(async () => { - const majorMinor = metadata.version.split(".").slice(0,2).join("."); + const majorMinor = metadata.version.split(".").slice(0, 2).join("."); await std.assert.pkg({ buildFn: default_, binaries: [ diff --git a/packages/wget/tangram.ts b/packages/wget/tangram.ts index 39dcb5a7..4b6e18ba 100644 --- a/packages/wget/tangram.ts +++ b/packages/wget/tangram.ts @@ -119,7 +119,8 @@ export const test = tg.target(async () => { wget -O $OUTPUT/tangram.svg https://www.tangram.dev/tangram.svg ` .env(default_()) - .checksum("unsafe"); + .checksum("unsafe") + .then(tg.Directory.expect); const exampleContents = await result .get("example") diff --git a/packages/xz/tangram.ts b/packages/xz/tangram.ts index 5353a1a4..04343683 100644 --- a/packages/xz/tangram.ts +++ b/packages/xz/tangram.ts @@ -11,7 +11,7 @@ export const source = tg.target(async () => { const extension = ".tar.gz"; const checksum = "sha256:b1d45295d3f71f25a4c9101bd7c8d16cb56348bbef3bbc738da0351e17c73317"; - const base = `https://github.com/tukaani-project/xz/releases/download/v${version}` + const base = `https://github.com/tukaani-project/xz/releases/download/v${version}`; return await std .download({ base, checksum, name, version, extension }) .then(tg.Directory.expect)