diff --git a/.changes/cargo-config-target.md b/.changes/cargo-config-target.md new file mode 100644 index 000000000..65d35eae6 --- /dev/null +++ b/.changes/cargo-config-target.md @@ -0,0 +1,6 @@ +--- +"cli.rs": patch +"cli.js": patch +--- + +Check if the default build target is set in the Cargo configuration. diff --git a/.changes/cli-detect-target-dir.md b/.changes/cli-detect-target-dir.md new file mode 100644 index 000000000..19ee4c57e --- /dev/null +++ b/.changes/cli-detect-target-dir.md @@ -0,0 +1,6 @@ +--- +"cli.rs": "patch" +"cli.js": "patch" +--- + +Use `cargo metadata` to detect the workspace root and target directory. diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index eb58fbb1c..ca9564bbb 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/core/tauri-runtime-wry/src/lib.rs @@ -2628,12 +2628,12 @@ fn handle_event_loop( for handler in handlers { handler(&event); } + } - let global_listeners = system_tray_manager.global_listeners.lock().unwrap(); - let global_listeners_iter = global_listeners.iter(); - for global_listener in global_listeners_iter { - global_listener(tray_id, &event); - } + let global_listeners = system_tray_manager.global_listeners.lock().unwrap(); + let global_listeners_iter = global_listeners.iter(); + for global_listener in global_listeners_iter { + global_listener(tray_id, &event); } } #[cfg(all(desktop, feature = "system-tray"))] @@ -2662,6 +2662,12 @@ fn handle_event_loop( handler(&event); } } + + let global_listeners = system_tray_manager.global_listeners.lock().unwrap(); + let global_listeners_iter = global_listeners.iter(); + for global_listener in global_listeners_iter { + global_listener(id.0, &event); + } } Event::WindowEvent { event, window_id, .. diff --git a/core/tauri/build.rs b/core/tauri/build.rs index cf3ec2a6f..c5b45b798 100644 --- a/core/tauri/build.rs +++ b/core/tauri/build.rs @@ -20,7 +20,7 @@ fn has_feature(feature: &str) -> bool { .unwrap() .push(feature.to_string()); - // when a feature is enabled, Cargo sets the `CARGO_FEATURE_` env var to 1 // https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts std::env::var(format!("CARGO_FEATURE_{}", AsShoutySnakeCase(feature))) .map(|x| x == "1") diff --git a/examples/api/yarn.lock b/examples/api/yarn.lock index b9cd0c3c2..717b6eb50 100644 --- a/examples/api/yarn.lock +++ b/examples/api/yarn.lock @@ -960,9 +960,9 @@ unconfig@^0.3.4: jiti "^1.13.0" undici@^5.2.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.8.0.tgz#dec9a8ccd90e5a1d81d43c0eab6503146d649a4f" - integrity sha512-1F7Vtcez5w/LwH2G2tGnFIihuWUlc58YidwLiCv+jR2Z50x0tNXpRRw7eOIJ+GvqCqIkg9SB7NWAJ/T9TLfv8Q== + version "5.9.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.9.1.tgz#fc9fd85dd488f965f153314a63d9426a11f3360b" + integrity sha512-6fB3a+SNnWEm4CJbgo0/CWR8RGcOCQP68SF4X0mxtYTq2VNN8T88NYrWVBAeSX+zb7bny2dx2iYhP3XHi00omg== unocss@^0.39.3: version "0.39.3" diff --git a/tooling/api/package.json b/tooling/api/package.json index 7304c014d..8c28dff8b 100644 --- a/tooling/api/package.json +++ b/tooling/api/package.json @@ -49,9 +49,9 @@ "@rollup/plugin-node-resolve": "13.3.0", "@rollup/plugin-sucrase": "4.0.4", "@rollup/plugin-typescript": "8.3.4", - "@typescript-eslint/eslint-plugin": "5.33.0", - "@typescript-eslint/parser": "5.33.0", - "eslint": "8.21.0", + "@typescript-eslint/eslint-plugin": "5.33.1", + "@typescript-eslint/parser": "5.33.1", + "eslint": "8.22.0", "eslint-config-prettier": "8.5.0", "eslint-config-standard-with-typescript": "21.0.1", "eslint-plugin-import": "2.26.0", @@ -61,7 +61,7 @@ "prettier": "2.7.1", "regenerator-runtime": "0.13.9", "rimraf": "3.0.2", - "rollup": "2.77.2", + "rollup": "2.78.0", "rollup-plugin-terser": "7.0.2", "tslib": "2.4.0", "typedoc": "0.23.10", diff --git a/tooling/api/yarn.lock b/tooling/api/yarn.lock index 535d6af5c..eb33b04fe 100644 --- a/tooling/api/yarn.lock +++ b/tooling/api/yarn.lock @@ -1359,14 +1359,14 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@5.33.0": - version "5.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.0.tgz#059798888720ec52ffa96c5f868e31a8f70fa3ec" - integrity sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg== +"@typescript-eslint/eslint-plugin@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.1.tgz#c0a480d05211660221eda963cc844732fe9b1714" + integrity sha512-S1iZIxrTvKkU3+m63YUOxYPKaP+yWDQrdhxTglVDVEVBf+aCSw85+BmJnyUaQQsk5TXFG/LpBu9fa+LrAQ91fQ== dependencies: - "@typescript-eslint/scope-manager" "5.33.0" - "@typescript-eslint/type-utils" "5.33.0" - "@typescript-eslint/utils" "5.33.0" + "@typescript-eslint/scope-manager" "5.33.1" + "@typescript-eslint/type-utils" "5.33.1" + "@typescript-eslint/utils" "5.33.1" debug "^4.3.4" functional-red-black-tree "^1.0.1" ignore "^5.2.0" @@ -1374,14 +1374,14 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@5.33.0": - version "5.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.33.0.tgz#26ec3235b74f0667414613727cb98f9b69dc5383" - integrity sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w== +"@typescript-eslint/parser@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.33.1.tgz#e4b253105b4d2a4362cfaa4e184e2d226c440ff3" + integrity sha512-IgLLtW7FOzoDlmaMoXdxG8HOCByTBXrB1V2ZQYSEV1ggMmJfAkMWTwUjjzagS6OkfpySyhKFkBw7A9jYmcHpZA== dependencies: - "@typescript-eslint/scope-manager" "5.33.0" - "@typescript-eslint/types" "5.33.0" - "@typescript-eslint/typescript-estree" "5.33.0" + "@typescript-eslint/scope-manager" "5.33.1" + "@typescript-eslint/types" "5.33.1" + "@typescript-eslint/typescript-estree" "5.33.1" debug "^4.3.4" "@typescript-eslint/parser@^4.0.0": @@ -1402,20 +1402,20 @@ "@typescript-eslint/types" "4.25.0" "@typescript-eslint/visitor-keys" "4.25.0" -"@typescript-eslint/scope-manager@5.33.0": - version "5.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz#509d7fa540a2c58f66bdcfcf278a3fa79002e18d" - integrity sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw== +"@typescript-eslint/scope-manager@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.33.1.tgz#8d31553e1b874210018ca069b3d192c6d23bc493" + integrity sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA== dependencies: - "@typescript-eslint/types" "5.33.0" - "@typescript-eslint/visitor-keys" "5.33.0" + "@typescript-eslint/types" "5.33.1" + "@typescript-eslint/visitor-keys" "5.33.1" -"@typescript-eslint/type-utils@5.33.0": - version "5.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.33.0.tgz#92ad1fba973c078d23767ce2d8d5a601baaa9338" - integrity sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA== +"@typescript-eslint/type-utils@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.33.1.tgz#1a14e94650a0ae39f6e3b77478baff002cec4367" + integrity sha512-X3pGsJsD8OiqhNa5fim41YtlnyiWMF/eKsEZGsHID2HcDqeSC5yr/uLOeph8rNF2/utwuI0IQoAK3fpoxcLl2g== dependencies: - "@typescript-eslint/utils" "5.33.0" + "@typescript-eslint/utils" "5.33.1" debug "^4.3.4" tsutils "^3.21.0" @@ -1424,10 +1424,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.25.0.tgz#0e444a5c5e3c22d7ffa5e16e0e60510b3de5af87" integrity sha512-+CNINNvl00OkW6wEsi32wU5MhHti2J25TJsJJqgQmJu3B3dYDBcmOxcE5w9cgoM13TrdE/5ND2HoEnBohasxRQ== -"@typescript-eslint/types@5.33.0": - version "5.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.33.0.tgz#d41c584831805554b063791338b0220b613a275b" - integrity sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw== +"@typescript-eslint/types@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.33.1.tgz#3faef41793d527a519e19ab2747c12d6f3741ff7" + integrity sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ== "@typescript-eslint/typescript-estree@4.25.0": version "4.25.0" @@ -1442,28 +1442,28 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@5.33.0": - version "5.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz#02d9c9ade6f4897c09e3508c27de53ad6bfa54cf" - integrity sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ== +"@typescript-eslint/typescript-estree@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.1.tgz#a573bd360790afdcba80844e962d8b2031984f34" + integrity sha512-JOAzJ4pJ+tHzA2pgsWQi4804XisPHOtbvwUyqsuuq8+y5B5GMZs7lI1xDWs6V2d7gE/Ez5bTGojSK12+IIPtXA== dependencies: - "@typescript-eslint/types" "5.33.0" - "@typescript-eslint/visitor-keys" "5.33.0" + "@typescript-eslint/types" "5.33.1" + "@typescript-eslint/visitor-keys" "5.33.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.33.0": - version "5.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.33.0.tgz#46797461ce3146e21c095d79518cc0f8ec574038" - integrity sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw== +"@typescript-eslint/utils@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.33.1.tgz#171725f924fe1fe82bb776522bb85bc034e88575" + integrity sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.33.0" - "@typescript-eslint/types" "5.33.0" - "@typescript-eslint/typescript-estree" "5.33.0" + "@typescript-eslint/scope-manager" "5.33.1" + "@typescript-eslint/types" "5.33.1" + "@typescript-eslint/typescript-estree" "5.33.1" eslint-scope "^5.1.1" eslint-utils "^3.0.0" @@ -1475,12 +1475,12 @@ "@typescript-eslint/types" "4.25.0" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@5.33.0": - version "5.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz#fbcbb074e460c11046e067bc3384b5d66b555484" - integrity sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw== +"@typescript-eslint/visitor-keys@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.1.tgz#0155c7571c8cd08956580b880aea327d5c34a18b" + integrity sha512-nwIxOK8Z2MPWltLKMLOEZwmfBZReqUdbEoHQXeCpa+sRVARe5twpJGHCB4dk9903Yaf0nMAlGbQfaAH92F60eg== dependencies: - "@typescript-eslint/types" "5.33.0" + "@typescript-eslint/types" "5.33.1" eslint-visitor-keys "^3.3.0" acorn-jsx@^5.3.2: @@ -2030,10 +2030,10 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@8.21.0: - version "8.21.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.21.0.tgz#1940a68d7e0573cef6f50037addee295ff9be9ef" - integrity sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA== +eslint@8.22.0: + version "8.22.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.22.0.tgz#78fcb044196dfa7eef30a9d65944f6f980402c48" + integrity sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA== dependencies: "@eslint/eslintrc" "^1.3.0" "@humanwhocodes/config-array" "^0.10.4" @@ -3105,10 +3105,10 @@ rollup-plugin-terser@7.0.2: serialize-javascript "^4.0.0" terser "^5.0.0" -rollup@2.77.2: - version "2.77.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.77.2.tgz#6b6075c55f9cc2040a5912e6e062151e42e2c4e3" - integrity sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g== +rollup@2.78.0: + version "2.78.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.78.0.tgz#00995deae70c0f712ea79ad904d5f6b033209d9e" + integrity sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg== optionalDependencies: fsevents "~2.3.2" diff --git a/tooling/cli/node/package.json b/tooling/cli/node/package.json index 968453034..f14dd9af9 100644 --- a/tooling/cli/node/package.json +++ b/tooling/cli/node/package.json @@ -37,7 +37,7 @@ } }, "devDependencies": { - "@napi-rs/cli": "2.11.1", + "@napi-rs/cli": "2.11.4", "cross-env": "7.0.3", "cross-spawn": "7.0.3", "fs-extra": "10.1.0", diff --git a/tooling/cli/node/yarn.lock b/tooling/cli/node/yarn.lock index ea5e054f4..d1c560289 100644 --- a/tooling/cli/node/yarn.lock +++ b/tooling/cli/node/yarn.lock @@ -669,10 +669,10 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@napi-rs/cli@2.11.1": - version "2.11.1" - resolved "https://registry.yarnpkg.com/@napi-rs/cli/-/cli-2.11.1.tgz#1fe30c3b12baa240dbaf8fcdeed53588d8340a15" - integrity sha512-JRfUgQTrogU/YrOoOgrZdnSopZemmT9ohet8SMxZXQZFtSIjOTSBQOC+vMrqKIfZmSKTtxE8cNIIlscHSP7PCA== +"@napi-rs/cli@2.11.4": + version "2.11.4" + resolved "https://registry.yarnpkg.com/@napi-rs/cli/-/cli-2.11.4.tgz#28bea72dd6758ce7fc94d515493c5bd1ef00b6ec" + integrity sha512-rjU651owB4GJetO3pnu3B8TyVM3Fis3AYb+U16bKxYyykp81S+dJlIgWc8Lc0t55PYbHlBM3hxdgy4pultxMAw== "@sinclair/typebox@^0.24.1": version "0.24.19" diff --git a/tooling/cli/src/info.rs b/tooling/cli/src/info.rs index 5dc6eefe4..ae2a04569 100644 --- a/tooling/cli/src/info.rs +++ b/tooling/cli/src/info.rs @@ -794,13 +794,10 @@ pub fn command(_options: Options) -> Result<()> { } else { None }; - let lock: Option = if let Ok(lock_contents) = - read_to_string(get_workspace_dir(&tauri_dir).join("Cargo.lock")) - { - toml::from_str(&lock_contents).ok() - } else { - None - }; + let lock: Option = get_workspace_dir() + .ok() + .and_then(|p| read_to_string(p.join("Cargo.lock")).ok()) + .and_then(|s| toml::from_str(&s).ok()); for (dep, label) in [ ("tauri", format!("{} {}", "tauri", "[RUST]".dimmed())), diff --git a/tooling/cli/src/interface/rust.rs b/tooling/cli/src/interface/rust.rs index 4e787e05e..0357934fc 100644 --- a/tooling/cli/src/interface/rust.rs +++ b/tooling/cli/src/interface/rust.rs @@ -8,7 +8,7 @@ use std::{ fs::{File, FileType}, io::{Read, Write}, path::{Path, PathBuf}, - process::ExitStatus, + process::{Command, ExitStatus}, str::FromStr, sync::{ mpsc::{channel, sync_channel}, @@ -20,7 +20,6 @@ use std::{ use anyhow::Context; #[cfg(target_os = "linux")] use heck::ToKebabCase; -use log::warn; use log::{debug, info}; use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; use serde::Deserialize; @@ -35,8 +34,10 @@ use crate::helpers::{ config::{reload as reload_config, wix_settings, Config}, }; +mod cargo_config; mod desktop; mod manifest; +use cargo_config::Config as CargoConfig; use manifest::{rewrite_manifest, Manifest}; #[derive(Debug, Default, Clone)] @@ -305,7 +306,7 @@ impl Rust { let process = Arc::new(Mutex::new(child)); let (tx, rx) = channel(); let tauri_path = tauri_dir(); - let workspace_path = get_workspace_dir(&tauri_path); + let workspace_path = get_workspace_dir()?; let watch_folders = if tauri_path == workspace_path { vec![tauri_path] @@ -439,22 +440,12 @@ impl CargoSettings { } } -#[derive(Deserialize)] -struct CargoBuildConfig { - #[serde(rename = "target-dir")] - target_dir: Option, -} - -#[derive(Deserialize)] -struct CargoConfig { - build: Option, -} - pub struct RustAppSettings { manifest: Manifest, cargo_settings: CargoSettings, cargo_package_settings: CargoPackageSettings, package_settings: PackageSettings, + cargo_config: CargoConfig, } impl AppSettings for RustAppSettings { @@ -642,11 +633,14 @@ impl RustAppSettings { default_run: cargo_package_settings.default_run.clone(), }; + let cargo_config = CargoConfig::load(&tauri_dir())?; + Ok(Self { manifest, cargo_settings, cargo_package_settings, package_settings, + cargo_config, }) } @@ -655,100 +649,60 @@ impl RustAppSettings { } pub fn out_dir(&self, target: Option, debug: bool) -> crate::Result { - let tauri_dir = tauri_dir(); - let workspace_dir = get_workspace_dir(&tauri_dir); - get_target_dir(&workspace_dir, target, !debug) + get_target_dir( + target + .as_deref() + .or_else(|| self.cargo_config.build().target()), + !debug, + ) } } -/// This function determines where 'target' dir is and suffixes it with 'release' or 'debug' -/// to determine where the compiled binary will be located. -fn get_target_dir( - project_root_dir: &Path, - target: Option, - is_release: bool, -) -> crate::Result { - let mut path: PathBuf = match std::env::var_os("CARGO_TARGET_DIR") { - Some(target_dir) => target_dir.into(), - None => { - let mut root_dir = project_root_dir.to_path_buf(); - let target_path: Option = loop { - // cargo reads configs under .cargo/config.toml or .cargo/config - let mut cargo_config_path = root_dir.join(".cargo/config"); - if !cargo_config_path.exists() { - cargo_config_path = root_dir.join(".cargo/config.toml"); - } - // if the path exists, parse it - if cargo_config_path.exists() { - let mut config_str = String::new(); - let mut config_file = File::open(&cargo_config_path) - .with_context(|| format!("failed to open {:?}", cargo_config_path))?; - config_file - .read_to_string(&mut config_str) - .with_context(|| "failed to read cargo config file")?; - let config: CargoConfig = - toml::from_str(&config_str).with_context(|| "failed to parse cargo config file")?; - if let Some(build) = config.build { - if let Some(target_dir) = build.target_dir { - break Some(target_dir.into()); - } - } - } - if !root_dir.pop() { - break None; - } - }; - target_path.unwrap_or_else(|| project_root_dir.join("target")) - } - }; +#[derive(Deserialize)] +struct CargoMetadata { + target_directory: PathBuf, + workspace_root: PathBuf, +} - if let Some(ref triple) = target { +fn get_cargo_metadata() -> crate::Result { + let output = Command::new("cargo") + .args(["metadata", "--no-deps", "--format-version", "1"]) + .current_dir(tauri_dir()) + .output()?; + + if !output.status.success() { + return Err(anyhow::anyhow!( + "cargo metadata command exited with a non zero exit code: {}", + String::from_utf8(output.stderr)? + )); + } + + Ok(serde_json::from_slice(&output.stdout)?) +} + +/// This function determines the 'target' directory and suffixes it with 'release' or 'debug' +/// to determine where the compiled binary will be located. +fn get_target_dir(target: Option<&str>, is_release: bool) -> crate::Result { + let mut path = get_cargo_metadata() + .with_context(|| "failed to get cargo metadata")? + .target_directory; + + if let Some(triple) = target { path.push(triple); } + path.push(if is_release { "release" } else { "debug" }); + Ok(path) } -/// Walks up the file system, looking for a Cargo.toml file -/// If one is found before reaching the root, then the current_dir's package belongs to that parent workspace if it's listed on [workspace.members]. -/// -/// If this package is part of a workspace, returns the path to the workspace directory -/// Otherwise returns the current directory. -pub fn get_workspace_dir(current_dir: &Path) -> PathBuf { - let mut dir = current_dir.to_path_buf(); - let project_path = dir.clone(); - - while dir.pop() { - if dir.join("Cargo.toml").exists() { - match CargoSettings::load(&dir) { - Ok(cargo_settings) => { - if let Some(workspace_settings) = cargo_settings.workspace { - if let Some(members) = workspace_settings.members { - if members.iter().any(|member| { - glob::glob(&dir.join(member).to_string_lossy()) - .unwrap() - .any(|p| p.unwrap() == project_path) - }) { - return dir; - } - } - } - } - Err(e) => { - warn!( - "Found `{}`, which may define a parent workspace, but \ - failed to parse it. If this is indeed a parent workspace, undefined behavior may occur: \ - \n {:#}", - dir.display(), - e - ); - } - } - } - } - - // Nothing found walking up the file system, return the starting directory - current_dir.to_path_buf() +/// Executes `cargo metadata` to get the workspace directory. +pub fn get_workspace_dir() -> crate::Result { + Ok( + get_cargo_metadata() + .with_context(|| "failed to get cargo metadata")? + .workspace_root, + ) } #[allow(unused_variables)] diff --git a/tooling/cli/src/interface/rust/cargo_config.rs b/tooling/cli/src/interface/rust/cargo_config.rs new file mode 100644 index 000000000..63a60aa6d --- /dev/null +++ b/tooling/cli/src/interface/rust/cargo_config.rs @@ -0,0 +1,123 @@ +use anyhow::{Context, Result}; +use serde::Deserialize; +use std::{ + fs, + path::{Path, PathBuf}, +}; + +struct PathAncestors<'a> { + current: Option<&'a Path>, +} + +impl<'a> PathAncestors<'a> { + fn new(path: &'a Path) -> PathAncestors<'a> { + PathAncestors { + current: Some(path), + } + } +} + +impl<'a> Iterator for PathAncestors<'a> { + type Item = &'a Path; + + fn next(&mut self) -> Option<&'a Path> { + if let Some(path) = self.current { + self.current = path.parent(); + + Some(path) + } else { + None + } + } +} + +#[derive(Default, Deserialize)] +pub struct BuildConfig { + target: Option, +} + +#[derive(Deserialize)] +pub struct ConfigSchema { + build: Option, +} + +#[derive(Default)] +pub struct Config { + build: BuildConfig, +} + +impl Config { + pub fn load(path: &Path) -> Result { + let mut config = Self::default(); + + for current in PathAncestors::new(path) { + if let Some(path) = get_file_path(¤t.join(".cargo"), "config", true)? { + let contents = fs::read_to_string(&path) + .with_context(|| format!("failed to read configuration file `{}`", path.display()))?; + let toml: ConfigSchema = toml::from_str(&contents) + .with_context(|| format!("could not parse TOML configuration in `{}`", path.display()))?; + + if let Some(target) = toml.build.and_then(|b| b.target) { + config.build.target = Some(target); + break; + } + } + } + + Ok(config) + } + + pub fn build(&self) -> &BuildConfig { + &self.build + } +} + +impl BuildConfig { + pub fn target(&self) -> Option<&str> { + self.target.as_deref() + } +} + +/// The purpose of this function is to aid in the transition to using +/// .toml extensions on Cargo's config files, which were historically not used. +/// Both 'config.toml' and 'credentials.toml' should be valid with or without extension. +/// When both exist, we want to prefer the one without an extension for +/// backwards compatibility, but warn the user appropriately. +fn get_file_path( + dir: &Path, + filename_without_extension: &str, + warn: bool, +) -> Result> { + let possible = dir.join(filename_without_extension); + let possible_with_extension = dir.join(format!("{}.toml", filename_without_extension)); + + if possible.exists() { + if warn && possible_with_extension.exists() { + // We don't want to print a warning if the version + // without the extension is just a symlink to the version + // WITH an extension, which people may want to do to + // support multiple Cargo versions at once and not + // get a warning. + let skip_warning = if let Ok(target_path) = fs::read_link(&possible) { + target_path == possible_with_extension + } else { + false + }; + + if !skip_warning { + log::warn!( + "Both `{}` and `{}` exist. Using `{}`", + possible.display(), + possible_with_extension.display(), + possible.display() + ); + } + } + + Ok(Some(possible)) + } else if possible_with_extension.exists() { + Ok(Some(possible_with_extension)) + } else { + Ok(None) + } +}