mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-25 03:33:36 +03:00
feat(cli): add support for Cargo's workspace inheritance for the package version, closes #5070 (#5775)
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
parent
f7a080a121
commit
cd8c074ae6
5
.changes/version-inheritance.md
Normal file
5
.changes/version-inheritance.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'cli.rs': 'minor'
|
||||
---
|
||||
|
||||
Add support for Cargo's workspace inheritance for the package version.
|
@ -3,7 +3,7 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
declare -a examples=("api" "sidecar" "updater" "resources" "tauri-dynamic-lib")
|
||||
declare -a examples=("api" "sidecar" "updater" "resources" "tauri-dynamic-lib" "workspace")
|
||||
declare -a tooling=("bench" "cli" "webdriver")
|
||||
|
||||
for example in "${examples[@]}"
|
||||
|
@ -21,7 +21,8 @@ exclude = [
|
||||
"examples/updater/src-tauri",
|
||||
"examples/resources/src-tauri",
|
||||
"examples/sidecar/src-tauri",
|
||||
"examples/web/core"
|
||||
"examples/web/core",
|
||||
"examples/workspace"
|
||||
]
|
||||
|
||||
# default to small, optimized workspace release binaries
|
||||
|
3111
examples/workspace/Cargo.lock
generated
Normal file
3111
examples/workspace/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
8
examples/workspace/Cargo.toml
Normal file
8
examples/workspace/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"core",
|
||||
"src-tauri"
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.0.0"
|
6
examples/workspace/core/Cargo.toml
Normal file
6
examples/workspace/core/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "core-api"
|
||||
version = { workspace = true }
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
3
examples/workspace/core/src/lib.rs
Normal file
3
examples/workspace/core/src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub fn run() {
|
||||
println!("run!");
|
||||
}
|
13
examples/workspace/index.html
Normal file
13
examples/workspace/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Workspace Example!</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
3
examples/workspace/src-tauri/.gitignore
vendored
Normal file
3
examples/workspace/src-tauri/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
27
examples/workspace/src-tauri/Cargo.toml
Normal file
27
examples/workspace/src-tauri/Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = { workspace = true }
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
repository = ""
|
||||
default-run = "app"
|
||||
edition = "2021"
|
||||
rust-version = "1.59"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { path = "../../../core/tauri", features = [] }
|
||||
core-api = { path = "../core" }
|
||||
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
|
||||
default = [ "custom-protocol" ]
|
||||
# this feature is used for production builds where `devPath` points to the filesystem
|
||||
# DO NOT remove this
|
||||
custom-protocol = [ "tauri/custom-protocol" ]
|
3
examples/workspace/src-tauri/build.rs
Normal file
3
examples/workspace/src-tauri/build.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
11
examples/workspace/src-tauri/src/main.rs
Normal file
11
examples/workspace/src-tauri/src/main.rs
Normal file
@ -0,0 +1,11 @@
|
||||
#![cfg_attr(
|
||||
all(not(debug_assertions), target_os = "windows"),
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
|
||||
fn main() {
|
||||
core_api::run();
|
||||
tauri::Builder::default()
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
66
examples/workspace/src-tauri/tauri.conf.json
Normal file
66
examples/workspace/src-tauri/tauri.conf.json
Normal file
@ -0,0 +1,66 @@
|
||||
{
|
||||
"build": {
|
||||
"distDir": [
|
||||
"../index.html"
|
||||
],
|
||||
"devPath": [
|
||||
"../index.html"
|
||||
]
|
||||
},
|
||||
"package": {
|
||||
"productName": "workspace"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "",
|
||||
"deb": {
|
||||
"depends": []
|
||||
},
|
||||
"externalBin": [],
|
||||
"icon": [
|
||||
"../../.icons/32x32.png",
|
||||
"../../.icons/128x128.png",
|
||||
"../../.icons/128x128@2x.png",
|
||||
"../../.icons/icon.icns",
|
||||
"../../.icons/icon.ico"
|
||||
],
|
||||
"identifier": "com.tauri.workspace",
|
||||
"longDescription": "",
|
||||
"macOS": {
|
||||
"entitlements": null,
|
||||
"exceptionDomain": "",
|
||||
"frameworks": [],
|
||||
"providerShortName": null,
|
||||
"signingIdentity": null
|
||||
},
|
||||
"resources": [],
|
||||
"shortDescription": "",
|
||||
"targets": "all",
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
}
|
||||
},
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"updater": {
|
||||
"active": false
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"fullscreen": false,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"title": "Workspace",
|
||||
"width": 800
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
20
tooling/cli/Cargo.lock
generated
20
tooling/cli/Cargo.lock
generated
@ -2005,6 +2005,15 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.5.0"
|
||||
@ -2755,6 +2764,16 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-value"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||
dependencies = [
|
||||
"ordered-float",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.137"
|
||||
@ -3152,6 +3171,7 @@ dependencies = [
|
||||
"regex",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde-value",
|
||||
"serde_json",
|
||||
"shared_child",
|
||||
"tauri-bundler",
|
||||
|
@ -79,6 +79,7 @@ html5ever = "0.25"
|
||||
kuchiki = "0.8"
|
||||
tokio = { version = "1", features = [ "macros", "sync" ] }
|
||||
common-path = "1"
|
||||
serde-value = "0.7.0"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
winapi = { version = "0.3", features = [ "handleapi", "processenv", "winbase", "wincon", "winnt" ] }
|
||||
|
@ -502,11 +502,77 @@ impl Rust {
|
||||
}
|
||||
}
|
||||
|
||||
// Taken from https://github.com/rust-lang/cargo/blob/70898e522116f6c23971e2a554b2dc85fd4c84cd/src/cargo/util/toml/mod.rs#L1008-L1065
|
||||
/// Enum that allows for the parsing of `field.workspace = true` in a Cargo.toml
|
||||
///
|
||||
/// It allows for things to be inherited from a workspace or defined as needed
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum MaybeWorkspace<T> {
|
||||
Workspace(TomlWorkspaceField),
|
||||
Defined(T),
|
||||
}
|
||||
|
||||
impl<'de, T: Deserialize<'de>> serde::de::Deserialize<'de> for MaybeWorkspace<T> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<MaybeWorkspace<T>, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
let value = serde_value::Value::deserialize(deserializer)?;
|
||||
if let Ok(workspace) = TomlWorkspaceField::deserialize(
|
||||
serde_value::ValueDeserializer::<D::Error>::new(value.clone()),
|
||||
) {
|
||||
return Ok(MaybeWorkspace::Workspace(workspace));
|
||||
}
|
||||
T::deserialize(serde_value::ValueDeserializer::<D::Error>::new(value))
|
||||
.map(MaybeWorkspace::Defined)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MaybeWorkspace<T> {
|
||||
fn resolve(
|
||||
self,
|
||||
label: &str,
|
||||
get_ws_field: impl FnOnce() -> anyhow::Result<T>,
|
||||
) -> anyhow::Result<T> {
|
||||
match self {
|
||||
MaybeWorkspace::Defined(value) => Ok(value),
|
||||
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => {
|
||||
get_ws_field().context(format!(
|
||||
"error inheriting `{}` from workspace root manifest's `workspace.package.{}`",
|
||||
label, label
|
||||
))
|
||||
}
|
||||
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: false }) => Err(anyhow::anyhow!(
|
||||
"`workspace=false` is unsupported for `package.{}`",
|
||||
label,
|
||||
)),
|
||||
}
|
||||
}
|
||||
fn _as_defined(&self) -> Option<&T> {
|
||||
match self {
|
||||
MaybeWorkspace::Workspace(_) => None,
|
||||
MaybeWorkspace::Defined(defined) => Some(defined),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
pub struct TomlWorkspaceField {
|
||||
workspace: bool,
|
||||
}
|
||||
|
||||
/// The `workspace` section of the app configuration (read from Cargo.toml).
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct WorkspaceSettings {
|
||||
/// the workspace members.
|
||||
members: Option<Vec<String>>,
|
||||
package: Option<WorkspacePackageSettings>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct WorkspacePackageSettings {
|
||||
/// the workspace members.
|
||||
version: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
@ -521,7 +587,7 @@ pub struct CargoPackageSettings {
|
||||
/// the package's name.
|
||||
pub name: Option<String>,
|
||||
/// the package's version.
|
||||
pub version: Option<String>,
|
||||
pub version: Option<MaybeWorkspace<String>>,
|
||||
/// the package's description.
|
||||
pub description: Option<String>,
|
||||
/// the package's homepage.
|
||||
@ -741,6 +807,9 @@ impl RustAppSettings {
|
||||
.version
|
||||
.clone()
|
||||
.expect("Cargo manifest must have the `package.version` field")
|
||||
.resolve("version", || {
|
||||
get_workspace_version()?.context("Workspace Cargo manifest must have the `workspace.package.version` field if a member tries to inherit the version")
|
||||
}).expect("Cargo project does not have a version")
|
||||
}),
|
||||
description: cargo_package_settings
|
||||
.description
|
||||
@ -842,6 +911,27 @@ pub fn get_workspace_dir() -> crate::Result<PathBuf> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_workspace_version() -> crate::Result<Option<String>> {
|
||||
// This will already fail because `cargo metadata` fails if there is no version in the workspace root when a package tries to inherit it.
|
||||
let toml_path = get_workspace_dir()
|
||||
.map(|p| p.join("Cargo.toml"))
|
||||
.with_context(|| "failed to get workspace Cargo.toml file")?;
|
||||
|
||||
let mut toml_str = String::new();
|
||||
let mut toml_file = File::open(toml_path).with_context(|| "failed to open Cargo.toml")?;
|
||||
toml_file
|
||||
.read_to_string(&mut toml_str)
|
||||
.with_context(|| "failed to read Cargo.toml")?;
|
||||
|
||||
Ok(
|
||||
toml::from_str::<CargoSettings>(&toml_str)
|
||||
.with_context(|| "failed to parse Cargo.toml")?
|
||||
.workspace
|
||||
.and_then(|ws| ws.package)
|
||||
.and_then(|p| p.version),
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn tauri_config_to_bundle_settings(
|
||||
manifest: &Manifest,
|
||||
|
Loading…
Reference in New Issue
Block a user