feat: add mainBinaryName option (#10977)

* feat: add `mainBinaryName` option

* remove unused imports [skip ci]

* enhance error message [skip ci]

* migrate `mainBinaryName`

* change file

* revert bin src_path

* add link

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
Amr Bashir 2024-09-15 13:51:01 +03:00 committed by GitHub
parent 3ad2427dc0
commit 35bd9dd3dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 188 additions and 135 deletions

View File

@ -0,0 +1,5 @@
---
'tauri-bundler': 'major:breaking'
---
Changed changelog file location in `deb` to `usr/share/doc/<product_name>/changelog.gz` instead of `usr/share/doc/<main_binary_name>/changelog.gz`. For tauri v1 users, the path is unchanged as `product_name` and `main_binary_name` used the same value.

View File

@ -0,0 +1,8 @@
---
"tauri": "patch:feat"
"tauri-utils": "patch:feat"
"tauri-cli": "patch:feat"
"tauri-bundler": "patch:feat"
---
Add `mainBinaryName` config option to set the file name for the main binary.

View File

@ -0,0 +1,5 @@
---
'tauri-bundler': 'major:breaking'
---
Changed resources directory location in `deb` and `rpm` to `/usr/lib/<product_name>` instead of `/usr/lib/<main_binary_name>`. For tauri v1 users, the path is unchanged as `product_name` and `main_binary_name` used the same value.

View File

@ -56,7 +56,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
// setup data to insert into shell script
let mut sh_map = BTreeMap::new();
sh_map.insert("arch", settings.target().split('-').next().unwrap());
sh_map.insert("crate_name", settings.main_binary_name());
sh_map.insert("product_name", settings.product_name());
sh_map.insert("appimage_filename", &appimage_filename);
let tauri_tools_path = settings

View File

@ -133,8 +133,8 @@ pub fn generate_data(
fn generate_changelog_file(settings: &Settings, data_dir: &Path) -> crate::Result<()> {
if let Some(changelog_src_path) = &settings.deb().changelog {
let mut src_file = File::open(changelog_src_path)?;
let bin_name = settings.main_binary_name();
let dest_path = data_dir.join(format!("usr/share/doc/{}/changelog.gz", bin_name));
let product_name = settings.product_name();
let dest_path = data_dir.join(format!("usr/share/doc/{product_name}/changelog.gz"));
let changelog_file = common::create_file(&dest_path)?;
let mut gzip_encoder = GzEncoder::new(changelog_file, Compression::new(9));
@ -306,7 +306,7 @@ fn generate_md5sums(control_dir: &Path, data_dir: &Path) -> crate::Result<()> {
/// Copy the bundle's resource files into an appropriate directory under the
/// `data_dir`.
fn copy_resource_files(settings: &Settings, data_dir: &Path) -> crate::Result<()> {
let resource_dir = data_dir.join("usr/lib").join(settings.main_binary_name());
let resource_dir = data_dir.join("usr/lib").join(settings.product_name());
settings.copy_resources(&resource_dir)
}

View File

@ -44,13 +44,14 @@ pub fn list_icon_files(
data_dir: &Path,
) -> crate::Result<BTreeMap<Icon, PathBuf>> {
let base_dir = data_dir.join("usr/share/icons/hicolor");
let main_binary_name = settings.main_binary_name()?;
let get_dest_path = |width: u32, height: u32, is_high_density: bool| {
base_dir.join(format!(
"{}x{}{}/apps/{}.png",
width,
height,
if is_high_density { "@2" } else { "" },
settings.main_binary_name()
main_binary_name
))
};
let mut icons = BTreeMap::new();
@ -97,8 +98,9 @@ pub fn generate_desktop_file(
custom_template_path: &Option<PathBuf>,
data_dir: &Path,
) -> crate::Result<(PathBuf, PathBuf)> {
let bin_name = settings.main_binary_name();
let desktop_file_name = format!("{bin_name}.desktop");
let bin_name = settings.main_binary_name()?;
let product_name = settings.product_name();
let desktop_file_name = format!("{product_name}.desktop");
let path = PathBuf::from("usr/share/applications").join(desktop_file_name);
let dest_path = PathBuf::from("/").join(&path);
let file_path = data_dir.join(&path);

View File

@ -141,12 +141,12 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
// Add resources
if settings.resource_files().count() > 0 {
let resource_dir = Path::new("/usr/lib").join(settings.main_binary_name());
let resource_dir = Path::new("/usr/lib").join(settings.product_name());
// Create an empty file, needed to add a directory to the RPM package
// (cf https://github.com/rpm-rs/rpm/issues/177)
let empty_file_path = &package_dir.join("empty");
File::create(empty_file_path)?;
// Then add the resource directory `/usr/lib/<binary_name>` to the package.
// Then add the resource directory `/usr/lib/<product_name>` to the package.
builder = builder.with_file(
empty_file_path,
FileOptions::new(resource_dir.to_string_lossy()).mode(FileMode::Dir { permissions: 0o755 }),

View File

@ -17,10 +17,10 @@ else
linuxdeploy_arch="$ARCH"
fi
mkdir -p "{{crate_name}}.AppDir"
cp -r ../appimage_deb/data/usr "{{crate_name}}.AppDir"
mkdir -p "{{product_name}}.AppDir"
cp -r ../appimage_deb/data/usr "{{product_name}}.AppDir"
cd "{{crate_name}}.AppDir"
cd "{{product_name}}.AppDir"
mkdir -p "usr/bin"
mkdir -p "usr/lib"
@ -56,14 +56,14 @@ find -L /usr/lib* -name libwebkit2gtkinjectedbundle.so -exec mkdir -p "$(dirname
( cd "{{tauri_tools_path}}" && ( wget -q -4 -N https://github.com/AppImage/AppImageKit/releases/download/continuous/AppRun-${ARCH} || wget -q -4 -N https://github.com/AppImage/AppImageKit/releases/download/12/AppRun-${ARCH} ) )
chmod +x "{{tauri_tools_path}}/AppRun-${ARCH}"
# We need AppRun to be installed as {{crate_name}}.AppDir/AppRun.
# We need AppRun to be installed as {{product_name}}.AppDir/AppRun.
# Otherwise the linuxdeploy scripts will default to symlinking our main bin instead and will crash on trying to launch.
cp "{{tauri_tools_path}}/AppRun-${ARCH}" AppRun
cp "{{icon_path}}" .DirIcon
ln -sf "{{icon_path}}" "{{crate_name}}.png"
ln -sf "{{icon_path}}" "{{product_name}}.png"
ln -sf "usr/share/applications/{{crate_name}}.desktop" "{{crate_name}}.desktop"
ln -sf "usr/share/applications/{{product_name}}.desktop" "{{product_name}}.desktop"
cd ..
@ -83,4 +83,4 @@ chmod +x "{{tauri_tools_path}}/linuxdeploy-${linuxdeploy_arch}.AppImage"
dd if=/dev/zero bs=1 count=3 seek=8 conv=notrunc of="{{tauri_tools_path}}/linuxdeploy-${linuxdeploy_arch}.AppImage"
OUTPUT="{{appimage_filename}}" "{{tauri_tools_path}}/linuxdeploy-${linuxdeploy_arch}.AppImage" --appimage-extract-and-run --appdir "{{crate_name}}.AppDir" --plugin gtk ${gst_plugin} --output appimage
OUTPUT="{{appimage_filename}}" "{{tauri_tools_path}}/linuxdeploy-${linuxdeploy_arch}.AppImage" --appimage-extract-and-run --appdir "{{product_name}}.AppDir" --plugin gtk ${gst_plugin} --output appimage

View File

@ -200,7 +200,7 @@ fn create_info_plist(
plist.insert("CFBundleDisplayName".into(), settings.product_name().into());
plist.insert(
"CFBundleExecutable".into(),
settings.main_binary_name().into(),
settings.main_binary_name()?.into(),
);
if let Some(path) = bundle_icon_file {
plist.insert(

View File

@ -170,7 +170,7 @@ fn generate_info_plist(
writeln!(
file,
" <key>CFBundleExecutable</key>\n <string>{}</string>",
settings.main_binary_name()
settings.main_binary_name()?
)?;
writeln!(
file,

View File

@ -5,6 +5,7 @@
use super::category::AppCategory;
use crate::bundle::{common, platform::target_triple};
use anyhow::Context;
pub use tauri_utils::config::WebviewInstallMode;
use tauri_utils::{
config::{BundleType, DeepLinkProtocol, FileAssociation, NSISInstallerMode, NsisCompression},
@ -617,8 +618,8 @@ pub struct BundleSettings {
#[derive(Clone, Debug)]
pub struct BundleBinary {
name: String,
src_path: Option<String>,
main: bool,
src_path: Option<String>,
}
impl BundleBinary {
@ -626,8 +627,8 @@ impl BundleBinary {
pub fn new(name: String, main: bool) -> Self {
Self {
name,
src_path: None,
main,
src_path: None,
}
}
@ -640,13 +641,6 @@ impl BundleBinary {
}
}
/// Sets the src path of the binary.
#[must_use]
pub fn set_src_path(mut self, src_path: Option<String>) -> Self {
self.src_path = src_path;
self
}
/// Mark the binary as the main executable.
pub fn set_main(&mut self, main: bool) {
self.main = main;
@ -657,9 +651,11 @@ impl BundleBinary {
self.name = name;
}
/// Returns the binary name.
pub fn name(&self) -> &str {
&self.name
/// Sets the src path of the binary.
#[must_use]
pub fn set_src_path(mut self, src_path: Option<String>) -> Self {
self.src_path = src_path;
self
}
/// Returns the binary `main` flag.
@ -667,6 +663,11 @@ impl BundleBinary {
self.main
}
/// Returns the binary name.
pub fn name(&self) -> &str {
&self.name
}
/// Returns the binary source path.
pub fn src_path(&self) -> Option<&String> {
self.src_path.as_ref()
@ -852,14 +853,24 @@ impl Settings {
}
/// Returns the file name of the binary being bundled.
pub fn main_binary_name(&self) -> &str {
pub fn main_binary(&self) -> crate::Result<&BundleBinary> {
self
.binaries
.iter()
.find(|bin| bin.main)
.expect("failed to find main binary")
.name
.as_str()
.context("failed to find main binary, make sure you have a `package > default-run` in the Cargo.toml file")
.map_err(Into::into)
}
/// Returns the file name of the binary being bundled.
pub fn main_binary_name(&self) -> crate::Result<&str> {
self
.binaries
.iter()
.find(|bin| bin.main)
.context("failed to find main binary, make sure you have a `package > default-run` in the Cargo.toml file")
.map(|b| b.name.as_str())
.map_err(Into::into)
}
/// Returns the path to the specified binary.

View File

@ -304,11 +304,7 @@ fn run_candle(
}
};
let main_binary = settings
.binaries()
.iter()
.find(|bin| bin.main())
.ok_or_else(|| anyhow::anyhow!("Failed to get main binary"))?;
let main_binary = settings.main_binary()?;
let mut args = vec![
"-arch".to_string(),
@ -404,13 +400,6 @@ pub fn build_wix_app_installer(
// target only supports x64.
log::info!("Target: {}", arch);
let main_binary = settings
.binaries()
.iter()
.find(|bin| bin.main())
.ok_or_else(|| anyhow::anyhow!("Failed to get main binary"))?;
let app_exe_source = settings.binary_path(main_binary);
let output_path = settings.project_out_directory().join("wix").join(arch);
if output_path.exists() {
@ -546,10 +535,6 @@ pub fn build_wix_app_installer(
let shortcut_guid = generate_package_guid(settings).to_string();
data.insert("shortcut_guid", to_json(shortcut_guid.as_str()));
// Note: `main_binary_name` is not used in our template but we keep it as it is potentially useful for custom temples
let main_binary_name = settings.main_binary_name().to_string();
data.insert("main_binary_name", to_json(&main_binary_name));
let binaries = generate_binaries_data(settings)?;
let binaries_json = to_json(binaries);
@ -572,7 +557,13 @@ pub fn build_wix_app_installer(
let merge_modules = get_merge_modules(settings)?;
data.insert("merge_modules", to_json(merge_modules));
data.insert("app_exe_source", to_json(app_exe_source));
// Note: `main_binary_name` is not used in our template but we keep it as it is potentially useful for custom temples
let main_binary_name = settings.main_binary_name()?;
data.insert("main_binary_name", to_json(main_binary_name));
let main_binary = settings.main_binary()?;
let main_binary_path = settings.binary_path(main_binary);
data.insert("main_binary_path", to_json(main_binary_path));
// copy icon from `settings.windows().icon_path` folder to resource folder near msi
let icon_path = copy_icon(settings, "icon.ico", &settings.windows().icon_path)?;

View File

@ -336,21 +336,9 @@ fn build_nsis_app_installer(
}
data.insert("language_files", to_json(language_files_paths));
let main_binary = settings
.binaries()
.iter()
.find(|bin| bin.main())
.ok_or_else(|| anyhow::anyhow!("Failed to get main binary"))?;
let main_binary = settings.main_binary()?;
let main_binary_path = settings.binary_path(main_binary).with_extension("exe");
data.insert(
"main_binary_name",
to_json(
main_binary_path
.file_stem()
.and_then(|file_name| file_name.to_str())
.unwrap_or_else(|| main_binary.name()),
),
);
data.insert("main_binary_name", to_json(main_binary.name()));
data.insert("main_binary_path", to_json(&main_binary_path));
let out_file = "nsis-output.exe";

View File

@ -139,7 +139,7 @@
{{/each~}}
</Component>
<Component Id="Path" Guid="{{path_component_guid}}" Win64="$(var.Win64)">
<File Id="Path" Source="{{app_exe_source}}" KeyPath="yes" Checksum="yes"/>
<File Id="Path" Source="{{main_binary_path}}" KeyPath="yes" Checksum="yes"/>
{{#each file_associations as |association| ~}}
{{#each association.ext as |ext| ~}}
<ProgId Id="{{../../product_name}}.{{ext}}" Advertise="yes" Description="{{association.description}}">

View File

@ -22,6 +22,13 @@
],
"pattern": "^[^/\\:*?\"<>|]+$"
},
"mainBinaryName": {
"description": "App main binary filename. Defaults to the name of your cargo crate.",
"type": [
"string",
"null"
]
},
"version": {
"description": "App version. It is a semver version number or a path to a `package.json` file containing the `version` field. If removed the version number from `Cargo.toml` is used.\n\n By default version 1.0 is used on Android.",
"type": [

View File

@ -9,7 +9,7 @@ use crate::{
app_paths::tauri_dir,
config::{get as get_config, ConfigHandle, FrontendDist},
},
interface::{AppInterface, AppSettings, Interface},
interface::{AppInterface, Interface},
ConfigValue, Result,
};
use anyhow::Context;
@ -83,10 +83,9 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
let app_settings = interface.app_settings();
let interface_options = options.clone().into();
let bin_path = app_settings.app_binary_path(&interface_options)?;
let out_dir = bin_path.parent().unwrap();
let out_dir = app_settings.out_dir(&interface_options)?;
interface.build(interface_options)?;
let bin_path = interface.build(interface_options)?;
log::info!(action ="Built"; "application at: {}", tauri_utils::display_path(&bin_path));
@ -100,7 +99,7 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
&interface,
&app_settings,
config_,
out_dir,
&out_dir,
)?;
}

View File

@ -121,8 +121,7 @@ pub fn command(options: Options, verbosity: u8) -> crate::Result<()> {
let app_settings = interface.app_settings();
let interface_options = options.clone().into();
let bin_path = app_settings.app_binary_path(&interface_options)?;
let out_dir = bin_path.parent().unwrap();
let out_dir = app_settings.out_dir(&interface_options)?;
bundle(
&options,
@ -131,7 +130,7 @@ pub fn command(options: Options, verbosity: u8) -> crate::Result<()> {
&interface,
&app_settings,
config_,
out_dir,
&out_dir,
)
}

View File

@ -55,10 +55,16 @@ pub trait AppSettings {
tauri_utils::platform::target_triple()?
};
let mut bins = self.get_binaries(&target)?;
if let Some(main_binary_name) = &config.main_binary_name {
let main = bins.iter_mut().find(|b| b.main()).context("no main bin?")?;
main.set_name(main_binary_name.to_owned());
}
let mut settings_builder = SettingsBuilder::new()
.package_settings(self.get_package_settings())
.bundle_settings(self.get_bundle_settings(config, &enabled_features)?)
.binaries(self.get_binaries(&target)?)
.binaries(bins)
.project_out_directory(out_dir)
.target(target)
.package_types(package_types);
@ -91,7 +97,7 @@ pub trait Interface: Sized {
fn new(config: &Config, target: Option<String>) -> crate::Result<Self>;
fn app_settings(&self) -> Arc<Self::AppSettings>;
fn env(&self) -> HashMap<&str, String>;
fn build(&mut self, options: Options) -> crate::Result<()>;
fn build(&mut self, options: Options) -> crate::Result<PathBuf>;
fn dev<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(
&mut self,
options: Options,

View File

@ -115,6 +115,7 @@ pub struct Rust {
app_settings: Arc<RustAppSettings>,
config_features: Vec<String>,
available_targets: Option<Vec<RustupTarget>>,
main_binary_name: Option<String>,
}
impl Interface for Rust {
@ -160,6 +161,7 @@ impl Interface for Rust {
Ok(Self {
app_settings: Arc::new(app_settings),
config_features: config.build.features.clone().unwrap_or_default(),
main_binary_name: config.main_binary_name.clone(),
available_targets: None,
})
}
@ -168,14 +170,14 @@ impl Interface for Rust {
self.app_settings.clone()
}
fn build(&mut self, options: Options) -> crate::Result<()> {
fn build(&mut self, options: Options) -> crate::Result<PathBuf> {
desktop::build(
options,
&self.app_settings,
&mut self.available_targets,
self.config_features.clone(),
)?;
Ok(())
self.main_binary_name.as_deref(),
)
}
fn dev<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(
@ -498,6 +500,7 @@ impl Rust {
&mut self.available_targets,
self.config_features.clone(),
&self.app_settings,
self.main_binary_name.clone(),
on_exit,
)
.map(|c| Box::new(c) as Box<dyn DevProcess + Send>)
@ -865,32 +868,30 @@ impl AppSettings for RustAppSettings {
let bin_name = binaries
.iter()
.find(|x| x.main())
.expect("failed to find main binary")
.context("failed to find main binary, make sure you have a `package > default-run` in the Cargo.toml file")?
.name();
let out_dir = self
.out_dir(options)
.with_context(|| "failed to get project out directory")?;
.context("failed to get project out directory")?;
let binary_extension: String = if self.target_triple.contains("windows") {
let ext = if self.target_triple.contains("windows") {
"exe"
} else {
""
}
.into();
};
Ok(out_dir.join(bin_name).with_extension(binary_extension))
Ok(out_dir.join(bin_name).with_extension(ext))
}
fn get_binaries(&self, target: &str) -> crate::Result<Vec<BundleBinary>> {
let mut binaries: Vec<BundleBinary> = vec![];
let binary_extension: String = if target.contains("windows") {
let ext = if target.contains("windows") {
".exe"
} else {
""
}
.into();
};
if let Some(bins) = &self.cargo_settings.bin {
let default_run = self
@ -899,9 +900,8 @@ impl AppSettings for RustAppSettings {
.clone()
.unwrap_or_default();
for bin in bins {
let name = format!("{}{}", bin.name, binary_extension);
let is_main =
bin.name == self.cargo_package_settings.name || bin.name.as_str() == default_run;
let name = format!("{}{}", bin.name, ext);
let is_main = bin.name == self.cargo_package_settings.name || bin.name == default_run;
binaries.push(BundleBinary::with_path(name, is_main, bin.path.clone()))
}
}
@ -912,12 +912,13 @@ impl AppSettings for RustAppSettings {
for entry in fs_bins {
let path = entry?.path();
if let Some(name) = path.file_stem() {
// see https://github.com/tauri-apps/tauri/pull/10977#discussion_r1759742414
let bin_exists = binaries.iter().any(|bin| {
bin.name() == name || path.ends_with(bin.src_path().unwrap_or(&"".to_string()))
});
if !bin_exists {
binaries.push(BundleBinary::new(
format!("{}{}", name.to_string_lossy(), &binary_extension),
format!("{}{}", name.to_string_lossy(), ext),
false,
))
}
@ -927,16 +928,13 @@ impl AppSettings for RustAppSettings {
if let Some(default_run) = self.package_settings.default_run.as_ref() {
if !binaries.iter_mut().any(|bin| bin.name() == default_run) {
binaries.push(BundleBinary::new(
format!("{}{}", default_run, binary_extension),
true,
));
binaries.push(BundleBinary::new(format!("{}{}", default_run, ext), true));
}
}
match binaries.len() {
0 => binaries.push(BundleBinary::new(
format!("{}{}", self.cargo_package_settings.name, &binary_extension),
format!("{}{}", self.cargo_package_settings.name, ext),
true,
)),
1 => binaries.get_mut(0).unwrap().set_main(true),

View File

@ -8,7 +8,9 @@ use crate::CommandExt;
use anyhow::Context;
use shared_child::SharedChild;
use std::{
fs,
io::{BufReader, ErrorKind, Write},
path::PathBuf,
process::{Command, ExitStatus, Stdio},
sync::{
atomic::{AtomicBool, Ordering},
@ -64,6 +66,7 @@ pub fn run_dev<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(
available_targets: &mut Option<Vec<RustupTarget>>,
config_features: Vec<String>,
app_settings: &RustAppSettings,
main_binary_name: Option<String>,
on_exit: F,
) -> crate::Result<impl DevProcess> {
let bin_path = app_settings.app_binary_path(&options)?;
@ -79,6 +82,9 @@ pub fn run_dev<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(
config_features,
move |status, reason| {
if status == Some(0) {
let main_binary_name = main_binary_name.as_deref();
let bin_path = rename_app(bin_path, main_binary_name).expect("failed to rename app");
let mut app = Command::new(bin_path);
app.stdout(os_pipe::dup_stdout().unwrap());
app.stderr(os_pipe::dup_stderr().unwrap());
@ -119,18 +125,19 @@ pub fn build(
app_settings: &RustAppSettings,
available_targets: &mut Option<Vec<RustupTarget>>,
config_features: Vec<String>,
) -> crate::Result<()> {
main_binary_name: Option<&str>,
) -> crate::Result<PathBuf> {
let out_dir = app_settings.out_dir(&options)?;
let bin_path = app_settings.app_binary_path(&options)?;
let out_dir = bin_path.parent().unwrap();
let bin_name = bin_path.file_stem().unwrap();
if !std::env::var("STATIC_VCRUNTIME").map_or(false, |v| v == "false") {
std::env::set_var("STATIC_VCRUNTIME", "true");
}
if options.target == Some("universal-apple-darwin".into()) {
std::fs::create_dir_all(out_dir).with_context(|| "failed to create project out directory")?;
std::fs::create_dir_all(&out_dir).with_context(|| "failed to create project out directory")?;
let bin_name = bin_path.file_stem().unwrap();
let mut lipo_cmd = Command::new("lipo");
lipo_cmd
@ -162,7 +169,7 @@ pub fn build(
.with_context(|| "failed to build app")?;
}
Ok(())
rename_app(bin_path, main_binary_name)
}
fn build_dev_app<F: FnOnce(Option<i32>, ExitReason) + Send + 'static>(
@ -363,6 +370,25 @@ fn validate_target(
Ok(())
}
fn rename_app(bin_path: PathBuf, main_binary_name: Option<&str>) -> crate::Result<PathBuf> {
if let Some(main_binary_name) = main_binary_name {
let new_path = bin_path
.with_file_name(main_binary_name)
.with_extension(bin_path.extension().unwrap_or_default());
fs::rename(&bin_path, &new_path).with_context(|| {
format!(
"failed to rename `{}` to `{}`",
tauri_utils::display_path(bin_path),
tauri_utils::display_path(&new_path),
)
})?;
Ok(new_path)
} else {
Ok(bin_path)
}
}
// taken from https://github.com/rust-lang/cargo/blob/78b10d4e611ab0721fc3aeaf0edd5dd8f4fdc372/src/cargo/core/shell.rs#L514
#[cfg(unix)]
mod terminal {

View File

@ -158,7 +158,9 @@ fn process_package_metadata(config: &mut Map<String, Value>) {
.map(|v| (v, "product-name"))
})
{
config.insert(key.into(), product_name);
config.insert(key.into(), product_name.clone());
// keep main binary name unchanged
config.insert("mainBinaryName".into(), product_name);
}
if let Some(version) = package_config.remove("version") {
@ -872,6 +874,10 @@ mod test {
// app information
assert_eq!(migrated["productName"], original["package"]["productName"]);
assert_eq!(
migrated["mainBinaryName"],
original["package"]["productName"]
);
assert_eq!(migrated["version"], original["package"]["version"]);
assert_eq!(
migrated["identifier"],

View File

@ -13,7 +13,7 @@ use crate::{
config::{get as get_tauri_config, ConfigHandle},
flock,
},
interface::{AppInterface, AppSettings, Interface, Options as InterfaceOptions},
interface::{AppInterface, Interface, Options as InterfaceOptions},
mobile::{write_options, CliOptions},
ConfigValue, Result,
};
@ -191,8 +191,7 @@ fn run_build(
};
let app_settings = interface.app_settings();
let bin_path = app_settings.app_binary_path(&interface_options)?;
let out_dir = bin_path.parent().unwrap();
let out_dir = app_settings.out_dir(&interface_options)?;
let _lock = flock::open_rw(out_dir.join("lock").with_extension("android"), "Android")?;
let cli_options = CliOptions {

View File

@ -13,7 +13,7 @@ use crate::{
config::{get as get_tauri_config, ConfigHandle},
flock,
},
interface::{AppInterface, AppSettings, Interface, MobileOptions, Options as InterfaceOptions},
interface::{AppInterface, Interface, MobileOptions, Options as InterfaceOptions},
mobile::{write_options, CliOptions, DevChild, DevProcess, TargetDevice},
ConfigValue, Result,
};
@ -186,8 +186,7 @@ fn run_dev(
};
let app_settings = interface.app_settings();
let bin_path = app_settings.app_binary_path(&interface_options)?;
let out_dir = bin_path.parent().unwrap();
let out_dir = app_settings.out_dir(&interface_options)?;
let _lock = flock::open_rw(out_dir.join("lock").with_extension("android"), "Android")?;
configure_cargo(&mut env, config)?;

View File

@ -271,12 +271,11 @@ fn run_build(
crate::build::setup(&interface, &mut build_options, tauri_config.clone(), true)?;
let app_settings = interface.app_settings();
let bin_path = app_settings.app_binary_path(&InterfaceOptions {
let out_dir = app_settings.out_dir(&InterfaceOptions {
debug: build_options.debug,
target: build_options.target.clone(),
..Default::default()
})?;
let out_dir = bin_path.parent().unwrap();
let _lock = flock::open_rw(out_dir.join("lock").with_extension("ios"), "iOS")?;
let cli_options = CliOptions {

View File

@ -13,7 +13,7 @@ use crate::{
config::{get as get_tauri_config, reload as reload_config, ConfigHandle},
flock,
},
interface::{AppInterface, AppSettings, Interface, MobileOptions, Options as InterfaceOptions},
interface::{AppInterface, Interface, MobileOptions, Options as InterfaceOptions},
mobile::{write_options, CliOptions, DevChild, DevProcess},
ConfigValue, Result,
};
@ -377,12 +377,11 @@ fn run_dev(
crate::dev::setup(&interface, &mut dev_options, tauri_config.clone())?;
let app_settings = interface.app_settings();
let bin_path = app_settings.app_binary_path(&InterfaceOptions {
let out_dir = app_settings.out_dir(&InterfaceOptions {
debug: !dev_options.release_mode,
target: dev_options.target.clone(),
..Default::default()
})?;
let out_dir = bin_path.parent().unwrap();
let _lock = flock::open_rw(out_dir.join("lock").with_extension("ios"), "iOS")?;
let set_host = options.host.is_some();

View File

@ -5,7 +5,7 @@
use super::{ensure_init, env, get_app, get_config, read_options, MobileTarget};
use crate::{
helpers::config::get as get_tauri_config,
interface::{AppInterface, AppSettings, Interface, Options as InterfaceOptions},
interface::{AppInterface, Interface, Options as InterfaceOptions},
mobile::ios::LIB_OUTPUT_FILE_NAME,
Result,
};
@ -215,14 +215,11 @@ pub fn command(options: Options) -> Result<()> {
target_env,
)?;
let bin_path = interface
.app_settings()
.app_binary_path(&InterfaceOptions {
debug: matches!(profile, Profile::Debug),
target: Some(rust_triple.into()),
..Default::default()
})?;
let out_dir = bin_path.parent().unwrap();
let out_dir = interface.app_settings().out_dir(&InterfaceOptions {
debug: matches!(profile, Profile::Debug),
target: Some(rust_triple.into()),
..Default::default()
})?;
let lib_path = out_dir.join(format!("lib{}.a", config.app().lib_name()));
if !lib_path.exists() {

View File

@ -282,14 +282,13 @@ pub fn get_app(target: Target, config: &TauriConfig, interface: &AppInterface) -
App::from_raw(tauri_dir().to_path_buf(), raw)
.unwrap()
.with_target_dir_resolver(move |target, profile| {
let bin_path = app_settings
.app_binary_path(&InterfaceOptions {
app_settings
.out_dir(&InterfaceOptions {
debug: matches!(profile, Profile::Debug),
target: Some(target.into()),
..Default::default()
})
.expect("failed to resolve target directory");
bin_path.parent().unwrap().to_path_buf()
.expect("failed to resolve target directory")
})
}

View File

@ -22,6 +22,13 @@
],
"pattern": "^[^/\\:*?\"<>|]+$"
},
"mainBinaryName": {
"description": "App main binary filename. Defaults to the name of your cargo crate.",
"type": [
"string",
"null"
]
},
"version": {
"description": "App version. It is a semver version number or a path to a `package.json` file containing the `version` field. If removed the version number from `Cargo.toml` is used.\n\n By default version 1.0 is used on Android.",
"type": [

View File

@ -2242,6 +2242,9 @@ pub struct Config {
#[serde(alias = "product-name")]
#[cfg_attr(feature = "schema", validate(regex(pattern = "^[^/\\:*?\"<>|]+$")))]
pub product_name: Option<String>,
/// App main binary filename. Defaults to the name of your cargo crate.
#[serde(alias = "main-binary-name")]
pub main_binary_name: Option<String>,
/// App version. It is a semver version number or a path to a `package.json` file containing the `version` field. If removed the version number from `Cargo.toml` is used.
///
/// By default version 1.0 is used on Android.
@ -2836,6 +2839,7 @@ mod build {
fn to_tokens(&self, tokens: &mut TokenStream) {
let schema = quote!(None);
let product_name = opt_str_lit(self.product_name.as_ref());
let main_binary_name = opt_str_lit(self.main_binary_name.as_ref());
let version = opt_str_lit(self.version.as_ref());
let identifier = str_lit(&self.identifier);
let app = &self.app;
@ -2848,6 +2852,7 @@ mod build {
::tauri::utils::config::Config,
schema,
product_name,
main_binary_name,
version,
identifier,
app,

View File

@ -312,7 +312,7 @@ fn resource_dir_from<P: AsRef<std::path::Path>>(
res = if curr_dir.ends_with("/data/usr/bin") {
// running from the deb bundle dir
exe_dir
.join(format!("../lib/{}", package_info.crate_name))
.join(format!("../lib/{}", package_info.name))
.canonicalize()
.map_err(Into::into)
} else if let Some(appdir) = &env.appdir {
@ -320,14 +320,11 @@ fn resource_dir_from<P: AsRef<std::path::Path>>(
Ok(PathBuf::from(format!(
"{}/usr/lib/{}",
appdir.display(),
package_info.crate_name
package_info.name
)))
} else {
// running bundle
Ok(PathBuf::from(format!(
"/usr/lib/{}",
package_info.crate_name
)))
Ok(PathBuf::from(format!("/usr/lib/{}", package_info.name)))
};
}

View File

@ -110,6 +110,7 @@ pub fn mock_context<R: Runtime, A: Assets<R>>(assets: A) -> crate::Context<R> {
config: Config {
schema: None,
product_name: Default::default(),
main_binary_name: Default::default(),
version: Default::default(),
identifier: Default::default(),
app: AppConfig {

View File

@ -1980,7 +1980,7 @@ tauri::Builder::default()
.set_progress_bar(crate::runtime::ProgressBarState {
status: progress_state.status,
progress: progress_state.progress,
desktop_filename: Some(format!("{}.desktop", self.package_info().crate_name)),
desktop_filename: Some(format!("{}.desktop", self.package_info().name)),
})
.map_err(Into::into)
}