@git.zone/tsrust 1.2.0 → 1.3.1
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.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/mod_cargo/classes.cargorunner.d.ts +2 -1
- package/dist_ts/mod_cargo/classes.cargorunner.js +10 -8
- package/dist_ts/mod_cli/classes.tsrustcli.d.ts +6 -0
- package/dist_ts/mod_cli/classes.tsrustcli.js +30 -15
- package/dist_ts/mod_toolchain/classes.toolchainmanager.d.ts +29 -0
- package/dist_ts/mod_toolchain/classes.toolchainmanager.js +101 -0
- package/dist_ts/mod_toolchain/index.d.ts +1 -0
- package/dist_ts/mod_toolchain/index.js +2 -0
- package/dist_ts/plugins.d.ts +2 -2
- package/dist_ts/plugins.js +3 -3
- package/package.json +4 -4
- package/readme.md +14 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +1 -0
- package/ts/mod_cargo/classes.cargorunner.ts +9 -7
- package/ts/mod_cli/classes.tsrustcli.ts +31 -14
- package/ts/mod_toolchain/classes.toolchainmanager.ts +119 -0
- package/ts/mod_toolchain/index.ts +1 -0
- package/ts/plugins.ts +2 -2
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@git.zone/tsrust',
|
|
6
|
-
version: '1.
|
|
6
|
+
version: '1.3.1',
|
|
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=
|
package/dist_ts/index.d.ts
CHANGED
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,
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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,
|
|
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',
|
|
@@ -42,24 +43,37 @@ export class TsRustCli {
|
|
|
42
43
|
constructor(cwd = process.cwd()) {
|
|
43
44
|
this.cwd = cwd;
|
|
44
45
|
this.cli = new plugins.smartcli.Smartcli();
|
|
45
|
-
const
|
|
46
|
-
this.config =
|
|
46
|
+
const smartconfigInstance = new plugins.smartconfig.Smartconfig(this.cwd);
|
|
47
|
+
this.config = smartconfigInstance.dataFor('@git.zone/tsrust', { targets: [] });
|
|
47
48
|
this.registerCommands();
|
|
48
49
|
}
|
|
49
50
|
registerCommands() {
|
|
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
|
-
//
|
|
57
|
-
const
|
|
58
|
-
|
|
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
|
|
@@ -84,7 +98,7 @@ export class TsRustCli {
|
|
|
84
98
|
const shouldClean = !!argvArg.clean;
|
|
85
99
|
const distDir = path.join(this.cwd, 'dist_rust');
|
|
86
100
|
const profile = isDebug ? 'debug' : 'release';
|
|
87
|
-
// Parse --target flag (can appear multiple times), fall back to
|
|
101
|
+
// Parse --target flag (can appear multiple times), fall back to smartconfig.json config
|
|
88
102
|
const cliTargets = argvArg.target;
|
|
89
103
|
const targets = cliTargets
|
|
90
104
|
? (Array.isArray(cliTargets) ? cliTargets : [cliTargets])
|
|
@@ -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
|
|
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/dist_ts/plugins.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as early from '@push.rocks/early';
|
|
2
|
-
import * as
|
|
2
|
+
import * as smartconfig from '@push.rocks/smartconfig';
|
|
3
3
|
import * as smartcli from '@push.rocks/smartcli';
|
|
4
4
|
import * as smartfile from '@push.rocks/smartfile';
|
|
5
5
|
import * as smartpath from '@push.rocks/smartpath';
|
|
6
6
|
import * as smartshell from '@push.rocks/smartshell';
|
|
7
|
-
export { early,
|
|
7
|
+
export { early, smartconfig, smartcli, smartfile, smartpath, smartshell, };
|
package/dist_ts/plugins.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as early from '@push.rocks/early';
|
|
2
|
-
import * as
|
|
2
|
+
import * as smartconfig from '@push.rocks/smartconfig';
|
|
3
3
|
import * as smartcli from '@push.rocks/smartcli';
|
|
4
4
|
import * as smartfile from '@push.rocks/smartfile';
|
|
5
5
|
import * as smartpath from '@push.rocks/smartpath';
|
|
6
6
|
import * as smartshell from '@push.rocks/smartshell';
|
|
7
|
-
export { early,
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
7
|
+
export { early, smartconfig, smartcli, smartfile, smartpath, smartshell, };
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEtBQUssTUFBTSxtQkFBbUIsQ0FBQztBQUMzQyxPQUFPLEtBQUssV0FBVyxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxRQUFRLE1BQU0sc0JBQXNCLENBQUM7QUFDakQsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssU0FBUyxNQUFNLHVCQUF1QixDQUFDO0FBQ25ELE9BQU8sS0FBSyxVQUFVLE1BQU0sd0JBQXdCLENBQUM7QUFFckQsT0FBTyxFQUNMLEtBQUssRUFDTCxXQUFXLEVBQ1gsUUFBUSxFQUNSLFNBQVMsRUFDVCxTQUFTLEVBQ1QsVUFBVSxHQUNYLENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@git.zone/tsrust",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
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",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"homepage": "https://code.foss.global/git.zone/tsrust#README",
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@push.rocks/early": "^4.0.4",
|
|
37
|
-
"@push.rocks/
|
|
38
|
-
"@push.rocks/smartcli": "^4.0.
|
|
37
|
+
"@push.rocks/smartconfig": "^6.0.0",
|
|
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": "^
|
|
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
|
-
> ⚡ **
|
|
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.
|
|
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:
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/index.ts
CHANGED
|
@@ -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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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> = {
|
|
@@ -52,8 +53,8 @@ export class TsRustCli {
|
|
|
52
53
|
constructor(cwd: string = process.cwd()) {
|
|
53
54
|
this.cwd = cwd;
|
|
54
55
|
this.cli = new plugins.smartcli.Smartcli();
|
|
55
|
-
const
|
|
56
|
-
this.config =
|
|
56
|
+
const smartconfigInstance = new plugins.smartconfig.Smartconfig(this.cwd);
|
|
57
|
+
this.config = smartconfigInstance.dataFor<ITsrustConfig>('@git.zone/tsrust', { targets: [] });
|
|
57
58
|
this.registerCommands();
|
|
58
59
|
}
|
|
59
60
|
|
|
@@ -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
|
-
//
|
|
70
|
-
const
|
|
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
|
|
|
@@ -106,7 +122,7 @@ export class TsRustCli {
|
|
|
106
122
|
const distDir = path.join(this.cwd, 'dist_rust');
|
|
107
123
|
const profile = isDebug ? 'debug' : 'release';
|
|
108
124
|
|
|
109
|
-
// Parse --target flag (can appear multiple times), fall back to
|
|
125
|
+
// Parse --target flag (can appear multiple times), fall back to smartconfig.json config
|
|
110
126
|
const cliTargets = (argvArg as any).target;
|
|
111
127
|
const targets: string[] = cliTargets
|
|
112
128
|
? (Array.isArray(cliTargets) ? cliTargets : [cliTargets])
|
|
@@ -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
|
|
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';
|
package/ts/plugins.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as early from '@push.rocks/early';
|
|
2
|
-
import * as
|
|
2
|
+
import * as smartconfig from '@push.rocks/smartconfig';
|
|
3
3
|
import * as smartcli from '@push.rocks/smartcli';
|
|
4
4
|
import * as smartfile from '@push.rocks/smartfile';
|
|
5
5
|
import * as smartpath from '@push.rocks/smartpath';
|
|
@@ -7,7 +7,7 @@ import * as smartshell from '@push.rocks/smartshell';
|
|
|
7
7
|
|
|
8
8
|
export {
|
|
9
9
|
early,
|
|
10
|
-
|
|
10
|
+
smartconfig,
|
|
11
11
|
smartcli,
|
|
12
12
|
smartfile,
|
|
13
13
|
smartpath,
|