Skip to content

Commit

Permalink
feat(bundler): Add support for creating NSIS bundles on unix hosts (#…
Browse files Browse the repository at this point in the history
…5788)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
  • Loading branch information
FabianLars and lucasfernog committed Jan 19, 2023
1 parent 35b587c commit 60e6f6c
Show file tree
Hide file tree
Showing 23 changed files with 317 additions and 152 deletions.
9 changes: 9 additions & 0 deletions .changes/nsis-linux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"tauri-bundler": minor
"tauri-utils": minor
"cli.rs": minor
"cli.js": minor
"tauri-build": minor
---

Add initial support for building `nsis` bundles on non-Windows platforms.
4 changes: 2 additions & 2 deletions core/tauri-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ serde_json = "1"
heck = "0.4"
json-patch = "0.3"

[target."cfg(windows)".dependencies]
winres = "0.1"
# dependencies for Windows targets
tauri-winres = "0.1"
semver = "1"

[features]
Expand Down
21 changes: 10 additions & 11 deletions core/tauri-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use std::path::{Path, PathBuf};

#[cfg(feature = "codegen")]
mod codegen;
#[cfg(windows)]
mod static_vcruntime;

#[cfg(feature = "codegen")]
Expand Down Expand Up @@ -344,25 +343,25 @@ pub fn try_build(attributes: Attributes) -> Result<()> {

#[allow(unused_mut, clippy::redundant_clone)]
let mut resources = config.tauri.bundle.resources.clone().unwrap_or_default();
#[cfg(windows)]
if let Some(fixed_webview2_runtime_path) = &config.tauri.bundle.windows.webview_fixed_runtime_path
{
resources.push(fixed_webview2_runtime_path.display().to_string());
if target_triple.contains("windows") {
if let Some(fixed_webview2_runtime_path) =
&config.tauri.bundle.windows.webview_fixed_runtime_path
{
resources.push(fixed_webview2_runtime_path.display().to_string());
}
}
copy_resources(ResourcePaths::new(resources.as_slice(), true), target_dir)?;

#[cfg(target_os = "macos")]
{
if let Some(version) = config.tauri.bundle.macos.minimum_system_version {
if target_triple.contains("darwin") {
if let Some(version) = &config.tauri.bundle.macos.minimum_system_version {
println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET={}", version);
}
}

#[cfg(windows)]
{
if target_triple.contains("windows") {
use anyhow::Context;
use semver::Version;
use winres::{VersionInfo, WindowsResource};
use tauri_winres::{VersionInfo, WindowsResource};

fn find_icon<F: Fn(&&String) -> bool>(config: &Config, predicate: F, default: &str) -> PathBuf {
let icon_path = config
Expand Down
2 changes: 1 addition & 1 deletion core/tauri-build/src/static_vcruntime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn override_msvcrt_lib() {
let f = fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(&path);
.open(path);
if let Ok(mut f) = f {
f.write_all(machine).unwrap();
f.write_all(bytes).unwrap();
Expand Down
21 changes: 11 additions & 10 deletions examples/api/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 12 additions & 7 deletions tooling/bundler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,23 @@ tempfile = "3.3.0"
log = { version = "0.4.17", features = [ "kv_unstable" ] }
dirs-next = "2.0"
encoding_rs = "0.8"
os_pipe = "1"

[target."cfg(target_os = \"windows\")".dependencies]
# dependencies for Windows targets
attohttpc = "0.24"
hex = "0.4"
semver = "1"
sha1 = "0.10"
sha2 = "0.10"
zip = "0.6"

# dependencies for code signing on Windows hosts
[target."cfg(target_os = \"windows\")".dependencies]
uuid = { version = "1", features = [ "v4", "v5" ] }
bitness = "0.4"
winreg = "0.10"
sha2 = "0.10"
sha1 = "0.10"
hex = "0.4"
winreg = "0.10" # Can only be compiled for Windows hosts
glob = "0.3"
zip = "0.6"
semver = "1"


[target."cfg(target_os = \"macos\")".dependencies]
icns = { package = "tauri-icns", version = "0.1" }
Expand Down
22 changes: 17 additions & 5 deletions tooling/bundler/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ mod path_utils;
mod platform;
mod settings;
mod updater_bundle;
#[cfg(target_os = "windows")]
mod windows;

pub use self::{
Expand Down Expand Up @@ -43,25 +42,38 @@ pub fn bundle_project(settings: Settings) -> crate::Result<Vec<Bundle>> {
let mut bundles = Vec::new();
let package_types = settings.package_types()?;

let target_os = settings
.target()
.split('-')
.nth(2)
.unwrap_or(std::env::consts::OS)
.replace("darwin", "macos");

if target_os != std::env::consts::OS {
warn!("Cross-platform compilation is experimental and does not support all features. Please use a matching host system for full compatibility.");
}

for package_type in &package_types {
let bundle_paths = match package_type {
#[cfg(target_os = "macos")]
PackageType::MacOsBundle => macos::app::bundle_project(&settings)?,
#[cfg(target_os = "macos")]
PackageType::IosBundle => macos::ios::bundle_project(&settings)?,
// dmg is dependant of MacOsBundle, we send our bundles to prevent rebuilding
#[cfg(target_os = "macos")]
PackageType::Dmg => macos::dmg::bundle_project(&settings, &bundles)?,

#[cfg(target_os = "windows")]
PackageType::WindowsMsi => windows::msi::bundle_project(&settings, false)?,
#[cfg(target_os = "windows")]
PackageType::Nsis => windows::nsis::bundle_project(&settings, false)?,

#[cfg(target_os = "linux")]
PackageType::Deb => linux::debian::bundle_project(&settings)?,
#[cfg(target_os = "linux")]
PackageType::Rpm => linux::rpm::bundle_project(&settings)?,
#[cfg(target_os = "linux")]
PackageType::AppImage => linux::appimage::bundle_project(&settings)?,
// dmg is dependant of MacOsBundle, we send our bundles to prevent rebuilding
#[cfg(target_os = "macos")]
PackageType::Dmg => macos::dmg::bundle_project(&settings, &bundles)?,

// updater is dependant of multiple bundle, we send our bundles to prevent rebuilding
PackageType::Updater => updater_bundle::bundle_project(&settings, &bundles)?,
_ => {
Expand Down
14 changes: 13 additions & 1 deletion tooling/bundler/src/bundle/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::{
fs::{self, File},
io::{self, BufReader, BufWriter},
path::Path,
process::{Command, Output, Stdio},
process::{Command, ExitStatus, Output, Stdio},
sync::{Arc, Mutex},
};

Expand Down Expand Up @@ -136,10 +136,22 @@ pub fn copy_dir(from: &Path, to: &Path) -> crate::Result<()> {
}

pub trait CommandExt {
// The `pipe` function sets the stdout and stderr to properly
// show the command output in the Node.js wrapper.
fn piped(&mut self) -> std::io::Result<ExitStatus>;
fn output_ok(&mut self) -> crate::Result<Output>;
}

impl CommandExt for Command {
fn piped(&mut self) -> std::io::Result<ExitStatus> {
self.stdout(os_pipe::dup_stdout()?);
self.stderr(os_pipe::dup_stderr()?);
let program = self.get_program().to_string_lossy().into_owned();
debug!(action = "Running"; "Command `{} {}`", program, self.get_args().map(|arg| arg.to_string_lossy()).fold(String::new(), |acc, arg| format!("{acc} {arg}")));

self.status().map_err(Into::into)
}

fn output_ok(&mut self) -> crate::Result<Output> {
let program = self.get_program().to_string_lossy().into_owned();
debug!(action = "Running"; "Command `{} {}`", program, self.get_args().map(|arg| arg.to_string_lossy()).fold(String::new(), |acc, arg| format!("{} {}", acc, arg)));
Expand Down
31 changes: 29 additions & 2 deletions tooling/bundler/src/bundle/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,8 @@ impl BundleBinary {
/// The Settings exposed by the module.
#[derive(Clone, Debug)]
pub struct Settings {
/// The log level.
log_level: log::Level,
/// the package settings.
package: PackageSettings,
/// the package types we're bundling.
Expand All @@ -453,6 +455,7 @@ pub struct Settings {
/// A builder for [`Settings`].
#[derive(Default)]
pub struct SettingsBuilder {
log_level: Option<log::Level>,
project_out_directory: Option<PathBuf>,
package_types: Option<Vec<PackageType>>,
package_settings: Option<PackageSettings>,
Expand Down Expand Up @@ -511,6 +514,13 @@ impl SettingsBuilder {
self
}

/// Sets the log level for spawned commands. Defaults to [`log::Level::Error`].
#[must_use]
pub fn log_level(mut self, level: log::Level) -> Self {
self.log_level.replace(level);
self
}

/// Builds a Settings from the CLI args.
///
/// Package settings will be read from Cargo.toml.
Expand All @@ -524,6 +534,7 @@ impl SettingsBuilder {
};

Ok(Settings {
log_level: self.log_level.unwrap_or(log::Level::Error),
package: self.package_settings.expect("package settings is required"),
package_types: self.package_types,
project_out_directory: self
Expand All @@ -544,6 +555,16 @@ impl SettingsBuilder {
}

impl Settings {
/// Sets the log level for spawned commands.
pub fn set_log_level(&mut self, level: log::Level) {
self.log_level = level;
}

/// Returns the log level for spawned commands.
pub fn log_level(&self) -> log::Level {
self.log_level
}

/// Returns the directory where the bundle should be placed.
pub fn project_out_directory(&self) -> &Path {
&self.project_out_directory
Expand Down Expand Up @@ -604,8 +625,14 @@ impl Settings {
///
/// Fails if the host/target's native package type is not supported.
pub fn package_types(&self) -> crate::Result<Vec<PackageType>> {
let target_os = std::env::consts::OS;
let mut platform_types = match target_os {
let target_os = self
.target
.split('-')
.nth(2)
.unwrap_or(std::env::consts::OS)
.replace("darwin", "macos");

let mut platform_types = match target_os.as_str() {
"macos" => vec![PackageType::MacOsBundle, PackageType::Dmg],
"ios" => vec![PackageType::IosBundle],
"linux" => vec![PackageType::Deb, PackageType::AppImage],
Expand Down
Loading

0 comments on commit 60e6f6c

Please sign in to comment.