@git.zone/tsrust 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/tsrust',
6
- version: '1.2.0',
6
+ version: '1.3.0',
7
7
  description: 'A tool for compiling Rust projects, detecting Cargo workspaces, building with cargo, and placing binaries in a conventional dist_rust directory.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLGtKQUFrSjtDQUNoSyxDQUFBIn0=
@@ -1,3 +1,4 @@
1
1
  export * from './mod_fs/index.js';
2
2
  export * from './mod_cargo/index.js';
3
3
  export * from './mod_cli/index.js';
4
+ export * from './mod_toolchain/index.js';
package/dist_ts/index.js CHANGED
@@ -3,5 +3,6 @@ plugins.early.start('@git.zone/tsrust');
3
3
  export * from './mod_fs/index.js';
4
4
  export * from './mod_cargo/index.js';
5
5
  export * from './mod_cli/index.js';
6
+ export * from './mod_toolchain/index.js';
6
7
  plugins.early.stop();
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBRXhDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLG9CQUFvQixDQUFDO0FBRW5DLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMifQ==
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBRXhDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsMEJBQTBCLENBQUM7QUFFekMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyJ9
@@ -6,7 +6,8 @@ export interface ICargoRunResult {
6
6
  export declare class CargoRunner {
7
7
  private shell;
8
8
  private rustDir;
9
- constructor(rustDir: string);
9
+ private envPrefix;
10
+ constructor(rustDir: string, envPrefix?: string);
10
11
  checkCargoInstalled(): Promise<boolean>;
11
12
  getCargoVersion(): Promise<string>;
12
13
  build(options?: {
@@ -2,18 +2,20 @@ import * as plugins from '../plugins.js';
2
2
  export class CargoRunner {
3
3
  shell;
4
4
  rustDir;
5
- constructor(rustDir) {
5
+ envPrefix;
6
+ constructor(rustDir, envPrefix = '') {
6
7
  this.rustDir = rustDir;
8
+ this.envPrefix = envPrefix;
7
9
  this.shell = new plugins.smartshell.Smartshell({
8
10
  executor: 'bash',
9
11
  });
10
12
  }
11
13
  async checkCargoInstalled() {
12
- const result = await this.shell.execSilent('cargo --version');
14
+ const result = await this.shell.execSilent(`${this.envPrefix}cargo --version`);
13
15
  return result.exitCode === 0;
14
16
  }
15
17
  async getCargoVersion() {
16
- const result = await this.shell.execSilent('cargo --version');
18
+ const result = await this.shell.execSilent(`${this.envPrefix}cargo --version`);
17
19
  return result.stdout.trim();
18
20
  }
19
21
  async build(options = {}) {
@@ -26,7 +28,7 @@ export class CargoRunner {
26
28
  }
27
29
  const profile = options.debug ? '' : ' --release';
28
30
  const targetFlag = options.target ? ` --target ${options.target}` : '';
29
- const command = `cd ${this.rustDir} && cargo build${profile}${targetFlag}`;
31
+ const command = `${this.envPrefix}cd ${this.rustDir} && cargo build${profile}${targetFlag}`;
30
32
  console.log(`Running: cargo build${profile}${targetFlag}`);
31
33
  const result = await this.shell.exec(command);
32
34
  return {
@@ -39,19 +41,19 @@ export class CargoRunner {
39
41
  * Ensures a rustup target is installed. If not present, installs it via `rustup target add`.
40
42
  */
41
43
  async ensureTarget(triple) {
42
- const listResult = await this.shell.execSilent('rustup target list --installed');
44
+ const listResult = await this.shell.execSilent(`${this.envPrefix}rustup target list --installed`);
43
45
  const installedTargets = listResult.stdout.split('\n').map((l) => l.trim());
44
46
  if (installedTargets.includes(triple)) {
45
47
  return;
46
48
  }
47
49
  console.log(`Installing rustup target: ${triple}`);
48
- const addResult = await this.shell.exec(`rustup target add ${triple}`);
50
+ const addResult = await this.shell.exec(`${this.envPrefix}rustup target add ${triple}`);
49
51
  if (addResult.exitCode !== 0) {
50
52
  throw new Error(`Failed to install rustup target ${triple}`);
51
53
  }
52
54
  }
53
55
  async clean() {
54
- const command = `cd ${this.rustDir} && cargo clean`;
56
+ const command = `${this.envPrefix}cd ${this.rustDir} && cargo clean`;
55
57
  const result = await this.shell.exec(command);
56
58
  return {
57
59
  success: result.exitCode === 0,
@@ -60,4 +62,4 @@ export class CargoRunner {
60
62
  };
61
63
  }
62
64
  }
63
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jYXJnb3J1bm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9jYXJnby9jbGFzc2VzLmNhcmdvcnVubmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBUXpDLE1BQU0sT0FBTyxXQUFXO0lBQ2QsS0FBSyxDQUFnQztJQUNyQyxPQUFPLENBQVM7SUFFeEIsWUFBWSxPQUFlO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztZQUM3QyxRQUFRLEVBQUUsTUFBTTtTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLG1CQUFtQjtRQUM5QixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDOUQsT0FBTyxNQUFNLENBQUMsUUFBUSxLQUFLLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRU0sS0FBSyxDQUFDLGVBQWU7UUFDMUIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzlELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFpRSxFQUFFO1FBQ3BGLElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2xCLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLENBQUMsQ0FBQztZQUMxQyxNQUFNLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNyQixDQUFDO1FBRUQsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbkIsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUM7UUFDbEQsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsYUFBYSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN2RSxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLGtCQUFrQixPQUFPLEdBQUcsVUFBVSxFQUFFLENBQUM7UUFFM0UsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsT0FBTyxHQUFHLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDM0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU5QyxPQUFPO1lBQ0wsT0FBTyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEtBQUssQ0FBQztZQUM5QixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVE7WUFDekIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1NBQ3RCLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQWM7UUFDdEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBQ2pGLE1BQU0sZ0JBQWdCLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM1RSxJQUFJLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE9BQU87UUFDVCxDQUFDO1FBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNuRCxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLHFCQUFxQixNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksU0FBUyxDQUFDLFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLG1DQUFtQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUs7UUFDaEIsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxpQkFBaUIsQ0FBQztRQUNwRCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTlDLE9BQU87WUFDTCxPQUFPLEVBQUUsTUFBTSxDQUFDLFFBQVEsS0FBSyxDQUFDO1lBQzlCLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtZQUN6QixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07U0FDdEIsQ0FBQztJQUNKLENBQUM7Q0FDRiJ9
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jYXJnb3J1bm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9jYXJnby9jbGFzc2VzLmNhcmdvcnVubmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBUXpDLE1BQU0sT0FBTyxXQUFXO0lBQ2QsS0FBSyxDQUFnQztJQUNyQyxPQUFPLENBQVM7SUFDaEIsU0FBUyxDQUFTO0lBRTFCLFlBQVksT0FBZSxFQUFFLFlBQW9CLEVBQUU7UUFDakQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDM0IsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1lBQzdDLFFBQVEsRUFBRSxNQUFNO1NBQ2pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsbUJBQW1CO1FBQzlCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxpQkFBaUIsQ0FBQyxDQUFDO1FBQy9FLE9BQU8sTUFBTSxDQUFDLFFBQVEsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVNLEtBQUssQ0FBQyxlQUFlO1FBQzFCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxpQkFBaUIsQ0FBQyxDQUFDO1FBQy9FLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFpRSxFQUFFO1FBQ3BGLElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2xCLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLENB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
@@ -4,6 +4,12 @@ export declare class TsRustCli {
4
4
  private config;
5
5
  constructor(cwd?: string);
6
6
  private registerCommands;
7
+ /**
8
+ * Resolves the Rust toolchain to use. Tries system cargo first,
9
+ * then falls back to a bundled toolchain at /tmp/tsrust_toolchain/.
10
+ * Returns the envPrefix string to prepend to shell commands.
11
+ */
12
+ private resolveToolchain;
7
13
  private registerStandardCommand;
8
14
  private registerCleanCommand;
9
15
  private detectRustDir;
@@ -3,6 +3,7 @@ import * as plugins from '../plugins.js';
3
3
  import { CargoConfig } from '../mod_cargo/index.js';
4
4
  import { CargoRunner } from '../mod_cargo/index.js';
5
5
  import { FsHelpers } from '../mod_fs/index.js';
6
+ import { ToolchainManager } from '../mod_toolchain/index.js';
6
7
  /** Maps friendly target names to Rust target triples */
7
8
  const targetAliasMap = {
8
9
  linux_amd64: 'x86_64-unknown-linux-gnu',
@@ -50,16 +51,29 @@ export class TsRustCli {
50
51
  this.registerStandardCommand();
51
52
  this.registerCleanCommand();
52
53
  }
54
+ /**
55
+ * Resolves the Rust toolchain to use. Tries system cargo first,
56
+ * then falls back to a bundled toolchain at /tmp/tsrust_toolchain/.
57
+ * Returns the envPrefix string to prepend to shell commands.
58
+ */
59
+ async resolveToolchain() {
60
+ // 1. Try system cargo
61
+ const systemRunner = new CargoRunner(this.cwd);
62
+ if (await systemRunner.checkCargoInstalled()) {
63
+ return ''; // system toolchain, no prefix needed
64
+ }
65
+ // 2. Fall back to bundled toolchain
66
+ console.log('System cargo not found. Checking for bundled toolchain...');
67
+ const toolchain = new ToolchainManager();
68
+ await toolchain.ensureInstalled();
69
+ return toolchain.getEnvPrefix();
70
+ }
53
71
  registerStandardCommand() {
54
72
  this.cli.standardCommand().subscribe(async (argvArg) => {
55
73
  const startTime = Date.now();
56
- // Check cargo is installed
57
- const runner = new CargoRunner(this.cwd); // temporary, just for version check
58
- if (!(await runner.checkCargoInstalled())) {
59
- console.error('Error: cargo is not installed or not in PATH.');
60
- console.error('Install Rust via https://rustup.rs/');
61
- process.exit(1);
62
- }
74
+ // Resolve toolchain (system or bundled fallback)
75
+ const envPrefix = await this.resolveToolchain();
76
+ const runner = new CargoRunner(this.cwd, envPrefix);
63
77
  const cargoVersion = await runner.getCargoVersion();
64
78
  console.log(`Using ${cargoVersion}`);
65
79
  // Detect rust directory
@@ -99,7 +113,7 @@ export class TsRustCli {
99
113
  await FsHelpers.ensureEmptyDir(distDir);
100
114
  for (const { triple, friendly } of resolvedTargets) {
101
115
  console.log(`\n--- Building for ${friendly} (${triple}) ---`);
102
- const cargoRunner = new CargoRunner(rustDir);
116
+ const cargoRunner = new CargoRunner(rustDir, envPrefix);
103
117
  const buildResult = await cargoRunner.build({ debug: isDebug, clean: shouldClean, target: triple });
104
118
  if (!buildResult.success) {
105
119
  console.error(`Build failed for target ${triple} with exit code ${buildResult.exitCode}`);
@@ -127,8 +141,8 @@ export class TsRustCli {
127
141
  }
128
142
  }
129
143
  else {
130
- // Native build (unchanged behavior)
131
- const cargoRunner = new CargoRunner(rustDir);
144
+ // Native build
145
+ const cargoRunner = new CargoRunner(rustDir, envPrefix);
132
146
  const buildResult = await cargoRunner.build({ debug: isDebug, clean: shouldClean });
133
147
  if (!buildResult.success) {
134
148
  console.error(`Build failed with exit code ${buildResult.exitCode}`);
@@ -158,8 +172,9 @@ export class TsRustCli {
158
172
  // Clean cargo build
159
173
  const rustDir = await this.detectRustDir();
160
174
  if (rustDir) {
175
+ const envPrefix = await this.resolveToolchain();
161
176
  console.log('Running cargo clean...');
162
- const runner = new CargoRunner(rustDir);
177
+ const runner = new CargoRunner(rustDir, envPrefix);
163
178
  await runner.clean();
164
179
  console.log('Cargo clean complete.');
165
180
  }
@@ -193,4 +208,4 @@ export const runCli = async () => {
193
208
  const cli = new TsRustCli();
194
209
  cli.run();
195
210
  };
196
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy50c3J1c3RjbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfY2xpL2NsYXNzZXMudHNydXN0Y2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRS9DLHdEQUF3RDtBQUN4RCxNQUFNLGNBQWMsR0FBMkI7SUFDN0MsV0FBVyxFQUFFLDBCQUEwQjtJQUN2QyxXQUFXLEVBQUUsMkJBQTJCO0lBQ3hDLGdCQUFnQixFQUFFLDJCQUEyQjtJQUM3QyxnQkFBZ0IsRUFBRSw0QkFBNEI7SUFDOUMsV0FBVyxFQUFFLHFCQUFxQjtJQUNsQyxXQUFXLEVBQUUsc0JBQXNCO0NBQ3BDLENBQUM7QUFFRiwrQ0FBK0M7QUFDL0MsTUFBTSxtQkFBbUIsR0FBMkIsRUFBRSxDQUFDO0FBQ3ZELEtBQUssTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7SUFDaEUsbUJBQW1CLENBQUMsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDO0FBQ3pDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGtCQUFrQixDQUFDLElBQVk7SUFDdEMsT0FBTyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDO0FBQ3RDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLFlBQVksQ0FBQyxNQUFjO0lBQ2xDLElBQUksbUJBQW1CLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUNoQyxPQUFPLG1CQUFt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
211
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy50c3J1c3RjbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfY2xpL2NsYXNzZXMudHNydXN0Y2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRTdELHdEQUF3RDtBQUN4RCxNQUFNLGNBQWMsR0FBMkI7SUFDN0MsV0FBVyxFQUFFLDBCQUEwQjtJQUN2QyxXQUFXLEVBQUUsMkJBQTJCO0lBQ3hDLGdCQUFnQixFQUFFLDJCQUEyQjtJQUM3QyxnQkFBZ0IsRUFBRSw0QkFBNEI7SUFDOUMsV0FBVyxFQUFFLHFCQUFxQjtJQUNsQyxXQUFXLEVBQUUsc0JBQXNCO0NBQ3BDLENBQUM7QUFFRiwrQ0FBK0M7QUFDL0MsTUFBTSxtQkFBbUIsR0FBMkIsRUFBRSxDQUFDO0FBQ3ZELEtBQUssTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7SUFDaEUsbUJBQW1CLENBQUMsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDO0FBQ3pDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGtCQUFrQixDQUFDLElBQVk7SUFDdEMsT0FBTyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDO0FBQ3RDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLFlBQVksQ0FBQyxNQUFjO0lBQ2xDLElBQUksbUJB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
@@ -0,0 +1,29 @@
1
+ export declare class ToolchainManager {
2
+ static TOOLCHAIN_DIR: string;
3
+ static RUSTUP_HOME: string;
4
+ static CARGO_HOME: string;
5
+ static BIN_DIR: string;
6
+ private shell;
7
+ constructor();
8
+ /**
9
+ * Returns the Rust host triple for the current platform.
10
+ */
11
+ getHostTriple(): string;
12
+ /**
13
+ * Checks if the bundled toolchain is already installed at TOOLCHAIN_DIR.
14
+ */
15
+ isInstalled(): Promise<boolean>;
16
+ /**
17
+ * Downloads rustup-init and installs a minimal Rust toolchain to TOOLCHAIN_DIR.
18
+ */
19
+ install(): Promise<void>;
20
+ /**
21
+ * Ensures the bundled toolchain is installed. Downloads if not present.
22
+ */
23
+ ensureInstalled(): Promise<void>;
24
+ /**
25
+ * Returns a shell prefix string that sets RUSTUP_HOME, CARGO_HOME, and PATH
26
+ * to point at the bundled toolchain. Prepend this to any shell command.
27
+ */
28
+ getEnvPrefix(): string;
29
+ }
@@ -0,0 +1,101 @@
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import * as plugins from '../plugins.js';
5
+ export class ToolchainManager {
6
+ static TOOLCHAIN_DIR = '/tmp/tsrust_toolchain';
7
+ static RUSTUP_HOME = '/tmp/tsrust_toolchain/rustup';
8
+ static CARGO_HOME = '/tmp/tsrust_toolchain/cargo';
9
+ static BIN_DIR = '/tmp/tsrust_toolchain/cargo/bin';
10
+ shell;
11
+ constructor() {
12
+ this.shell = new plugins.smartshell.Smartshell({
13
+ executor: 'bash',
14
+ });
15
+ }
16
+ /**
17
+ * Returns the Rust host triple for the current platform.
18
+ */
19
+ getHostTriple() {
20
+ const platform = os.platform();
21
+ const arch = os.arch();
22
+ if (platform === 'linux' && arch === 'x64')
23
+ return 'x86_64-unknown-linux-gnu';
24
+ if (platform === 'linux' && arch === 'arm64')
25
+ return 'aarch64-unknown-linux-gnu';
26
+ if (platform === 'darwin' && arch === 'x64')
27
+ return 'x86_64-apple-darwin';
28
+ if (platform === 'darwin' && arch === 'arm64')
29
+ return 'aarch64-apple-darwin';
30
+ throw new Error(`Unsupported platform: ${platform}/${arch}. Please install Rust manually via https://rustup.rs/`);
31
+ }
32
+ /**
33
+ * Checks if the bundled toolchain is already installed at TOOLCHAIN_DIR.
34
+ */
35
+ async isInstalled() {
36
+ const cargoPath = path.join(ToolchainManager.BIN_DIR, 'cargo');
37
+ try {
38
+ const stat = await fs.promises.stat(cargoPath);
39
+ return stat.isFile();
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ /**
46
+ * Downloads rustup-init and installs a minimal Rust toolchain to TOOLCHAIN_DIR.
47
+ */
48
+ async install() {
49
+ const triple = this.getHostTriple();
50
+ const rustupInitUrl = `https://static.rust-lang.org/rustup/dist/${triple}/rustup-init`;
51
+ const rustupInitPath = path.join(ToolchainManager.TOOLCHAIN_DIR, 'rustup-init');
52
+ // Ensure toolchain directory exists
53
+ await fs.promises.mkdir(ToolchainManager.TOOLCHAIN_DIR, { recursive: true });
54
+ console.log(`Downloading rustup-init for ${triple}...`);
55
+ const downloadResult = await this.shell.exec(`curl -sSf -o ${rustupInitPath} ${rustupInitUrl} && chmod +x ${rustupInitPath}`);
56
+ if (downloadResult.exitCode !== 0) {
57
+ throw new Error(`Failed to download rustup-init: ${downloadResult.stdout}`);
58
+ }
59
+ console.log('Installing minimal Rust toolchain to /tmp/tsrust_toolchain/...');
60
+ const installCmd = [
61
+ `RUSTUP_HOME="${ToolchainManager.RUSTUP_HOME}"`,
62
+ `CARGO_HOME="${ToolchainManager.CARGO_HOME}"`,
63
+ rustupInitPath,
64
+ '-y',
65
+ '--default-toolchain stable',
66
+ '--profile minimal',
67
+ '--no-modify-path',
68
+ ].join(' ');
69
+ const installResult = await this.shell.exec(installCmd);
70
+ if (installResult.exitCode !== 0) {
71
+ throw new Error(`Failed to install Rust toolchain: ${installResult.stdout}`);
72
+ }
73
+ // Verify installation
74
+ const verifyResult = await this.shell.execSilent(`${this.getEnvPrefix()}cargo --version`);
75
+ if (verifyResult.exitCode !== 0) {
76
+ throw new Error('Rust toolchain installation verification failed.');
77
+ }
78
+ console.log(`Installed: ${verifyResult.stdout.trim()}`);
79
+ // Clean up rustup-init binary
80
+ await fs.promises.unlink(rustupInitPath).catch(() => { });
81
+ }
82
+ /**
83
+ * Ensures the bundled toolchain is installed. Downloads if not present.
84
+ */
85
+ async ensureInstalled() {
86
+ if (await this.isInstalled()) {
87
+ console.log('Using bundled Rust toolchain from /tmp/tsrust_toolchain/');
88
+ return;
89
+ }
90
+ await this.install();
91
+ }
92
+ /**
93
+ * Returns a shell prefix string that sets RUSTUP_HOME, CARGO_HOME, and PATH
94
+ * to point at the bundled toolchain. Prepend this to any shell command.
95
+ */
96
+ getEnvPrefix() {
97
+ return (`export RUSTUP_HOME="${ToolchainManager.RUSTUP_HOME}" CARGO_HOME="${ToolchainManager.CARGO_HOME}" && ` +
98
+ `export PATH="${ToolchainManager.BIN_DIR}:$PATH" && `);
99
+ }
100
+ }
101
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy50b29sY2hhaW5tYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbW9kX3Rvb2xjaGFpbi9jbGFzc2VzLnRvb2xjaGFpbm1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFFekMsTUFBTSxPQUFPLGdCQUFnQjtJQUNwQixNQUFNLENBQUMsYUFBYSxHQUFHLHVCQUF1QixDQUFDO0lBQy9DLE1BQU0sQ0FBQyxXQUFXLEdBQUcsOEJBQThCLENBQUM7SUFDcEQsTUFBTSxDQUFDLFVBQVUsR0FBRyw2QkFBNkIsQ0FBQztJQUNsRCxNQUFNLENBQUMsT0FBTyxHQUFHLGlDQUFpQyxDQUFDO0lBRWxELEtBQUssQ0FBZ0M7SUFFN0M7UUFDRSxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7WUFDN0MsUUFBUSxFQUFFLE1BQU07U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ksYUFBYTtRQUNsQixNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDL0IsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1FBRXZCLElBQUksUUFBUSxLQUFLLE9BQU8sSUFBSSxJQUFJLEtBQUssS0FBSztZQUFFLE9BQU8sMEJBQTBCLENBQUM7UUFDOUUsSUFBSSxRQUFRLEtBQUssT0FBTyxJQUFJLElBQUksS0FBSyxPQUFPO1lBQUUsT0FBTywyQkFBMkIsQ0FBQztRQUNqRixJQUFJLFFBQVEsS0FBSyxRQUFRLElBQUksSUFBSSxLQUFLLEtBQUs7WUFB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
@@ -0,0 +1 @@
1
+ export * from './classes.toolchainmanager.js';
@@ -0,0 +1,2 @@
1
+ export * from './classes.toolchainmanager.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfdG9vbGNoYWluL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsK0JBQStCLENBQUMifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@git.zone/tsrust",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "private": false,
5
5
  "description": "A tool for compiling Rust projects, detecting Cargo workspaces, building with cargo, and placing binaries in a conventional dist_rust directory.",
6
6
  "main": "dist_ts/index.js",
@@ -35,7 +35,7 @@
35
35
  "dependencies": {
36
36
  "@push.rocks/early": "^4.0.4",
37
37
  "@push.rocks/npmextra": "^5.3.3",
38
- "@push.rocks/smartcli": "^4.0.19",
38
+ "@push.rocks/smartcli": "^4.0.20",
39
39
  "@push.rocks/smartfile": "^13.1.2",
40
40
  "@push.rocks/smartpath": "^6.0.0",
41
41
  "@push.rocks/smartshell": "^3.0.6",
@@ -45,7 +45,7 @@
45
45
  "@git.zone/tsbuild": "^4.1.2",
46
46
  "@git.zone/tsrun": "^2.0.1",
47
47
  "@git.zone/tstest": "^3.1.4",
48
- "@types/node": "^22.15.0"
48
+ "@types/node": "^25.2.2"
49
49
  },
50
50
  "files": [
51
51
  "ts/**/*",
package/readme.md CHANGED
@@ -20,7 +20,7 @@ Or as a project-level dev dependency:
20
20
  pnpm install --save-dev @git.zone/tsrust
21
21
  ```
22
22
 
23
- > ⚡ **Prerequisite:** You need a working Rust toolchain. Install via [rustup.rs](https://rustup.rs/) if you haven't already.
23
+ > ⚡ **No Rust required!** If `cargo` isn't found on your system, `tsrust` automatically downloads and installs a minimal Rust toolchain to `/tmp/tsrust_toolchain/`. This gives a zero-setup experience. If you already have Rust installed, `tsrust` uses your system toolchain.
24
24
 
25
25
  ## The Convention
26
26
 
@@ -44,7 +44,7 @@ tsrust
44
44
  ```
45
45
 
46
46
  This will:
47
- 1. Verify that `cargo` is available
47
+ 1. Detect the Rust toolchain (system `cargo`, or auto-install to `/tmp/tsrust_toolchain/`)
48
48
  2. Locate your `rust/` directory (containing `Cargo.toml`)
49
49
  3. Parse the workspace to discover all `[[bin]]` targets
50
50
  4. Run `cargo build --release` with full streaming output
@@ -65,6 +65,18 @@ Copied rustproxy (13.4 MB) -> dist_rust/rustproxy
65
65
  Done in 29.2s
66
66
  ```
67
67
 
68
+ ### Automatic Rust Toolchain
69
+
70
+ `tsrust` provides a zero-setup experience through automatic toolchain management:
71
+
72
+ 1. **System toolchain detected** → uses it as-is (no download, no overhead)
73
+ 2. **No system toolchain** → checks `/tmp/tsrust_toolchain/` for a previously installed bundled toolchain
74
+ 3. **No bundled toolchain** → downloads `rustup-init` and installs a minimal Rust toolchain (~70-90 MB download) to `/tmp/tsrust_toolchain/`
75
+
76
+ The bundled toolchain is stored in `/tmp/`, so it's cleaned up on reboot. Subsequent runs reuse the existing installation. This is ideal for CI environments and quick starts where you don't want to manage a system-wide Rust install.
77
+
78
+ Supported platforms for automatic install: Linux (x64, arm64) and macOS (x64, arm64).
79
+
68
80
  ### 🐛 Debug Build
69
81
 
70
82
  Build with the debug profile instead of release:
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/tsrust',
6
- version: '1.2.0',
6
+ version: '1.3.0',
7
7
  description: 'A tool for compiling Rust projects, detecting Cargo workspaces, building with cargo, and placing binaries in a conventional dist_rust directory.'
8
8
  }
package/ts/index.ts CHANGED
@@ -4,5 +4,6 @@ plugins.early.start('@git.zone/tsrust');
4
4
  export * from './mod_fs/index.js';
5
5
  export * from './mod_cargo/index.js';
6
6
  export * from './mod_cli/index.js';
7
+ export * from './mod_toolchain/index.js';
7
8
 
8
9
  plugins.early.stop();
@@ -9,21 +9,23 @@ export interface ICargoRunResult {
9
9
  export class CargoRunner {
10
10
  private shell: plugins.smartshell.Smartshell;
11
11
  private rustDir: string;
12
+ private envPrefix: string;
12
13
 
13
- constructor(rustDir: string) {
14
+ constructor(rustDir: string, envPrefix: string = '') {
14
15
  this.rustDir = rustDir;
16
+ this.envPrefix = envPrefix;
15
17
  this.shell = new plugins.smartshell.Smartshell({
16
18
  executor: 'bash',
17
19
  });
18
20
  }
19
21
 
20
22
  public async checkCargoInstalled(): Promise<boolean> {
21
- const result = await this.shell.execSilent('cargo --version');
23
+ const result = await this.shell.execSilent(`${this.envPrefix}cargo --version`);
22
24
  return result.exitCode === 0;
23
25
  }
24
26
 
25
27
  public async getCargoVersion(): Promise<string> {
26
- const result = await this.shell.execSilent('cargo --version');
28
+ const result = await this.shell.execSilent(`${this.envPrefix}cargo --version`);
27
29
  return result.stdout.trim();
28
30
  }
29
31
 
@@ -39,7 +41,7 @@ export class CargoRunner {
39
41
 
40
42
  const profile = options.debug ? '' : ' --release';
41
43
  const targetFlag = options.target ? ` --target ${options.target}` : '';
42
- const command = `cd ${this.rustDir} && cargo build${profile}${targetFlag}`;
44
+ const command = `${this.envPrefix}cd ${this.rustDir} && cargo build${profile}${targetFlag}`;
43
45
 
44
46
  console.log(`Running: cargo build${profile}${targetFlag}`);
45
47
  const result = await this.shell.exec(command);
@@ -55,20 +57,20 @@ export class CargoRunner {
55
57
  * Ensures a rustup target is installed. If not present, installs it via `rustup target add`.
56
58
  */
57
59
  public async ensureTarget(triple: string): Promise<void> {
58
- const listResult = await this.shell.execSilent('rustup target list --installed');
60
+ const listResult = await this.shell.execSilent(`${this.envPrefix}rustup target list --installed`);
59
61
  const installedTargets = listResult.stdout.split('\n').map((l) => l.trim());
60
62
  if (installedTargets.includes(triple)) {
61
63
  return;
62
64
  }
63
65
  console.log(`Installing rustup target: ${triple}`);
64
- const addResult = await this.shell.exec(`rustup target add ${triple}`);
66
+ const addResult = await this.shell.exec(`${this.envPrefix}rustup target add ${triple}`);
65
67
  if (addResult.exitCode !== 0) {
66
68
  throw new Error(`Failed to install rustup target ${triple}`);
67
69
  }
68
70
  }
69
71
 
70
72
  public async clean(): Promise<ICargoRunResult> {
71
- const command = `cd ${this.rustDir} && cargo clean`;
73
+ const command = `${this.envPrefix}cd ${this.rustDir} && cargo clean`;
72
74
  const result = await this.shell.exec(command);
73
75
 
74
76
  return {
@@ -3,6 +3,7 @@ import * as plugins from '../plugins.js';
3
3
  import { CargoConfig } from '../mod_cargo/index.js';
4
4
  import { CargoRunner } from '../mod_cargo/index.js';
5
5
  import { FsHelpers } from '../mod_fs/index.js';
6
+ import { ToolchainManager } from '../mod_toolchain/index.js';
6
7
 
7
8
  /** Maps friendly target names to Rust target triples */
8
9
  const targetAliasMap: Record<string, string> = {
@@ -62,18 +63,33 @@ export class TsRustCli {
62
63
  this.registerCleanCommand();
63
64
  }
64
65
 
66
+ /**
67
+ * Resolves the Rust toolchain to use. Tries system cargo first,
68
+ * then falls back to a bundled toolchain at /tmp/tsrust_toolchain/.
69
+ * Returns the envPrefix string to prepend to shell commands.
70
+ */
71
+ private async resolveToolchain(): Promise<string> {
72
+ // 1. Try system cargo
73
+ const systemRunner = new CargoRunner(this.cwd);
74
+ if (await systemRunner.checkCargoInstalled()) {
75
+ return ''; // system toolchain, no prefix needed
76
+ }
77
+
78
+ // 2. Fall back to bundled toolchain
79
+ console.log('System cargo not found. Checking for bundled toolchain...');
80
+ const toolchain = new ToolchainManager();
81
+ await toolchain.ensureInstalled();
82
+ return toolchain.getEnvPrefix();
83
+ }
84
+
65
85
  private registerStandardCommand(): void {
66
86
  this.cli.standardCommand().subscribe(async (argvArg) => {
67
87
  const startTime = Date.now();
68
88
 
69
- // Check cargo is installed
70
- const runner = new CargoRunner(this.cwd); // temporary, just for version check
71
- if (!(await runner.checkCargoInstalled())) {
72
- console.error('Error: cargo is not installed or not in PATH.');
73
- console.error('Install Rust via https://rustup.rs/');
74
- process.exit(1);
75
- }
89
+ // Resolve toolchain (system or bundled fallback)
90
+ const envPrefix = await this.resolveToolchain();
76
91
 
92
+ const runner = new CargoRunner(this.cwd, envPrefix);
77
93
  const cargoVersion = await runner.getCargoVersion();
78
94
  console.log(`Using ${cargoVersion}`);
79
95
 
@@ -125,7 +141,7 @@ export class TsRustCli {
125
141
 
126
142
  for (const { triple, friendly } of resolvedTargets) {
127
143
  console.log(`\n--- Building for ${friendly} (${triple}) ---`);
128
- const cargoRunner = new CargoRunner(rustDir);
144
+ const cargoRunner = new CargoRunner(rustDir, envPrefix);
129
145
  const buildResult = await cargoRunner.build({ debug: isDebug, clean: shouldClean, target: triple });
130
146
 
131
147
  if (!buildResult.success) {
@@ -159,8 +175,8 @@ export class TsRustCli {
159
175
  }
160
176
  }
161
177
  } else {
162
- // Native build (unchanged behavior)
163
- const cargoRunner = new CargoRunner(rustDir);
178
+ // Native build
179
+ const cargoRunner = new CargoRunner(rustDir, envPrefix);
164
180
  const buildResult = await cargoRunner.build({ debug: isDebug, clean: shouldClean });
165
181
 
166
182
  if (!buildResult.success) {
@@ -199,8 +215,9 @@ export class TsRustCli {
199
215
  // Clean cargo build
200
216
  const rustDir = await this.detectRustDir();
201
217
  if (rustDir) {
218
+ const envPrefix = await this.resolveToolchain();
202
219
  console.log('Running cargo clean...');
203
- const runner = new CargoRunner(rustDir);
220
+ const runner = new CargoRunner(rustDir, envPrefix);
204
221
  await runner.clean();
205
222
  console.log('Cargo clean complete.');
206
223
  }
@@ -0,0 +1,119 @@
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import * as plugins from '../plugins.js';
5
+
6
+ export class ToolchainManager {
7
+ public static TOOLCHAIN_DIR = '/tmp/tsrust_toolchain';
8
+ public static RUSTUP_HOME = '/tmp/tsrust_toolchain/rustup';
9
+ public static CARGO_HOME = '/tmp/tsrust_toolchain/cargo';
10
+ public static BIN_DIR = '/tmp/tsrust_toolchain/cargo/bin';
11
+
12
+ private shell: plugins.smartshell.Smartshell;
13
+
14
+ constructor() {
15
+ this.shell = new plugins.smartshell.Smartshell({
16
+ executor: 'bash',
17
+ });
18
+ }
19
+
20
+ /**
21
+ * Returns the Rust host triple for the current platform.
22
+ */
23
+ public getHostTriple(): string {
24
+ const platform = os.platform();
25
+ const arch = os.arch();
26
+
27
+ if (platform === 'linux' && arch === 'x64') return 'x86_64-unknown-linux-gnu';
28
+ if (platform === 'linux' && arch === 'arm64') return 'aarch64-unknown-linux-gnu';
29
+ if (platform === 'darwin' && arch === 'x64') return 'x86_64-apple-darwin';
30
+ if (platform === 'darwin' && arch === 'arm64') return 'aarch64-apple-darwin';
31
+
32
+ throw new Error(
33
+ `Unsupported platform: ${platform}/${arch}. Please install Rust manually via https://rustup.rs/`
34
+ );
35
+ }
36
+
37
+ /**
38
+ * Checks if the bundled toolchain is already installed at TOOLCHAIN_DIR.
39
+ */
40
+ public async isInstalled(): Promise<boolean> {
41
+ const cargoPath = path.join(ToolchainManager.BIN_DIR, 'cargo');
42
+ try {
43
+ const stat = await fs.promises.stat(cargoPath);
44
+ return stat.isFile();
45
+ } catch {
46
+ return false;
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Downloads rustup-init and installs a minimal Rust toolchain to TOOLCHAIN_DIR.
52
+ */
53
+ public async install(): Promise<void> {
54
+ const triple = this.getHostTriple();
55
+ const rustupInitUrl = `https://static.rust-lang.org/rustup/dist/${triple}/rustup-init`;
56
+ const rustupInitPath = path.join(ToolchainManager.TOOLCHAIN_DIR, 'rustup-init');
57
+
58
+ // Ensure toolchain directory exists
59
+ await fs.promises.mkdir(ToolchainManager.TOOLCHAIN_DIR, { recursive: true });
60
+
61
+ console.log(`Downloading rustup-init for ${triple}...`);
62
+ const downloadResult = await this.shell.exec(
63
+ `curl -sSf -o ${rustupInitPath} ${rustupInitUrl} && chmod +x ${rustupInitPath}`
64
+ );
65
+ if (downloadResult.exitCode !== 0) {
66
+ throw new Error(`Failed to download rustup-init: ${downloadResult.stdout}`);
67
+ }
68
+
69
+ console.log('Installing minimal Rust toolchain to /tmp/tsrust_toolchain/...');
70
+ const installCmd = [
71
+ `RUSTUP_HOME="${ToolchainManager.RUSTUP_HOME}"`,
72
+ `CARGO_HOME="${ToolchainManager.CARGO_HOME}"`,
73
+ rustupInitPath,
74
+ '-y',
75
+ '--default-toolchain stable',
76
+ '--profile minimal',
77
+ '--no-modify-path',
78
+ ].join(' ');
79
+
80
+ const installResult = await this.shell.exec(installCmd);
81
+ if (installResult.exitCode !== 0) {
82
+ throw new Error(`Failed to install Rust toolchain: ${installResult.stdout}`);
83
+ }
84
+
85
+ // Verify installation
86
+ const verifyResult = await this.shell.execSilent(
87
+ `${this.getEnvPrefix()}cargo --version`
88
+ );
89
+ if (verifyResult.exitCode !== 0) {
90
+ throw new Error('Rust toolchain installation verification failed.');
91
+ }
92
+ console.log(`Installed: ${verifyResult.stdout.trim()}`);
93
+
94
+ // Clean up rustup-init binary
95
+ await fs.promises.unlink(rustupInitPath).catch(() => {});
96
+ }
97
+
98
+ /**
99
+ * Ensures the bundled toolchain is installed. Downloads if not present.
100
+ */
101
+ public async ensureInstalled(): Promise<void> {
102
+ if (await this.isInstalled()) {
103
+ console.log('Using bundled Rust toolchain from /tmp/tsrust_toolchain/');
104
+ return;
105
+ }
106
+ await this.install();
107
+ }
108
+
109
+ /**
110
+ * Returns a shell prefix string that sets RUSTUP_HOME, CARGO_HOME, and PATH
111
+ * to point at the bundled toolchain. Prepend this to any shell command.
112
+ */
113
+ public getEnvPrefix(): string {
114
+ return (
115
+ `export RUSTUP_HOME="${ToolchainManager.RUSTUP_HOME}" CARGO_HOME="${ToolchainManager.CARGO_HOME}" && ` +
116
+ `export PATH="${ToolchainManager.BIN_DIR}:$PATH" && `
117
+ );
118
+ }
119
+ }
@@ -0,0 +1 @@
1
+ export * from './classes.toolchainmanager.js';