Compare commits

...

186 Commits

Author SHA1 Message Date
Xuhui Zheng
926a57bb08 feat(windows): NSIS uninstaller icon and header image support (#15201)
* feat: NSIS uninstaller support.

* chore: fix typo and update schema.

* fix: comments and alias.

* fix: add pages for uninst sidebar.

* chore: fix typo in comments of fields.

* fix: group HEADERIMAGE.

* fix: remove welcome/finish of uninstaller.

* fix: remove uninstaller_sidebar_image.

* Update crates/tauri-utils/src/config.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* chore: revert comments.

* chore: update schema.

* Update crates/tauri-utils/src/config.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* Update crates/tauri-utils/src/config.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* fix: typo of installer_icon.

* chore: add change file.

* fix: typo.

* chore: update config.json.

* Update .changes/feat-uninstaller-icon-image.md

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* fix: revert alias.

* chore: update comments in settings.rs.

* chore: update comments.

* fix: installer.nsi

* fix: installer.nsi

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2026-04-08 16:10:55 +08:00
signadou
074299c08d feat: add Bring All to Front predefined menu item type (#14307)
* Add Bring All to Front predefined menu item type

* Format and update changefile

* Update .changes/add-bring-all-to-front-predefined-menu-item-type.md
2026-04-07 23:34:01 +08:00
dependabot[bot]
ec5381e951 chore(deps-dev): bump vite from 8.0.0 to 8.0.5 (#15204)
* chore(deps-dev): bump vite from 8.0.0 to 8.0.5

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.0.0 to 8.0.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.0.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix audit

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2026-04-07 12:52:05 +08:00
lanyeeee
b27be063ff feat: add eval_with_callback to Webview and WebviewWindow (#14925)
* feat: add `eval_with_callback` to Webview and WebviewWindow

* docs: fix eval_with_callback docs and add change file

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2026-04-01 12:14:20 +08:00
Fabian-Lars
cdf5276478 chore(deps): update ctor and napi (#15183) 2026-03-31 12:44:38 +02:00
Amr Bashir
e5b00795c2 feat: cover more cases for data-tauri-drag=region="deep", add example for QA (#15164) 2026-03-28 02:03:30 +02:00
Lucas Fernandes Nogueira
5a0ca7edbb feat(bundler): support Liquid Glass icons, closes #14207 (#14671)
* feat(bundler): support Liquid Glass icons, closes #14207

the `icon` config now supports loading an Assets.car directly or a `.icon` (Icon Composer asset) that gets compiled into an Assets.car file

* fmt

* fix build

* add version checks

* fmt

* fix icns fallback

* fmt
2026-03-26 13:58:58 -03:00
Tony
5dc2cee603 fea(wix): add minimum webview2 version support (#14793)
* feat(wix): add minimum webview2 version option

* Add change file

* Format

* Move comments inside `#if` block

* add breaking change notes

* Add deprecation to description schema

* Merge remote-tracking branch 'upstream/dev' into wix-minimum-webview2-version

* Merge branch 'dev' into wix-minimum-webview2-version
2026-03-26 23:39:05 +08:00
renovate[bot]
3b5b2cc125 chore(deps): update dependency rollup to v4.60.0 (#15154) 2026-03-25 22:12:22 +08:00
Thomas Eizinger
e032c3b342 refactor: replace kuchikiki with dom_query (#14959)
* test: add more unit-tests for `html` module

* refactor: remove html dependencies from `tauri-cli`

* feat: introduce `html-manipulation-2` feature

* Remove deprecation

* Use new feature flag

* Unroll `build` feature

* Introduce `build-2` feature

* Reduce diff

* Use `build-2` in more places

* Add docs

* Refactor `inject_script_hashes`

* Refactor `with_head`

* Rename serialize and parse functions

* Add changes file

* Remove unused function

* Update changelog

* Remove test

* Update wry

* Add todo comments
we don't have the git blame data in html2, better do it now or never
find it again

* refactor `with_head` to `ensure_head`

* Remove unused casts

* Avoid using format to construct html elements
which has the potential to get injected

* Feature gate `inline_isolation`

* Keep old prepends appends

* Fix `inline_isolation_replaces_src_with_content` test

* End meta tag

* Mirror test to old html module

* Use back to `append_html` for csp and link issue

* Try out dom query main branch

* Use nodes instead to avoid an extra clone

* Use wry 0.54.4 and dom_query 0.27

* Mark stability

* Remove `PatternObject`

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2026-03-25 20:58:51 +08:00
renovate[bot]
386312c73a chore(deps): update dependency rollup to v4.59.1 (#15150)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-24 17:54:31 +01:00
Tony
d34497ef15 refactor(runtime-wry): remove RefCell hack (#14862)
* refactor(runtime-wry): remove RefCell hack

* Remove `Sync` requirement on `on_new_window`

* Merge branch 'dev' into remove-ref-cell-hack

* Add change file
2026-03-24 23:39:50 +08:00
Joshua Megnauth
4017a7ed73 feat: Allow getting inner PathBuf from SafePathBuf (#14908)
* Allow getting inner PathBuf from SafePathBuf

SafePathBuf implements AsRef<Path> which is ergonomic and useful.
However, some APIs take owned PathBufs. This leads to clunky code where
the caller has to get a &Path from the SafePathBuf then take ownership
of that path. Ideally, if a user has a SafePathBuf and needs a PathBuf,
they won't need to allocate again just to get the inner PathBuf back.

* Apply suggestion from @Legend-Master
2026-03-24 16:35:05 +08:00
Lucas Fernandes Nogueira
093e2b47c0 feat(mobile): multi-window support (#14484)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2026-03-23 17:32:02 +01:00
renovate[bot]
f0381b4bdf chore(deps): update rust crate tar to v0.4.45 [security] (#15129)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-21 10:08:33 +08:00
sftse
d730770bb9 Refactors (#15117)
* refactor(tauri-build): make better use of OsString

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* refactor(tauri-build): dont wrap const value in function

* refactor(tauri-build): None codepath is never used, replace Option<Vec> with Vec

* refactor(tauri): use blocking apis where it makes sense

* refactor(tauri): better use of std::fs API

* refactor(tauri): rewind to start

* refactor(tauri): fmt

* add change file
2026-03-20 18:18:29 +08:00
Seto Elkahfi
80c1425af8 fix(cli): fix ios build when Metal Toolchain exist in the system (#14921) 2026-03-20 09:32:24 +01:00
Fabian-Lars
1ef6a119b1 chore(deps): Update cargo-mobile2 and toml crates (#15115)
* chore(deps): Update cargo-mobile2 and toml crates

* remove toml from tauri-build cargotoml

* 0.22.3

* try a range

* json5 and changefile

* Revert "json5 and changefile"

This reverts commit eda416ba79.

* keep changefile
2026-03-18 18:02:04 +01:00
Fabian-Lars
aabb42f949 chore(deps): update wrangler & flatted to fix audit (#15116) 2026-03-18 09:11:44 +01:00
Sam Lidder
fcb702ec4d fix(cli): allow build --bundles nsis arg in linux+macOS (#14954) 2026-03-17 22:12:44 +01:00
Tony
f17240bf6c refactor: reduce nesting in AppManager::get_asset (#15114) 2026-03-17 18:38:42 +08:00
llogiq
1fa1db5cd9 chore: reduce cloning in EmbeddedAssets::get (#15112)
* reduce cloning in `EmbeddedAssets::get`

* Apply suggestion from @Legend-Master

* Fix github suggestion

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2026-03-17 12:10:51 +08:00
William Justin
8db451c791 fix(cli): ignore keystore.properties in Android templates (#14996) 2026-03-16 13:09:02 +01:00
renovate[bot]
15b311155f chore(deps): update dependency vite to v8 and @sveltejs/vite-plugin-svelte to v7 (#15103)
* chore(deps): update dependency @sveltejs/vite-plugin-svelte to v7

* Update vite to v8

* Update devalue

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2026-03-13 20:03:56 +08:00
Tony
812b2990e7 ci: fix duplicated audit runs (#15104) 2026-03-13 19:25:29 +08:00
Shaun Hamilton
c8d7003b23 fix(bundler): set linuxdeploy arch to i386 (#15102)
Co-authored-by: Fabian-Lars <30730186+FabianLars@users.noreply.github.com>
2026-03-12 22:36:04 +01:00
Eden Lundie
2679ddd5eb fix(ios): fix deadlock during Swift plugin command handling (#15101) 2026-03-12 16:27:49 +01:00
Lucas Nogueira
3f77cc1ee6 fix: drag.js generated CSP regression from #15062 2026-03-10 14:39:01 -03:00
Amr Bashir
2dd9b15a2b feat: add data-tauri-drag-region="deep" (#15062)
* feat: add `data-tauri-drag-region="deep"`

supersedes #6362

* Update data-tauri-drag-region-deep.md

* summary is also clickable

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2026-03-10 09:25:41 -03:00
Amr Bashir
eacd36a4ea refactor(macos-sign): use base64 crate instead of Command (#15038)
* refactor(macos-sign): use base64 crate instead of Command

* add base64 crate as a dependency

* add change file

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2026-03-10 09:14:58 -03:00
Tony
6cb86c9e42 chore(deps): update @rollup/plugin-terser to v1 (#15057) 2026-03-08 10:54:28 +01:00
Fabian-Lars
50833703e4 ci(test-core): split cache per target (#15048) 2026-03-06 13:40:41 +01:00
Tony
8718d08163 enhance(cli): add context before prompting password (#15033)
* enhance(cli): add context before prompting password

* Add change file
2026-03-05 11:38:02 +08:00
Tony
8230973ae8 chore: update js dependencies to fix audit (#15031)
* chore: update js dependencies

* Add serialize-javascript override
2026-03-04 21:10:25 +08:00
Tony
9b17a7aeae fix(ci): bump rustsec/audit-check to v2 and ignore time audit (#15030)
* fix(ci): bump rustsec/audit-check to v2

* Run on pull requests

* Add to ignore list
2026-03-04 18:11:01 +08:00
github-actions[bot]
d86827980d apply version updates (#14897)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-04 16:37:29 +08:00
Tony
3a65cc6885 fix(test): disable resolve_resource_dir on Android (#15026) 2026-03-03 22:37:10 +08:00
Tony
52cf195b78 refactor(cli): reduce some nesting code (#14844)
* refactor(cli): reduce some nesting code

* Handle all paths and config file change not first

* Bring back is_ignore
2026-03-03 21:27:55 +08:00
Tony
c3cbff3f74 fix: resource path handles ./ path differently (#14662)
* fix: resource path handles `./` path differently

* Setup CI for tauri utils

* Wrong job name

* Fix tests

* Always run tests and don't run doc tests

* Add change file

* Re-use `test-core` workflow

* Format

* Avoid path clone by calculating target first

* Test tauri-utils first with step instead of matrix

* Use `matrix.platform.command`

* Document `current_dest` and `current_pattern`

* More docs

* Merge remote-tracking branch 'upstream/dev' into refactor-resource-path-iter

* Test with doc tests

* Revert "Test with doc tests"

This reverts commit 388bee9328.

* Merge branch 'dev' into refactor-resource-path-iter

* Merge branch 'dev' into refactor-resource-path-iter
2026-03-03 21:15:44 +08:00
Tony
33754ae5e3 fix(cli): unusable empty password private keys (#15022)
* fix(cli): unusable empty password private keys

* Bump minisign to 0.9 and revert other changes

* Lock to `=0.7.3`
2026-03-03 20:23:50 +08:00
Tony
3935dee121 Add AI tool policy to contributing guide (#15002)
* Add AI tool policy to contrubuting guide

* Apply suggestions from code review

Co-authored-by: Fabian-Lars <30730186+FabianLars@users.noreply.github.com>

* nonsense -> nonsensical

---------

Co-authored-by: Fabian-Lars <30730186+FabianLars@users.noreply.github.com>
2026-03-03 17:45:42 +08:00
dependabot[bot]
33932a72b2 chore(deps-dev): bump svelte from 5.51.5 to 5.53.5 (#15015)
Bumps [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte) from 5.51.5 to 5.53.5.
- [Release notes](https://github.com/sveltejs/svelte/releases)
- [Changelog](https://github.com/sveltejs/svelte/blob/main/packages/svelte/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/svelte/commits/svelte@5.53.5/packages/svelte)

---
updated-dependencies:
- dependency-name: svelte
  dependency-version: 5.53.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-01 11:27:29 +08:00
renovate[bot]
7d3c7593a9 chore(deps): update dependency rollup to v4.59.0 (#15001)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-28 22:07:20 +08:00
BiggerRain
f20256bca5 chore: fix clippy warnings (#14999) 2026-02-26 14:35:45 +01:00
renovate[bot]
03514414d9 chore(deps): update dependency rollup to v4.58.0 (#14991)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-25 11:13:03 +08:00
montyc1999
7b16dafb1d fix(tauri-utils): sort csp/plugin/header config maps during codegen so generate_context! is deterministic (#14986)
* fix(tauri-utils): sort csp/plugin/header config maps during codegen so generate_context! is deterministic

* add comments explaining rationale, and todo for removing the hack in v3
2026-02-23 23:14:56 +08:00
dependabot[bot]
7782c5525a chore(deps-dev): bump svelte from 5.35.6 to 5.51.5 (#14973)
Bumps [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte) from 5.35.6 to 5.51.5.
- [Release notes](https://github.com/sveltejs/svelte/releases)
- [Changelog](https://github.com/sveltejs/svelte/blob/main/packages/svelte/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/svelte/commits/svelte@5.51.5/packages/svelte)

---
updated-dependencies:
- dependency-name: svelte
  dependency-version: 5.51.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-20 21:14:55 +08:00
renovate[bot]
aa0bf8bd19 chore(deps): update eslint monorepo to v10 (major) (#14922)
* chore(deps): update eslint monorepo to v10

* Update typescript-eslint and plugin security
2026-02-20 20:58:41 +08:00
dependabot[bot]
91fb0e161f chore(deps): bump keccak from 0.1.5 to 0.1.6 (#14972)
Bumps [keccak](https://github.com/RustCrypto/sponges) from 0.1.5 to 0.1.6.
- [Commits](https://github.com/RustCrypto/sponges/compare/keccak-v0.1.5...keccak-v0.1.6)

---
updated-dependencies:
- dependency-name: keccak
  dependency-version: 0.1.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 19:39:52 +08:00
montyc1999
88c05689c8 fix(deps): disable default-features in objc2 crates (#14967) 2026-02-18 21:31:23 +01:00
Varun Chawla
6252432f07 fix(bundler): swap WIX registry search order to prioritize InstallDir (#14945) 2026-02-16 17:34:58 +01:00
FabianLars
2d0b80eb1c Revert "chore(deps): update rust crate time to v0.3.47 [security] (#14902)"
This reverts commit 86c8c870c8.
2026-02-15 14:19:06 +01:00
renovate[bot]
86c8c870c8 chore(deps): update rust crate time to v0.3.47 [security] (#14902)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-15 14:02:39 +01:00
cui
476e8ee7f3 fix(core): fix content-boundaries start/end order in asset protocol (#14938) 2026-02-15 13:53:01 +01:00
Lucas Fernandes Nogueira
0d1cb83bab fix(cli): missing options on mobile dev/build commands (#14932)
* fix(cli): missing options on mobile dev/build commands

* avoid duplicated flags

* clippy
2026-02-12 21:12:00 -03:00
Lucas Fernandes Nogueira
35c35f27ae fix(cli): features should support a comma separated list (#14931) 2026-02-12 12:24:40 -03:00
renovate[bot]
7d01aa0417 chore(deps): update dependency rollup to v4.57.1 (#14868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-05 23:16:42 +08:00
Tony
7be58a1c64 chore(bundler): bring back binary patching log (#14894)
* chore(bundler): bring back binary patching log

* Fix change tag
2026-02-05 17:59:16 +08:00
dependabot[bot]
06374a902a chore(deps): bump bytes from 1.9.0 to 1.11.1 (#14890)
Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.9.0 to 1.11.1.
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.9.0...v1.11.1)

---
updated-dependencies:
- dependency-name: bytes
  dependency-version: 1.11.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-04 23:06:29 +08:00
github-actions[bot]
c37368f339 apply version updates (#14884)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-03 11:54:01 -03:00
goosewobbler
06f911aaff fix: don't inherit stdout from parent (#14871) 2026-02-03 11:20:42 -03:00
Lucas Fernandes Nogueira
eb5d88427a fix(codegen): Context generation with custom assets (#14883)
when custom assets are provided (`tauri::generate_context!(assets = my_assets)`) we can't use the fn inner logic directly and capture variables - we must pass them as arguments
2026-02-03 11:01:12 -03:00
FabianLars
540c5b4e59 chore(deps): update wrangler for undici update 2026-02-03 00:56:28 +01:00
FabianLars
5dbb37bab1 chore(api.js): Re-release 2.10.0 as 2.10.1 to fix npm package 2026-02-03 00:32:07 +01:00
FabianLars
19ded696de apply version updates 2026-02-02 23:05:28 +01:00
Fabian-Lars
08558b8ba4 chore(bundler): update gtk3 docs links in code comments (#14872) 2026-02-02 20:15:28 +01:00
Fabian-Lars
ce8fddb464 chore(deps): unlock webkit2gtk patch version (#14873) 2026-02-02 20:15:02 +01:00
Lucas Fernandes Nogueira
517b81e970 chore(api): release 2.10 (#14876)
api, CLI and tauri crates must be in sync
2026-02-02 16:09:22 -03:00
Lucas Fernandes Nogueira
cd68b03ee5 feat(ci): use trusted publishers for NPM publishing (#14874)
* feat(ci): use trusted publishers for NPM publishing

* bump npm version

* update npm

* use empty NODE_AUTH_TOKEN

* entire workflow permissions
2026-02-02 16:09:01 -03:00
github-actions[bot]
8d67af37b6 apply version updates (#14639)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-02 09:15:37 -03:00
Tunglies
9f0306fbcc refactor: rewrite some &String to &str (#14857)
* perf(tauri-build): refactor find_icon to use &str to remove unnecessary clones

* refactor(perf-tauri-build): remove obsolete changelog for find_icon refactor

* refactor(tauri-build): inline find_icon logic to simplify window icon path retrieval

* refactor(context): update find_icon predicate to use &str

* refactor(context): simplify predicate in find_icon to accept &&String

* Update crates/tauri-build/src/lib.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2026-01-31 21:48:00 +08:00
renovate[bot]
f7c083cd41 chore(deps): update dependency rollup to v4.57.0 (#14820) 2026-01-31 20:32:55 +08:00
sftse
32576120fd Fix busy loop (#14839)
* refactor(tauri-cli):  remove unneeded Arc<Mutex>

* fix(tauri-cli): remove busy-looping
2026-01-29 11:13:03 +08:00
sftse
e3fdcb5002 refactor tauri-cli (#14836)
* refactor(tauri-cli): use OsString where possible

* refactor(tauri-cli): remove needless scoping blocks

* refactor(tauri-cli): make return type concrete

* refactor(tauri-cli): use ?

* refactor(tauri-cli): coerce later to trait object

* refactor(tauri-cli): remove clone

* refactor(tauri-cli): make better use of static OnceLock

* fix(tauri-cli): upgrade atomics to SeqCst

* Add change file

* Update .changes/change-pr-14836.md

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2026-01-29 10:39:00 +08:00
sftse
d453e2e06a refactor(tauri-cli): remove trait implemented only once (#14840) 2026-01-29 10:35:55 +08:00
Fabian-Lars
20b99f9281 refactor: split appimage bundler in multiple files to support new backends (#14841) 2026-01-28 20:27:51 +01:00
sftse
3a4e165b6f Less statics fixup (#14833)
* fix(tauri-cli): be more conservative to preserve behavior (#14804)

* refactor(tauri-cli): move app path initialization into commands
2026-01-27 16:33:11 +08:00
Fabian-Lars
efc4c26ebc chore: fix clippy lints (#14834) 2026-01-26 17:13:08 +01:00
Tony
7fca58230f chore(deps): update nsis_tauri_utils to 0.5.3 (#14830) 2026-01-26 17:55:27 +08:00
Kf637
c769f211fc feat(nsis): add Norwegian language support for installer (#14824)
* feat(nsis): add Norwegian language support for installer

* feat(nsis): add Norwegian language support for installer strings

* Add change file
2026-01-25 16:30:50 +08:00
Oscar Beaumont
4d5d78daf6 fix(specta): don't use #[specta(rename = ...)] with tauri::ipc::Channel (#14812) 2026-01-24 11:00:40 +01:00
renovate[bot]
4794a6ba22 chore(deps): update dependency rollup to v4.55.2 (#14808)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-22 14:09:19 +01:00
dependabot[bot]
09a4e7f55a chore(deps-dev): bump wrangler from 4.20.3 to 4.59.1 (#14806)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 14:06:29 +01:00
Fabian-Lars
c862a0bd8c fix(core): update error wording for invalid version field (#14800)
* fix(core): update error wording for invalid version field

fixes #14799

* fmt
2026-01-21 10:42:15 +08:00
Quentin Goinaud
f82594410c feat(cli): allow electron to start tauri (#13253)
Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
2026-01-20 22:19:05 +01:00
Ishita Singh
853ed4642f fix(android): improve error handling for external storage file access (#14442)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2026-01-20 21:52:11 +01:00
Tony
53611c4d7b fix(cli): only watch dependent workspace members (#14747)
* fix(cli): only watch dependent workspace members

* Use manifest path instead of `workspace_default_members`

* Add change file

* Merge remote-tracking branch 'upstream/dev' into only-watch-dependencies

* `bug` not `fix`

* Merge branch 'dev' into only-watch-dependencies

* Remove `CargoMetadataExpended`

* Merge remote-tracking branch 'upstream/dev' into only-watch-dependencies

* Remove top level `.taurignore`

* Load ignore files from workspace root
2026-01-20 17:52:34 +08:00
Lucas Fernandes Nogueira
62aa13a124 fix(cli): Android build --apk and --aab flags requiring a value (#14629)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2026-01-19 20:32:43 +01:00
Luke
e919a760ed feat(webview-window): add set_simple_fullscreen to WebviewWindow (#14619)
* feat(webview): add set_simple_fullscreen to WebviewWindow

* add changes

* Combine per platform fn to one

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2026-01-19 11:38:37 +08:00
kandrelczyk
0575dd287e fix(bundler): patch bundle type via string replacement (#14521)
Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2026-01-18 23:51:02 +01:00
Lucas Fernandes Nogueira
eccff97588 fix(cli): possibly empty associated-domains entitlement (#14779) 2026-01-18 19:01:36 +01:00
Tony
08e35fcda0 refactor(cli): remove mutex on config (#14791)
* refactor(cli): remove mutex on config

* Fix ios

* Clippy

* Fix ios

* Unused import

* Fix ios closure and clippy

* Import `ConfigMetadata`

* Remove life time tags
2026-01-18 21:09:36 +08:00
Tony
10a8066db3 refactor(cli): reorder a few parameters (#14792) 2026-01-18 20:57:36 +08:00
Tony
ea31b07f19 fix(cli): inspect's description (#14789) 2026-01-17 19:23:12 +02:00
sftse
7f7d9aac21 Less statics (#14668)
* refactor(tauri-cli): introduce replacement functions

* refactor(tauri-cli): apply replacement to remove.rs

* refactor(tauri-cli): apply replacement to icon.rs

* refactor(tauri-cli): apply replacement to bundle.rs

* refactor(tauri-cli): apply replacement to build.rs

* refactor(tauri-cli): apply replacement to add.rs

* refactor(tauri-cli): apply replacement to dev.rs

* refactor(tauri-cli): less controlflow

* refactor(tauri-cli): split config loading from locking static

* refactor(tauri-cli): remove duplicate checks covered by if let Some(tauri_dir) = tauri_dir

tauri_dir.is_some() must be true, otherwise the entire block is not run, so the frontend_dir check
is irrelevant

* fmt

* refactor(tauri-cli): apply replacement to inspect.rs

* refactor(tauri-cli): dont use statics for config

* refactor(tauri-cli): finish threading directory paths through functions

* fix: clippy

* fixup CI

* refactor(tauri-cli): dont need mutex

* refactor(tauri-cli): rescope mutex use to minimal necessary

* fix CI, reduce mutex use

* fixup PR #14607

* fix: clippy

* refactor(tauri-cli): remove ConfigHandle

* refactor(tauri-cli): remove more unwraps and panicing functions

* refactor(tauri-cli): less mutexes

* refactor(tauri-cli): undo mistaken change, address review comment

* Split android build to 2 functions

* Pass in dirs to migration v1 like the v2 beta

* Add change file

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2026-01-17 23:52:42 +08:00
yy
7873c4a1c6 docs: fix typos in comments (#14787) 2026-01-17 12:30:14 +01:00
Fabian-Lars
123d63a0c1 chore: change webkit2gtk bump to minor 2026-01-15 17:00:58 +01:00
Fabian-Lars
75057c7c08 chore(deps): update wry to 0.54 and webkit2gtk-rs to 2.0.2 (#14778) 2026-01-15 14:48:45 +01:00
sftse
268bb339f0 build(tauri-macos-sign): remove once-cell-regex (#14766)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2026-01-15 13:14:30 +01:00
renovate[bot]
07788af13f chore(deps): update rust crate signal-hook-tokio to 0.4 (#14729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2026-01-15 12:53:18 +01:00
renovate[bot]
9a53c84ec0 chore(deps): update dependency globals to v17 (#14730)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-15 12:28:04 +01:00
renovate[bot]
137576e8a4 chore(deps): update dependency rollup to v4.55.1 (#14746)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-15 11:51:21 +01:00
Wuelfhis Asuaje
1b0e335d3f Fix: Updater signer failed signing file without extension (#14713)
* fixing bug where updater signer failed signing file withou extension

* removing  unnecessary unwrap()

* Adding change file. Removing commnent. Adding TODO.

* Apply suggestions from code review

---------

Co-authored-by: Wuelfhis Asuaje <wasuaje@shorecg.com>
Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2026-01-14 09:09:45 +08:00
Amr Bashir
84b04c4a8d fix: fix leftover inconsistent env var in tauri signer sign command (#14759) 2026-01-11 20:37:52 +02:00
Tony
897529d7a2 fix: map rustls-tls to reqwest/rustls-no-provider (#14726)
Co-authored-by: FabianLars <github@fabianlars.de>
2026-01-08 15:14:51 +01:00
dependabot[bot]
3d102e0c13 chore(deps): bump rsa from 0.9.7 to 0.9.10 (#14738)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-06 19:26:47 +01:00
Fabian-Lars
fea4d02403 chore(deps): update rkyv, closes #14734 (#14736) 2026-01-06 11:16:00 +01:00
Tony
a03219ca19 refactor(cli): disable jsonschema resolving external resources (#14725)
* refactor(cli): disable jsonschema resolving external resources

* Move `CONFIG_SCHEMA_VALIDATOR` to fn

* Format

* Update ureq to fix compile on linux

* New clippy warnings
2026-01-03 19:30:42 +08:00
renovate[bot]
b75ea5bead chore(deps): update rust crate reqwest to 0.13 (#14724)
* chore(deps): update rust crate reqwest to 0.13

* Fix feature name

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2026-01-03 12:34:59 +08:00
Fabian-Lars
dcd1a65889 chore: fix tests (#14720)
* chore: fix tests

* windows
2026-01-02 16:02:23 +01:00
Camilla F
9b242e40c8 fix: BSD support in tauri-runtime (#14700)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-12-29 17:29:07 +01:00
Bruno Verachten
1dbf6fd067 feat(cli): add RISC-V 64-bit pre-built binary support (#14685)
* feat(cli): add RISC-V 64-bit pre-built binary support

Add riscv64gc-unknown-linux-gnu target to the tauri-cli release workflow,
enabling pre-built binaries for RISC-V 64-bit Linux systems.

This eliminates the multi-hour QEMU compilation time that currently blocks
RISC-V adoption of Tauri apps. Native compilation on RISC-V hardware
takes ~63 minutes.

Changes:
- Add RISC-V entry to build matrix with self-hosted runner support
- Support custom `runs_on` field for matrix entries (falls back to `os`)
- Skip dtolnay/rust-toolchain and rust-cache for self-hosted runners
- Source ~/.cargo/env for self-hosted runners where Rust is pre-installed

Tested on:
- Hardware: Banana Pi F3 (RISC-V64, 16GB RAM)
- OS: Debian Trixie (required for WebKit2GTK RISC-V support)
- Build time: 1h 2m 28s
- Binary: ELF 64-bit RISC-V, 16MB stripped

* feat(cli): use cross for RISC-V cross-compilation

Switch from self-hosted runners to cross-rs for building RISC-V binaries.
This approach is simpler and doesn't require maintaining self-hosted infrastructure.

Local testing confirms cross builds a valid RISC-V binary in ~4 minutes.

* refactor(cli): address review feedback for RISC-V workflow

- Skip Rust toolchain and cache setup for cross builds (unnecessary)
- Pin cross version to 0.2.5 for reproducibility
- Fix Linux dependencies condition to match ubuntu-* variants
2025-12-29 10:21:49 -03:00
Tony
8a43e4f9d9 refactor: use u64 instead of usize for nonce gen (#14708) 2025-12-29 08:43:09 -03:00
sftse
a2abe2e6bc refactor(cli): simplify features: Option<Vec<String>> to Vec<String> (#14607)
* refactor: use empty vector for features instead of None

* refactor: reorder

* add change file

* comment: highlight places where serialization is used

* refactor: simplify serialization

* Update .changes/empty-vec-instead-of-none.md

* Update crates/tauri-cli/src/mobile/ios/mod.rs

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-12-29 13:54:51 +08:00
Tony
51f0fcb69c docs: pixel units (#14702) 2025-12-28 10:40:03 +08:00
Tony
0650852d14 docs: things related to WebviewUrl (#14692)
* Typos

* Rename to `handler`/`protocol_handler`

* Fix the `AssetResolver::get` fallback docs

* Refactor and update the docs for `get_url`

* Rename the remaining ones to `get_app_url`

* Apply suggestions from code review

Co-authored-by: Fabian-Lars <github@fabianlars.de>

* Generate schema
2025-12-25 20:05:02 +08:00
Kushal Meghani
c1d82eb3a3 fix(linux): reuse WebContext to prevent WebKitNetworkProcess leak (#14628)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-12-25 13:03:15 +01:00
renovate[bot]
51a0d6d66d chore(deps): update dependency rollup to v4.54.0 (#14688)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-23 22:49:57 +08:00
renovate[bot]
7f48ee9068 chore(deps): update rust crate toml_edit to 0.24 (#14683)
* chore(deps): update rust crate toml_edit to 0.24

* Downgrade indexmap to 2.11.4 for MSRV

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-12-21 22:04:33 +08:00
renovate[bot]
e290642fb4 chore(deps): update dependency rollup to v4.53.5 (#14676)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-19 17:15:17 +08:00
renovate[bot]
b79386010d chore(deps): update dependency rollup to v4.53.4 (#14670)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-18 22:49:52 +08:00
Tony
ff5d76ca21 fix: default WindowConfig::focus to false in Default::default (#14653) 2025-12-14 16:21:44 +08:00
sftse
2d28e3143e Cleanups (#14632)
* refactor(tauri-utils): current_dest and current_pattern always change in-sync, group them to one Option

* refactor(tauri-utils): pass path as explicit argument instead of implicitly through self

* refactor(tauri-utils): remove struct field that is never set to Some

* refactor(tauri-cli): use OsString, OsStr where possible

* refactor(tauri-cli): Deref Arc early

* refactor(tauri-cli): lock config before passing to build::setup()

* refactor(tauri-build, tauri-utils): bettern pattern matching and borrowing

* refactor(tauri-cli): dont need Arc if already have static

* fix(tauri-cli): race condition initializing static flag, remove unnecessary OnceLock

* refactor(tauri-cli): use expect

* refactor(tauri-cli): remove unnecessary OnceLock

* refactor(tauri-cli): better use of dunce api

* refactor(tauri-cli): rename
2025-12-09 21:38:14 +08:00
renovate[bot]
18c69df8c7 chore(deps): update worker-rs crates to 0.7 (#14638)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-12-09 13:42:27 +01:00
github-actions[bot]
f2e0405dc2 apply version updates (#14592)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-12-09 12:41:05 +01:00
FabianLars
54e8d93db1 ci(renovate): group worker-rs updates 2025-12-09 12:11:53 +01:00
Tony
251203b896 fix(linux): work area returns logical rect (#14637) 2025-12-09 18:05:12 +08:00
Tony
91becd9e4f fix(nsis): plugins not signed (#14627) 2025-12-08 20:13:52 +08:00
Tony
018b4db22e fix(bundler): skip signing for nsis uninstaller on --no-sign (#14625) 2025-12-08 20:13:43 +08:00
Tony
731dd5bfdc docs: remove $APP and $LOG from FsScope (#14623) 2025-12-07 23:09:11 +08:00
Tony
7b1b3514df changes(cli): log npm package version parse in debug level (#14621) 2025-12-07 21:06:27 +08:00
sftse
546b296405 fix(tauri-bundler): add a bit more context to error message (#14606) 2025-12-05 11:56:34 +08:00
Tunglies
514cf21e14 chore(deps): update num-bigint-dig to version 0.8.6 (#14591)
* chore(deps): update num-bigint-dig to version 0.8.6

* Update .changes/bump-version-num-bigint-dig.md

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-12-02 10:20:35 +08:00
renovate[bot]
60174527c0 chore(deps): update rust crate ico to 0.5 (#14589)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-02 10:19:09 +08:00
chfaft
4176f93ae4 feat(bundler): consider extensions defined in main.wxs. (#14570)
* feat(bundler): consider extensions defined in main.wxs.

* chore(bundler): apply nitpick and add a change file.

* Update crates/tauri-bundler/src/bundle/windows/msi/mod.rs

chore(bundler): avoid clone and use reference.

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* Update .changes/support-template-extensions.md

chore(bundler): reclassify changes.

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-12-02 09:58:35 +08:00
github-actions[bot]
4408f72af6 apply version updates (#14467)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-30 11:22:38 +01:00
Fabian-Lars
1496145f82 fix(bundler): typo in 32bit arch (#14585)
* fix(bundler): typo in 32bit arch

* changefile
2025-11-30 07:49:33 +01:00
hrzlgnm
f022b2d1ae fix(cli): Skip signing bundles entirely if --no-sign is requested (#14582)
Closes #14581
2025-11-30 11:45:43 +08:00
Fabian-Lars
1573c72402 fix: remove \\r from schema files on windows (#14561) 2025-11-26 11:22:45 +01:00
renovate[bot]
dd7e59a495 chore(deps): update dependency rollup to v4.53.3 (#14519)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-24 13:25:01 +08:00
Fabian-Lars
2d2a1be429 docs(cli): fix formatting of paths 2025-11-20 15:02:46 +01:00
Fabian-Lars
afdd288eab chore(deps): update js-yaml (#14498) 2025-11-19 11:53:13 +01:00
Fabian-Lars
79a7d9ec01 fix(cli): change Cargo.toml version check to debug log (#14468) 2025-11-18 16:08:17 +01:00
Tony
f855caf8a3 fix(cli): mismatched versions check for pnpm (#14481) 2025-11-18 18:16:29 +08:00
Tunglies
ee3cc4a91b perf: remove needless clones in various files for improved performance (#14475)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-11-17 15:27:49 +01:00
Tony
b5ef603d84 chore(deps): update NSIS to 3.11 (#14478) 2025-11-16 21:56:05 +08:00
Tunglies
ce98d87ce0 refactor: remove needless collect (#14474)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-11-16 12:49:20 +01:00
Aleksey Ponomarev
ad1dec2e24 fix(core): properly handle async errors in addPluginListener (#14464)
* fix(core): properly handle async errors in addPluginListener

The previous implementation used .then() after invoke() without await, which prevented the catch block from handling rejected promises. Now using await to properly catch errors and allow fallback to camelCase registerListener method.

* Change file and generate `bundle.global.js`

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-11-15 12:07:51 +08:00
renovate[bot]
beffcd880f chore(deps): update dependency rollup to v4.53.2 (#14459)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-15 10:23:57 +08:00
github-actions[bot]
956031d73d apply version updates (#14458)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-13 09:14:14 -03:00
Lucas Fernandes Nogueira
4b00130b86 refactor(core): improve iOS log messages from stdout/stderr (#14385)
* refactor(core): improve iOS log messages from stdout/stderr

move the stdout/stderr forward logic to Swift so it does not consume a Rust thread and never deadlocks on the simulator

I had to work on this because i'm facing #12172 again on latest Xcode (26.1)

* patch
2025-11-13 08:18:50 -03:00
Tony
8e3bd63db9 perf(codegen): wrap generated context in a fn (#14457)
* perf(codegen): wrap generated context in a fn

* Add comment about the reasoning
2025-11-13 15:24:10 +08:00
renovate[bot]
cfe47871a5 chore(deps): update dependency rollup to v4.53.1 (#14444)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-12 22:05:17 +08:00
Fabian-Lars
236f55b7aa docs: enable dynamic-acl feature on docs.rs (#14452) 2025-11-12 10:21:18 +01:00
github-actions[bot]
9bb7e79e97 apply version updates (#14425)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-09 12:48:27 +01:00
FabianLars
d566679a99 ci: don't re-generate lockfile on prepublish 2025-11-09 12:08:57 +01:00
Kushal Meghani
3899d456d4 Address review comments (#14426)
* Address review comments

* Revert comments in `impl FromStr for ConfigValue`
2025-11-07 09:38:05 +08:00
Tony
b586ecf1f4 fix(cli): demultiply tiny skia pixels (#14416)
* fix(cli): demultiply tiny skia pixels

* Pull resize out to a function `resize_image`

* Move comments as well

* Use cow for older rust versions
2025-11-06 10:12:10 +08:00
Fabian-Lars
dd70d213cd chore(deps): update minisign to 0.8 (#14415) 2025-11-05 14:58:54 +01:00
Kushal Meghani
d06a1994e9 refactor: improve cli code readability (#14333) 2025-11-05 13:48:32 +01:00
github-actions[bot]
b446a858de apply version updates (#14409)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-04 17:00:19 +01:00
renovate[bot]
85ba5315c2 chore(deps): update dependency @types/node to v24 (#14376)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-04 11:27:01 +01:00
Adam
779612ac84 fix(cli): respect required-features field from Cargo.toml (#14379)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-11-04 11:16:01 +01:00
Fabian-Lars
22edc65aad fix(bundler/cli): set user-agent when fetching build tools (#14408) 2025-11-04 10:53:44 +01:00
Tony
9a19226369 fix(nsis): uninstall fails when manually close app on kill app dialog (#14410) 2025-11-04 17:18:21 +08:00
Chase Knowlden
fd8c30b4f1 fix: premultiply alpha before resizing (fix #14351) (#14353)
* fix: Premultiply alpha before resizing

* feat: Use rayon for process speedup

* Fix change tag

* `cargo fmt`

* Document reasoning & use imageops::resize directly

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-11-04 11:16:11 +08:00
renovate[bot]
18464d9481 chore(deps): update dependency vitest to v4 (#14361)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-02 17:21:40 +08:00
Tony
b80f9deb5f chore: fix new clippy warnings (derive default) (#14395)
* chore: fix new clippy warnings (derive default)

* Fix left over `#[cfg(feature = "isolation")]`
2025-10-31 21:12:41 +08:00
Sebastian Neubauer
1afa9df6d5 fix(tauri-utils): Use write_if_changed more (#13621)
Replace `fs::write` with `write_if_changed` in two places. This can
prevent unnecessary rebuilds. (I didn’t encounter any, but this should
be ok nonetheless.)
2025-10-31 09:19:35 +08:00
Fabian-Lars
75a1fec705 ci: don't cache pnpm files in version-or-publish workflow (#14392) 2025-10-30 10:25:12 +01:00
github-actions[bot]
100dc94c48 apply version updates (#14378)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-29 15:15:51 +01:00
Fabian-Lars
7f710b8f3b fix(bundler): inline linuxdeploy plugin scripts (#14390) 2025-10-29 14:50:33 +01:00
Braden Wong
bda1d22369 docs(webviewWindow): fix incorrect import in JSDoc example (#14388)
The getByLabel method is a static method on WebviewWindow, not Webview.
Updated the JSDoc example to import and use the correct class name.
2025-10-29 15:34:16 +08:00
Tony
28b9e7c7b8 fix: throw on custom protocol IPC fails (#14377) 2025-10-28 18:07:50 +08:00
renovate[bot]
3056d44d96 chore(deps): update dependency @rollup/plugin-typescript to v12.3.0 (#14364)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-28 15:57:47 +08:00
kandrelczyk
fc017ee257 add info to error message (fix 14186) (#14368)
* add info to error message

* changes file and  linux only warning

Signed-off-by: Krzysztof Andrelczyk <cristof@curiana.net>

* Update change file

---------

Signed-off-by: Krzysztof Andrelczyk <cristof@curiana.net>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-10-28 15:03:48 +08:00
github-actions[bot]
67c7418c06 apply version updates (#14348)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-22 13:38:43 +02:00
Fabian-Lars
f59bf9d539 chore: Add missing changefile for tauri-macos-sign (#14337) 2025-10-22 12:28:10 +02:00
Fabian-Lars
4b6b8690ab chore: remove --cfg docsrs to fix docs.rs builds (#14347) 2025-10-22 11:33:30 +02:00
renovate[bot]
cdc5594286 chore(deps): update dependency rollup to v4.52.5 (#14339)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-21 17:09:40 +08:00
dependabot[bot]
a1c231ec29 chore(deps-dev): bump vite from 7.1.5 to 7.1.11 (#14336)
* chore(deps-dev): bump vite from 7.1.5 to 7.1.11

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.5 to 7.1.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.11
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Dedupe

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-10-21 16:30:28 +08:00
Tony
752c923002 chore: fix some typos (#14334) 2025-10-20 22:51:28 +08:00
github-actions[bot]
cb28f4368c apply version updates (#14137)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-20 09:49:46 -03:00
Lucas Nogueira
6aa7f2d852 chore(deps): minor bump plugin, codegen and macros crates 2025-10-20 09:25:07 -03:00
Lucas Nogueira
06f26bbb24 chore(deps): update tao to 0.34.5 2025-10-20 09:20:13 -03:00
Lucas Fernandes Nogueira
68cb318979 feat(core): add stop, restart, destroy and configuration changed Android hooks (#14328)
* feat(core): add pause, destroy and configuration changed Android hooks

* Apply suggestions from code review
2025-10-20 08:49:26 -03:00
295 changed files with 11058 additions and 6807 deletions

View File

@@ -6,4 +6,6 @@ ignore = [
"RUSTSEC-2020-0095",
# proc-macro-error is unmaintained
"RUSTSEC-2024-0370",
# time crate can't be updated in the repo because of MSRV, users are unaffected
"RUSTSEC-2026-0009",
]

View File

@@ -1,5 +0,0 @@
---
"@tauri-apps/api": minor:feat
---
Adds the `scrollBarStyle` option to the Webview and WebviewBuilder constructors.

View File

@@ -1,6 +0,0 @@
---
"tauri-cli": minor:feat
"tauri-utils": minor:feat
---
Adds the `scrollBarStyle` option to the window configuration.

View File

@@ -1,9 +0,0 @@
---
"tauri-runtime-wry": minor:feat
"tauri-runtime": minor:feat
"tauri": minor:feat
---
Adds the `scroll_bar_style` option to the Webview and WebviewWindow builders.
The possible values for this option are gated behind conditional compilation
flags, and will need to be applied using conditional compilation if customised.

View File

@@ -1,6 +0,0 @@
---
'tauri-cli': 'minor:feat'
'tauri-bundler': 'minor:feat'
---
Add a `--no-sign` flag to the `tauri build` and `tauri bundle` commands to skip the code signing step, improving the developer experience for local testing and development without requiring code signing keys.

View File

@@ -1,5 +0,0 @@
---
'tauri-cli': 'patch:enhance'
---
Add support for Android's adaptive and themed icons.

View File

@@ -0,0 +1,6 @@
---
'tauri': 'minor:feat'
'@tauri-apps/api': 'minor:feat'
---
Add Bring All to Front predefined menu item type

View File

@@ -1,5 +0,0 @@
---
"tauri": minor:feat
---
Added mobile app plugin to support exit and back button press event.

View File

@@ -1,6 +0,0 @@
---
'tauri-cli': 'patch:bug'
'@tauri-apps/cli': patch:bug
---
Strip Windows-only extensions from the binary path so an Android project initialized on Windows can be used on UNIX systems.

View File

@@ -1,5 +0,0 @@
---
"tauri": patch:bug
---
Properly deserialize Android plugin args with key starting with `is` (previously treated as a getter instead of a field name).

View File

@@ -1,8 +0,0 @@
---
"tauri-cli": minor:feat
"@tauri-apps/cli": minor:feat
"tauri-build": minor:feat
"tauri-utils": minor:feat
---
Add `tauri.conf.json > bundle > android > autoIncrementVersionCode` config option to automatically increment the Android version code.

View File

@@ -1,5 +0,0 @@
---
"@tauri-apps/api": minor:feat
---
Added `app > onBackButtonPress` for Android back button handling.

5
.changes/base64.md Normal file
View File

@@ -0,0 +1,5 @@
---
"tauri-macos-sign": patch:enhance
---
Do not rely on system base64 CLI to decode certificates.

View File

@@ -1,6 +0,0 @@
---
'tauri-cli': 'minor:enhance'
'@tauri-apps/cli': minor:enhance
---
Update cargo-mobile2 to 0.21, enhancing error messages and opening Xcode when multiple apps are installed.

View File

@@ -0,0 +1,6 @@
---
"tauri-build": patch:enhance
"tauri": patch:enhance
---
Simplify async-sync code boundaries, no externally visible changes

View File

@@ -27,12 +27,6 @@
"dryRunCommand": true,
"pipe": true
},
{
"command": "cargo generate-lockfile",
"dryRunCommand": true,
"runFromRoot": true,
"pipe": true
},
{
"command": "cargo audit ${ process.env.CARGO_AUDIT_OPTIONS || '' }",
"dryRunCommand": true,

View File

@@ -1,6 +0,0 @@
---
"tauri-utils": "minor:enhance"
"@tauri-apps/api": "minor:enhance"
---
Added a config to set a data_directory relative to the app-specific data dir in JavaScript and `tauri.conf.json`.

View File

@@ -0,0 +1,5 @@
---
"tauri": minor:feat
---
Add `data-tauri-drag-region="deep"` so clicks on non-clickable children will drag as well. Can still opt out of drag on some regions using `data-tauri-drag-region="false"`

View File

@@ -1,6 +0,0 @@
---
"@tauri-apps/cli": patch:enhance
"tauri-cli": patch:enhance
---
Set a default log level filter when running `tauri add log`.

View File

@@ -1,6 +0,0 @@
---
"tauri-cli": minor:feat
"@tauri-apps/cli": minor:feat
---
Try to detect ANDROID_HOME and NDK_HOME environment variables from default system locations and install them if needed using the Android Studio command line tools.

View File

@@ -0,0 +1,7 @@
---
'tauri': 'minor:feat'
'tauri-runtime': 'minor:feat'
'tauri-runtime-wry': 'minor:feat'
---
Add `eval_with_callback` to the Tauri webview APIs and runtime dispatch layers.

View File

@@ -0,0 +1,13 @@
---
"tauri-bundler": minor:feat
"tauri-cli": minor:feat
"@tauri-apps/cli": minor:feat
"tauri-utils": minor:feat
---
Added uninstaller icon and uninstaller header image support for NSIS installer.
Notes:
- For `tauri-bundler` lib users, the `NsisSettings` now has 2 new fields `uninstaller_icon` and `uninstaller_header_image` which can be a breaking change
- When bundling with NSIS, users can add `uninstallerIcon` and `uninstallerHeaderImage` under `bundle > windows > nsis` to configure them.

View File

@@ -1,6 +0,0 @@
---
"tauri-cli": minor:feat
"@tauri-apps/cli": minor:feat
---
Added support to defining the content type of the declared file association on macOS (maps to LSItemContentTypes property).

View File

@@ -1,6 +0,0 @@
---
"tauri-cli": minor:feat
"@tauri-apps/cli": minor:feat
---
Added support to defining the metadata for custom types declared in `tauri.conf.json > bundle > fileAssociations > exportedType` via the `UTExportedTypeDeclarations` Info.plist property.

View File

@@ -1,5 +0,0 @@
---
"tauri-utils": minor:feat
---
Added `FileAssociation::exported_type` and `FileAssociation::content_types` for better support to defining custom types on macOS.

View File

@@ -1,6 +0,0 @@
---
'tauri-cli': 'patch:bug'
'@tauri-apps/cli': patch:bug
---
Enhance Android build script usage on Windows by attempting to run cmd, bat and exe formats.

View File

@@ -0,0 +1,7 @@
---
"tauri-bundler": patch:bug
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
Fix `build --bundles` to allow `nsis` arg in linux+macOS

View File

@@ -1,5 +0,0 @@
---
"tauri-codegen": patch:bug
---
Do not hash empty scripts when generating the Content-Security-Policy SHA-256 hashes.

View File

@@ -1,5 +0,0 @@
---
"tauri-codegen": patch:bug
---
Fix JavaScript SHA256 hash generation on Windows not ignoring carriage return characters.

View File

@@ -1,6 +0,0 @@
---
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
Fix iOS CLI usage after modifying the package name.

View File

@@ -0,0 +1,6 @@
---
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
Fix iOS build failure when `Metal Toolchain` is installed by using explicit `$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain` path instead of `$(TOOLCHAIN_DIR)` for Swift library search paths.

View File

@@ -1,6 +0,0 @@
---
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
Replaced the non-standard nerd font character with ` ⱼₛ` in `tarui info`

View File

@@ -1,6 +0,0 @@
---
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
Wait for dev server to exit before exiting the CLI when the app is closed on `tauri dev --no-watch`.

View File

@@ -1,6 +0,0 @@
---
"@tauri-apps/cli": patch:bug
"tauri-cli": patch:bug
---
Resolve local IP address when `tauri.conf.json > build > devUrl` host is `0.0.0.0`.

View File

@@ -1,8 +0,0 @@
---
"@tauri-apps/cli": minor:enhance
"tauri-cli": minor:enhance
"tauri-bundler": minor:enhance
---
Improve error messages with more context.

View File

@@ -1,8 +0,0 @@
---
"tauri-utils": minor:feat
"tauri-cli": minor:feat
"@tauri-apps/cli": minor:feat
---
Added `bundle > macOS > infoPlist` and `bundle > iOS > infoPlist` configurations to allow defining custom Info.plist extensions.

View File

@@ -1,6 +0,0 @@
---
"@tauri-apps/cli": minor:enhance
"tauri-cli": minor:enhance
---
Prompt to install the iOS platform if it isn't installed yet.

View File

@@ -1,5 +0,0 @@
---
"tauri": minor:feat
---
Support async Swift plugin methods (`completionHandler:`) in PluginManager

View File

@@ -0,0 +1,5 @@
---
"tauri-bundler": patch:bug
---
Correct GitHub Release URL path for Linux i686 tooling.

View File

@@ -1,5 +0,0 @@
---
tauri-bundler: patch:bug
---
Set `APPIMAGE_EXTRACT_AND_RUN` on top of using the `--appimage-extra-and-run` cli arg for linuxdeploy.

View File

@@ -0,0 +1,5 @@
---
"tauri-bundler": minor:feat
---
Added support to Liquid Glass icons.

View File

@@ -1,5 +0,0 @@
---
"tauri-runtime-wry": patch:bug
---
Always try to create macOS WebKit webview, even if webkit runtime doesn't get detected correctly

View File

@@ -1,6 +0,0 @@
---
"@tauri-apps/cli": patch:bug
"tauri-cli": patch:bug
---
Fixes mobile project initialization when using `pnpx` or `pnpm dlx`.

View File

@@ -1,6 +0,0 @@
---
"@tauri-apps/cli": minor:feat
"tauri-cli": minor:feat
---
Added `ios run` and `android run` commands to run the app in production mode.

View File

@@ -0,0 +1,8 @@
---
"tauri": minor:feat
"tauri-runtime-wry": minor:feat
"tauri-runtime": minor:feat
"tauri-utils": minor:feat
---
Support creating multiple windows on Android (activity embedding) and iOS (scenes).

View File

@@ -0,0 +1,6 @@
---
"tauri": minor:changes
"tauri-runtime-wry": minor:changes
---
The new window handler passed to `on_new_window` no longer requires `Sync`, and runs on main thread on Windows, aligning with other platforms

View File

@@ -1,5 +0,0 @@
---
"tauri-utils": patch:feat
---
Added `html::normalize_script_for_csp`.

View File

@@ -3,4 +3,4 @@
"@tauri-apps/cli": patch:enhance
---
Check mismatched versions in `tauri info`
Show the context before prompting for updater signing key password

View File

@@ -1,5 +0,0 @@
---
"tauri-bundler": minor:breaking
---
Changed `MacOsSettings::info_plist_path` to `MacOsSettings::info_plist`.

View File

@@ -1,5 +0,0 @@
---
"@tauri-apps/api": patch:bug
---
Fix `core > addPluginListener` failing on command permission check.

View File

@@ -0,0 +1,5 @@
---
"tauri": patch:enhance
---
Implement retrieving inner PathBuf from SafePathBuf to ease using APIs that require an owned PathBuf

View File

@@ -1,6 +0,0 @@
---
"tauri": "patch:bug"
"tauri-macros": "patch:bug"
---
Fix the stack overflow when having too many commands in a single invoke handler in release build

View File

@@ -0,0 +1,6 @@
---
"tauri-utils": minor:deps
---
Add new `html-manipulation-2` and `build-2` feature flags that use `dom_query` instead of `kuchikiki` for HTML parsing / manipulation.
This allows downstream users to remove `kuchikiki` and its dependencies from their dependency tree.

View File

@@ -1,5 +0,0 @@
---
"tauri-bundler": minor:feat
---
Support providing `plist::Value` as macOS entitlements.

5
.changes/tauri-dbus.md Normal file
View File

@@ -0,0 +1,5 @@
---
tauri: minor:feat
---
Added `dbus` feature flag (enabled by default) which is required for theme detection on Linux.

5
.changes/toml-ver.md Normal file
View File

@@ -0,0 +1,5 @@
---
tauri-utils: patch:deps
---
Changed `toml` crate version from `0.9` to `">=0.9, <=1"`

View File

@@ -1,7 +0,0 @@
---
"tauri-cli": minor:feat
"@tauri-apps/cli": minor:feat
"tauri-utils": minor:feat
---
Added support to universal app links on macOS with the `plugins > deep-link > desktop > domains` configuration.

View File

@@ -1,7 +0,0 @@
---
"tauri-cli": patch:enhance
"@tauri-apps/cli": patch:enhance
---
Warn if productName is empty when initializing mobile project.

View File

@@ -0,0 +1,12 @@
---
"tauri-bundler": minor:feat
"tauri-cli": minor:feat
"@tauri-apps/cli": minor:feat
---
Added support for `minimumWebview2Version` option support for the MSI (Wix) installer, the old `bundle > windows > nsis > minimumWebview2Version` is now deprecated in favor of `bundle > windows > minimumWebview2Version`
Notes:
- For anyone relying on the `WVRTINSTALLED` `Property` tag in `main.wxs`, it is now renamed to `INSTALLED_WEBVIEW2_VERSION`
- For `tauri-bundler` lib users, the `WindowsSettings` now has a new field `minimum_webview2_version` which can be a breaking change

View File

@@ -5,6 +5,7 @@ Hi! We, the maintainers, are really excited that you are interested in contribut
- [Issue Reporting Guidelines](#issue-reporting-guidelines)
- [Pull Request Guidelines](#pull-request-guidelines)
- [Development Guide](#development-guide)
- [AI Tool Policy](#ai-tool-policy)
## Issue Reporting Guidelines
@@ -33,11 +34,9 @@ Hi! We, the maintainers, are really excited that you are interested in contribut
- It's OK to have multiple small commits as you work on the PR - we will let GitHub automatically squash it before merging.
- If adding new feature:
- Provide convincing reason to add this feature. Ideally you should open a suggestion issue first and have it greenlighted before working on it.
- If fixing a bug:
- If you are resolving a special issue, add `(fix: #xxxx[,#xxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `fix: update entities encoding/decoding (fix #3899)`.
- Provide detailed description of the bug in the PR, or link to an issue that does.
@@ -98,7 +97,7 @@ You can use `cargo install --path . --debug` to speed up test builds.
You can build the Rust documentation locally running the following script:
```bash
$ RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features --open
$ cargo +nightly doc --all-features --open
```
### Developing the JS API
@@ -106,6 +105,16 @@ $ RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features --open
The JS API provides bindings between the developer's JS in the Webview and the built-in Tauri APIs, written in Rust. Its code is located in [/packages/api](https://github.com/tauri-apps/tauri/tree/dev/packages/api).
After making changes to the code, run `pnpm build` to build it. To test your changes, we recommend using the API example app, located in [/examples/api](https://github.com/tauri-apps/tauri/tree/dev/examples/api). It will automatically use your local copy of the JS API and provides a helpful UI to test the various commands.
## AI Tool Policy
It takes a lot of time to review a Pull Request while it's very easy to make a nonsensical but plausible looking one using AI tools.
It is unfair for other contributors and the reviewers to spend much of the time dealing with this, hence these rules:
1. Review and test all LLM-generated content before submitting, you're the one responsible for it, not the AI.
2. Don't use AI to respond to review comments (except for translations).
We will close the Pull Request with a `ai-slop` tag if you failed to do so.
## Financial Contribution
Tauri is an MIT-licensed open source project. Its ongoing development can be supported via [GitHub Sponsors](https://github.com/sponsors/tauri-apps) or [Open Collective](https://opencollective.com/tauri). We prefer GitHub Sponsors as donations made are doubled through the matching fund program.

View File

@@ -8,7 +8,16 @@ on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
pull_request:
paths:
- '.github/workflows/audit.yml'
- '**/Cargo.lock'
- '**/Cargo.toml'
- '**/package.json'
- '**/pnpm-lock.yaml'
push:
branches:
- dev
paths:
- '.github/workflows/audit.yml'
- '**/Cargo.lock'
@@ -26,7 +35,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: rust audit
uses: rustsec/audit-check@v1
uses: rustsec/audit-check@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -61,7 +61,7 @@ jobs:
actions: write # required for workflow_dispatch
contents: write # required to create new releases
pull-requests: write # required to open version update pr
id-token: write # pnpm provenance
id-token: write # pnpm provenance / oidc token
outputs:
change: ${{ steps.covector.outputs.change }}
commandRan: ${{ steps.covector.outputs.commandRan }}
@@ -74,11 +74,9 @@ jobs:
with:
fetch-depth: 0
- run: npm i -g --force corepack
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: 20
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
node-version: 24
- name: cargo login
run: cargo login ${{ secrets.ORG_CRATES_IO_TOKEN }}
@@ -96,7 +94,6 @@ jobs:
uses: jbolda/covector/packages/action@covector-v0
id: covector
env:
NODE_AUTH_TOKEN: ${{ secrets.ORG_NPM_TOKEN }}
CARGO_AUDIT_OPTIONS: ${{ secrets.CARGO_AUDIT_OPTIONS }}
NPM_CONFIG_PROVENANCE: true
with:

View File

@@ -20,6 +20,10 @@ defaults:
run:
working-directory: packages/cli/
permissions:
contents: write # update release
id-token: write # oidc token
jobs:
build:
strategy:
@@ -116,7 +120,7 @@ jobs:
if: ${{ !matrix.settings.docker }}
with:
targets: ${{ matrix.settings.target }}
- uses: Swatinem/rust-cache@v1
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.settings.target }}
if: ${{ matrix.settings.docker }}
@@ -366,16 +370,13 @@ jobs:
- test-linux-x64-gnu-binding
- test-linux-x64-musl-binding
#- test-linux-arm-bindings
permissions:
contents: write # update release
id-token: write # npm provenance
steps:
- uses: actions/checkout@v4
- run: npm i -g --force corepack
- name: Setup node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 20
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm i --frozen-lockfile --ignore-scripts
@@ -390,10 +391,8 @@ jobs:
shell: bash
- name: Publish
run: |
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
npm publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.ORG_NPM_TOKEN }}
NODE_AUTH_TOKEN: ''
RELEASE_ID: ${{ github.event.client_payload.releaseId || inputs.releaseId }}
NPM_CONFIG_PROVENANCE: true

View File

@@ -38,35 +38,62 @@ jobs:
rust_target: aarch64-pc-windows-msvc
ext: '.exe'
args: ''
- os: ubuntu-22.04
rust_target: riscv64gc-unknown-linux-gnu
ext: ''
args: ''
cross: true
steps:
- uses: actions/checkout@v4
- name: 'Setup Rust'
if: ${{ !matrix.config.cross }}
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.config.rust_target }}
- uses: Swatinem/rust-cache@v2
if: ${{ !matrix.config.cross }}
with:
key: ${{ matrix.config.rust_target }}
- name: install Linux dependencies
if: matrix.config.os == 'ubuntu-latest'
if: ${{ !matrix.config.cross && startsWith(matrix.config.os, 'ubuntu') }}
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev
- name: Install cross
if: ${{ matrix.config.cross }}
uses: taiki-e/install-action@v2
with:
tool: cross@0.2.5
- name: Build CLI
if: ${{ !matrix.config.cross }}
run: cargo build --manifest-path ./crates/tauri-cli/Cargo.toml --profile release-size-optimized ${{ matrix.config.args }}
- name: Build CLI (cross)
if: ${{ matrix.config.cross }}
run: cross build --manifest-path ./crates/tauri-cli/Cargo.toml --target ${{ matrix.config.rust_target }} --profile release-size-optimized ${{ matrix.config.args }}
- name: Upload CLI
if: ${{ !matrix.config.cross }}
uses: actions/upload-artifact@v4
with:
name: cargo-tauri-${{ matrix.config.rust_target }}${{ matrix.config.ext }}
path: target/release-size-optimized/cargo-tauri${{ matrix.config.ext }}
if-no-files-found: error
- name: Upload CLI (cross)
if: ${{ matrix.config.cross }}
uses: actions/upload-artifact@v4
with:
name: cargo-tauri-${{ matrix.config.rust_target }}${{ matrix.config.ext }}
path: target/${{ matrix.config.rust_target }}/release-size-optimized/cargo-tauri${{ matrix.config.ext }}
if-no-files-found: error
upload:
needs: build
runs-on: ubuntu-latest

View File

@@ -90,14 +90,26 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
prefix-key: v3
key: ${{ matrix.platform.target }}
save-if: ${{ matrix.features.key == 'all' }}
- name: test
- name: test tauri-utils
if: ${{ !matrix.platform.cross }}
# Using --lib --bins --tests to skip doc tests
run: cargo ${{ matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --lib --bins --tests --manifest-path crates/tauri-utils/Cargo.toml
- name: test tauri-utils (using cross)
if: ${{ matrix.platform.cross }}
# Using --lib --bins --tests to skip doc tests
run: |
cargo install cross --git https://github.com/cross-rs/cross --rev 51f46f296253d8122c927c5bb933e3c4f27cc317 --locked
cross ${{ matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --lib --bins --tests --manifest-path crates/tauri-utils/Cargo.toml
- name: test tauri
if: ${{ !matrix.platform.cross }}
run: cargo ${{ matrix.features.key == 'no-default' && 'check' || matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --manifest-path crates/tauri/Cargo.toml
- name: test (using cross)
- name: test tauri (using cross)
if: ${{ matrix.platform.cross }}
run: |
cargo install cross --git https://github.com/cross-rs/cross --rev 51f46f296253d8122c927c5bb933e3c4f27cc317 --locked

View File

@@ -57,7 +57,7 @@ function checkChangeFiles(changeFiles) {
for (const [file, packages] of unknownTagsEntries) {
for (const { package, tag } of packages) {
console.error(
`Package \`${package}\` has an uknown change tag ${tag} in ${file} `
`Package \`${package}\` has an unknown change tag ${tag} in ${file} `
)
}
}

View File

@@ -29,7 +29,7 @@ const ignore = [
async function checkFile(file) {
if (
extensions.some((e) => file.endsWith(e))
&& !ignore.some((i) => file.includes(`/${i}/`) || path.basename(file) == i)
&& !ignore.some((i) => file.includes(`/${i}/`) || path.basename(file) === i)
) {
const fileStream = fs.createReadStream(file)
const rl = readline.createInterface({

View File

@@ -1,16 +0,0 @@
.changes
.devcontainer
.docker
.github
.scripts
.vscode
audits
bench
packages/api
packages/cli
crates/tauri-cli
crates/tauri-bundler
crates/tauri-driver
crates/tauri-macos-sign
crates/tauri-schema-generator
crates/tests

1424
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,59 @@
# Changelog
## \[2.5.6]
### Dependencies
- Upgraded to `tauri-utils@2.8.3`
- Upgraded to `tauri-codegen@2.5.5`
## \[2.5.5]
### Dependencies
- Upgraded to `tauri-codegen@2.5.4`
## \[2.5.4]
### Enhancements
- [`2d28e3143`](https://www.github.com/tauri-apps/tauri/commit/2d28e3143ee3d97d7570ea03877aa00a0d6e47d0) ([#14632](https://www.github.com/tauri-apps/tauri/pull/14632) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Small code refactors for improved code readability. No user facing changes.
### Dependencies
- Upgraded to `tauri-utils@2.8.2`
- Upgraded to `tauri-codegen@2.5.3`
## \[2.5.3]
### Dependencies
- Upgraded to `tauri-utils@2.8.1`
- Upgraded to `tauri-codegen@2.5.2`
## \[2.5.2]
### Dependencies
- Upgraded to `tauri-codegen@2.5.1`
## \[2.5.1]
### Bug Fixes
- [`4b6b8690a`](https://www.github.com/tauri-apps/tauri/commit/4b6b8690ab886ebdf1307951cffbe03e31280baa) ([#14347](https://www.github.com/tauri-apps/tauri/pull/14347) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
## \[2.5.0]
### New Features
- [`3b4fac201`](https://www.github.com/tauri-apps/tauri/commit/3b4fac2017832d426dd07c5e24e26684eda57f7b) ([#14194](https://www.github.com/tauri-apps/tauri/pull/14194)) Add `tauri.conf.json > bundle > android > autoIncrementVersionCode` config option to automatically increment the Android version code.
### Dependencies
- Upgraded to `tauri-utils@2.8.0`
- Upgraded to `tauri-codegen@2.5.0`
## \[2.4.1]
### Enhancements

View File

@@ -1,6 +1,6 @@
[package]
name = "tauri-build"
version = "2.4.1"
version = "2.5.6"
description = "build time code to pair with https://crates.io/crates/tauri"
exclude = ["CHANGELOG.md", "/target"]
readme = "README.md"
@@ -22,15 +22,13 @@ targets = [
"x86_64-linux-android",
"x86_64-apple-ios",
]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
anyhow = "1"
quote = { version = "1", optional = true }
tauri-codegen = { version = "2.4.0", path = "../tauri-codegen", optional = true }
tauri-utils = { version = "2.7.0", path = "../tauri-utils", features = [
"build",
tauri-codegen = { version = "2.5.5", path = "../tauri-codegen", optional = true }
tauri-utils = { version = "2.8.3", path = "../tauri-utils", features = [
"build-2",
"resources",
] }
cargo_toml = "0.22"
@@ -43,7 +41,6 @@ tauri-winres = "0.3"
semver = "1"
dirs = "6"
glob = "0.3"
toml = "0.9"
# Our code requires at least 0.8.21 so don't simplify this to 0.8
schemars = { version = "0.8.21", features = ["preserve_order"] }

View File

@@ -157,7 +157,7 @@ fn read_plugins_manifests() -> Result<BTreeMap<String, Manifest>> {
Ok(manifests)
}
struct InlinedPuginsAcl {
struct InlinedPluginsAcl {
manifests: BTreeMap<String, Manifest>,
permission_files: BTreeMap<String, Vec<PermissionFile>>,
}
@@ -165,7 +165,7 @@ struct InlinedPuginsAcl {
fn inline_plugins(
out_dir: &Path,
inlined_plugins: HashMap<&'static str, InlinedPlugin>,
) -> Result<InlinedPuginsAcl> {
) -> Result<InlinedPluginsAcl> {
let mut acl_manifests = BTreeMap::new();
let mut permission_files_map = BTreeMap::new();
@@ -250,7 +250,7 @@ permissions = [{default_permissions}]
acl_manifests.insert(name.into(), manifest);
}
Ok(InlinedPuginsAcl {
Ok(InlinedPluginsAcl {
manifests: acl_manifests,
permission_files: permission_files_map,
})

View File

@@ -57,7 +57,7 @@ fn copy_binaries(
binaries: ResourcePaths,
target_triple: &str,
path: &Path,
package_name: Option<&String>,
package_name: Option<&str>,
) -> Result<()> {
for src in binaries {
let src = src?;
@@ -165,21 +165,21 @@ fn copy_frameworks(dest_dir: &Path, frameworks: &[String]) -> Result<()> {
.with_context(|| format!("Failed to create frameworks output directory at {dest_dir:?}"))?;
for framework in frameworks.iter() {
if framework.ends_with(".framework") {
let src_path = PathBuf::from(framework);
let src_path = Path::new(framework);
let src_name = src_path
.file_name()
.expect("Couldn't get framework filename");
let dest_path = dest_dir.join(src_name);
copy_dir(&src_path, &dest_path)?;
copy_dir(src_path, &dest_path)?;
continue;
} else if framework.ends_with(".dylib") {
let src_path = PathBuf::from(framework);
let src_path = Path::new(framework);
if !src_path.exists() {
return Err(anyhow::anyhow!("Library not found: {}", framework));
}
let src_name = src_path.file_name().expect("Couldn't get library filename");
let dest_path = dest_dir.join(src_name);
copy_file(&src_path, &dest_path)?;
copy_file(src_path, &dest_path)?;
continue;
} else if framework.contains('/') {
return Err(anyhow::anyhow!(
@@ -192,12 +192,8 @@ fn copy_frameworks(dest_dir: &Path, frameworks: &[String]) -> Result<()> {
continue;
}
}
if copy_framework_from(&PathBuf::from("/Library/Frameworks/"), framework, dest_dir)?
|| copy_framework_from(
&PathBuf::from("/Network/Library/Frameworks/"),
framework,
dest_dir,
)?
if copy_framework_from("/Library/Frameworks/".as_ref(), framework, dest_dir)?
|| copy_framework_from("/Network/Library/Frameworks/".as_ref(), framework, dest_dir)?
{
continue;
}
@@ -263,7 +259,7 @@ impl WindowsAttributes {
}
}
/// Creates the default attriute set wihtou the default app manifest.
/// Creates the default attribute set without the default app manifest.
#[must_use]
pub fn new_without_app_manifest() -> Self {
Self {
@@ -415,7 +411,8 @@ impl Attributes {
}
pub fn is_dev() -> bool {
env::var("DEP_TAURI_DEV").expect("missing `cargo:dev` instruction, please update tauri to latest")
env::var_os("DEP_TAURI_DEV")
.expect("missing `cargo:dev` instruction, please update tauri to latest")
== "true"
}
@@ -462,7 +459,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
println!("cargo:rerun-if-env-changed=TAURI_CONFIG");
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_os = env::var_os("CARGO_CFG_TARGET_OS").unwrap();
let mobile = target_os == "ios" || target_os == "android";
cfg_alias("desktop", !mobile);
cfg_alias("mobile", mobile);
@@ -507,7 +504,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
let cargo_toml_path = Path::new("Cargo.toml").canonicalize()?;
let mut manifest = Manifest::<cargo_toml::Value>::from_path_with_metadata(cargo_toml_path)?;
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
manifest::check(&config, &mut manifest)?;
@@ -533,7 +530,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
ResourcePaths::new(&external_binaries(paths, &target_triple, &target), true),
&target_triple,
target_dir,
manifest.package.as_ref().map(|p| &p.name),
manifest.package.as_ref().map(|p| p.name.as_ref()),
)?;
}
@@ -542,7 +539,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
.bundle
.resources
.clone()
.unwrap_or_else(|| BundleResources::List(Vec::new()));
.unwrap_or(BundleResources::List(Vec::new()));
if target_triple.contains("windows") {
if let Some(fixed_webview2_runtime_path) = match &config.bundle.windows.webview_install_mode {
WebviewInstallMode::FixedRuntime { path } => Some(path),
@@ -591,21 +588,19 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
use semver::Version;
use tauri_winres::{VersionInfo, WindowsResource};
fn find_icon<F: Fn(&&String) -> bool>(config: &Config, predicate: F, default: &str) -> PathBuf {
let icon_path = config
.bundle
.icon
.iter()
.find(|i| predicate(i))
.cloned()
.unwrap_or_else(|| default.to_string());
icon_path.into()
}
let window_icon_path = attributes
.windows_attributes
.window_icon_path
.unwrap_or_else(|| find_icon(&config, |i| i.ends_with(".ico"), "icons/icon.ico"));
.unwrap_or_else(|| {
config
.bundle
.icon
.iter()
.find(|i| i.ends_with(".ico"))
.map(AsRef::as_ref)
.unwrap_or("icons/icon.ico")
.into()
});
let mut res = WindowsResource::new();
@@ -688,7 +683,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
}
}
"msvc" => {
if env::var("STATIC_VCRUNTIME").is_ok_and(|v| v == "true") {
if env::var_os("STATIC_VCRUNTIME").is_some_and(|v| v == "true") {
static_vcruntime::build();
}
}

View File

@@ -23,7 +23,7 @@ struct AllowlistedDependency {
name: String,
alias: Option<String>,
kind: DependencyKind,
all_cli_managed_features: Option<Vec<&'static str>>,
all_cli_managed_features: Vec<&'static str>,
expected_features: Vec<String>,
}
@@ -33,7 +33,7 @@ pub fn check(config: &Config, manifest: &mut Manifest) -> Result<()> {
name: "tauri-build".into(),
alias: None,
kind: DependencyKind::Build,
all_cli_managed_features: Some(vec!["isolation"]),
all_cli_managed_features: vec!["isolation"],
expected_features: match config.app.security.pattern {
PatternKind::Isolation { .. } => vec!["isolation".to_string()],
_ => vec![],
@@ -43,12 +43,10 @@ pub fn check(config: &Config, manifest: &mut Manifest) -> Result<()> {
name: "tauri".into(),
alias: None,
kind: DependencyKind::Normal,
all_cli_managed_features: Some(
AppConfig::all_features()
.into_iter()
.filter(|f| f != &"tray-icon")
.collect(),
),
all_cli_managed_features: AppConfig::all_features()
.into_iter()
.filter(|f| f != &"tray-icon")
.collect(),
expected_features: config
.app
.features()
@@ -129,23 +127,13 @@ fn check_features(dependency: Dependency, metadata: &AllowlistedDependency) -> R
Dependency::Inherited(dep) => dep.features,
};
let diff = if let Some(all_cli_managed_features) = &metadata.all_cli_managed_features {
features_diff(
&features
.into_iter()
.filter(|f| all_cli_managed_features.contains(&f.as_str()))
.collect::<Vec<String>>(),
&metadata.expected_features,
)
} else {
features_diff(
&features
.into_iter()
.filter(|f| f.starts_with("allow-"))
.collect::<Vec<String>>(),
&metadata.expected_features,
)
};
let diff = features_diff(
&features
.into_iter()
.filter(|f| metadata.all_cli_managed_features.contains(&f.as_str()))
.collect::<Vec<String>>(),
&metadata.expected_features,
);
let mut error_message = String::new();
if !diff.remove.is_empty() {

View File

@@ -15,7 +15,8 @@ pub fn generate_gradle_files(project_dir: PathBuf) -> Result<()> {
"// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n".to_string();
let mut app_build_gradle = "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
val implementation by configurations
dependencies {"
dependencies {
implementation(\"androidx.lifecycle:lifecycle-process:2.10.0\")"
.to_string();
for (env, value) in std::env::vars_os() {

View File

@@ -1,5 +1,118 @@
# Changelog
## \[2.8.1]
### Bug Fixes
- [`6252432f0`](https://www.github.com/tauri-apps/tauri/commit/6252432f0757d896d7a61819bbff127efac5a156) ([#14945](https://www.github.com/tauri-apps/tauri/pull/14945) by [@veeceey](https://www.github.com/tauri-apps/tauri/../../veeceey)) Fix WIX installer registry search order so that the named `InstallDir` key takes priority over the NSIS default key, preventing install location from changing on updates.
### What's Changed
- [`7be58a1c6`](https://www.github.com/tauri-apps/tauri/commit/7be58a1c643a7ed6d0f484a7e1134022618eb2b2) ([#14894](https://www.github.com/tauri-apps/tauri/pull/14894) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Log patching bundle type information again
### Dependencies
- Upgraded to `tauri-utils@2.8.3`
## \[2.8.0]
### Enhancements
- [`c769f211f`](https://www.github.com/tauri-apps/tauri/commit/c769f211fcaa543884c9d0f87ebd2ee106c01382) ([#14824](https://www.github.com/tauri-apps/tauri/pull/14824) by [@Kf637](https://www.github.com/tauri-apps/tauri/../../Kf637)) feat(nsis): add Norwegian language support for installer.
### Bug Fixes
- [`7fca58230`](https://www.github.com/tauri-apps/tauri/commit/7fca58230f97c3e6834134419514a0c7dbbe784b) ([#14830](https://www.github.com/tauri-apps/tauri/pull/14830) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Updated `nsis_tauri_utils` to 0.5.3:
- Use an alternative method `CreateProcessWithTokenW` to run programs as user, this fixed a problem that the program launched with the previous method can't query its own handle
### What's Changed
- [`0575dd287`](https://www.github.com/tauri-apps/tauri/commit/0575dd287e021b61d2aedf64d62ae84a2c925fb4) ([#14521](https://www.github.com/tauri-apps/tauri/pull/14521) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Change the way bundle type information is added to binary files. Instead of looking up the value of a variable we simply look for the default value.
### Dependencies
- Upgraded to `tauri-utils@2.8.2`
- Upgraded to `tauri-macos-sign@2.3.3`
## \[2.7.5]
### Enhancements
- [`4176f93ae`](https://www.github.com/tauri-apps/tauri/commit/4176f93ae43ef66714c4934feb3df19df3a3e28a) ([#14570](https://www.github.com/tauri-apps/tauri/pull/14570) by [@chfaft](https://www.github.com/tauri-apps/tauri/../../chfaft)) Consider extensions that are defined in the wxs template.
### Bug Fixes
- [`018b4db22`](https://www.github.com/tauri-apps/tauri/commit/018b4db22e167fa67b37b0933e192a0f3556d3e5) ([#14625](https://www.github.com/tauri-apps/tauri/pull/14625) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Skip signing for NSIS uninstaller when using `--no-sign` flag
- [`91becd9e4`](https://www.github.com/tauri-apps/tauri/commit/91becd9e4fa2db089ddc6b21dadc06133e939e08) ([#14627](https://www.github.com/tauri-apps/tauri/pull/14627) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix NSIS plugins not being signed due to wrong path handlings
### Dependencies
- Upgraded to `tauri-macos-sign@2.3.2`
## \[2.7.4]
### Bug Fixes
- [`1496145f8`](https://www.github.com/tauri-apps/tauri/commit/1496145f8222649efeff22b819a96208670bbea1) ([#14585](https://www.github.com/tauri-apps/tauri/pull/14585) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the AppImage bundler to fail with 404 errors for 32-bit builds.
### Performance Improvements
- [`ce98d87ce`](https://www.github.com/tauri-apps/tauri/commit/ce98d87ce0aaa907285852eb80691197424e03c3) ([#14474](https://www.github.com/tauri-apps/tauri/pull/14474) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) refactor: remove needless collect. No user facing changes.
- [`ee3cc4a91`](https://www.github.com/tauri-apps/tauri/commit/ee3cc4a91bf1315ecaefe90f423ffd55ef6c40db) ([#14475](https://www.github.com/tauri-apps/tauri/pull/14475) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) perf: remove needless clones in various files for improved performance. No user facing changes.
### Dependencies
- Upgraded to `tauri-macos-sign@2.3.1`
- Upgraded to `tauri-utils@2.8.1`
- [`b5ef603d8`](https://www.github.com/tauri-apps/tauri/commit/b5ef603d84bd8044625e50dcfdabb099b2e9fdd9) ([#14478](https://www.github.com/tauri-apps/tauri/pull/14478) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Updated NSIS from 3.8 to 3.11
## \[2.7.3]
### Enhancements
- [`22edc65aa`](https://www.github.com/tauri-apps/tauri/commit/22edc65aad0b3e45515008e8e0866112da70c8a1) ([#14408](https://www.github.com/tauri-apps/tauri/pull/14408) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Set user-agent in bundler and cli http requests when fetching build tools.
### Bug Fixes
- [`9a1922636`](https://www.github.com/tauri-apps/tauri/commit/9a192263693d71123a9953e2a6ee60fad07500b4) ([#14410](https://www.github.com/tauri-apps/tauri/pull/14410) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix uninstall fails if you close the app manually during the 'Click Ok to kill it' dialog
## \[2.7.2]
### Enhancements
- [`7f710b8f3`](https://www.github.com/tauri-apps/tauri/commit/7f710b8f3b509ed327d76761926511cf56e66b2d) ([#14390](https://www.github.com/tauri-apps/tauri/pull/14390) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Inline linuxdeploy plugins which were previously downloaded from `https://raw.githubusercontent.com` which lately blocks many users with a 429 error.
- [`fc017ee25`](https://www.github.com/tauri-apps/tauri/commit/fc017ee2577f48615367ea519386d3f37837e2c1) ([#14368](https://www.github.com/tauri-apps/tauri/pull/14368) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Mention symbol stripping on Linux in binary patch failed warning message
## \[2.7.1]
### Dependencies
- Upgraded to `tauri-macos-sign@2.3.0`
## \[2.7.0]
### New Features
- [`2a06d1006`](https://www.github.com/tauri-apps/tauri/commit/2a06d10066a806e392efe8bfb16d943ee0b0b61d) ([#14052](https://www.github.com/tauri-apps/tauri/pull/14052)) Add a `--no-sign` flag to the `tauri build` and `tauri bundle` commands to skip the code signing step, improving the developer experience for local testing and development without requiring code signing keys.
- [`cc8c0b531`](https://www.github.com/tauri-apps/tauri/commit/cc8c0b53171173dbd1d01781a50de1a3ea159031) ([#14031](https://www.github.com/tauri-apps/tauri/pull/14031)) Support providing `plist::Value` as macOS entitlements.
### Enhancements
- [`b06b3bd09`](https://www.github.com/tauri-apps/tauri/commit/b06b3bd091b0fed26cdcfb23cacb0462a7a9cc2d) ([#14126](https://www.github.com/tauri-apps/tauri/pull/14126)) Improve error messages with more context.
### Bug Fixes
- [`06d4a4ed6`](https://www.github.com/tauri-apps/tauri/commit/06d4a4ed6c146d6c7782016cf90037b56b944445) ([#14241](https://www.github.com/tauri-apps/tauri/pull/14241)) Set `APPIMAGE_EXTRACT_AND_RUN` on top of using the `--appimage-extra-and-run` cli arg for linuxdeploy.
### Dependencies
- Upgraded to `tauri-utils@2.8.0`
### Breaking Changes
- [`ed7c9a410`](https://www.github.com/tauri-apps/tauri/commit/ed7c9a4100e08c002212265549d12130d021ad1e) ([#14108](https://www.github.com/tauri-apps/tauri/pull/14108)) Changed `MacOsSettings::info_plist_path` to `MacOsSettings::info_plist`.
## \[2.6.1]
### Bug Fixes

View File

@@ -1,6 +1,6 @@
[package]
name = "tauri-bundler"
version = "2.6.1"
version = "2.8.1"
authors = [
"George Burton <burtonageo@gmail.com>",
"Tauri Programme within The Commons Conservancy",
@@ -15,7 +15,7 @@ rust-version = "1.77.2"
exclude = ["CHANGELOG.md", "/target", "rustfmt.toml"]
[dependencies]
tauri-utils = { version = "2.7.0", path = "../tauri-utils", features = [
tauri-utils = { version = "2.8.3", path = "../tauri-utils", features = [
"resources",
] }
image = "0.25"
@@ -59,7 +59,7 @@ features = ["Win32_System_SystemInformation", "Win32_System_Diagnostics_Debug"]
[target."cfg(target_os = \"macos\")".dependencies]
icns = { package = "tauri-icns", version = "0.1" }
time = { version = "0.3", features = ["formatting"] }
tauri-macos-sign = { version = "2.2.0", path = "../tauri-macos-sign" }
tauri-macos-sign = { version = "2.3.3", path = "../tauri-macos-sign" }
[target."cfg(target_os = \"linux\")".dependencies]
heck = "0.5"

View File

@@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT
mod category;
mod kmp;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "macos")]
@@ -15,28 +16,63 @@ mod windows;
use tauri_utils::{display_path, platform::Target as TargetPlatform};
const BUNDLE_VAR_TOKEN: &[u8] = b"__TAURI_BUNDLE_TYPE_VAR_UNK";
/// Patch a binary with bundle type information
fn patch_binary(binary: &PathBuf, package_type: &PackageType) -> crate::Result<()> {
match package_type {
#[cfg(target_os = "linux")]
PackageType::AppImage | PackageType::Deb | PackageType::Rpm => {
log::info!(
"Patching binary {:?} for type {}",
binary,
package_type.short_name()
);
linux::patch_binary(binary, package_type)?;
#[cfg(target_os = "linux")]
let bundle_type = match package_type {
crate::PackageType::Deb => b"__TAURI_BUNDLE_TYPE_VAR_DEB",
crate::PackageType::Rpm => b"__TAURI_BUNDLE_TYPE_VAR_RPM",
crate::PackageType::AppImage => b"__TAURI_BUNDLE_TYPE_VAR_APP",
// NSIS installers can be built in linux using cargo-xwin
crate::PackageType::Nsis => b"__TAURI_BUNDLE_TYPE_VAR_NSS",
_ => {
return Err(crate::Error::InvalidPackageType(
package_type.short_name().to_owned(),
"Linux".to_owned(),
))
}
PackageType::Nsis | PackageType::WindowsMsi => {
log::info!(
"Patching binary {:?} for type {}",
binary,
package_type.short_name()
);
windows::patch_binary(binary, package_type)?;
};
#[cfg(target_os = "windows")]
let bundle_type = match package_type {
crate::PackageType::Nsis => b"__TAURI_BUNDLE_TYPE_VAR_NSS",
crate::PackageType::WindowsMsi => b"__TAURI_BUNDLE_TYPE_VAR_MSI",
_ => {
return Err(crate::Error::InvalidPackageType(
package_type.short_name().to_owned(),
"Windows".to_owned(),
))
}
_ => (),
}
};
#[cfg(target_os = "macos")]
let bundle_type = match package_type {
// NSIS installers can be built in macOS using cargo-xwin
crate::PackageType::Nsis => b"__TAURI_BUNDLE_TYPE_VAR_NSS",
crate::PackageType::MacOsBundle | crate::PackageType::Dmg => {
// skip patching for macOS-native bundles
return Ok(());
}
_ => {
return Err(crate::Error::InvalidPackageType(
package_type.short_name().to_owned(),
"macOS".to_owned(),
))
}
};
log::info!(
"Patching {} with bundle type information: {}",
display_path(binary),
package_type.short_name()
);
let mut file_data = std::fs::read(binary).expect("Could not read binary file.");
let bundle_var_index =
kmp::index_of(BUNDLE_VAR_TOKEN, &file_data).ok_or(crate::Error::MissingBundleTypeVar)?;
file_data[bundle_var_index..bundle_var_index + BUNDLE_VAR_TOKEN.len()]
.copy_from_slice(bundle_type);
std::fs::write(binary, &file_data).map_err(|e| crate::Error::BinaryWriteError(e.to_string()))?;
Ok(())
}
@@ -92,22 +128,17 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
.expect("Main binary missing in settings");
let main_binary_path = settings.binary_path(main_binary);
// When packaging multiple binary types, we make a copy of the unsigned main_binary so that we can
// restore it after each package_type step. This avoids two issues:
// We make a copy of the unsigned main_binary so that we can restore it after each package_type step.
// This allows us to patch the binary correctly and avoids two issues:
// - modifying a signed binary without updating its PE checksum can break signature verification
// - codesigning tools should handle calculating+updating this, we just need to ensure
// (re)signing is performed after every `patch_binary()` operation
// - signing an already-signed binary can result in multiple signatures, causing verification errors
let main_binary_reset_required = matches!(target_os, TargetPlatform::Windows)
&& settings.windows().can_sign()
&& package_types.len() > 1;
let mut unsigned_main_binary_copy = tempfile::tempfile()?;
if main_binary_reset_required {
let mut unsigned_main_binary = std::fs::File::open(&main_binary_path)?;
std::io::copy(&mut unsigned_main_binary, &mut unsigned_main_binary_copy)?;
}
// TODO: change this to work on a copy while preserving the main binary unchanged
let mut main_binary_copy = tempfile::tempfile()?;
let mut main_binary_orignal = std::fs::File::open(&main_binary_path)?;
std::io::copy(&mut main_binary_orignal, &mut main_binary_copy)?;
let mut main_binary_signed = false;
let mut bundles = Vec::<Bundle>::new();
for package_type in &package_types {
// bundle was already built! e.g. DMG already built .app
@@ -121,16 +152,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
// sign main binary for every package type after patch
if matches!(target_os, TargetPlatform::Windows) && settings.windows().can_sign() {
if main_binary_signed && main_binary_reset_required {
let mut signed_main_binary = std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.open(&main_binary_path)?;
unsigned_main_binary_copy.seek(SeekFrom::Start(0))?;
std::io::copy(&mut unsigned_main_binary_copy, &mut signed_main_binary)?;
}
windows::sign::try_sign(&main_binary_path, settings)?;
main_binary_signed = true;
}
let bundle_paths = match package_type {
@@ -153,7 +175,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
#[cfg(target_os = "windows")]
PackageType::WindowsMsi => windows::msi::bundle_project(settings, false)?,
// note: don't restrict to windows as NSIS installers can be built in linux using cargo-xwin
// don't restrict to windows as NSIS installers can be built in linux+macOS using cargo-xwin
PackageType::Nsis => windows::nsis::bundle_project(settings, false)?,
#[cfg(target_os = "linux")]
@@ -172,6 +194,14 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
package_type: package_type.to_owned(),
bundle_paths,
});
// Restore unsigned and unpatched binary
let mut modified_main_binary = std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.open(&main_binary_path)?;
main_binary_copy.seek(SeekFrom::Start(0))?;
std::io::copy(&mut main_binary_copy, &mut modified_main_binary)?;
}
if let Some(updater) = settings.updater() {
@@ -241,11 +271,10 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
return Ok(bundles);
}
let bundles_wo_updater = bundles
let finished_bundles = bundles
.iter()
.filter(|b| b.package_type != PackageType::Updater)
.collect::<Vec<_>>();
let finished_bundles = bundles_wo_updater.len();
.count();
let pluralised = if finished_bundles == 1 {
"bundle"
} else {
@@ -274,7 +303,7 @@ fn sign_binaries_if_needed(settings: &Settings, target_os: &TargetPlatform) -> c
if matches!(target_os, TargetPlatform::Windows) {
if settings.windows().can_sign() {
if settings.no_sign() {
log::info!("Skipping binary signing due to --no-sign flag.");
log::warn!("Skipping binary signing due to --no-sign flag.");
return Ok(());
}

View File

@@ -0,0 +1,59 @@
// Copyright 2016-2019 Cargo-Bundle developers <https://github.com/burtonageo/cargo-bundle>
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
// KnuthMorrisPratt algorithm
// based on https://github.com/howeih/rust_kmp
pub fn index_of(pattern: &[u8], target: &[u8]) -> Option<usize> {
let failure_function = find_failure_function(pattern);
let mut t_i: usize = 0;
let mut p_i: usize = 0;
let target_len = target.len();
let mut result_idx = None;
let pattern_len = pattern.len();
while (t_i < target_len) && (p_i < pattern_len) {
if target[t_i] == pattern[p_i] {
if result_idx.is_none() {
result_idx.replace(t_i);
}
t_i += 1;
p_i += 1;
if p_i >= pattern_len {
return result_idx;
}
} else {
if p_i == 0 {
p_i = 0;
t_i += 1;
} else {
p_i = failure_function[p_i - 1];
}
result_idx = None;
}
}
None
}
fn find_failure_function(pattern: &[u8]) -> Vec<usize> {
let mut i = 1;
let mut j = 0;
let pattern_length = pattern.len();
let end_i = pattern_length - 1;
let mut failure_function = vec![0usize; pattern_length];
while i <= end_i {
if pattern[i] == pattern[j] {
failure_function[i] = j + 1;
i += 1;
j += 1;
} else if j == 0 {
failure_function[i] = 0;
i += 1;
} else {
j = failure_function[j - 1];
}
}
failure_function
}

View File

@@ -0,0 +1,165 @@
#! /bin/bash
# abort on all errors
set -e
if [ "$DEBUG" != "" ]; then
set -x
fi
script=$(readlink -f "$0")
show_usage() {
echo "Usage: $script --appdir <path to AppDir>"
echo
echo "Bundles GStreamer plugins into an AppDir"
echo
echo "Required variables:"
echo " LINUXDEPLOY=\".../linuxdeploy\" path to linuxdeploy (e.g., AppImage); set automatically when plugin is run directly by linuxdeploy"
echo
echo "Optional variables:"
echo " GSTREAMER_INCLUDE_BAD_PLUGINS=\"1\" (default: disabled; set to empty string or unset to disable)"
echo " GSTREAMER_PLUGINS_DIR=\"...\" (directory containing GStreamer plugins; default: guessed based on main distro architecture)"
echo " GSTREAMER_HELPERS_DIR=\"...\" (directory containing GStreamer helper tools like gst-plugin-scanner; default: guessed based on main distro architecture)"
echo " GSTREAMER_VERSION=\"1.0\" (default: 1.0)"
}
while [ "$1" != "" ]; do
case "$1" in
--plugin-api-version)
echo "0"
exit 0
;;
--appdir)
APPDIR="$2"
shift
shift
;;
--help)
show_usage
exit 0
;;
*)
echo "Invalid argument: $1"
echo
show_usage
exit 1
;;
esac
done
if [ "$APPDIR" == "" ]; then
show_usage
exit 1
fi
if ! which patchelf &>/dev/null && ! type patchelf &>/dev/null; then
echo "Error: patchelf not found"
echo
show_usage
exit 2
fi
if [[ "$LINUXDEPLOY" == "" ]]; then
echo "Error: \$LINUXDEPLOY not set"
echo
show_usage
exit 3
fi
mkdir -p "$APPDIR"
export GSTREAMER_VERSION="${GSTREAMER_VERSION:-1.0}"
plugins_target_dir="$APPDIR"/usr/lib/gstreamer-"$GSTREAMER_VERSION"
helpers_target_dir="$APPDIR"/usr/lib/gstreamer"$GSTREAMER_VERSION"/gstreamer-"$GSTREAMER_VERSION"
if [ "$GSTREAMER_PLUGINS_DIR" != "" ]; then
plugins_dir="${GSTREAMER_PLUGINS_DIR}"
elif [ -d /usr/lib/"$(uname -m)"-linux-gnu/gstreamer-"$GSTREAMER_VERSION" ]; then
plugins_dir=/usr/lib/$(uname -m)-linux-gnu/gstreamer-"$GSTREAMER_VERSION"
else
plugins_dir=/usr/lib/gstreamer-"$GSTREAMER_VERSION"
fi
if [ "$GSTREAMER_HELPERS_DIR" != "" ]; then
helpers_dir="${GSTREAMER_HELPERS_DIR}"
else
helpers_dir=/usr/lib/$(uname -m)-linux-gnu/gstreamer"$GSTREAMER_VERSION"/gstreamer-"$GSTREAMER_VERSION"
fi
if [ ! -d "$plugins_dir" ]; then
echo "Error: could not find plugins directory: $plugins_dir"
exit 1
fi
mkdir -p "$plugins_target_dir"
echo "Copying plugins into $plugins_target_dir"
for i in "$plugins_dir"/*; do
[ -d "$i" ] && continue
[ ! -f "$i" ] && echo "File does not exist: $i" && continue
echo "Copying plugin: $i"
cp "$i" "$plugins_target_dir"
done
"$LINUXDEPLOY" --appdir "$APPDIR"
for i in "$plugins_target_dir"/*; do
[ -d "$i" ] && continue
[ ! -f "$i" ] && echo "File does not exist: $i" && continue
(file "$i" | grep -v ELF --silent) && echo "Ignoring non ELF file: $i" && continue
echo "Manually setting rpath for $i"
patchelf --set-rpath '$ORIGIN/..:$ORIGIN' "$i"
done
mkdir -p "$helpers_target_dir"
echo "Copying helpers in $helpers_target_dir"
for i in "$helpers_dir"/*; do
[ -d "$i" ] && continue
[ ! -f "$i" ] && echo "File does not exist: $i" && continue
echo "Copying helper: $i"
cp "$i" "$helpers_target_dir"
done
for i in "$helpers_target_dir"/*; do
[ -d "$i" ] && continue
[ ! -f "$i" ] && echo "File does not exist: $i" && continue
(file "$i" | grep -v ELF --silent) && echo "Ignoring non ELF file: $i" && continue
echo "Manually setting rpath for $i"
patchelf --set-rpath '$ORIGIN/../..' "$i"
done
echo "Installing AppRun hook"
mkdir -p "$APPDIR"/apprun-hooks
if [ "$GSTREAMER_VERSION" == "1.0" ]; then
cat > "$APPDIR"/apprun-hooks/linuxdeploy-plugin-gstreamer.sh <<\EOF
#! /bin/bash
export GST_REGISTRY_REUSE_PLUGIN_SCANNER="no"
export GST_PLUGIN_SYSTEM_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0"
export GST_PLUGIN_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0"
export GST_PLUGIN_SCANNER_1_0="${APPDIR}/usr/lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner"
export GST_PTP_HELPER_1_0="${APPDIR}/usr/lib/gstreamer1.0/gstreamer-1.0/gst-ptp-helper"
EOF
elif [ "$GSTREAMER_VERSION" == "0.10" ]; then
cat > "$APPDIR"/apprun-hooks/linuxdeploy-plugin-gstreamer.sh <<\EOF
#! /bin/bash
export GST_REGISTRY_REUSE_PLUGIN_SCANNER="no"
export GST_PLUGIN_SYSTEM_PATH_0_10="${APPDIR}/usr/lib/gstreamer-1.0"
export GST_PLUGIN_SCANNER_0_10="${APPDIR}/usr/lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner"
export GST_PTP_HELPER_0_10="${APPDIR}/usr/lib/gstreamer1.0/gstreamer-1.0/gst-ptp-helper"
EOF
else
echo "Warning: unknown GStreamer version: $GSTREAMER_VERSION, cannot install AppRun hook"
fi

View File

@@ -0,0 +1,327 @@
#! /usr/bin/env bash
# GTK3 environment variables: https://docs.gtk.org/gtk3/running.html
# GTK4 environment variables: https://docs.gtk.org/gtk4/running.html
# abort on all errors
set -e
if [ "$DEBUG" != "" ]; then
set -x
verbose="--verbose"
fi
script=$(readlink -f "$0")
show_usage() {
echo "Usage: $script --appdir <path to AppDir>"
echo
echo "Bundles resources for applications that use GTK into an AppDir"
echo
echo "Required variables:"
echo " LINUXDEPLOY=\".../linuxdeploy\" path to linuxdeploy (e.g., AppImage); set automatically when plugin is run directly by linuxdeploy"
#echo
#echo "Optional variables:"
#echo " DEPLOY_GTK_VERSION (major version of GTK to deploy, e.g. '2', '3' or '4'; auto-detect by default)"
}
variable_is_true() {
local var="$1"
if [ -n "$var" ] && { [ "$var" == "true" ] || [ "$var" -gt 0 ]; } 2> /dev/null; then
return 0 # true
else
return 1 # false
fi
}
get_pkgconf_variable() {
local variable="$1"
local library="$2"
local default_path="$3"
path="$("$PKG_CONFIG" --variable="$variable" "$library")"
if [ -n "$path" ]; then
echo "$path"
elif [ -n "$default_path" ]; then
echo "$default_path"
else
echo "$0: there is no '$variable' variable for '$library' library." > /dev/stderr
echo "Please check the '$library.pc' file is present in \$PKG_CONFIG_PATH (you may need to install the appropriate -dev/-devel package)." > /dev/stderr
exit 1
fi
}
copy_tree() {
local src=("${@:1:$#-1}")
local dst="${*:$#}"
for elem in "${src[@]}"; do
mkdir -p "${dst::-1}$elem"
cp "$elem" --archive --parents --target-directory="$dst" $verbose
done
}
search_tool() {
local tool="$1"
local directory="$2"
if command -v "$tool"; then
return 0
fi
PATH_ARRAY=(
"/usr/lib/$(uname -m)-linux-gnu/$directory/$tool"
"/usr/lib/$directory/$tool"
"/usr/bin/$tool"
"/usr/bin/$tool-64"
"/usr/bin/$tool-32"
)
for path in "${PATH_ARRAY[@]}"; do
if [ -x "$path" ]; then
echo "$path"
return 0
fi
done
}
#DEPLOY_GTK_VERSION="${DEPLOY_GTK_VERSION:-0}" # When not set by user, this variable use the integer '0' as a sentinel value
DEPLOY_GTK_VERSION=3 # Force GTK3 for tauri apps
APPDIR=
while [ "$1" != "" ]; do
case "$1" in
--plugin-api-version)
echo "0"
exit 0
;;
--appdir)
APPDIR="$2"
shift
shift
;;
--help)
show_usage
exit 0
;;
*)
echo "Invalid argument: $1"
echo
show_usage
exit 1
;;
esac
done
if [ "$APPDIR" == "" ]; then
show_usage
exit 1
fi
mkdir -p "$APPDIR"
# make lib64 writable again.
chmod +w "$APPDIR"/usr/lib64 || true
if command -v pkgconf > /dev/null; then
PKG_CONFIG="pkgconf"
elif command -v pkg-config > /dev/null; then
PKG_CONFIG="pkg-config"
else
echo "$0: pkg-config/pkgconf not found in PATH, aborting"
exit 1
fi
if ! command -v find &>/dev/null && ! type find &>/dev/null; then
echo -e "$0: find not found.\nInstall findutils then re-run the plugin."
exit 1
fi
if [ -z "$LINUXDEPLOY" ]; then
echo -e "$0: LINUXDEPLOY environment variable is not set.\nDownload a suitable linuxdeploy AppImage, set the environment variable and re-run the plugin."
exit 1
fi
gtk_versions=0 # Count major versions of GTK when auto-detect GTK version
if [ "$DEPLOY_GTK_VERSION" -eq 0 ]; then
echo "Determining which GTK version to deploy"
while IFS= read -r -d '' file; do
if [ "$DEPLOY_GTK_VERSION" -ne 2 ] && ldd "$file" | grep -q "libgtk-x11-2.0.so"; then
DEPLOY_GTK_VERSION=2
gtk_versions="$((gtk_versions+1))"
fi
if [ "$DEPLOY_GTK_VERSION" -ne 3 ] && ldd "$file" | grep -q "libgtk-3.so"; then
DEPLOY_GTK_VERSION=3
gtk_versions="$((gtk_versions+1))"
fi
if [ "$DEPLOY_GTK_VERSION" -ne 4 ] && ldd "$file" | grep -q "libgtk-4.so"; then
DEPLOY_GTK_VERSION=4
gtk_versions="$((gtk_versions+1))"
fi
done < <(find "$APPDIR/usr/bin" -executable -type f -print0)
fi
if [ "$gtk_versions" -gt 1 ]; then
echo "$0: can not deploy multiple GTK versions at the same time."
echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}."
exit 1
elif [ "$DEPLOY_GTK_VERSION" -eq 0 ]; then
echo "$0: failed to auto-detect GTK version."
echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}."
exit 1
fi
echo "Installing AppRun hook"
HOOKSDIR="$APPDIR/apprun-hooks"
HOOKFILE="$HOOKSDIR/linuxdeploy-plugin-gtk.sh"
mkdir -p "$HOOKSDIR"
cat > "$HOOKFILE" <<\EOF
#! /usr/bin/env bash
gsettings get org.gnome.desktop.interface gtk-theme 2> /dev/null | grep -qi "dark" && GTK_THEME_VARIANT="dark" || GTK_THEME_VARIANT="light"
APPIMAGE_GTK_THEME="${APPIMAGE_GTK_THEME:-"Adwaita:$GTK_THEME_VARIANT"}" # Allow user to override theme (discouraged)
export APPDIR="${APPDIR:-"$(dirname "$(realpath "$0")")"}" # Workaround to run extracted AppImage
export GTK_DATA_PREFIX="$APPDIR"
export GTK_THEME="$APPIMAGE_GTK_THEME" # Custom themes are broken
export GDK_BACKEND=x11 # Crash with Wayland backend on Wayland - We tested it without it and ended up with this: https://github.com/tauri-apps/tauri/issues/8541
export XDG_DATA_DIRS="$APPDIR/usr/share:/usr/share:$XDG_DATA_DIRS" # g_get_system_data_dirs() from GLib
EOF
echo "Installing GLib schemas"
# Note: schemasdir is undefined on Ubuntu 16.04
glib_schemasdir="$(get_pkgconf_variable "schemasdir" "gio-2.0" "/usr/share/glib-2.0/schemas")"
copy_tree "$glib_schemasdir" "$APPDIR/"
glib-compile-schemas "$APPDIR/$glib_schemasdir"
cat >> "$HOOKFILE" <<EOF
export GSETTINGS_SCHEMA_DIR="\$APPDIR/$glib_schemasdir"
EOF
case "$DEPLOY_GTK_VERSION" in
2)
# https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/pull/20#issuecomment-826354261
echo "WARNING: Gtk+2 applications are not fully supported by this plugin"
;;
3)
echo "Installing GTK 3.0 modules"
gtk3_exec_prefix="$(get_pkgconf_variable "exec_prefix" "gtk+-3.0")"
gtk3_libdir="$(get_pkgconf_variable "libdir" "gtk+-3.0")/gtk-3.0"
#gtk3_path="$gtk3_libdir/modules" export GTK_PATH="\$APPDIR/$gtk3_path"
gtk3_immodulesdir="$gtk3_libdir/$(get_pkgconf_variable "gtk_binary_version" "gtk+-3.0")/immodules"
gtk3_printbackendsdir="$gtk3_libdir/$(get_pkgconf_variable "gtk_binary_version" "gtk+-3.0")/printbackends"
gtk3_immodules_cache_file="$(dirname "$gtk3_immodulesdir")/immodules.cache"
gtk3_immodules_query="$(search_tool "gtk-query-immodules-3.0" "libgtk-3-0")"
copy_tree "$gtk3_libdir" "$APPDIR/"
cat >> "$HOOKFILE" <<EOF
export GTK_EXE_PREFIX="\$APPDIR/$gtk3_exec_prefix"
export GTK_PATH="\$APPDIR/$gtk3_libdir:/usr/lib64/gtk-3.0:/usr/lib/x86_64-linux-gnu/gtk-3.0"
export GTK_IM_MODULE_FILE="\$APPDIR/$gtk3_immodules_cache_file"
EOF
if [ -x "$gtk3_immodules_query" ]; then
echo "Updating immodules cache in $APPDIR/$gtk3_immodules_cache_file"
"$gtk3_immodules_query" > "$APPDIR/$gtk3_immodules_cache_file"
else
echo "WARNING: gtk-query-immodules-3.0 not found"
fi
if [ ! -f "$APPDIR/$gtk3_immodules_cache_file" ]; then
echo "WARNING: immodules.cache file is missing"
fi
sed -i "s|$gtk3_libdir/3.0.0/immodules/||g" "$APPDIR/$gtk3_immodules_cache_file"
;;
4)
echo "Installing GTK 4.0 modules"
gtk4_exec_prefix="$(get_pkgconf_variable "exec_prefix" "gtk4" "/usr")"
gtk4_libdir="$(get_pkgconf_variable "libdir" "gtk4")/gtk-4.0"
gtk4_path="$gtk4_libdir/modules"
copy_tree "$gtk4_libdir" "$APPDIR/"
cat >> "$HOOKFILE" <<EOF
export GTK_EXE_PREFIX="\$APPDIR/$gtk4_exec_prefix"
export GTK_PATH="\$APPDIR/$gtk4_path"
EOF
;;
*)
echo "$0: '$DEPLOY_GTK_VERSION' is not a valid GTK major version."
echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}."
exit 1
esac
echo "Installing GDK PixBufs"
gdk_libdir="$(get_pkgconf_variable "libdir" "gdk-pixbuf-2.0")"
gdk_pixbuf_binarydir="$(get_pkgconf_variable "gdk_pixbuf_binarydir" "gdk-pixbuf-2.0")"
gdk_pixbuf_cache_file="$(get_pkgconf_variable "gdk_pixbuf_cache_file" "gdk-pixbuf-2.0")"
gdk_pixbuf_moduledir="$(get_pkgconf_variable "gdk_pixbuf_moduledir" "gdk-pixbuf-2.0")"
# Note: gdk_pixbuf_query_loaders variable is not defined on some systems
gdk_pixbuf_query="$(search_tool "gdk-pixbuf-query-loaders" "gdk-pixbuf-2.0")"
copy_tree "$gdk_pixbuf_binarydir" "$APPDIR/"
cat >> "$HOOKFILE" <<EOF
export GDK_PIXBUF_MODULE_FILE="\$APPDIR/$gdk_pixbuf_cache_file"
EOF
if [ -x "$gdk_pixbuf_query" ]; then
echo "Updating pixbuf cache in $APPDIR/$gdk_pixbuf_cache_file"
"$gdk_pixbuf_query" > "$APPDIR/$gdk_pixbuf_cache_file"
else
echo "WARNING: gdk-pixbuf-query-loaders not found"
fi
if [ ! -f "$APPDIR/$gdk_pixbuf_cache_file" ]; then
echo "WARNING: loaders.cache file is missing"
fi
sed -i "s|$gdk_pixbuf_moduledir/||g" "$APPDIR/$gdk_pixbuf_cache_file"
echo "Copying more libraries"
gobject_libdir="$(get_pkgconf_variable "libdir" "gobject-2.0")"
gio_libdir="$(get_pkgconf_variable "libdir" "gio-2.0")"
librsvg_libdir="$(get_pkgconf_variable "libdir" "librsvg-2.0")"
pango_libdir="$(get_pkgconf_variable "libdir" "pango")"
pangocairo_libdir="$(get_pkgconf_variable "libdir" "pangocairo")"
pangoft2_libdir="$(get_pkgconf_variable "libdir" "pangoft2")"
FIND_ARRAY=(
"$gdk_libdir" "libgdk_pixbuf-*.so*"
"$gobject_libdir" "libgobject-*.so*"
"$gio_libdir" "libgio-*.so*"
"$librsvg_libdir" "librsvg-*.so*"
"$pango_libdir" "libpango-*.so*"
"$pangocairo_libdir" "libpangocairo-*.so*"
"$pangoft2_libdir" "libpangoft2-*.so*"
)
LIBRARIES=()
for (( i=0; i<${#FIND_ARRAY[@]}; i+=2 )); do
directory=${FIND_ARRAY[i]}
library=${FIND_ARRAY[i+1]}
while IFS= read -r -d '' file; do
LIBRARIES+=( "--library=$file" )
done < <(find "$directory" \( -type l -o -type f \) -name "$library" -print0)
done
env LINUXDEPLOY_PLUGIN_MODE=1 "$LINUXDEPLOY" --appdir="$APPDIR" "${LIBRARIES[@]}"
# Create symbolic links as a workaround
# Details: https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/issues/24#issuecomment-1030026529
echo "Manually setting rpath for GTK modules"
PATCH_ARRAY=(
"$gtk3_immodulesdir"
"$gtk3_printbackendsdir"
"$gdk_pixbuf_moduledir"
)
for directory in "${PATCH_ARRAY[@]}"; do
while IFS= read -r -d '' file; do
ln $verbose -s "${file/\/usr\/lib\//}" "$APPDIR/usr/lib"
done < <(find "$directory" -name '*.so' -print0)
done
# set write permission on lib64 again to make it deletable.
chmod +w "$APPDIR"/usr/lib64 || true
# We have to copy the files first to not get permission errors when we assign gio_extras_dir
find /usr/lib* -name libgiognutls.so -exec mkdir -p "$APPDIR"/"$(dirname '{}')" \; -exec cp --parents '{}' "$APPDIR/" \; || true
# related files that we seemingly don't need:
# libgiolibproxy.so - libgiognomeproxy.so - glib-pacrunner
gio_extras_dir=$(find "$APPDIR"/usr/lib* -name libgiognutls.so -exec dirname '{}' \; 2>/dev/null)
cat >> "$HOOKFILE" <<EOF
export GIO_EXTRA_MODULES="\$APPDIR/${gio_extras_dir#"$APPDIR"/}"
EOF
#binary patch absolute paths in libwebkit files
find "$APPDIR"/usr/lib* -name 'libwebkit*' -exec sed -i -e "s|/usr|././|g" '{}' \;

View File

@@ -3,7 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use super::debian;
use super::{super::debian, write_and_make_executable};
use crate::{
bundle::settings::Arch,
error::{Context, ErrorExt},
@@ -232,7 +232,7 @@ fn prepare_tools(tools_path: &Path, arch: &str, verbose: bool) -> crate::Result<
write_and_make_executable(&apprun, data)?;
}
let linuxdeploy_arch = if arch == "i686" { "i383" } else { arch };
let linuxdeploy_arch = if arch == "i686" { "i386" } else { arch };
let linuxdeploy = tools_path.join(format!("linuxdeploy-{linuxdeploy_arch}.AppImage"));
if !linuxdeploy.exists() {
let data = download(&format!("https://github.com/tauri-apps/binary-releases/releases/download/linuxdeploy/linuxdeploy-{linuxdeploy_arch}.AppImage"))?;
@@ -280,12 +280,3 @@ fn prepare_tools(tools_path: &Path, arch: &str, verbose: bool) -> crate::Result<
Ok(linuxdeploy)
}
fn write_and_make_executable(path: &Path, data: Vec<u8>) -> std::io::Result<()> {
use std::os::unix::fs::PermissionsExt;
fs::write(path, data)?;
fs::set_permissions(path, fs::Permissions::from_mode(0o770))?;
Ok(())
}

View File

@@ -0,0 +1,25 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use std::{
fs,
path::{Path, PathBuf},
};
use crate::Settings;
mod linuxdeploy;
pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
linuxdeploy::bundle_project(settings)
}
fn write_and_make_executable(path: &Path, data: Vec<u8>) -> std::io::Result<()> {
use std::os::unix::fs::PermissionsExt;
fs::write(path, data)?;
fs::set_permissions(path, fs::Permissions::from_mode(0o770))?;
Ok(())
}

View File

@@ -119,8 +119,9 @@ pub fn generate_data(
for bin in settings.binaries() {
let bin_path = settings.binary_path(bin);
fs_utils::copy_file(&bin_path, &bin_dir.join(bin.name()))
.with_context(|| format!("Failed to copy binary from {bin_path:?}"))?;
let trgt = bin_dir.join(bin.name());
fs_utils::copy_file(&bin_path, &trgt)
.with_context(|| format!("Failed to copy binary from {bin_path:?} to {trgt:?}"))?;
}
copy_resource_files(settings, &data_dir).with_context(|| "Failed to copy resource files")?;

View File

@@ -7,8 +7,3 @@ pub mod appimage;
pub mod debian;
pub mod freedesktop;
pub mod rpm;
mod util;
#[cfg(target_os = "linux")]
pub use util::patch_binary;

View File

@@ -1,59 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
/// Change value of __TAURI_BUNDLE_TYPE static variable to mark which package type it was bundled in
#[cfg(target_os = "linux")]
pub fn patch_binary(
binary_path: &std::path::PathBuf,
package_type: &crate::PackageType,
) -> crate::Result<()> {
let mut file_data = std::fs::read(binary_path).expect("Could not read binary file.");
let elf = match goblin::Object::parse(&file_data)? {
goblin::Object::Elf(elf) => elf,
_ => return Err(crate::Error::GenericError("Not an ELF file".to_owned())),
};
let offset = find_bundle_type_symbol(elf).ok_or(crate::Error::MissingBundleTypeVar)?;
let offset = offset as usize;
if offset + 3 <= file_data.len() {
let chars = &mut file_data[offset..offset + 3];
match package_type {
crate::PackageType::Deb => chars.copy_from_slice(b"DEB"),
crate::PackageType::Rpm => chars.copy_from_slice(b"RPM"),
crate::PackageType::AppImage => chars.copy_from_slice(b"APP"),
_ => {
return Err(crate::Error::InvalidPackageType(
package_type.short_name().to_owned(),
"linux".to_owned(),
))
}
}
std::fs::write(binary_path, &file_data)
.map_err(|error| crate::Error::BinaryWriteError(error.to_string()))?;
} else {
return Err(crate::Error::BinaryOffsetOutOfRange);
}
Ok(())
}
/// Find address of a symbol in relocations table
#[cfg(target_os = "linux")]
fn find_bundle_type_symbol(elf: goblin::elf::Elf<'_>) -> Option<i64> {
for sym in elf.syms.iter() {
if let Some(name) = elf.strtab.get_at(sym.st_name) {
if name == "__TAURI_BUNDLE_TYPE" {
for reloc in elf.dynrelas.iter() {
if reloc.r_offset == sym.st_value {
return Some(reloc.r_addend.unwrap());
}
}
}
}
}
None
}

View File

@@ -23,7 +23,7 @@
// files into the `Contents` directory of the bundle.
use super::{
icon::create_icns_file,
icon::{app_icon_name_from_assets_car, create_assets_car_file, create_icns_file},
sign::{notarize, notarize_auth, notarize_without_stapling, sign, SignTarget},
};
use crate::{
@@ -65,26 +65,30 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
log::info!(action = "Bundling"; "{} ({})", app_product_name, app_bundle_path.display());
if app_bundle_path.exists() {
fs::remove_dir_all(&app_bundle_path).fs_context(
"failed to remove old app bundle",
app_bundle_path.to_path_buf(),
)?;
fs::remove_dir_all(&app_bundle_path)
.fs_context("failed to remove old app bundle", &app_bundle_path)?;
}
let bundle_directory = app_bundle_path.join("Contents");
fs::create_dir_all(&bundle_directory).fs_context(
"failed to create bundle directory",
bundle_directory.to_path_buf(),
)?;
fs::create_dir_all(&bundle_directory)
.fs_context("failed to create bundle directory", &bundle_directory)?;
let resources_dir = bundle_directory.join("Resources");
let bin_dir = bundle_directory.join("MacOS");
let mut sign_paths = Vec::new();
let bundle_icon_file: Option<PathBuf> =
{ create_icns_file(&resources_dir, settings).with_context(|| "Failed to create app icon")? };
let bundle_icon_file =
create_icns_file(&resources_dir, settings).with_context(|| "Failed to create app icon")?;
create_info_plist(&bundle_directory, bundle_icon_file, settings)
.with_context(|| "Failed to create Info.plist")?;
let assets_car_file = create_assets_car_file(&resources_dir, settings)
.with_context(|| "Failed to create app Assets.car")?;
create_info_plist(
&bundle_directory,
bundle_icon_file,
assets_car_file,
settings,
)
.with_context(|| "Failed to create Info.plist")?;
let framework_paths = copy_frameworks_to_bundle(&bundle_directory, settings)
.with_context(|| "Failed to bundle frameworks")?;
@@ -140,7 +144,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
if matches!(e, NotarizeAuthError::MissingTeamId) {
return Err(e.into());
} else {
log::warn!("skipping app notarization, {}", e.to_string());
log::warn!("skipping app notarization, {e}");
}
}
}
@@ -208,6 +212,7 @@ fn copy_custom_files_to_bundle(bundle_directory: &Path, settings: &Settings) ->
fn create_info_plist(
bundle_dir: &Path,
bundle_icon_file: Option<PathBuf>,
assets_car_file: Option<PathBuf>,
settings: &Settings,
) -> crate::Result<()> {
let mut plist = plist::Dictionary::new();
@@ -217,17 +222,6 @@ fn create_info_plist(
"CFBundleExecutable".into(),
settings.main_binary_name()?.into(),
);
if let Some(path) = bundle_icon_file {
plist.insert(
"CFBundleIconFile".into(),
path
.file_name()
.expect("No file name")
.to_string_lossy()
.into_owned()
.into(),
);
}
plist.insert(
"CFBundleIdentifier".into(),
settings.bundle_identifier().into(),
@@ -366,6 +360,27 @@ fn create_info_plist(
);
}
if let Some(path) = bundle_icon_file {
plist.insert(
"CFBundleIconFile".into(),
path
.file_name()
.expect("No file name")
.to_string_lossy()
.into_owned()
.into(),
);
}
if let Some(assets_car_file) = assets_car_file {
if let Some(icon_name) = app_icon_name_from_assets_car(&assets_car_file) {
// only set CFBundleIconName for the Assets.car, CFBundleIconFile is the fallback icns file
plist.insert("CFBundleIconName".into(), icon_name.clone().into());
} else {
log::warn!("Failed to get icon name from Assets.car file");
}
}
if let Some(protocols) = settings.deep_link_protocols() {
plist.insert(
"CFBundleURLTypes".into(),
@@ -459,20 +474,12 @@ fn copy_frameworks_to_bundle(
) -> crate::Result<Vec<SignTarget>> {
let mut paths = Vec::new();
let frameworks = settings
.macos()
.frameworks
.as_ref()
.cloned()
.unwrap_or_default();
let frameworks = settings.macos().frameworks.clone().unwrap_or_default();
if frameworks.is_empty() {
return Ok(paths);
}
let dest_dir = bundle_directory.join("Frameworks");
fs::create_dir_all(&dest_dir).fs_context(
"failed to create Frameworks directory",
dest_dir.to_path_buf(),
)?;
fs::create_dir_all(&dest_dir).fs_context("failed to create Frameworks directory", &dest_dir)?;
for framework in frameworks.iter() {
if framework.ends_with(".framework") {
let src_path = PathBuf::from(framework);

View File

@@ -4,13 +4,14 @@
// SPDX-License-Identifier: MIT
use crate::bundle::Settings;
use crate::utils::{self, fs_utils};
use crate::utils::{self, fs_utils, CommandExt};
use std::{
cmp::min,
ffi::OsStr,
fs::{self, File},
io::{self, BufWriter},
path::{Path, PathBuf},
process::Command,
};
use image::GenericImageView;
@@ -63,6 +64,11 @@ pub fn create_icns_file(out_dir: &Path, settings: &Settings) -> crate::Result<Op
let mut images_to_resize: Vec<(image::DynamicImage, u32, u32)> = vec![];
for icon_path in settings.icon_files() {
let icon_path = icon_path?;
if icon_path.extension().map_or(false, |ext| ext == "car") {
continue;
}
let icon = image::open(&icon_path)?;
let density = if utils::is_retina(&icon_path) { 2 } else { 1 };
let (w, h) = icon.dimensions();
@@ -113,3 +119,206 @@ fn make_icns_image(img: image::DynamicImage) -> io::Result<icns::Image> {
};
icns::Image::from_data(pixel_format, img.width(), img.height(), img.into_bytes())
}
/// Creates an Assets.car file from a .icon file if there are any in the settings.
/// Uses an existing Assets.car file if it exists in the settings.
/// Returns the path to the Assets.car file.
pub fn create_assets_car_file(
out_dir: &Path,
settings: &Settings,
) -> crate::Result<Option<PathBuf>> {
let Some(icons) = settings.icons() else {
return Ok(None);
};
// If one of the icon files is already a CAR file, just use that.
let mut icon_composer_icon_path = None;
for icon in icons {
let icon_path = Path::new(&icon).to_path_buf();
if icon_path.extension() == Some(OsStr::new("car")) {
let dest_path = out_dir.join("Assets.car");
fs_utils::copy_file(&icon_path, &dest_path)?;
return Ok(Some(dest_path));
}
if icon_path.extension() == Some(OsStr::new("icon")) {
icon_composer_icon_path.replace(icon_path);
}
}
let Some(icon_composer_icon_path) = icon_composer_icon_path else {
return Ok(None);
};
// Check actool version - must be >= 26
if let Some(version) = get_actool_version() {
// Parse the major version number (before the dot)
let major_version: Option<u32> = version.split('.').next().and_then(|s| s.parse().ok());
if let Some(major) = major_version {
if major < 26 {
log::error!("actool version is less than 26, skipping Assets.car file creation. Please update Xcode to 26 or above and try again.");
return Ok(None);
}
} else {
// If we can't parse the version, return None to be safe
log::error!("failed to parse actool version, skipping Assets.car file creation");
return Ok(None);
}
} else {
log::error!("failed to get actool version, skipping Assets.car file creation");
// If we can't get the version, return None to be safe
return Ok(None);
}
// Create a temporary directory for actool work
let temp_dir = tempfile::tempdir()
.map_err(|e| crate::Error::GenericError(format!("failed to create temp dir: {e}")))?;
let icon_dest_path = temp_dir.path().join("Icon.icon");
let output_path = temp_dir.path().join("out");
// Copy the input .icon directory to the temp directory
if icon_composer_icon_path.is_dir() {
fs_utils::copy_dir(&icon_composer_icon_path, &icon_dest_path)?;
} else {
return Err(crate::Error::GenericError(format!(
"{} must be a directory",
icon_composer_icon_path.display()
)));
}
// Create the output directory
fs::create_dir_all(&output_path)?;
// Run actool command
let mut cmd = Command::new("actool");
cmd.arg(&icon_dest_path);
cmd.arg("--compile");
cmd.arg(&output_path);
cmd.arg("--output-format");
cmd.arg("human-readable-text");
cmd.arg("--notices");
cmd.arg("--warnings");
cmd.arg("--output-partial-info-plist");
cmd.arg(output_path.join("assetcatalog_generated_info.plist"));
cmd.arg("--app-icon");
cmd.arg("Icon");
cmd.arg("--include-all-app-icons");
cmd.arg("--accent-color");
cmd.arg("AccentColor");
cmd.arg("--enable-on-demand-resources");
cmd.arg("NO");
cmd.arg("--development-region");
cmd.arg("en");
cmd.arg("--target-device");
cmd.arg("mac");
cmd.arg("--minimum-deployment-target");
cmd.arg("26.0");
cmd.arg("--platform");
cmd.arg("macosx");
cmd.output_ok()?;
let assets_car_path = output_path.join("Assets.car");
if !assets_car_path.exists() {
return Err(crate::Error::GenericError(
"actool did not generate Assets.car file".to_owned(),
));
}
// copy to out_dir
fs_utils::copy_file(&assets_car_path, &out_dir.join("Assets.car"))?;
Ok(Some(out_dir.join("Assets.car")))
}
#[derive(serde::Deserialize)]
struct AssetsCarInfo {
#[serde(rename = "AssetType", default)]
asset_type: String,
#[serde(rename = "Name", default)]
name: String,
}
pub fn app_icon_name_from_assets_car(assets_car_path: &Path) -> Option<String> {
let Ok(output) = Command::new("assetutil")
.arg("--info")
.arg(assets_car_path)
.output_ok()
.inspect_err(|e| log::error!("Failed to get app icon name from Assets.car file: {e}"))
else {
return None;
};
let output = String::from_utf8(output.stdout).ok()?;
let assets_car_info: Vec<AssetsCarInfo> = serde_json::from_str(&output)
.inspect_err(|e| log::error!("Failed to parse Assets.car file info: {e}"))
.ok()?;
assets_car_info
.iter()
.find(|info| info.asset_type == "Icon Image")
.map(|info| info.name.clone())
}
/// Returns the actool short bundle version by running `actool --version --output-format=human-readable-text`.
/// Returns `None` if the command fails or the output cannot be parsed.
pub fn get_actool_version() -> Option<String> {
let Ok(output) = Command::new("actool")
.arg("--version")
.arg("--output-format=human-readable-text")
.output_ok()
.inspect_err(|e| log::error!("Failed to get actool version: {e}"))
else {
return None;
};
let output = String::from_utf8(output.stdout).ok()?;
parse_actool_version(&output)
}
fn parse_actool_version(output: &str) -> Option<String> {
// The output format is:
// /* com.apple.actool.version */
// bundle-version: 24411
// short-bundle-version: 26.1
for line in output.lines() {
let line = line.trim();
if let Some(version) = line.strip_prefix("short-bundle-version:") {
return Some(version.trim().to_string());
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_actool_version() {
let output = r#"/* com.apple.actool.version */
some other line
bundle-version: 24411
short-bundle-version: 26.1
another line
"#;
let version = parse_actool_version(output).expect("Failed to parse version");
assert_eq!(version, "26.1");
}
#[test]
fn test_parse_actool_version_missing_fields() {
let output = r#"/* com.apple.actool.version */
bundle-version: 24411
"#;
assert!(parse_actool_version(output).is_none());
}
#[test]
fn test_parse_actool_version_empty() {
assert!(parse_actool_version("").is_none());
}
}

View File

@@ -44,15 +44,11 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
log::info!(action = "Bundling"; "{} ({})", app_product_name, app_bundle_path.display());
if app_bundle_path.exists() {
fs::remove_dir_all(&app_bundle_path).fs_context(
"failed to remove old app bundle",
app_bundle_path.to_path_buf(),
)?;
fs::remove_dir_all(&app_bundle_path)
.fs_context("failed to remove old app bundle", &app_bundle_path)?;
}
fs::create_dir_all(&app_bundle_path).fs_context(
"failed to create bundle directory",
app_bundle_path.to_path_buf(),
)?;
fs::create_dir_all(&app_bundle_path)
.fs_context("failed to create bundle directory", &app_bundle_path)?;
for src in settings.resource_files() {
let src = src?;
@@ -110,7 +106,10 @@ fn generate_icon_files(bundle_dir: &Path, settings: &Settings) -> crate::Result<
// Fall back to non-PNG files for any missing sizes.
for icon_path in settings.icon_files() {
let icon_path = icon_path?;
if icon_path.extension() == Some(OsStr::new("png")) {
if icon_path
.extension()
.map_or(false, |ext| ext == "png" || ext == "car")
{
continue;
} else if icon_path.extension() == Some(OsStr::new("icns")) {
let icon_family = icns::IconFamily::read(File::open(&icon_path)?)?;

View File

@@ -21,7 +21,7 @@ pub fn keychain(identity: Option<&str>) -> crate::Result<Option<tauri_macos_sign
var_os("APPLE_CERTIFICATE"),
var_os("APPLE_CERTIFICATE_PASSWORD"),
) {
// import user certificate - useful for for CI build
// import user certificate - useful for CI build
let keychain =
tauri_macos_sign::Keychain::with_certificate(&certificate_encoded, &certificate_password)
.map_err(Box::new)?;

View File

@@ -126,7 +126,7 @@ const ALL_PACKAGE_TYPES: &[PackageType] = &[
PackageType::IosBundle,
#[cfg(target_os = "windows")]
PackageType::WindowsMsi,
#[cfg(target_os = "windows")]
// NSIS installers can be built on all platforms but it's hidden in the --help output on macOS/Linux.
PackageType::Nsis,
#[cfg(target_os = "macos")]
PackageType::MacOsBundle,
@@ -231,7 +231,7 @@ pub struct AppImageSettings {
pub struct RpmSettings {
/// The list of RPM dependencies your application relies on.
pub depends: Option<Vec<String>>,
/// the list of of RPM dependencies your application recommends.
/// the list of RPM dependencies your application recommends.
pub recommends: Option<Vec<String>>,
/// The list of RPM dependencies your application provides.
pub provides: Option<Vec<String>>,
@@ -470,6 +470,13 @@ pub struct NsisSettings {
pub sidebar_image: Option<PathBuf>,
/// The path to an icon file used as the installer icon.
pub installer_icon: Option<PathBuf>,
/// The path to an icon file used as the uninstaller icon.
pub uninstaller_icon: Option<PathBuf>,
/// The path to a bitmap file to display on the header of uninstallers pages.
/// Defaults to [`Self::header_image`]. If this is set but [`Self::header_image`] is not, a default image from NSIS will be applied to `header_image`
///
/// The recommended dimensions are 150px x 57px.
pub uninstaller_header_image: Option<PathBuf>,
/// Whether the installation will be for all users or just the current user.
pub install_mode: NSISInstallerMode,
/// A list of installer languages.
@@ -532,6 +539,10 @@ pub struct NsisSettings {
/// Try to ensure that the WebView2 version is equal to or newer than this version,
/// if the user's WebView2 is older than this version,
/// the installer will try to trigger a WebView2 update.
#[deprecated(
since = "2.8.0",
note = "Use `WindowsSettings::minimum_webview2_version` instead."
)]
pub minimum_webview2_version: Option<String>,
}
@@ -587,6 +598,10 @@ pub struct WindowsSettings {
/// if you are on another platform and want to cross-compile and sign you will
/// need to use another tool like `osslsigncode`.
pub sign_command: Option<CustomSignCommandSettings>,
/// Try to ensure that the WebView2 version is equal to or newer than this version,
/// if the user's WebView2 is older than this version,
/// the installer will try to trigger a WebView2 update.
pub minimum_webview2_version: Option<String>,
}
impl WindowsSettings {
@@ -612,6 +627,7 @@ mod _default {
webview_install_mode: Default::default(),
allow_downgrades: true,
sign_command: None,
minimum_webview2_version: None,
}
}
}
@@ -795,6 +811,8 @@ pub struct Settings {
local_tools_directory: Option<PathBuf>,
/// the bundle settings.
bundle_settings: BundleSettings,
/// Same as `bundle_settings.icon`, but without the .icon directory.
icon_files: Option<Vec<String>>,
/// the binaries to bundle.
binaries: Vec<BundleBinary>,
/// The target platform.
@@ -906,6 +924,14 @@ impl SettingsBuilder {
};
let target_platform = TargetPlatform::from_triple(&target);
let icon_files = self.bundle_settings.icon.as_ref().map(|paths| {
paths
.iter()
.filter(|p| !p.ends_with(".icon"))
.cloned()
.collect()
});
Ok(Settings {
log_level: self.log_level.unwrap_or(log::Level::Error),
package: self
@@ -925,6 +951,7 @@ impl SettingsBuilder {
.map(|bins| external_binaries(bins, &target, &target_platform)),
..self.bundle_settings
},
icon_files,
target_platform,
target,
no_sign: self.no_sign,
@@ -958,6 +985,11 @@ impl Settings {
&self.target_platform
}
/// Raw list of icons.
pub fn icons(&self) -> Option<&Vec<String>> {
self.bundle_settings.icon.as_ref()
}
/// Returns the architecture for the binary being bundled (e.g. "arm", "x86" or "x86_64").
pub fn binary_arch(&self) -> Arch {
if self.target.starts_with("x86_64") {
@@ -1092,7 +1124,7 @@ impl Settings {
/// Returns an iterator over the icon files to be used for this bundle.
pub fn icon_files(&self) -> ResourcePaths<'_> {
match self.bundle_settings.icon {
match self.icon_files {
Some(ref paths) => ResourcePaths::new(paths.as_slice(), false),
None => ResourcePaths::new(&[], false),
}

View File

@@ -14,5 +14,3 @@ pub use util::{
NSIS_OUTPUT_FOLDER_NAME, NSIS_UPDATER_OUTPUT_FOLDER_NAME, WIX_OUTPUT_FOLDER_NAME,
WIX_UPDATER_OUTPUT_FOLDER_NAME,
};
pub use util::patch_binary;

View File

@@ -70,12 +70,16 @@
<Property Id="ARPURLUPDATEINFO" Value="{{homepage}}"/>
{{/if}}
<!-- NOTE: The order of RegistrySearch elements below matters. In WIX, when multiple
RegistrySearch elements are listed under a single Property, the LAST successful
match wins. We list the NSIS default-key search first and the MSI InstallDir
search second so that the MSI-specific path takes priority when both keys exist. -->
<Property Id="INSTALLDIR">
<!-- First attempt: Search for "InstallDir" -->
<RegistrySearch Id="PrevInstallDirWithName" Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="InstallDir" Type="raw" />
<!-- Second attempt: If the first fails, search for the default key value (this is how the nsis installer currently stores the path) -->
<!-- First attempt: Search for the default key value (this is how the nsis installer stores the path) -->
<RegistrySearch Id="PrevInstallDirNoName" Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Type="raw" />
<!-- Second attempt: Search for "InstallDir" which takes priority if found (this is how the msi installer stores the path) -->
<RegistrySearch Id="PrevInstallDirWithName" Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="InstallDir" Type="raw" />
</Property>
<!-- launch app checkbox -->
@@ -279,38 +283,62 @@
{{#if install_webview}}
<!-- WebView2 -->
<Property Id="WVRTINSTALLED">
<RegistrySearch Id="WVRTInstalledSystem" Root="HKLM" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw" Win64="no" />
<RegistrySearch Id="WVRTInstalledUser" Root="HKCU" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw"/>
<Property Id="INSTALLED_WEBVIEW2_VERSION">
<RegistrySearch Id="Webview2VersionSystemx64" Root="HKLM" Key="SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw" />
<RegistrySearch Id="Webview2VersionSystemx86" Root="HKLM" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw" />
<RegistrySearch Id="Webview2VersionUser" Root="HKCU" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw"/>
</Property>
{{#if download_bootstrapper}}
<!-- Download webview bootstrapper mode -->
<CustomAction Id='DownloadAndInvokeBootstrapper' Directory="INSTALLDIR" Execute="deferred" ExeCommand='powershell.exe -NoProfile -windowstyle hidden try [\{] [\[]Net.ServicePointManager[\]]::SecurityProtocol = [\[]Net.SecurityProtocolType[\]]::Tls12 [\}] catch [\{][\}]; Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -OutFile "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" ; Start-Process -FilePath "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" -ArgumentList ({{webview_installer_args}} &apos;/install&apos;) -Wait' Return='check'/>
<InstallExecuteSequence>
<Custom Action='DownloadAndInvokeBootstrapper' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
<![CDATA[NOT(REMOVE OR INSTALLED_WEBVIEW2_VERSION)]]>
</Custom>
</InstallExecuteSequence>
{{/if}}
<!-- Embedded webview bootstrapper mode -->
{{#if webview2_bootstrapper_path}}
<!-- Embedded webview bootstrapper mode -->
<Binary Id="MicrosoftEdgeWebview2Setup.exe" SourceFile="{{webview2_bootstrapper_path}}"/>
<CustomAction Id='InvokeBootstrapper' BinaryKey='MicrosoftEdgeWebview2Setup.exe' Execute="deferred" ExeCommand='{{webview_installer_args}} /install' Return='check' />
<InstallExecuteSequence>
<Custom Action='InvokeBootstrapper' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
<![CDATA[NOT(REMOVE OR INSTALLED_WEBVIEW2_VERSION)]]>
</Custom>
</InstallExecuteSequence>
{{/if}}
<!-- Embedded offline installer -->
{{#if webview2_installer_path}}
<!-- Embedded offline installer -->
<Binary Id="MicrosoftEdgeWebView2RuntimeInstaller.exe" SourceFile="{{webview2_installer_path}}"/>
<CustomAction Id='InvokeStandalone' BinaryKey='MicrosoftEdgeWebView2RuntimeInstaller.exe' Execute="deferred" ExeCommand='{{webview_installer_args}} /install' Return='check' />
<InstallExecuteSequence>
<Custom Action='InvokeStandalone' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
<![CDATA[NOT(REMOVE OR INSTALLED_WEBVIEW2_VERSION)]]>
</Custom>
</InstallExecuteSequence>
{{/if}}
{{#if minimum_webview2_version}}
<!-- Update WebView2 if minimum version requirement not met -->
<Property Id="MINIMUM_WEBVIEW2_VERSION" Value="{{minimum_webview2_version}}" />
<Property Id="EDGEUPDATE_PATH">
<RegistrySearch Id="EdgeUpdateLocalMachine64" Root="HKLM" Key="SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate" Name="path" Type="raw" />
<RegistrySearch Id="EdgeUpdateLocalMachine32" Root="HKLM" Key="SOFTWARE\Microsoft\EdgeUpdate" Name="path" Type="raw"/>
<RegistrySearch Id="EdgeUpdateCurrentUser" Root="HKCU" Key="SOFTWARE\Microsoft\EdgeUpdate" Name="path" Type="raw"/>
</Property>
<!-- Chromium updater docs: https://source.chromium.org/chromium/chromium/src/+/main:docs/updater/user_manual.md -->
<!-- Modified from "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft EdgeWebView\ModifyPath" -->
<CustomAction Id="UpdateWebView2ViaEdgeUpdate" Execute="deferred" Property="EDGEUPDATE_PATH" Return="check" Impersonate="no" ExeCommand="/install appguid={F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}&amp;needsadmin=true" />
<InstallExecuteSequence>
<Custom Action='UpdateWebView2ViaEdgeUpdate' Before='InstallFinalize'>
<![CDATA[
NOT REMOVE
AND INSTALLED_WEBVIEW2_VERSION
AND (INSTALLED_WEBVIEW2_VERSION < MINIMUM_WEBVIEW2_VERSION)
]]>
</Custom>
</InstallExecuteSequence>
{{/if}}

View File

@@ -532,6 +532,13 @@ pub fn build_wix_app_installer(
}
}
if let Some(minimum_webview2_version) = &settings.windows().minimum_webview2_version {
data.insert(
"minimum_webview2_version",
to_json(minimum_webview2_version),
);
}
if let Some(license) = settings.license_file() {
if license.ends_with(".rtf") {
data.insert("license", to_json(license));
@@ -753,26 +760,28 @@ pub fn build_wix_app_installer(
}
let main_wxs_path = output_path.join("main.wxs");
fs::write(main_wxs_path, handlebars.render("main.wxs", &data)?)?;
fs::write(&main_wxs_path, handlebars.render("main.wxs", &data)?)?;
let mut candle_inputs = vec![("main.wxs".into(), Vec::new())];
let mut candle_inputs = vec![];
let current_dir = std::env::current_dir()?;
let extension_regex = Regex::new("\"http://schemas.microsoft.com/wix/(\\w+)\"")?;
for fragment_path in fragment_paths {
let fragment_path = current_dir.join(fragment_path);
let fragment_content = fs::read_to_string(&fragment_path)?;
let fragment_handlebars = Handlebars::new();
let fragment = fragment_handlebars.render_template(&fragment_content, &data)?;
let input_paths =
std::iter::once(main_wxs_path).chain(fragment_paths.iter().map(|p| current_dir.join(p)));
for input_path in input_paths {
let input_content = fs::read_to_string(&input_path)?;
let input_handlebars = Handlebars::new();
let input = input_handlebars.render_template(&input_content, &data)?;
let mut extensions = Vec::new();
for cap in extension_regex.captures_iter(&fragment) {
for cap in extension_regex.captures_iter(&input) {
let path = wix_toolset_path.join(format!("Wix{}.dll", &cap[1]));
if settings.windows().can_sign() {
try_sign(&path, settings)?;
}
extensions.push(path);
}
candle_inputs.push((fragment_path, extensions));
candle_inputs.push((input_path, extensions));
}
let mut fragment_extensions = HashSet::new();

View File

@@ -41,6 +41,8 @@ ${StrLoc}
!define INSTALLERICON "{{installer_icon}}"
!define SIDEBARIMAGE "{{sidebar_image}}"
!define HEADERIMAGE "{{header_image}}"
!define UNINSTALLERICON "{{uninstaller_icon}}"
!define UNINSTALLERHEADERIMAGE "{{uninstaller_header_image}}"
!define MAINBINARYNAME "{{main_binary_name}}"
!define MAINBINARYSRCPATH "{{main_binary_path}}"
!define BUNDLEID "{{bundle_id}}"
@@ -129,10 +131,26 @@ VIAddVersionKey "ProductVersion" "${VERSION}"
!define MUI_WELCOMEFINISHPAGE_BITMAP "${SIDEBARIMAGE}"
!endif
; Installer header image
; Enable header images for installer and uninstaller pages when either image is configured.
!if "${HEADERIMAGE}" != ""
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "${HEADERIMAGE}"
!else if "${UNINSTALLERHEADERIMAGE}" != ""
!define MUI_HEADERIMAGE
!endif
; Installer header image
!if "${HEADERIMAGE}" != ""
!define MUI_HEADERIMAGE_BITMAP "${HEADERIMAGE}"
!endif
; Uninstaller header image
!if "${UNINSTALLERHEADERIMAGE}" != ""
!define MUI_HEADERIMAGE_UNBITMAP "${UNINSTALLERHEADERIMAGE}"
!endif
; Uninstaller icon
!if "${UNINSTALLERICON}" != ""
!define MUI_UNICON "${UNINSTALLERICON}"
!endif
; Define registry key to store installer language

View File

@@ -0,0 +1,27 @@
LangString addOrReinstall ${LANG_NORWEGIAN} "Legg til/reinstaller komponenter"
LangString alreadyInstalled ${LANG_NORWEGIAN} "Allerede installert"
LangString alreadyInstalledLong ${LANG_NORWEGIAN} "${PRODUCTNAME} ${VERSION} er allerede installert. Velg operasjonen du vil utføre og klikk Neste for å fortsette."
LangString appRunning ${LANG_NORWEGIAN} "{{product_name}} kjører! Lukk den først og prøv igjen."
LangString appRunningOkKill ${LANG_NORWEGIAN} "{{product_name}} kjører!$\nKlikk OK for å avslutte den"
LangString chooseMaintenanceOption ${LANG_NORWEGIAN} "Velg vedlikeholdsoperasjonen som skal utføres."
LangString choowHowToInstall ${LANG_NORWEGIAN} "Velg hvordan du vil installere ${PRODUCTNAME}."
LangString createDesktop ${LANG_NORWEGIAN} "Opprett skrivebordssnarvei"
LangString dontUninstall ${LANG_NORWEGIAN} "Ikke avinstaller"
LangString dontUninstallDowngrade ${LANG_NORWEGIAN} "Ikke avinstaller (nedgradering uten avinstallasjon er deaktivert for denne installasjonen)"
LangString failedToKillApp ${LANG_NORWEGIAN} "Kunne ikke avslutte {{product_name}}. Lukk den først og prøv igjen"
LangString installingWebview2 ${LANG_NORWEGIAN} "Installerer WebView2..."
LangString newerVersionInstalled ${LANG_NORWEGIAN} "En nyere versjon av ${PRODUCTNAME} er allerede installert! Det anbefales ikke at du installerer en eldre versjon. Hvis du virkelig vil installere denne eldre versjonen, er det bedre å avinstallere den nåværende versjonen først. Velg operasjonen du vil utføre og klikk Neste for å fortsette."
LangString older ${LANG_NORWEGIAN} "eldre"
LangString olderOrUnknownVersionInstalled ${LANG_NORWEGIAN} "En $R4-versjon av ${PRODUCTNAME} er installert på systemet ditt. Det anbefales at du avinstallerer den nåværende versjonen før installasjon. Velg operasjonen du vil utføre og klikk Neste for å fortsette."
LangString silentDowngrades ${LANG_NORWEGIAN} "Nedgraderinger er deaktivert for denne installasjonen. Kan ikke fortsette med stille installasjon; bruk den grafiske installasjonen i stedet.$\n"
LangString unableToUninstall ${LANG_NORWEGIAN} "Kunne ikke avinstallere!"
LangString uninstallApp ${LANG_NORWEGIAN} "Avinstaller ${PRODUCTNAME}"
LangString uninstallBeforeInstalling ${LANG_NORWEGIAN} "Avinstaller før installasjon"
LangString unknown ${LANG_NORWEGIAN} "ukjent"
LangString webview2AbortError ${LANG_NORWEGIAN} "Kunne ikke installere WebView2! Appen kan ikke kjøre uten den. Prøv å starte installasjonen på nytt."
LangString webview2DownloadError ${LANG_NORWEGIAN} "Feil: Nedlasting av WebView2 mislyktes - $0"
LangString webview2DownloadSuccess ${LANG_NORWEGIAN} "WebView2-bootstrapper lastet ned"
LangString webview2Downloading ${LANG_NORWEGIAN} "Laster ned WebView2-bootstrapper..."
LangString webview2InstallError ${LANG_NORWEGIAN} "Feil: Installering av WebView2 mislyktes med avslutningskode $1"
LangString webview2InstallSuccess ${LANG_NORWEGIAN} "WebView2 ble installert"
LangString deleteAppData ${LANG_NORWEGIAN} "Slett programdata"

View File

@@ -36,12 +36,12 @@ use std::{
// URLS for the NSIS toolchain.
#[cfg(target_os = "windows")]
const NSIS_URL: &str =
"https://github.com/tauri-apps/binary-releases/releases/download/nsis-3/nsis-3.zip";
"https://github.com/tauri-apps/binary-releases/releases/download/nsis-3.11/nsis-3.11.zip";
#[cfg(target_os = "windows")]
const NSIS_SHA1: &str = "057e83c7d82462ec394af76c87d06733605543d4";
const NSIS_SHA1: &str = "EF7FF767E5CBD9EDD22ADD3A32C9B8F4500BB10D";
const NSIS_TAURI_UTILS_URL: &str =
"https://github.com/tauri-apps/nsis-tauri-utils/releases/download/nsis_tauri_utils-v0.5.1/nsis_tauri_utils.dll";
const NSIS_TAURI_UTILS_SHA1: &str = "B053B2E5FDB97257954C8F935D80964F056520AE";
"https://github.com/tauri-apps/nsis-tauri-utils/releases/download/nsis_tauri_utils-v0.5.3/nsis_tauri_utils.dll";
const NSIS_TAURI_UTILS_SHA1: &str = "75197FEE3C6A814FE035788D1C34EAD39349B860";
#[cfg(target_os = "windows")]
const NSIS_REQUIRED_FILES: &[&str] = &[
@@ -55,6 +55,9 @@ const NSIS_REQUIRED_FILES: &[&str] = &[
"Include/x64.nsh",
"Include/nsDialogs.nsh",
"Include/WinMessages.nsh",
"Include/Win/COM.nsh",
"Include/Win/Propkey.nsh",
"Include/Win/RestartManager.nsh",
];
const NSIS_PLUGIN_FILES: &[&str] = &[
"NSISdl.dll",
@@ -125,7 +128,7 @@ fn get_and_extract_nsis(nsis_toolset_path: &Path, _tauri_tools_path: &Path) -> c
let data = download_and_verify(NSIS_URL, NSIS_SHA1, HashAlgorithm::Sha1)?;
log::info!("extracting NSIS");
crate::utils::http_utils::extract_zip(&data, _tauri_tools_path)?;
fs::rename(_tauri_tools_path.join("nsis-3.08"), nsis_toolset_path)?;
fs::rename(_tauri_tools_path.join("nsis-3.11"), nsis_toolset_path)?;
}
// download additional plugins
@@ -295,8 +298,12 @@ fn build_nsis_app_installer(
data.insert("copyright", to_json(settings.copyright_string()));
if settings.windows().can_sign() {
let sign_cmd = format!("{:?}", sign_command("%1", &settings.sign_params())?);
data.insert("uninstaller_sign_cmd", to_json(sign_cmd));
if settings.no_sign() {
log::warn!("Skipping signing for NSIS uninstaller due to --no-sign flag.");
} else {
let sign_cmd = format!("{:?}", sign_command("%1", &settings.sign_params())?);
data.insert("uninstaller_sign_cmd", to_json(sign_cmd));
}
}
let version = settings.version_string();
@@ -347,6 +354,20 @@ fn build_nsis_app_installer(
);
}
if let Some(uninstaller_icon) = &nsis.uninstaller_icon {
data.insert(
"uninstaller_icon",
to_json(dunce::canonicalize(uninstaller_icon)?),
);
}
if let Some(uninstaller_header_image) = &nsis.uninstaller_header_image {
data.insert(
"uninstaller_header_image",
to_json(dunce::canonicalize(uninstaller_header_image)?),
);
}
if let Some(installer_hooks) = &nsis.installer_hooks {
let installer_hooks = dunce::canonicalize(installer_hooks)?;
data.insert("installer_hooks", to_json(installer_hooks));
@@ -355,7 +376,12 @@ fn build_nsis_app_installer(
if let Some(start_menu_folder) = &nsis.start_menu_folder {
data.insert("start_menu_folder", to_json(start_menu_folder));
}
if let Some(minimum_webview2_version) = &nsis.minimum_webview2_version {
#[allow(deprecated)]
if let Some(minimum_webview2_version) = nsis
.minimum_webview2_version
.as_ref()
.or(settings.windows().minimum_webview2_version.as_ref())
{
data.insert(
"minimum_webview2_version",
to_json(minimum_webview2_version),
@@ -614,13 +640,16 @@ fn build_nsis_app_installer(
fs::create_dir_all(nsis_installer_path.parent().unwrap())?;
if settings.windows().can_sign() {
log::info!("Signing NSIS plugins");
for dll in NSIS_PLUGIN_FILES {
let path = additional_plugins_path.join(dll);
if path.exists() {
try_sign(&path, settings)?;
} else {
log::warn!("Could not find {}, skipping signing", path.display());
if let Some(plugin_copy_path) = &maybe_plugin_copy_path {
let plugin_copy_path = plugin_copy_path.join("x86-unicode");
log::info!("Signing NSIS plugins");
for dll in NSIS_PLUGIN_FILES {
let path = plugin_copy_path.join(dll);
if path.exists() {
try_sign(&path, settings)?;
} else {
log::warn!("Could not find {}, skipping signing", path.display());
}
}
}
}
@@ -857,6 +886,7 @@ fn get_lang_data(lang: &str) -> Option<(String, &[u8])> {
"swedish" => include_bytes!("./languages/Swedish.nsh"),
"portuguese" => include_bytes!("./languages/Portuguese.nsh"),
"ukrainian" => include_bytes!("./languages/Ukrainian.nsh"),
"norwegian" => include_bytes!("./languages/Norwegian.nsh"),
_ => return None,
};
Some((path, content))

View File

@@ -48,6 +48,7 @@
Pop $R0
Sleep 500
${If} $R0 = 0
${OrIf} $R0 = 2
Goto app_check_done_${UniqueID}
${Else}
IfSilent silent_${UniqueID} ui_${UniqueID}

View File

@@ -266,8 +266,7 @@ pub fn try_sign<P: AsRef<Path>>(file_path: P, settings: &Settings) -> crate::Res
pub fn should_sign(file_path: &Path) -> crate::Result<bool> {
let is_binary = file_path
.extension()
.and_then(|extension| extension.to_str())
.is_some_and(|extension| matches!(extension, "exe" | "dll"));
.is_some_and(|ext| ext == "exe" || ext == "dll");
if !is_binary {
return Ok(false);
}

View File

@@ -77,75 +77,3 @@ pub fn os_bitness<'a>() -> Option<&'a str> {
_ => None,
}
}
pub fn patch_binary(binary_path: &PathBuf, package_type: &crate::PackageType) -> crate::Result<()> {
let mut file_data = std::fs::read(binary_path)?;
let pe = match goblin::Object::parse(&file_data)? {
goblin::Object::PE(pe) => pe,
_ => {
return Err(crate::Error::BinaryParseError(
std::io::Error::new(std::io::ErrorKind::InvalidInput, "binary is not a PE file").into(),
));
}
};
let tauri_bundle_section = pe
.sections
.iter()
.find(|s| s.name().unwrap_or_default() == ".taubndl")
.ok_or(crate::Error::MissingBundleTypeVar)?;
let data_offset = tauri_bundle_section.pointer_to_raw_data as usize;
let pointer_size = if pe.is_64 { 8 } else { 4 };
let ptr_bytes = file_data
.get(data_offset..data_offset + pointer_size)
.ok_or(crate::Error::BinaryOffsetOutOfRange)?;
// `try_into` is safe to `unwrap` here because we have already checked the slice's size through `get`
let ptr_value = if pe.is_64 {
u64::from_le_bytes(ptr_bytes.try_into().unwrap())
} else {
u32::from_le_bytes(ptr_bytes.try_into().unwrap()).into()
};
let rdata_section = pe
.sections
.iter()
.find(|s| s.name().unwrap_or_default() == ".rdata")
.ok_or_else(|| {
crate::Error::BinaryParseError(
std::io::Error::new(std::io::ErrorKind::InvalidInput, ".rdata section not found").into(),
)
})?;
let rva = ptr_value.checked_sub(pe.image_base as u64).ok_or_else(|| {
crate::Error::BinaryParseError(
std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid RVA offset").into(),
)
})?;
// see "Relative virtual address (RVA)" for explanation of offset arithmetic here:
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#general-concepts
let file_offset = rdata_section.pointer_to_raw_data as usize
+ (rva as usize).saturating_sub(rdata_section.virtual_address as usize);
// Overwrite the string at that offset
let string_bytes = file_data
.get_mut(file_offset..file_offset + 3)
.ok_or(crate::Error::BinaryOffsetOutOfRange)?;
match package_type {
crate::PackageType::Nsis => string_bytes.copy_from_slice(b"NSS"),
crate::PackageType::WindowsMsi => string_bytes.copy_from_slice(b"MSI"),
_ => {
return Err(crate::Error::InvalidPackageType(
package_type.short_name().to_owned(),
"windows".to_owned(),
));
}
}
std::fs::write(binary_path, &file_data)
.map_err(|e| crate::Error::BinaryWriteError(e.to_string()))?;
Ok(())
}

Some files were not shown because too many files have changed in this diff Show More