Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/cli-multiple-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@tauri-apps/cli": minor:feat
"tauri-cli": minor:feat
---

Allow merging multiple configuration values on `tauri dev`, `tauri build`, `tauri bundle`, `tauri android dev`, `tauri android build`, `tauri ios dev` and `tauri ios build`.
15 changes: 12 additions & 3 deletions crates/tauri-cli/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,15 @@ pub struct Options {
/// Skip the bundling step even if `bundle > active` is `true` in tauri config.
#[clap(long)]
pub no_bundle: bool,
/// JSON string or path to JSON file to merge with tauri.conf.json
/// JSON strings or path to JSON files to merge with the default configuration file
///
/// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.
///
/// Note that a platform-specific file is looked up and merged with the default file by default
/// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json)
/// but you can use this for more specific use cases such as different build flavors.
#[clap(short, long)]
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
/// Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments.
pub args: Vec<String>,
/// Skip prompting for values
Expand All @@ -68,7 +74,10 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
.map(Target::from_triple)
.unwrap_or_else(Target::current);

let config = get_config(target, options.config.as_ref().map(|c| &c.0))?;
let config = get_config(
target,
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
)?;

let mut interface = AppInterface::new(
config.lock().unwrap().as_ref().unwrap(),
Expand Down
15 changes: 12 additions & 3 deletions crates/tauri-cli/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ pub struct Options {
/// Note that the `updater` bundle is not automatically added so you must specify it if the updater is enabled.
#[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')]
pub bundles: Option<Vec<BundleFormat>>,
/// JSON string or path to JSON file to merge with tauri.conf.json
/// JSON strings or path to JSON files to merge with the default configuration file
///
/// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.
///
/// Note that a platform-specific file is looked up and merged with the default file by default
/// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json)
/// but you can use this for more specific use cases such as different build flavors.
#[clap(short, long)]
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
/// Space or comma separated list of features, should be the same features passed to `tauri build` if any.
#[clap(short, long, action = ArgAction::Append, num_args(0..))]
pub features: Option<Vec<String>>,
Expand Down Expand Up @@ -109,7 +115,10 @@ pub fn command(options: Options, verbosity: u8) -> crate::Result<()> {
.map(Target::from_triple)
.unwrap_or_else(Target::current);

let config = get_config(target, options.config.as_ref().map(|c| &c.0))?;
let config = get_config(
target,
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
)?;

let interface = AppInterface::new(
config.lock().unwrap().as_ref().unwrap(),
Expand Down
38 changes: 17 additions & 21 deletions crates/tauri-cli/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,15 @@ pub struct Options {
/// Exit on panic
#[clap(short, long)]
pub exit_on_panic: bool,
/// JSON string or path to JSON file to merge with tauri.conf.json
/// JSON strings or path to JSON files to merge with the default configuration file
///
/// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.
///
/// Note that a platform-specific file is looked up and merged with the default file by default
/// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json)
/// but you can use this for more specific use cases such as different build flavors.
#[clap(short, long)]
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
/// Run the code in release mode
#[clap(long = "release")]
pub release_mode: bool,
Expand Down Expand Up @@ -104,7 +110,10 @@ fn command_internal(mut options: Options) -> Result<()> {
.map(Target::from_triple)
.unwrap_or_else(Target::current);

let config = get_config(target, options.config.as_ref().map(|c| &c.0))?;
let config = get_config(
target,
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
)?;

let mut interface = AppInterface::new(
config.lock().unwrap().as_ref().unwrap(),
Expand Down Expand Up @@ -262,26 +271,13 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
let server_url = format!("http://{server_url}");
dev_url = Some(server_url.parse().unwrap());

if let Some(c) = &mut options.config {
if let Some(build) = c
.0
.as_object_mut()
.and_then(|root| root.get_mut("build"))
.and_then(|build| build.as_object_mut())
{
build.insert("devUrl".into(), server_url.into());
options.config.push(crate::ConfigValue(serde_json::json!({
"build": {
"devUrl": server_url
}
} else {
options
.config
.replace(crate::ConfigValue(serde_json::json!({
"build": {
"devUrl": server_url
}
})));
}
})));

reload_config(options.config.as_ref().map(|c| &c.0))?;
reload_config(&options.config.iter().map(|c| &c.0).collect::<Vec<_>>())?;
}
}
}
Expand Down
40 changes: 26 additions & 14 deletions crates/tauri-cli/src/helpers/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ fn config_handle() -> &'static ConfigHandle {

/// Gets the static parsed config from `tauri.conf.json`.
fn get_internal(
merge_config: Option<&serde_json::Value>,
merge_configs: &[&serde_json::Value],
reload: bool,
target: Target,
) -> crate::Result<ConfigHandle> {
Expand All @@ -162,12 +162,17 @@ fn get_internal(
);
}

if let Some(merge_config) = merge_config {
if !merge_configs.is_empty() {
let mut merge_config = serde_json::Value::Object(Default::default());
for conf in merge_configs {
merge(&mut merge_config, conf);
}

let merge_config_str = serde_json::to_string(&merge_config).unwrap();
set_var("TAURI_CONFIG", merge_config_str);
merge(&mut config, merge_config);
merge(&mut config, &merge_config);
extensions.insert(MERGE_CONFIG_EXTENSION_NAME.into(), merge_config.clone());
};
}

if config_path.extension() == Some(OsStr::new("json"))
|| config_path.extension() == Some(OsStr::new("json5"))
Expand Down Expand Up @@ -217,35 +222,42 @@ fn get_internal(
Ok(config_handle().clone())
}

pub fn get(
target: Target,
merge_config: Option<&serde_json::Value>,
) -> crate::Result<ConfigHandle> {
get_internal(merge_config, false, target)
pub fn get(target: Target, merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigHandle> {
get_internal(merge_configs, false, target)
}

pub fn reload(merge_config: Option<&serde_json::Value>) -> crate::Result<ConfigHandle> {
pub fn reload(merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigHandle> {
let target = config_handle()
.lock()
.unwrap()
.as_ref()
.map(|conf| conf.target);
if let Some(target) = target {
get_internal(merge_config, true, target)
get_internal(merge_configs, true, target)
} else {
Err(anyhow::anyhow!("config not loaded"))
}
}

/// merges the loaded config with the given value
pub fn merge_with(merge_config: &serde_json::Value) -> crate::Result<ConfigHandle> {
pub fn merge_with(merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigHandle> {
let handle = config_handle();

if merge_configs.is_empty() {
return Ok(handle.clone());
}

if let Some(config_metadata) = &mut *handle.lock().unwrap() {
let merge_config_str = serde_json::to_string(merge_config).unwrap();
let mut merge_config = serde_json::Value::Object(Default::default());
for conf in merge_configs {
merge(&mut merge_config, conf);
}

let merge_config_str = serde_json::to_string(&merge_config).unwrap();
set_var("TAURI_CONFIG", merge_config_str);

let mut value = serde_json::to_value(config_metadata.inner.clone())?;
merge(&mut value, merge_config);
merge(&mut value, &merge_config);
config_metadata.inner = serde_json::from_value(value)?;

Ok(handle.clone())
Expand Down
2 changes: 1 addition & 1 deletion crates/tauri-cli/src/info/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use tauri_utils::platform::Target;
pub fn items(frontend_dir: Option<&PathBuf>, tauri_dir: Option<&Path>) -> Vec<SectionItem> {
let mut items = Vec::new();
if tauri_dir.is_some() {
if let Ok(config) = crate::helpers::config::get(Target::current(), None) {
if let Ok(config) = crate::helpers::config::get(Target::current(), &[]) {
let config_guard = config.lock().unwrap();
let config = config_guard.as_ref().unwrap();

Expand Down
2 changes: 1 addition & 1 deletion crates/tauri-cli/src/inspect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn wix_upgrade_code() -> Result<()> {
crate::helpers::app_paths::resolve();

let target = tauri_utils::platform::Target::Windows;
let config = crate::helpers::config::get(target, None)?;
let config = crate::helpers::config::get(target, &[])?;

let interface = AppInterface::new(config.lock().unwrap().as_ref().unwrap(), None)?;

Expand Down
16 changes: 8 additions & 8 deletions crates/tauri-cli/src/interface/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub struct Options {
pub target: Option<String>,
pub features: Option<Vec<String>>,
pub args: Vec<String>,
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
pub no_watch: bool,
}

Expand Down Expand Up @@ -101,7 +101,7 @@ pub struct MobileOptions {
pub debug: bool,
pub features: Option<Vec<String>>,
pub args: Vec<String>,
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
pub no_watch: bool,
}

Expand Down Expand Up @@ -207,14 +207,14 @@ impl Interface for Rust {
rx.recv().unwrap();
Ok(())
} else {
let config = options.config.clone().map(|c| c.0);
let merge_configs = options.config.iter().map(|c| &c.0).collect::<Vec<_>>();
let run = Arc::new(|rust: &mut Rust| {
let on_exit = on_exit.clone();
rust.run_dev(options.clone(), run_args.clone(), move |status, reason| {
on_exit(status, reason)
})
});
self.run_dev_watcher(config, run)
self.run_dev_watcher(&merge_configs, run)
}
}

Expand All @@ -236,9 +236,9 @@ impl Interface for Rust {
runner(options)?;
Ok(())
} else {
let config = options.config.clone().map(|c| c.0);
let merge_configs = options.config.iter().map(|c| &c.0).collect::<Vec<_>>();
let run = Arc::new(|_rust: &mut Rust| runner(options.clone()));
self.run_dev_watcher(config, run)
self.run_dev_watcher(&merge_configs, run)
}
}

Expand Down Expand Up @@ -487,7 +487,7 @@ impl Rust {

fn run_dev_watcher<F: Fn(&mut Rust) -> crate::Result<Box<dyn DevProcess + Send>>>(
&mut self,
config: Option<serde_json::Value>,
merge_configs: &[&serde_json::Value],
run: Arc<F>,
) -> crate::Result<()> {
let child = run(self)?;
Expand Down Expand Up @@ -537,7 +537,7 @@ impl Rust {
if let Some(event_path) = event.paths.first() {
if !ignore_matcher.is_ignore(event_path, event_path.is_dir()) {
if is_configuration_file(self.app_settings.target, event_path) {
if let Ok(config) = reload_config(config.as_ref()) {
if let Ok(config) = reload_config(merge_configs) {
let (manifest, modified) =
rewrite_manifest(config.lock().unwrap().as_ref().unwrap())?;
if modified {
Expand Down
12 changes: 9 additions & 3 deletions crates/tauri-cli/src/mobile/android/android_studio_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub fn command(options: Options) -> Result<()> {
Profile::Debug
};

let tauri_config = get_tauri_config(tauri_utils::platform::Target::Android, None)?;
let tauri_config = get_tauri_config(tauri_utils::platform::Target::Android, &[])?;

let (config, metadata, cli_options) = {
let tauri_config_guard = tauri_config.lock().unwrap();
Expand All @@ -72,8 +72,14 @@ pub fn command(options: Options) -> Result<()> {
MobileTarget::Android,
)?;

if let Some(config) = &cli_options.config {
crate::helpers::config::merge_with(&config.0)?;
if !cli_options.config.is_empty() {
crate::helpers::config::merge_with(
&cli_options
.config
.iter()
.map(|conf| &conf.0)
.collect::<Vec<_>>(),
)?;
}

let env = env()?;
Expand Down
16 changes: 13 additions & 3 deletions crates/tauri-cli/src/mobile/android/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,15 @@ pub struct Options {
/// List of cargo features to activate
#[clap(short, long, action = ArgAction::Append, num_args(0..))]
pub features: Option<Vec<String>>,
/// JSON string or path to JSON file to merge with tauri.conf.json
/// JSON strings or path to JSON files to merge with the default configuration file
///
/// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.
///
/// Note that a platform-specific file is looked up and merged with the default file by default
/// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json)
/// but you can use this for more specific use cases such as different build flavors.
#[clap(short, long)]
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
/// Whether to split the APKs and AABs per ABIs.
#[clap(long)]
pub split_per_abi: bool,
Expand Down Expand Up @@ -105,7 +111,11 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {

let tauri_config = get_tauri_config(
tauri_utils::platform::Target::Android,
options.config.as_ref().map(|c| &c.0),
&options
.config
.iter()
.map(|conf| &conf.0)
.collect::<Vec<_>>(),
)?;
let (interface, config, metadata) = {
let tauri_config_guard = tauri_config.lock().unwrap();
Expand Down
16 changes: 13 additions & 3 deletions crates/tauri-cli/src/mobile/android/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,15 @@ pub struct Options {
/// Exit on panic
#[clap(short, long)]
exit_on_panic: bool,
/// JSON string or path to JSON file to merge with tauri.conf.json
/// JSON strings or path to JSON files to merge with the default configuration file
///
/// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.
///
/// Note that a platform-specific file is looked up and merged with the default file by default
/// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json)
/// but you can use this for more specific use cases such as different build flavors.
#[clap(short, long)]
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
/// Run the code in release mode
#[clap(long = "release")]
pub release_mode: bool,
Expand Down Expand Up @@ -126,7 +132,11 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> {

let tauri_config = get_tauri_config(
tauri_utils::platform::Target::Android,
options.config.as_ref().map(|c| &c.0),
&options
.config
.iter()
.map(|conf| &conf.0)
.collect::<Vec<_>>(),
)?;

let env = env()?;
Expand Down
2 changes: 1 addition & 1 deletion crates/tauri-cli/src/mobile/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn exec(
#[allow(unused_variables)] reinstall_deps: bool,
skip_targets_install: bool,
) -> Result<App> {
let tauri_config = get_tauri_config(target.platform_target(), None)?;
let tauri_config = get_tauri_config(target.platform_target(), &[])?;

let tauri_config_guard = tauri_config.lock().unwrap();
let tauri_config_ = tauri_config_guard.as_ref().unwrap();
Expand Down
Loading