Skip to content

Commit 232265c

Browse files
feat: bundle type detection at runtime via binary patching (#13209)
* patch binary with bundle type info * only patch if the updater is included * fix linux warnings * patch binary when updaer is configured * patch binary with bundle type info only patch if the updater is included fix linux warnings patch binary when updaer is configured * fix formatting * fix license header * fix taplo error * move __TAURI_BUNDLE_TYPE to utils * export get_current_bundle_type * macos fix * cleanup, add api * update change file * fix windows * fmt, fix rust version support * fix macos --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
1 parent 02440b8 commit 232265c

File tree

19 files changed

+376
-62
lines changed

19 files changed

+376
-62
lines changed

.changes/app-bundle-type.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@tauri-apps/api": patch:feat
3+
---
4+
5+
Added `getBundleType` to the app module.

.changes/patch-binaries.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
tauri-cli: patch:enhance
3+
---
4+
5+
Binaries are patched before bundling to add the type of a bundle they will placed in. This information will be used during update process to select the correct target.

.changes/platform-bundle-type.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-utils": patch:feat
3+
---
4+
5+
Added `platform::bundle_type`.

.gitignore

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,55 @@
1-
# dependency directories
2-
node_modules/
3-
4-
# Optional npm and yarn cache directory
5-
.npm/
6-
.yarn/
7-
8-
# Output of 'npm pack'
9-
*.tgz
10-
11-
# dotenv environment variables file
12-
.env
13-
14-
# .vscode workspace settings file
15-
.vscode/settings.json
16-
.vscode/launch.json
17-
.vscode/tasks.json
18-
19-
# npm, yarn and bun lock files
20-
package-lock.json
21-
yarn.lock
22-
bun.lockb
23-
24-
# rust compiled folders
25-
target/
26-
27-
# test video for streaming example
28-
streaming_example_test_video.mp4
29-
30-
# examples /gen directory
31-
/examples/**/src-tauri/gen/
32-
/bench/**/src-tauri/gen/
33-
34-
# logs
35-
logs
36-
*.log
37-
npm-debug.log*
38-
yarn-debug.log*
39-
yarn-error.log*
40-
41-
# runtime data
42-
pids
43-
*.pid
44-
*.seed
45-
*.pid.lock
46-
47-
# miscellaneous
48-
/.vs
49-
.DS_Store
50-
.Thumbs.db
51-
*.sublime*
52-
.idea
53-
debug.log
54-
TODO.md
1+
# dependency directories
2+
node_modules/
3+
4+
# Optional npm and yarn cache directory
5+
.npm/
6+
.yarn/
7+
8+
# Output of 'npm pack'
9+
*.tgz
10+
11+
# dotenv environment variables file
12+
.env
13+
14+
# .vscode workspace settings file
15+
.vscode/settings.json
16+
.vscode/launch.json
17+
.vscode/tasks.json
18+
19+
# npm, yarn and bun lock files
20+
package-lock.json
21+
yarn.lock
22+
bun.lockb
23+
24+
# rust compiled folders
25+
target/
26+
27+
# test video for streaming example
28+
streaming_example_test_video.mp4
29+
30+
# examples /gen directory
31+
/examples/**/src-tauri/gen/
32+
/bench/**/src-tauri/gen/
33+
34+
# logs
35+
logs
36+
*.log
37+
npm-debug.log*
38+
yarn-debug.log*
39+
yarn-error.log*
40+
41+
# runtime data
42+
pids
43+
*.pid
44+
*.seed
45+
*.pid.lock
46+
47+
# miscellaneous
48+
/.vs
49+
.DS_Store
50+
.Thumbs.db
51+
*.sublime*
52+
.idea
53+
debug.log
54+
TODO.md
55+
.aider*

Cargo.lock

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/tauri-bundler/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ dunce = "1"
4343
url = "2"
4444
uuid = { version = "1", features = ["v4", "v5"] }
4545
regex = "1"
46+
goblin = "0.9"
4647

4748
[target."cfg(target_os = \"windows\")".dependencies]
4849
bitness = "0.4"

crates/tauri-bundler/src/bundle.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,32 @@ mod windows;
1515

1616
use tauri_utils::{display_path, platform::Target as TargetPlatform};
1717

18+
/// Patch a binary with bundle type information
19+
fn patch_binary(binary: &PathBuf, package_type: &PackageType) -> crate::Result<()> {
20+
match package_type {
21+
#[cfg(target_os = "linux")]
22+
PackageType::AppImage | PackageType::Deb | PackageType::Rpm => {
23+
log::info!(
24+
"Patching binary {:?} for type {}",
25+
binary,
26+
package_type.short_name()
27+
);
28+
linux::patch_binary(binary, package_type)?;
29+
}
30+
PackageType::Nsis | PackageType::WindowsMsi => {
31+
log::info!(
32+
"Patching binary {:?} for type {}",
33+
binary,
34+
package_type.short_name()
35+
);
36+
windows::patch_binary(binary, package_type)?;
37+
}
38+
_ => (),
39+
}
40+
41+
Ok(())
42+
}
43+
1844
pub use self::{
1945
category::AppCategory,
2046
settings::{
@@ -87,13 +113,21 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
87113
}
88114
}
89115

116+
let main_binary = settings
117+
.binaries()
118+
.iter()
119+
.find(|b| b.main())
120+
.expect("Main binary missing in settings");
121+
90122
let mut bundles = Vec::<Bundle>::new();
91123
for package_type in &package_types {
92124
// bundle was already built! e.g. DMG already built .app
93125
if bundles.iter().any(|b| b.package_type == *package_type) {
94126
continue;
95127
}
96128

129+
patch_binary(&settings.binary_path(main_binary), package_type)?;
130+
97131
let bundle_paths = match package_type {
98132
#[cfg(target_os = "macos")]
99133
PackageType::MacOsBundle => macos::app::bundle_project(settings)?,

crates/tauri-bundler/src/bundle/linux/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,8 @@ pub mod appimage;
77
pub mod debian;
88
pub mod freedesktop;
99
pub mod rpm;
10+
11+
mod util;
12+
13+
#[cfg(target_os = "linux")]
14+
pub use util::patch_binary;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
2+
// SPDX-License-Identifier: Apache-2.0
3+
// SPDX-License-Identifier: MIT
4+
5+
/// Change value of __TAURI_BUNDLE_TYPE static variable to mark which package type it was bundled in
6+
#[cfg(target_os = "linux")]
7+
pub fn patch_binary(
8+
binary_path: &std::path::PathBuf,
9+
package_type: &crate::PackageType,
10+
) -> crate::Result<()> {
11+
let mut file_data = std::fs::read(binary_path).expect("Could not read binary file.");
12+
13+
let elf = match goblin::Object::parse(&file_data)? {
14+
goblin::Object::Elf(elf) => elf,
15+
_ => return Err(crate::Error::GenericError("Not an ELF file".to_owned())),
16+
};
17+
18+
let offset = find_bundle_type_symbol(elf).ok_or(crate::Error::MissingBundleTypeVar)?;
19+
let offset = offset as usize;
20+
if offset + 3 <= file_data.len() {
21+
let chars = &mut file_data[offset..offset + 3];
22+
match package_type {
23+
crate::PackageType::Deb => chars.copy_from_slice(b"DEB"),
24+
crate::PackageType::Rpm => chars.copy_from_slice(b"RPM"),
25+
crate::PackageType::AppImage => chars.copy_from_slice(b"APP"),
26+
_ => {
27+
return Err(crate::Error::InvalidPackageType(
28+
package_type.short_name().to_owned(),
29+
"linux".to_owned(),
30+
))
31+
}
32+
}
33+
34+
std::fs::write(binary_path, &file_data)
35+
.map_err(|error| crate::Error::BinaryWriteError(error.to_string()))?;
36+
} else {
37+
return Err(crate::Error::BinaryOffsetOutOfRange);
38+
}
39+
40+
Ok(())
41+
}
42+
43+
/// Find address of a symbol in relocations table
44+
#[cfg(target_os = "linux")]
45+
fn find_bundle_type_symbol(elf: goblin::elf::Elf<'_>) -> Option<i64> {
46+
for sym in elf.syms.iter() {
47+
if let Some(name) = elf.strtab.get_at(sym.st_name) {
48+
if name == "__TAURI_BUNDLE_TYPE" {
49+
for reloc in elf.dynrelas.iter() {
50+
if reloc.r_offset == sym.st_value {
51+
return Some(reloc.r_addend.unwrap());
52+
}
53+
}
54+
}
55+
}
56+
}
57+
58+
None
59+
}

crates/tauri-bundler/src/bundle/windows/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#[cfg(target_os = "windows")]
77
pub mod msi;
8+
89
pub mod nsis;
910
pub mod sign;
1011

@@ -13,3 +14,5 @@ pub use util::{
1314
NSIS_OUTPUT_FOLDER_NAME, NSIS_UPDATER_OUTPUT_FOLDER_NAME, WIX_OUTPUT_FOLDER_NAME,
1415
WIX_UPDATER_OUTPUT_FOLDER_NAME,
1516
};
17+
18+
pub use util::patch_binary;

0 commit comments

Comments
 (0)