Fix cargo command not found after Rust installation

This commit is contained in:
Tw93
2025-10-13 19:41:28 +08:00
parent 3d4c018641
commit e7c10f6527
4 changed files with 120 additions and 4 deletions

View File

@@ -70,17 +70,18 @@ If you're running macOS 26 Beta and encounter compilation errors related to `mac
[env]
# Fix for macOS 26 Beta compatibility issues
# Forces use of compatible SDK when building on macOS 26 Beta
MACOSX_DEPLOYMENT_TARGET = "15.5"
SDKROOT = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk"
MACOSX_DEPLOYMENT_TARGET = "15.0"
SDKROOT = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
```
This file is already in `.gitignore` and should not be committed to the repository.
**Root Cause**: macOS 26 Beta uses newer system frameworks that aren't yet supported by the current Xcode SDK (15.5). This configuration forces the build to use the compatible SDK version.
**Root Cause**: macOS 26 Beta uses newer system frameworks that aren't yet fully compatible with Tauri's dependencies. This configuration uses the universal SDK symlink which automatically points to your system's available SDK version.
### Common Build Issues
- **Rust compilation errors**: Run `cargo clean` in `src-tauri/` directory
- **`cargo` command not found after installation**: Pake CLI now reloads the Rust environment automatically, but if the issue persists reopen your terminal or run `source ~/.cargo/env` (macOS/Linux) / `call %USERPROFILE%\.cargo\env` (Windows) before retrying
- **Node dependency issues**: Delete `node_modules` and run `pnpm install`
- **Permission errors on macOS**: Run `sudo xcode-select --reset`

View File

@@ -4,7 +4,7 @@ import chalk from 'chalk';
import prompts from 'prompts';
import { PakeAppOptions } from '@/types';
import { checkRustInstalled, installRust } from '@/helpers/rust';
import { checkRustInstalled, ensureRustEnv, installRust } from '@/helpers/rust';
import { mergeConfig } from '@/helpers/merge';
import tauriConfig from '@/helpers/tauriConfig';
import { generateIdentifierSafeName } from '@/utils/name';
@@ -77,6 +77,8 @@ export default abstract class BaseBuilder {
logger.warn('✼ See more in https://tauri.app/start/prerequisites/.');
}
ensureRustEnv();
if (!checkRustInstalled()) {
const res = await prompts({
type: 'confirm',

63
bin/helpers/rust.ts vendored
View File

@@ -1,3 +1,6 @@
import os from 'os';
import path from 'path';
import fsExtra from 'fs-extra';
import chalk from 'chalk';
import { execaSync } from 'execa';
@@ -6,6 +9,64 @@ import { IS_WIN } from '@/utils/platform';
import { shellExec } from '@/utils/shell';
import { isChinaDomain } from '@/utils/ip';
function normalizePathForComparison(targetPath: string) {
const normalized = path.normalize(targetPath);
return IS_WIN ? normalized.toLowerCase() : normalized;
}
function getCargoHomeCandidates(): string[] {
const candidates = new Set<string>();
if (process.env.CARGO_HOME) {
candidates.add(process.env.CARGO_HOME);
}
const homeDir = os.homedir();
if (homeDir) {
candidates.add(path.join(homeDir, '.cargo'));
}
if (IS_WIN && process.env.USERPROFILE) {
candidates.add(path.join(process.env.USERPROFILE, '.cargo'));
}
return Array.from(candidates).filter(Boolean);
}
function ensureCargoBinOnPath() {
const currentPath = process.env.PATH || '';
const segments = currentPath.split(path.delimiter).filter(Boolean);
const normalizedSegments = new Set(
segments.map((segment) => normalizePathForComparison(segment)),
);
const additions: string[] = [];
let cargoHomeSet = Boolean(process.env.CARGO_HOME);
for (const cargoHome of getCargoHomeCandidates()) {
const binDir = path.join(cargoHome, 'bin');
if (
fsExtra.pathExistsSync(binDir) &&
!normalizedSegments.has(normalizePathForComparison(binDir))
) {
additions.push(binDir);
normalizedSegments.add(normalizePathForComparison(binDir));
}
if (!cargoHomeSet && fsExtra.pathExistsSync(cargoHome)) {
process.env.CARGO_HOME = cargoHome;
cargoHomeSet = true;
}
}
if (additions.length) {
const prefix = additions.join(path.delimiter);
process.env.PATH = segments.length
? `${prefix}${path.delimiter}${segments.join(path.delimiter)}`
: prefix;
}
}
export function ensureRustEnv() {
ensureCargoBinOnPath();
}
export async function installRust() {
const isActions = process.env.GITHUB_ACTIONS;
const isInChina = await isChinaDomain('sh.rustup.rs');
@@ -22,6 +83,7 @@ export async function installRust() {
IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac,
);
spinner.succeed(chalk.green('✔ Rust installed successfully!'));
ensureRustEnv();
} catch (error) {
spinner.fail(chalk.red('✕ Rust installation failed!'));
console.error(error.message);
@@ -30,6 +92,7 @@ export async function installRust() {
}
export function checkRustInstalled() {
ensureCargoBinOnPath();
try {
execaSync('rustc', ['--version']);
return true;

50
dist/cli.js vendored
View File

@@ -6,6 +6,7 @@ import path from 'path';
import fsExtra from 'fs-extra';
import { fileURLToPath } from 'url';
import prompts from 'prompts';
import os from 'os';
import { execa, execaSync } from 'execa';
import crypto from 'crypto';
import ora from 'ora';
@@ -284,6 +285,52 @@ async function isChinaIP(ip, domain) {
}
}
function normalizePathForComparison(targetPath) {
const normalized = path.normalize(targetPath);
return IS_WIN ? normalized.toLowerCase() : normalized;
}
function getCargoHomeCandidates() {
const candidates = new Set();
if (process.env.CARGO_HOME) {
candidates.add(process.env.CARGO_HOME);
}
const homeDir = os.homedir();
if (homeDir) {
candidates.add(path.join(homeDir, '.cargo'));
}
if (IS_WIN && process.env.USERPROFILE) {
candidates.add(path.join(process.env.USERPROFILE, '.cargo'));
}
return Array.from(candidates).filter(Boolean);
}
function ensureCargoBinOnPath() {
const currentPath = process.env.PATH || '';
const segments = currentPath.split(path.delimiter).filter(Boolean);
const normalizedSegments = new Set(segments.map((segment) => normalizePathForComparison(segment)));
const additions = [];
let cargoHomeSet = Boolean(process.env.CARGO_HOME);
for (const cargoHome of getCargoHomeCandidates()) {
const binDir = path.join(cargoHome, 'bin');
if (fsExtra.pathExistsSync(binDir) &&
!normalizedSegments.has(normalizePathForComparison(binDir))) {
additions.push(binDir);
normalizedSegments.add(normalizePathForComparison(binDir));
}
if (!cargoHomeSet && fsExtra.pathExistsSync(cargoHome)) {
process.env.CARGO_HOME = cargoHome;
cargoHomeSet = true;
}
}
if (additions.length) {
const prefix = additions.join(path.delimiter);
process.env.PATH = segments.length
? `${prefix}${path.delimiter}${segments.join(path.delimiter)}`
: prefix;
}
}
function ensureRustEnv() {
ensureCargoBinOnPath();
}
async function installRust() {
const isActions = process.env.GITHUB_ACTIONS;
const isInChina = await isChinaDomain('sh.rustup.rs');
@@ -295,6 +342,7 @@ async function installRust() {
try {
await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac);
spinner.succeed(chalk.green('✔ Rust installed successfully!'));
ensureRustEnv();
}
catch (error) {
spinner.fail(chalk.red('✕ Rust installation failed!'));
@@ -303,6 +351,7 @@ async function installRust() {
}
}
function checkRustInstalled() {
ensureCargoBinOnPath();
try {
execaSync('rustc', ['--version']);
return true;
@@ -674,6 +723,7 @@ class BaseBuilder {
logger.warn('✼ The first use requires installing system dependencies.');
logger.warn('✼ See more in https://tauri.app/start/prerequisites/.');
}
ensureRustEnv();
if (!checkRustInstalled()) {
const res = await prompts({
type: 'confirm',