mirror of
https://github.com/tauri-apps/tauri.git
synced 2025-01-01 23:42:33 +03:00
feat(bundler) bundle all binaries from the project (#726)
This commit is contained in:
parent
522c86a956
commit
055d777a42
6
.changes/bundler-binaries.md
Normal file
6
.changes/bundler-binaries.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-bundler": minor
|
||||
---
|
||||
|
||||
The bundler now bundles all binaries from your project ([[[bin]] target tables](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries)) and [src/bin folder](https://doc.rust-lang.org/cargo/guide/project-layout.html).
|
||||
When multiple binaries are used, make sure to use the [default-run](https://doc.rust-lang.org/cargo/reference/manifest.html#the-default-run-field) config field.
|
@ -15,8 +15,10 @@ mod tauri_config;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod wix;
|
||||
|
||||
pub use self::common::{print_error, print_finished, print_info};
|
||||
pub use self::settings::{BuildArtifact, PackageType, Settings};
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use self::common::print_info;
|
||||
pub use self::common::{print_error, print_finished};
|
||||
pub use self::settings::{PackageType, Settings};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -42,7 +42,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
};
|
||||
let package_base_name = format!(
|
||||
"{}_{}_{}",
|
||||
settings.binary_name(),
|
||||
settings.main_binary_name(),
|
||||
settings.version_string(),
|
||||
arch
|
||||
);
|
||||
@ -57,17 +57,17 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
remove_dir_all(&output_path)?;
|
||||
}
|
||||
std::fs::create_dir_all(output_path.clone())?;
|
||||
let app_dir_path = output_path.join(format!("{}.AppDir", settings.binary_name()));
|
||||
let appimage_path = output_path.join(format!("{}.AppImage", settings.binary_name()));
|
||||
let app_dir_path = output_path.join(format!("{}.AppDir", settings.main_binary_name()));
|
||||
let appimage_path = output_path.join(format!("{}.AppImage", settings.main_binary_name()));
|
||||
path_utils::create(app_dir_path.clone(), true)?;
|
||||
|
||||
let upcase = settings.binary_name().to_uppercase();
|
||||
let upcase_app_name = settings.main_binary_name().to_uppercase();
|
||||
|
||||
// setup data to insert into shell script
|
||||
let mut sh_map = BTreeMap::new();
|
||||
sh_map.insert("app_name", settings.binary_name());
|
||||
sh_map.insert("app_name", settings.main_binary_name());
|
||||
sh_map.insert("bundle_name", package_base_name.as_str());
|
||||
sh_map.insert("app_name_uppercase", upcase.as_str());
|
||||
sh_map.insert("app_name_uppercase", upcase_app_name.as_str());
|
||||
|
||||
// initialize shell script template.
|
||||
let temp = HANDLEBARS.render("appimage", &sh_map)?;
|
||||
|
@ -57,7 +57,9 @@ fn symlink_file(src: &Path, dst: &Path) -> io::Result<()> {
|
||||
/// Copies a regular file from one path to another, creating any parent
|
||||
/// directories of the destination path as necessary. Fails if the source path
|
||||
/// is a directory or doesn't exist.
|
||||
pub fn copy_file(from: &Path, to: &Path) -> crate::Result<()> {
|
||||
pub fn copy_file(from: impl AsRef<Path>, to: impl AsRef<Path>) -> crate::Result<()> {
|
||||
let from = from.as_ref();
|
||||
let to = to.as_ref();
|
||||
if !from.exists() {
|
||||
return Err(crate::Error::GenericError(format!(
|
||||
"{:?} does not exist",
|
||||
@ -212,6 +214,7 @@ pub fn print_warning(message: &str) -> crate::Result<()> {
|
||||
}
|
||||
|
||||
/// Prints a Info message to stderr.
|
||||
#[cfg(windows)]
|
||||
pub fn print_info(message: &str) -> crate::Result<()> {
|
||||
if let Some(mut output) = term::stderr() {
|
||||
safe_term_attr(&mut output, term::Attr::Bold)?;
|
||||
|
@ -48,7 +48,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
};
|
||||
let package_base_name = format!(
|
||||
"{}_{}_{}",
|
||||
settings.binary_name(),
|
||||
settings.main_binary_name(),
|
||||
settings.version_string(),
|
||||
arch
|
||||
);
|
||||
@ -93,12 +93,14 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
pub fn generate_data(settings: &Settings, package_dir: &Path) -> crate::Result<PathBuf> {
|
||||
// Generate data files.
|
||||
let data_dir = package_dir.join("data");
|
||||
let bin_name = settings.binary_name();
|
||||
let binary_dest = data_dir.join("usr/bin").join(bin_name);
|
||||
let bin_dir = data_dir.join("usr/bin");
|
||||
|
||||
common::copy_file(settings.binary_path(), &binary_dest)
|
||||
.with_context(|| "Failed to copy binary file")?;
|
||||
for bin in settings.binaries() {
|
||||
let bin_path = settings.binary_path(bin);
|
||||
common::copy_file(&bin_path, &bin_dir.join(bin.name()))
|
||||
.with_context(|| format!("Failed to copy binary from {:?}", bin_path))?;
|
||||
}
|
||||
|
||||
transfer_resource_files(settings, &data_dir).with_context(|| "Failed to copy resource files")?;
|
||||
|
||||
settings
|
||||
@ -119,7 +121,7 @@ pub fn generate_data(settings: &Settings, package_dir: &Path) -> crate::Result<P
|
||||
|
||||
/// Generates the bootstrap script file.
|
||||
fn generate_bootstrap_file(settings: &Settings, data_dir: &Path) -> crate::Result<()> {
|
||||
let bin_name = settings.binary_name();
|
||||
let bin_name = settings.main_binary_name();
|
||||
let bin_dir = data_dir.join("usr/bin");
|
||||
|
||||
let bootstrap_file_name = format!("__{}-bootstrapper", bin_name);
|
||||
@ -180,7 +182,7 @@ exit 0",
|
||||
|
||||
/// Generate the application desktop file and store it under the `data_dir`.
|
||||
fn generate_desktop_file(settings: &Settings, data_dir: &Path) -> crate::Result<()> {
|
||||
let bin_name = settings.binary_name();
|
||||
let bin_name = settings.main_binary_name();
|
||||
let desktop_file_name = format!("{}.desktop", bin_name);
|
||||
let desktop_file_path = data_dir
|
||||
.join("usr/share/applications")
|
||||
@ -293,7 +295,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 transfer_resource_files(settings: &Settings, data_dir: &Path) -> crate::Result<()> {
|
||||
let resource_dir = data_dir.join("usr/lib").join(settings.binary_name());
|
||||
let resource_dir = data_dir.join("usr/lib").join(settings.main_binary_name());
|
||||
settings.copy_resources(&resource_dir)
|
||||
}
|
||||
|
||||
@ -306,7 +308,7 @@ fn generate_icon_files(settings: &Settings, data_dir: &PathBuf) -> crate::Result
|
||||
width,
|
||||
height,
|
||||
if is_high_density { "@2x" } else { "" },
|
||||
settings.binary_name()
|
||||
settings.main_binary_name()
|
||||
))
|
||||
};
|
||||
let mut sizes = BTreeSet::new();
|
||||
|
@ -51,9 +51,13 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
generate_icon_files(&bundle_dir, settings).with_context(|| "Failed to create app icons")?;
|
||||
generate_info_plist(&bundle_dir, settings, &icon_filenames)
|
||||
.with_context(|| "Failed to create Info.plist")?;
|
||||
let bin_path = bundle_dir.join(&settings.bundle_name());
|
||||
common::copy_file(settings.binary_path(), &bin_path)
|
||||
.with_context(|| format!("Failed to copy binary from {:?}", settings.binary_path()))?;
|
||||
|
||||
for bin in settings.binaries() {
|
||||
let bin_path = settings.binary_path(bin);
|
||||
common::copy_file(&bin_path, &bundle_dir.join(bin.name()))
|
||||
.with_context(|| format!("Failed to copy binary from {:?}", bin_path))?;
|
||||
}
|
||||
|
||||
Ok(vec![bundle_dir])
|
||||
}
|
||||
|
||||
@ -159,7 +163,7 @@ fn generate_info_plist(
|
||||
write!(
|
||||
file,
|
||||
" <key>CFBundleExecutable</key>\n <string>{}</string>\n",
|
||||
settings.binary_name()
|
||||
settings.main_binary_name()
|
||||
)?;
|
||||
write!(
|
||||
file,
|
||||
|
@ -1,4 +1,3 @@
|
||||
use super::common;
|
||||
use super::settings::Settings;
|
||||
use super::wix;
|
||||
|
||||
|
@ -73,8 +73,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
.copy_binaries(&bin_dir)
|
||||
.with_context(|| "Failed to copy external binaries")?;
|
||||
|
||||
copy_binary_to_bundle(&bundle_directory, settings)
|
||||
.with_context(|| format!("Failed to copy binary from {:?}", settings.binary_path()))?;
|
||||
copy_binaries_to_bundle(&bundle_directory, settings)?;
|
||||
|
||||
let use_bootstrapper = settings.osx_use_bootstrapper();
|
||||
if use_bootstrapper {
|
||||
@ -84,13 +83,15 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
Ok(vec![app_bundle_path])
|
||||
}
|
||||
|
||||
// Copies the app's binary to the bundle.
|
||||
fn copy_binary_to_bundle(bundle_directory: &Path, settings: &Settings) -> crate::Result<()> {
|
||||
// Copies the app's binaries to the bundle.
|
||||
fn copy_binaries_to_bundle(bundle_directory: &Path, settings: &Settings) -> crate::Result<()> {
|
||||
let dest_dir = bundle_directory.join("MacOS");
|
||||
common::copy_file(
|
||||
settings.binary_path(),
|
||||
&dest_dir.join(settings.binary_name()),
|
||||
)
|
||||
for bin in settings.binaries() {
|
||||
let bin_path = settings.binary_path(bin);
|
||||
common::copy_file(&bin_path, &dest_dir.join(bin.name()))
|
||||
.with_context(|| format!("Failed to copy binary from {:?}", bin_path))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Creates the bootstrap script file.
|
||||
@ -179,7 +180,7 @@ fn create_info_plist(
|
||||
if use_bootstrapper {
|
||||
"__bootstrapper"
|
||||
} else {
|
||||
settings.binary_name()
|
||||
settings.main_binary_name()
|
||||
}
|
||||
)?;
|
||||
if let Some(path) = bundle_icon_file {
|
||||
|
@ -84,17 +84,6 @@ const ALL_PACKAGE_TYPES: &[PackageType] = &[
|
||||
PackageType::AppImage,
|
||||
];
|
||||
|
||||
/// The build artifact we're bundling.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum BuildArtifact {
|
||||
/// The main application.
|
||||
Main,
|
||||
/// A named binary which is inside of the [bin] section of your Cargo.toml.
|
||||
Bin(String),
|
||||
/// An example app of your crate.
|
||||
Example(String),
|
||||
}
|
||||
|
||||
/// The bundle settings of the BuildArtifact we're bundling.
|
||||
#[derive(Clone, Debug, Deserialize, Default)]
|
||||
struct BundleSettings {
|
||||
@ -207,6 +196,8 @@ struct PackageSettings {
|
||||
authors: Option<Vec<String>>,
|
||||
/// the package's metadata.
|
||||
metadata: Option<MetadataSettings>,
|
||||
/// the default binary to run.
|
||||
default_run: Option<String>,
|
||||
}
|
||||
|
||||
/// The `workspace` section of the app configuration (read from Cargo.toml).
|
||||
@ -216,6 +207,12 @@ struct WorkspaceSettings {
|
||||
members: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct BinarySettings {
|
||||
name: String,
|
||||
path: Option<String>,
|
||||
}
|
||||
|
||||
/// The Cargo settings (Cargo.toml root descriptor).
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct CargoSettings {
|
||||
@ -227,6 +224,43 @@ struct CargoSettings {
|
||||
///
|
||||
/// it's present if the read Cargo.toml belongs to a workspace root.
|
||||
workspace: Option<WorkspaceSettings>,
|
||||
/// the binary targets configuration.
|
||||
bin: Option<Vec<BinarySettings>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BundleBinary {
|
||||
name: String,
|
||||
src_path: Option<String>,
|
||||
main: bool,
|
||||
}
|
||||
|
||||
impl BundleBinary {
|
||||
pub fn new(name: String, main: bool) -> Self {
|
||||
Self {
|
||||
name: if cfg!(windows) {
|
||||
format!("{}.exe", name)
|
||||
} else {
|
||||
name
|
||||
},
|
||||
src_path: None,
|
||||
main,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_src_path(mut self, src_path: Option<String>) -> Self {
|
||||
self.src_path = src_path;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &String {
|
||||
&self.name
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn main(&self) -> bool {
|
||||
self.main
|
||||
}
|
||||
}
|
||||
|
||||
/// The Settings exposed by the module.
|
||||
@ -244,16 +278,12 @@ pub struct Settings {
|
||||
features: Option<Vec<String>>,
|
||||
/// the directory where the bundles will be placed.
|
||||
project_out_directory: PathBuf,
|
||||
/// the type of build artifact we're bundling.
|
||||
build_artifact: BuildArtifact,
|
||||
/// whether we should build the app with release mode or not.
|
||||
is_release: bool,
|
||||
/// the path to the binary (project_out_directory + bin_name).
|
||||
binary_path: PathBuf,
|
||||
/// the binary name we're bundling.
|
||||
binary_name: String,
|
||||
/// the bundle settings.
|
||||
bundle_settings: BundleSettings,
|
||||
/// the binaries to bundle.
|
||||
binaries: Vec<BundleBinary>,
|
||||
}
|
||||
|
||||
impl CargoSettings {
|
||||
@ -294,13 +324,6 @@ impl Settings {
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
let build_artifact = if let Some(bin) = matches.value_of("bin") {
|
||||
BuildArtifact::Bin(bin.to_string())
|
||||
} else if let Some(example) = matches.value_of("example") {
|
||||
BuildArtifact::Example(example.to_string())
|
||||
} else {
|
||||
BuildArtifact::Main
|
||||
};
|
||||
let is_release = matches.is_present("release");
|
||||
let target = match matches.value_of("target") {
|
||||
Some(triple) => Some((triple.to_string(), TargetInfo::from_str(triple)?)),
|
||||
@ -329,7 +352,7 @@ impl Settings {
|
||||
}
|
||||
};
|
||||
let workspace_dir = Settings::get_workspace_dir(¤t_dir);
|
||||
let target_dir = Settings::get_target_dir(&workspace_dir, &target, is_release, &build_artifact);
|
||||
let target_dir = Settings::get_target_dir(&workspace_dir, &target, is_release);
|
||||
let bundle_settings = match tauri_config {
|
||||
Ok(config) => merge_settings(BundleSettings::default(), config.tauri.bundle),
|
||||
Err(e) => {
|
||||
@ -353,23 +376,49 @@ impl Settings {
|
||||
}
|
||||
}
|
||||
};
|
||||
let (bundle_settings, binary_name) = match build_artifact {
|
||||
BuildArtifact::Main => (bundle_settings, package.name.clone()),
|
||||
BuildArtifact::Bin(ref name) => (
|
||||
bundle_settings_from_table(&bundle_settings.bin, "bin", name)?,
|
||||
name.clone(),
|
||||
),
|
||||
BuildArtifact::Example(ref name) => (
|
||||
bundle_settings_from_table(&bundle_settings.example, "example", name)?,
|
||||
name.clone(),
|
||||
),
|
||||
};
|
||||
let binary_name = if cfg!(windows) {
|
||||
format!("{}.{}", &binary_name, "exe")
|
||||
} else {
|
||||
binary_name
|
||||
};
|
||||
let binary_path = target_dir.join(&binary_name);
|
||||
|
||||
let mut binaries: Vec<BundleBinary> = vec![];
|
||||
if let Some(bin) = cargo_settings.bin {
|
||||
let default_run = package.default_run.clone().unwrap_or("".to_string());
|
||||
for binary in bin {
|
||||
binaries.push(
|
||||
BundleBinary::new(
|
||||
binary.name.clone(),
|
||||
binary.name.as_str() == package.name || binary.name.as_str() == default_run,
|
||||
)
|
||||
.set_src_path(binary.path),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let mut bins_path = PathBuf::from(current_dir);
|
||||
bins_path.push("src/bin");
|
||||
if let Ok(fs_bins) = std::fs::read_dir(bins_path) {
|
||||
for entry in fs_bins {
|
||||
let path = entry?.path();
|
||||
if let Some(name) = path.file_stem() {
|
||||
if !binaries.iter().any(|bin| {
|
||||
bin.name.as_str() == name
|
||||
|| path.ends_with(bin.src_path.as_ref().unwrap_or(&"".to_string()))
|
||||
}) {
|
||||
binaries.push(BundleBinary::new(name.to_string_lossy().to_string(), false))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(default_run) = package.default_run.as_ref() {
|
||||
if !binaries.iter().any(|bin| bin.name.as_str() == default_run) {
|
||||
binaries.push(BundleBinary::new(default_run.to_string(), true));
|
||||
}
|
||||
}
|
||||
|
||||
if binaries.len() == 1 {
|
||||
binaries.get_mut(0).and_then(|bin| {
|
||||
bin.main = true;
|
||||
Some(bin)
|
||||
});
|
||||
}
|
||||
|
||||
let bundle_settings = parse_external_bin(bundle_settings)?;
|
||||
|
||||
@ -378,11 +427,9 @@ impl Settings {
|
||||
package_types,
|
||||
target,
|
||||
features,
|
||||
build_artifact,
|
||||
is_release,
|
||||
project_out_directory: target_dir,
|
||||
binary_path,
|
||||
binary_name,
|
||||
binaries,
|
||||
bundle_settings,
|
||||
})
|
||||
}
|
||||
@ -393,16 +440,12 @@ impl Settings {
|
||||
project_root_dir: &PathBuf,
|
||||
target: &Option<(String, TargetInfo)>,
|
||||
is_release: bool,
|
||||
build_artifact: &BuildArtifact,
|
||||
) -> PathBuf {
|
||||
let mut path = project_root_dir.join("target");
|
||||
if let &Some((ref triple, _)) = target {
|
||||
path.push(triple);
|
||||
}
|
||||
path.push(if is_release { "release" } else { "debug" });
|
||||
if let &BuildArtifact::Example(_) = build_artifact {
|
||||
path.push("examples");
|
||||
}
|
||||
path
|
||||
}
|
||||
|
||||
@ -454,13 +497,25 @@ impl Settings {
|
||||
}
|
||||
|
||||
/// Returns the file name of the binary being bundled.
|
||||
pub fn binary_name(&self) -> &str {
|
||||
&self.binary_name
|
||||
pub fn main_binary_name(&self) -> &str {
|
||||
self
|
||||
.binaries
|
||||
.iter()
|
||||
.find(|bin| bin.main)
|
||||
.expect("failed to find main binary")
|
||||
.name
|
||||
.as_str()
|
||||
}
|
||||
|
||||
/// Returns the path to the binary being bundled.
|
||||
pub fn binary_path(&self) -> &Path {
|
||||
&self.binary_path
|
||||
/// Returns the path to the specified binary.
|
||||
pub fn binary_path(&self, binary: &BundleBinary) -> PathBuf {
|
||||
let mut path = self.project_out_directory.clone();
|
||||
path.push(binary.name());
|
||||
path
|
||||
}
|
||||
|
||||
pub fn binaries(&self) -> &Vec<BundleBinary> {
|
||||
&self.binaries
|
||||
}
|
||||
|
||||
/// If a list of package types was specified by the command-line, returns
|
||||
@ -524,11 +579,6 @@ impl Settings {
|
||||
self.features.to_owned()
|
||||
}
|
||||
|
||||
/// Returns the artifact that is being bundled.
|
||||
pub fn build_artifact(&self) -> &BuildArtifact {
|
||||
&self.build_artifact
|
||||
}
|
||||
|
||||
/// Returns true if the bundle is being compiled in release mode, false if
|
||||
/// it's being compiled in debug mode.
|
||||
pub fn is_release_build(&self) -> bool {
|
||||
@ -719,23 +769,6 @@ impl Settings {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the bundle settings from a map.
|
||||
/// It can be used to get the bundle settings from the [example] or [bin] section of Cargo.toml
|
||||
fn bundle_settings_from_table(
|
||||
opt_map: &Option<HashMap<String, BundleSettings>>,
|
||||
map_name: &str,
|
||||
bundle_name: &str,
|
||||
) -> crate::Result<BundleSettings> {
|
||||
if let Some(bundle_settings) = opt_map.as_ref().and_then(|map| map.get(bundle_name)) {
|
||||
Ok(bundle_settings.clone())
|
||||
} else {
|
||||
return Err(crate::Error::GenericError(format!(
|
||||
"No 'bundle:{}:{}' keys section in the tauri.conf.json file",
|
||||
map_name, bundle_name
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses the external binaries to bundle, adding the target triple suffix to each of them.
|
||||
fn parse_external_bin(bundle_settings: BundleSettings) -> crate::Result<BundleSettings> {
|
||||
let target_triple = target_triple()?;
|
||||
|
@ -70,9 +70,9 @@
|
||||
<Component Id="Path" Guid="{{{path_component_guid}}}" Win64="$(var.Win64)">
|
||||
<File Id="Path" Source="{{{app_exe_source}}}" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
{{#each external_binaries as |external_bin| ~}}
|
||||
<Component Id="{{ external_bin.id }}" Guid="{{external_bin.guid}}" Win64="$(var.Win64)">
|
||||
<File Id="Path_{{ external_bin.id }}" Source="{{external_bin.path}}" KeyPath="yes"/>
|
||||
{{#each binaries as |bin| ~}}
|
||||
<Component Id="{{ bin.id }}" Guid="{{bin.guid}}" Win64="$(var.Win64)">
|
||||
<File Id="Path_{{ bin.id }}" Source="{{bin.path}}" KeyPath="yes"/>
|
||||
</Component>
|
||||
{{/each~}}
|
||||
{{{resources}}}
|
||||
@ -140,8 +140,8 @@
|
||||
Level="1"
|
||||
Absent="allow">
|
||||
<ComponentRef Id="Path"/>
|
||||
{{#each external_binaries as |external_bin| ~}}
|
||||
<ComponentRef Id="{{ external_bin.id }}"/>
|
||||
{{#each binaries as |bin| ~}}
|
||||
<ComponentRef Id="{{ bin.id }}"/>
|
||||
{{/each~}}
|
||||
</Feature>
|
||||
</Feature>
|
||||
|
@ -57,15 +57,16 @@ lazy_static! {
|
||||
/// Mapper between a resource directory name and its ResourceDirectory descriptor.
|
||||
type ResourceMap = BTreeMap<String, ResourceDirectory>;
|
||||
|
||||
/// An external binary to bundle with WIX.
|
||||
/// A binary to bundle with WIX.
|
||||
/// External binaries or additional project binaries are represented with this data structure.
|
||||
/// This data structure is needed because WIX requires each path to have its own `id` and `guid`.
|
||||
#[derive(Serialize)]
|
||||
struct ExternalBinary {
|
||||
struct Binary {
|
||||
/// the GUID to use on the WIX XML.
|
||||
guid: String,
|
||||
/// the id to use on the WIX XML.
|
||||
id: String,
|
||||
/// the external binary path.
|
||||
/// the binary path.
|
||||
path: String,
|
||||
}
|
||||
|
||||
@ -135,8 +136,7 @@ impl ResourceDirectory {
|
||||
/// Copies the icons to the binary path, under the `resources` folder,
|
||||
/// and returns the path to that directory.
|
||||
fn copy_icons(settings: &Settings) -> crate::Result<PathBuf> {
|
||||
let base_dir = settings.binary_path();
|
||||
let base_dir = base_dir.parent().expect("Failed to get dir");
|
||||
let base_dir = settings.project_out_directory();
|
||||
|
||||
let resource_dir = base_dir.join("resources");
|
||||
|
||||
@ -323,11 +323,20 @@ fn run_candle(
|
||||
}
|
||||
};
|
||||
|
||||
let main_binary = settings
|
||||
.binaries()
|
||||
.iter()
|
||||
.find(|bin| bin.main())
|
||||
.ok_or_else(|| anyhow::anyhow!("Failed to get main binary"))?;
|
||||
|
||||
let args = vec![
|
||||
"-arch".to_string(),
|
||||
arch.to_string(),
|
||||
wxs_file_name.to_string(),
|
||||
format!("-dSourceDir={}", settings.binary_path().display()),
|
||||
format!(
|
||||
"-dSourceDir={}",
|
||||
settings.binary_path(main_binary).display()
|
||||
),
|
||||
];
|
||||
|
||||
let candle_exe = wix_toolset_path.join("candle.exe");
|
||||
@ -434,7 +443,7 @@ pub fn build_wix_app_installer(
|
||||
data.insert("manufacturer", to_json(manufacturer.as_str()));
|
||||
let upgrade_code = Uuid::new_v5(
|
||||
&Uuid::NAMESPACE_DNS,
|
||||
format!("{}.app.x64", &settings.binary_name()).as_bytes(),
|
||||
format!("{}.app.x64", &settings.main_binary_name()).as_bytes(),
|
||||
)
|
||||
.to_string();
|
||||
|
||||
@ -446,13 +455,13 @@ 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()));
|
||||
|
||||
let app_exe_name = settings.binary_name().to_string();
|
||||
let app_exe_name = settings.main_binary_name().to_string();
|
||||
data.insert("app_exe_name", to_json(&app_exe_name));
|
||||
|
||||
let external_binaries = generate_external_binary_data(&settings)?;
|
||||
let binaries = generate_binaries_data(&settings)?;
|
||||
|
||||
let external_binaries_json = to_json(&external_binaries);
|
||||
data.insert("external_binaries", external_binaries_json);
|
||||
let binaries_json = to_json(&binaries);
|
||||
data.insert("binaries", binaries_json);
|
||||
|
||||
let resources = generate_resource_data(&settings)?;
|
||||
let mut resources_wix_string = String::from("");
|
||||
@ -468,7 +477,12 @@ pub fn build_wix_app_installer(
|
||||
data.insert("resources", to_json(resources_wix_string));
|
||||
data.insert("resource_file_ids", to_json(files_ids));
|
||||
|
||||
let app_exe_source = settings.binary_path().display().to_string();
|
||||
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).display().to_string();
|
||||
|
||||
data.insert("app_exe_source", to_json(&app_exe_source));
|
||||
|
||||
@ -508,9 +522,9 @@ pub fn build_wix_app_installer(
|
||||
Ok(target)
|
||||
}
|
||||
|
||||
/// Generates the data required for the external binaries bundling.
|
||||
fn generate_external_binary_data(settings: &Settings) -> crate::Result<Vec<ExternalBinary>> {
|
||||
let mut external_binaries = Vec::new();
|
||||
/// Generates the data required for the external binaries and extra binaries bundling.
|
||||
fn generate_binaries_data(settings: &Settings) -> crate::Result<Vec<Binary>> {
|
||||
let mut binaries = Vec::new();
|
||||
let regex = Regex::new(r"[^\w\d\.]")?;
|
||||
let cwd = std::env::current_dir()?;
|
||||
for src in settings.external_binaries() {
|
||||
@ -524,8 +538,8 @@ fn generate_external_binary_data(settings: &Settings) -> crate::Result<Vec<Exter
|
||||
|
||||
let guid = generate_guid(filename.as_bytes()).to_string();
|
||||
|
||||
external_binaries.push(ExternalBinary {
|
||||
guid: guid,
|
||||
binaries.push(Binary {
|
||||
guid,
|
||||
path: cwd
|
||||
.join(src)
|
||||
.into_os_string()
|
||||
@ -535,7 +549,23 @@ fn generate_external_binary_data(settings: &Settings) -> crate::Result<Vec<Exter
|
||||
});
|
||||
}
|
||||
|
||||
Ok(external_binaries)
|
||||
for bin in settings.binaries() {
|
||||
let filename = bin.name();
|
||||
let guid = generate_guid(filename.as_bytes()).to_string();
|
||||
if !bin.main() {
|
||||
binaries.push(Binary {
|
||||
guid,
|
||||
path: settings
|
||||
.binary_path(bin)
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("failed to read binary path"),
|
||||
id: regex.replace_all(&filename, "").to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Ok(binaries)
|
||||
}
|
||||
|
||||
/// Generates the data required for the resource bundling on wix
|
||||
|
@ -2,9 +2,9 @@ mod bundle;
|
||||
mod error;
|
||||
pub use error::{Error, Result};
|
||||
|
||||
use crate::bundle::{
|
||||
bundle_project, check_icons, print_info, BuildArtifact, PackageType, Settings,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use crate::bundle::print_info;
|
||||
use crate::bundle::{bundle_project, check_icons, PackageType, Settings};
|
||||
|
||||
use clap::{crate_version, App, AppSettings, Arg, SubCommand};
|
||||
|
||||
@ -16,18 +16,11 @@ use std::process;
|
||||
// Runs `cargo build` to make sure the binary file is up-to-date.
|
||||
fn build_project_if_unbuilt(settings: &Settings) -> crate::Result<()> {
|
||||
let mut args = vec!["build".to_string()];
|
||||
|
||||
if let Some(triple) = settings.target_triple() {
|
||||
args.push(format!("--target={}", triple));
|
||||
}
|
||||
match settings.build_artifact() {
|
||||
&BuildArtifact::Main => {}
|
||||
&BuildArtifact::Bin(ref name) => {
|
||||
args.push(format!("--bin={}", name));
|
||||
}
|
||||
&BuildArtifact::Example(ref name) => {
|
||||
args.push(format!("--example={}", name));
|
||||
}
|
||||
}
|
||||
|
||||
if settings.is_release_build() {
|
||||
args.push("--release".to_string());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user