mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
Merge remote-tracking branch 'origin/dev' into feat/truly-portable-appimage
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@tauri-apps/api": minor:feat
|
||||
---
|
||||
|
||||
Adds the `scrollBarStyle` option to the Webview and WebviewBuilder constructors.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"tauri-cli": minor:feat
|
||||
"tauri-utils": minor:feat
|
||||
---
|
||||
|
||||
Adds the `scrollBarStyle` option to the window configuration.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'tauri-cli': 'patch:enhance'
|
||||
---
|
||||
|
||||
Add support for Android's adaptive and themed icons.
|
||||
5
.changes/android-external-files-fix.md
Normal file
5
.changes/android-external-files-fix.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch:bug
|
||||
---
|
||||
|
||||
Fixed 500 error when accessing local video files in Android external storage directory via `convertFileSrc`. Added better error handling and logging for Android external storage access to help diagnose permission and accessibility issues.
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:enhance
|
||||
"@tauri-apps/cli": patch:enhance
|
||||
"tauri-cli": patch:enhance
|
||||
---
|
||||
|
||||
Check mismatched versions in `tauri info`
|
||||
Allow electron to run the CLI directly
|
||||
7
.changes/change-pr-14632.md
Normal file
7
.changes/change-pr-14632.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri-utils": patch:enhance
|
||||
"tauri-build": patch:enhance
|
||||
"tauri-cli": patch:enhance
|
||||
---
|
||||
|
||||
Small code refactors for improved code readability. No user facing changes.
|
||||
5
.changes/change-pr-14766.md
Normal file
5
.changes/change-pr-14766.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-macos-sign": patch:deps
|
||||
---
|
||||
|
||||
Remove once-cell-regex from direct dependencies.
|
||||
5
.changes/change-pr-14812.md
Normal file
5
.changes/change-pr-14812.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch:bug
|
||||
---
|
||||
|
||||
fix(specta): don't use `#[specta(rename = ...)]` with `tauri::ipc::Channel`
|
||||
5
.changes/change-pr-14824.md
Normal file
5
.changes/change-pr-14824.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'tauri-bundler': 'patch:enhance'
|
||||
---
|
||||
|
||||
feat(nsis): add Norwegian language support for installer.
|
||||
@@ -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,
|
||||
|
||||
@@ -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`.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"@tauri-apps/cli": patch:enhance
|
||||
"tauri-cli": patch:enhance
|
||||
---
|
||||
|
||||
Set a default log level filter when running `tauri add log`.
|
||||
6
.changes/empty-vec-instead-of-none.md
Normal file
6
.changes/empty-vec-instead-of-none.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tauri-apps/cli": patch:enhance
|
||||
"tauri-cli": patch:enhance
|
||||
---
|
||||
|
||||
Simplified internal representation of `features: Option<Vec<String>>` with `Vec<String>`, no user facing changes
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
6
.changes/fix-android-bundle-flag.md
Normal file
6
.changes/fix-android-bundle-flag.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
---
|
||||
|
||||
Fix `android build`'s `--aab` and `--apk` flags requiring a value to be provided.
|
||||
8
.changes/fix-binary-patching.md
Normal file
8
.changes/fix-binary-patching.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"tauri": minor:changes
|
||||
"tauri-cli": minor:changes
|
||||
"tauri-bundler": minor:changes
|
||||
"@tauri-apps/cli": minor:changes
|
||||
---
|
||||
|
||||
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.
|
||||
6
.changes/fix-empty-entitlements.md
Normal file
6
.changes/fix-empty-entitlements.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
---
|
||||
|
||||
Fix empty associated-domains entitlements when domains are not configured for deep links.
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
"tauri-cli": patch:bug
|
||||
---
|
||||
|
||||
Fix iOS CLI usage after modifying the package name.
|
||||
Fixed the command description for `tauri inspect`
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"tauri-cli": patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
---
|
||||
|
||||
Replaced the non-standard nerd font character with ` ⱼₛ` in `tarui info`
|
||||
@@ -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`.
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
"@tauri-apps/cli": minor:enhance
|
||||
"tauri-cli": minor:enhance
|
||||
"tauri-bundler": minor:enhance
|
||||
---
|
||||
|
||||
Improve error messages with more context.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"tauri": minor:feat
|
||||
---
|
||||
|
||||
Support async Swift plugin methods (`completionHandler:`) in PluginManager
|
||||
5
.changes/linux-webcontext.md
Normal file
5
.changes/linux-webcontext.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
tauri-runtime-wry: patch:bug
|
||||
---
|
||||
|
||||
On Linux, keep the WebContext alive to prevent zombie WebKit processes after repeatedly closing all windows and re-opening them.
|
||||
@@ -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.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"@tauri-apps/cli": patch:bug
|
||||
"tauri-cli": patch:bug
|
||||
---
|
||||
|
||||
Fixes mobile project initialization when using `pnpx` or `pnpm dlx`.
|
||||
@@ -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.
|
||||
9
.changes/nsis-run-as-user.md
Normal file
9
.changes/nsis-run-as-user.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
"tauri-bundler": patch:bug
|
||||
"tauri-cli": patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
---
|
||||
|
||||
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
|
||||
6
.changes/only-watch-dependencies.md
Normal file
6
.changes/only-watch-dependencies.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tauri-apps/cli": patch:bug
|
||||
"tauri-cli": patch:bug
|
||||
---
|
||||
|
||||
Only watch dependent workspace members when running `tauri dev` instead of watching on all members
|
||||
6
.changes/reduce-internal-statics.md
Normal file
6
.changes/reduce-internal-statics.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tauri-apps/cli": patch:changes
|
||||
"tauri-cli": patch:changes
|
||||
---
|
||||
|
||||
Refactored internal use of static on config and directory resolvings, no user facing changes, please report any regressions if you encounter any
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"tauri-bundler": minor:breaking
|
||||
---
|
||||
|
||||
Changed `MacOsSettings::info_plist_path` to `MacOsSettings::info_plist`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@tauri-apps/api": patch:bug
|
||||
---
|
||||
|
||||
Fix `core > addPluginListener` failing on command permission check.
|
||||
6
.changes/runtime-bsd.md
Normal file
6
.changes/runtime-bsd.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
tauri-runtime: patch:bug
|
||||
tauri-runtime-wry: patch:bug
|
||||
---
|
||||
|
||||
Fix compilation errors when targeting BSD.
|
||||
14
.changes/signing-env-vars.md
Normal file
14
.changes/signing-env-vars.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
"tauri-cli": patch:enhance
|
||||
"@tauri-apps/cli": patch:enhance
|
||||
---
|
||||
|
||||
Added new environment variables for `tauri signer sign` command, to align with existing environment variables used in `tauri build`, `tauri bundle` and `tauri signer generate`
|
||||
- `TAURI_SIGNING_PRIVATE_KEY`
|
||||
- `TAURI_SIGNING_PRIVATE_KEY_PATH`
|
||||
- `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`
|
||||
|
||||
The old environment variables are deprecated and will be removed in a future release.
|
||||
- `TAURI_PRIVATE_KEY`
|
||||
- `TAURI_PRIVATE_KEY_PATH`
|
||||
- `TAURI_PRIVATE_KEY_PASSWORD`
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"tauri-bundler": minor:feat
|
||||
---
|
||||
|
||||
Support providing `plist::Value` as macOS entitlements.
|
||||
@@ -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.
|
||||
6
.changes/updater-signer-files-without-extension.md
Normal file
6
.changes/updater-signer-files-without-extension.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
tauri-cli: patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
---
|
||||
|
||||
`tauri signer sign` doesn't work for files without an extension
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
"tauri-cli": patch:enhance
|
||||
"@tauri-apps/cli": patch:enhance
|
||||
---
|
||||
|
||||
Warn if productName is empty when initializing mobile project.
|
||||
|
||||
7
.changes/webkitgtk202.md
Normal file
7
.changes/webkitgtk202.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
tauri-runtime-wry: minor:deps
|
||||
tauri-runtime: minor:deps
|
||||
tauri: minor:deps
|
||||
---
|
||||
|
||||
**Breaking Change** for `with_webview` users: Updated webkit2gtk-rs crates to `v2.0.2`.
|
||||
7
.changes/webview-set-simple-fullscreen.md
Normal file
7
.changes/webview-set-simple-fullscreen.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'tauri': 'minor:feat'
|
||||
---
|
||||
|
||||
Add `set_simple_fullscreen` method to `WebviewWindow`.
|
||||
|
||||
This method was already available on the `Window` type and is now also available on `WebviewWindow` for consistency. On macOS, it toggles fullscreen mode without creating a new macOS Space. On other platforms, it falls back to regular fullscreen.
|
||||
5
.changes/window-config-focus-default-true.md
Normal file
5
.changes/window-config-focus-default-true.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
tauri: patch:bug
|
||||
---
|
||||
|
||||
`WindowConfig::focus` is set to `false` in `WindowConfig::default()`
|
||||
6
.changes/wry-054.md
Normal file
6
.changes/wry-054.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
tauri-runtime-wry: patch:deps
|
||||
tauri: patch:deps
|
||||
---
|
||||
|
||||
Update wry to `v0.54`.
|
||||
4
.github/CONTRIBUTING.md
vendored
4
.github/CONTRIBUTING.md
vendored
@@ -33,11 +33,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 +96,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
|
||||
|
||||
@@ -78,7 +78,6 @@ jobs:
|
||||
with:
|
||||
node-version: 20
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: cargo login
|
||||
run: cargo login ${{ secrets.ORG_CRATES_IO_TOKEN }}
|
||||
|
||||
29
.github/workflows/publish-cli-rs.yml
vendored
29
.github/workflows/publish-cli-rs.yml
vendored
@@ -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
|
||||
|
||||
@@ -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} `
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
|
||||
16
.taurignore
16
.taurignore
@@ -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
|
||||
689
Cargo.lock
generated
689
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,35 @@
|
||||
# Changelog
|
||||
|
||||
## \[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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-build"
|
||||
version = "2.4.1"
|
||||
version = "2.5.3"
|
||||
description = "build time code to pair with https://crates.io/crates/tauri"
|
||||
exclude = ["CHANGELOG.md", "/target"]
|
||||
readme = "README.md"
|
||||
@@ -22,14 +22,12 @@ 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 = [
|
||||
tauri-codegen = { version = "2.5.2", path = "../tauri-codegen", optional = true }
|
||||
tauri-utils = { version = "2.8.1", path = "../tauri-utils", features = [
|
||||
"build",
|
||||
"resources",
|
||||
] }
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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 {
|
||||
@@ -499,7 +495,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
|
||||
println!("cargo:rustc-env=TAURI_ANDROID_PACKAGE_NAME_PREFIX={android_package_prefix}");
|
||||
|
||||
if let Some(project_dir) = env::var_os("TAURI_ANDROID_PROJECT_PATH").map(PathBuf::from) {
|
||||
mobile::generate_gradle_files(project_dir, &config)?;
|
||||
mobile::generate_gradle_files(project_dir)?;
|
||||
}
|
||||
|
||||
cfg_alias("dev", is_dev());
|
||||
|
||||
@@ -2,18 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::{fs::write, path::PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use semver::Version;
|
||||
use tauri_utils::{config::Config, write_if_changed};
|
||||
use tauri_utils::write_if_changed;
|
||||
|
||||
use crate::is_dev;
|
||||
|
||||
pub fn generate_gradle_files(project_dir: PathBuf, config: &Config) -> Result<()> {
|
||||
pub fn generate_gradle_files(project_dir: PathBuf) -> Result<()> {
|
||||
let gradle_settings_path = project_dir.join("tauri.settings.gradle");
|
||||
let app_build_gradle_path = project_dir.join("app").join("tauri.build.gradle.kts");
|
||||
let app_tauri_properties_path = project_dir.join("app").join("tauri.properties");
|
||||
|
||||
let mut gradle_settings =
|
||||
"// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n".to_string();
|
||||
@@ -21,7 +17,6 @@ pub fn generate_gradle_files(project_dir: PathBuf, config: &Config) -> Result<()
|
||||
val implementation by configurations
|
||||
dependencies {"
|
||||
.to_string();
|
||||
let mut app_tauri_properties = Vec::new();
|
||||
|
||||
for (env, value) in std::env::vars_os() {
|
||||
let env = env.to_string_lossy();
|
||||
@@ -54,32 +49,6 @@ dependencies {"
|
||||
|
||||
app_build_gradle.push_str("\n}");
|
||||
|
||||
if let Some(version) = config.version.as_ref() {
|
||||
app_tauri_properties.push(format!("tauri.android.versionName={version}"));
|
||||
if let Some(version_code) = config.bundle.android.version_code.as_ref() {
|
||||
app_tauri_properties.push(format!("tauri.android.versionCode={version_code}"));
|
||||
} else if let Ok(version) = Version::parse(version) {
|
||||
let mut version_code = version.major * 1000000 + version.minor * 1000 + version.patch;
|
||||
|
||||
if is_dev() {
|
||||
version_code = version_code.clamp(1, 2100000000);
|
||||
}
|
||||
|
||||
if version_code == 0 {
|
||||
return Err(anyhow::anyhow!(
|
||||
"You must change the `version` in `tauri.conf.json`. The default value `0.0.0` is not allowed for Android package and must be at least `0.0.1`."
|
||||
));
|
||||
} else if version_code > 2100000000 {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Invalid version code {}. Version code must be between 1 and 2100000000. You must change the `version` in `tauri.conf.json`.",
|
||||
version_code
|
||||
));
|
||||
}
|
||||
|
||||
app_tauri_properties.push(format!("tauri.android.versionCode={version_code}"));
|
||||
}
|
||||
}
|
||||
|
||||
// Overwrite only if changed to not trigger rebuilds
|
||||
write_if_changed(&gradle_settings_path, gradle_settings)
|
||||
.context("failed to write tauri.settings.gradle")?;
|
||||
@@ -87,28 +56,8 @@ dependencies {"
|
||||
write_if_changed(&app_build_gradle_path, app_build_gradle)
|
||||
.context("failed to write tauri.build.gradle.kts")?;
|
||||
|
||||
if !app_tauri_properties.is_empty() {
|
||||
let app_tauri_properties_content = format!(
|
||||
"// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n{}",
|
||||
app_tauri_properties.join("\n")
|
||||
);
|
||||
if std::fs::read_to_string(&app_tauri_properties_path)
|
||||
.map(|o| o != app_tauri_properties_content)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
write(&app_tauri_properties_path, app_tauri_properties_content)
|
||||
.context("failed to write tauri.properties")?;
|
||||
}
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed={}", gradle_settings_path.display());
|
||||
println!("cargo:rerun-if-changed={}", app_build_gradle_path.display());
|
||||
if !app_tauri_properties.is_empty() {
|
||||
println!(
|
||||
"cargo:rerun-if-changed={}",
|
||||
app_tauri_properties_path.display()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,83 @@
|
||||
# Changelog
|
||||
|
||||
## \[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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-bundler"
|
||||
version = "2.6.1"
|
||||
version = "2.7.5"
|
||||
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.1", 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.2", path = "../tauri-macos-sign" }
|
||||
|
||||
[target."cfg(target_os = \"linux\")".dependencies]
|
||||
heck = "0.5"
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
mod category;
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
mod kmp;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod linux;
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -15,29 +17,46 @@ mod windows;
|
||||
|
||||
use tauri_utils::{display_path, platform::Target as TargetPlatform};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
const BUNDLE_VAR_TOKEN: &[u8] = b"__TAURI_BUNDLE_TYPE_VAR_UNK";
|
||||
/// Patch a binary with bundle type information
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
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)?;
|
||||
}
|
||||
PackageType::Nsis | PackageType::WindowsMsi => {
|
||||
log::info!(
|
||||
"Patching binary {:?} for type {}",
|
||||
binary,
|
||||
package_type.short_name()
|
||||
);
|
||||
windows::patch_binary(binary, package_type)?;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
let mut file_data = std::fs::read(binary).expect("Could not read binary file.");
|
||||
|
||||
if let Some(bundle_var_index) = kmp::index_of(BUNDLE_VAR_TOKEN, &file_data) {
|
||||
#[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",
|
||||
_ => {
|
||||
return Err(crate::Error::InvalidPackageType(
|
||||
package_type.short_name().to_owned(),
|
||||
"Linux".to_owned(),
|
||||
))
|
||||
}
|
||||
};
|
||||
#[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(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
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()))?;
|
||||
} else {
|
||||
return Err(crate::Error::MissingBundleTypeVar);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -92,22 +111,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
|
||||
@@ -115,22 +129,14 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
|
||||
continue;
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
if let Err(e) = patch_binary(&main_binary_path, package_type) {
|
||||
log::warn!("Failed to add bundler type to the binary: {e}. Updater plugin may not be able to update this package. This shouldn't normally happen, please report it to https://github.com/tauri-apps/tauri/issues");
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@@ -172,6 +178,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 +255,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 +287,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(());
|
||||
}
|
||||
|
||||
|
||||
61
crates/tauri-bundler/src/bundle/kmp/mod.rs
Normal file
61
crates/tauri-bundler/src/bundle/kmp/mod.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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
|
||||
|
||||
// Knuth–Morris–Pratt algorithm
|
||||
// based on https://github.com/howeih/rust_kmp
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
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
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
# GTK3 environment variables: https://developer.gnome.org/gtk3/stable/gtk-running.html
|
||||
# GTK4 environment variables: https://developer.gnome.org/gtk4/stable/gtk-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" '{}' \;
|
||||
|
||||
@@ -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")?;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -65,16 +65,12 @@ 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");
|
||||
@@ -459,20 +455,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);
|
||||
|
||||
@@ -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?;
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -257,7 +257,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>>,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -753,26 +753,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();
|
||||
|
||||
@@ -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"
|
||||
@@ -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();
|
||||
@@ -614,13 +621,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 +867,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))
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ pub enum Error {
|
||||
#[error("Failed to write binary file changes: `{0}`")]
|
||||
BinaryWriteError(String),
|
||||
/// Invalid offset while patching binary file
|
||||
#[deprecated]
|
||||
#[error("Invalid offset while patching binary file")]
|
||||
BinaryOffsetOutOfRange,
|
||||
/// Unsupported architecture.
|
||||
|
||||
@@ -14,6 +14,8 @@ use sha2::Digest;
|
||||
use url::Url;
|
||||
use zip::ZipArchive;
|
||||
|
||||
const BUNDLER_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
|
||||
|
||||
fn generate_github_mirror_url_from_template(github_url: &str) -> Option<String> {
|
||||
std::env::var("TAURI_BUNDLER_TOOLS_GITHUB_MIRROR_TEMPLATE")
|
||||
.ok()
|
||||
@@ -47,7 +49,15 @@ fn generate_github_alternative_url(url: &str) -> Option<(ureq::Agent, String)> {
|
||||
|
||||
generate_github_mirror_url_from_template(url)
|
||||
.or_else(|| generate_github_mirror_url_from_base(url))
|
||||
.map(|alt_url| (ureq::agent(), alt_url))
|
||||
.map(|alt_url| {
|
||||
(
|
||||
ureq::Agent::config_builder()
|
||||
.user_agent(BUNDLER_USER_AGENT)
|
||||
.build()
|
||||
.into(),
|
||||
alt_url,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn create_agent_and_url(url: &str) -> (ureq::Agent, String) {
|
||||
@@ -55,22 +65,21 @@ fn create_agent_and_url(url: &str) -> (ureq::Agent, String) {
|
||||
}
|
||||
|
||||
pub(crate) fn base_ureq_agent() -> ureq::Agent {
|
||||
#[allow(unused_mut)]
|
||||
let mut config_builder = ureq::Agent::config_builder()
|
||||
.user_agent(BUNDLER_USER_AGENT)
|
||||
.proxy(ureq::Proxy::try_from_env());
|
||||
|
||||
#[cfg(feature = "platform-certs")]
|
||||
let agent: ureq::Agent = ureq::Agent::config_builder()
|
||||
.tls_config(
|
||||
{
|
||||
config_builder = config_builder.tls_config(
|
||||
ureq::tls::TlsConfig::builder()
|
||||
.root_certs(ureq::tls::RootCerts::PlatformVerifier)
|
||||
.build(),
|
||||
)
|
||||
.proxy(ureq::Proxy::try_from_env())
|
||||
.build()
|
||||
.into();
|
||||
#[cfg(not(feature = "platform-certs"))]
|
||||
let agent: ureq::Agent = ureq::Agent::config_builder()
|
||||
.proxy(ureq::Proxy::try_from_env())
|
||||
.build()
|
||||
.into();
|
||||
agent
|
||||
);
|
||||
}
|
||||
|
||||
config_builder.build().into()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
@@ -1,5 +1,108 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.9.6]
|
||||
|
||||
### What's Changed
|
||||
|
||||
- [`7b1b3514d`](https://www.github.com/tauri-apps/tauri/commit/7b1b3514df771e6e9859b9f54fa4df332433948e) ([#14621](https://www.github.com/tauri-apps/tauri/pull/14621) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Errors like `Error Failed to parse version 2 for for NPM package tauri` when there was no `package-lock.json` file present yet or when using ones like `link:./tauri` are now only logged in `--verbose` mode.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-macos-sign@2.3.2`
|
||||
- Upgraded to `tauri-bundler@2.7.5`
|
||||
|
||||
## \[2.9.5]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`f022b2d1a`](https://www.github.com/tauri-apps/tauri/commit/f022b2d1ae57612e39c75782926f2f341d9034a8) ([#14582](https://www.github.com/tauri-apps/tauri/pull/14582) by [@hrzlgnm](https://www.github.com/tauri-apps/tauri/../../hrzlgnm)) Fixed an issue that caused the cli to error out with missing private key, in case the option `--no-sign` was requested and the `tauri.config` has signing key set and the plugin `tauri-plugin-updater` is used.
|
||||
- [`f855caf8a`](https://www.github.com/tauri-apps/tauri/commit/f855caf8a3830aa5dd6d0b039312866a5d9c3606) ([#14481](https://www.github.com/tauri-apps/tauri/pull/14481) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fixed the mismatched tauri package versions check didn't work for pnpm
|
||||
- [`79a7d9ec0`](https://www.github.com/tauri-apps/tauri/commit/79a7d9ec01be1a371b8e923848140fea75e9caed) ([#14468](https://www.github.com/tauri-apps/tauri/pull/14468) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the cli to print errors like `Error Failed to parse version 2 for crate tauri` when there was no `Cargo.lock` file present yet. This will still be logged in `--verbose` mode.
|
||||
|
||||
### 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-bundler@2.7.4`
|
||||
- Upgraded to `tauri-macos-sign@2.3.1`
|
||||
- Upgraded to `tauri-utils@2.8.1`
|
||||
|
||||
## \[2.9.4]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`b586ecf1f`](https://www.github.com/tauri-apps/tauri/commit/b586ecf1f4b3b087f9aa6c4668c2c18b1b7925f4) ([#14416](https://www.github.com/tauri-apps/tauri/pull/14416) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Premultiply Alpha before Resizing which gets rid of the gray fringe around the icons for svg images.
|
||||
|
||||
## \[2.9.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.
|
||||
- [`779612ac8`](https://www.github.com/tauri-apps/tauri/commit/779612ac8425a787626da4cefdb9eaf7d63bea18) ([#14379](https://www.github.com/tauri-apps/tauri/pull/14379) by [@moubctez](https://www.github.com/tauri-apps/tauri/../../moubctez)) Properly read the `required-features` field of binaries in Cargo.toml to prevent bundling issues when the features weren't enabled.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`fd8c30b4f`](https://www.github.com/tauri-apps/tauri/commit/fd8c30b4f1bca8dd7165c5c0ebe7fbfd17662153) ([#14353](https://www.github.com/tauri-apps/tauri/pull/14353) by [@ChaseKnowlden](https://www.github.com/tauri-apps/tauri/../../ChaseKnowlden)) Premultiply Alpha before Resizing which gets rid of the gray fringe around the icons.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-bundler@2.7.3`
|
||||
|
||||
## \[2.9.2]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-bundler@2.7.2`
|
||||
|
||||
## \[2.9.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-macos-sign@2.3.0`
|
||||
- Upgraded to `tauri-bundler@2.7.1`
|
||||
|
||||
## \[2.9.0]
|
||||
|
||||
### New Features
|
||||
|
||||
- [`f5851ee00`](https://www.github.com/tauri-apps/tauri/commit/f5851ee00d6d1f4d560a220ca5a728fedd525092) ([#14089](https://www.github.com/tauri-apps/tauri/pull/14089)) Adds the `scrollBarStyle` option to the window configuration.
|
||||
- [`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.
|
||||
- [`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.
|
||||
- [`673867aa0`](https://www.github.com/tauri-apps/tauri/commit/673867aa0e1ccd766ee879ffe96aba58c758613c) ([#14094](https://www.github.com/tauri-apps/tauri/pull/14094)) 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.
|
||||
- [`3d6868d09`](https://www.github.com/tauri-apps/tauri/commit/3d6868d09c323d68a152f3c3f8c7256311bd020a) ([#14128](https://www.github.com/tauri-apps/tauri/pull/14128)) Added support to defining the content type of the declared file association on macOS (maps to LSItemContentTypes property).
|
||||
- [`3d6868d09`](https://www.github.com/tauri-apps/tauri/commit/3d6868d09c323d68a152f3c3f8c7256311bd020a) ([#14128](https://www.github.com/tauri-apps/tauri/pull/14128)) Added support to defining the metadata for custom types declared in `tauri.conf.json > bundle > fileAssociations > exportedType` via the `UTExportedTypeDeclarations` Info.plist property.
|
||||
- [`ed7c9a410`](https://www.github.com/tauri-apps/tauri/commit/ed7c9a4100e08c002212265549d12130d021ad1e) ([#14108](https://www.github.com/tauri-apps/tauri/pull/14108)) Added `bundle > macOS > infoPlist` and `bundle > iOS > infoPlist` configurations to allow defining custom Info.plist extensions.
|
||||
- [`75082cc5b`](https://www.github.com/tauri-apps/tauri/commit/75082cc5b340e30e2c4b4cd4bd6a1fe5382164aa) ([#14120](https://www.github.com/tauri-apps/tauri/pull/14120)) Added `ios run` and `android run` commands to run the app in production mode.
|
||||
- [`cc8c0b531`](https://www.github.com/tauri-apps/tauri/commit/cc8c0b53171173dbd1d01781a50de1a3ea159031) ([#14031](https://www.github.com/tauri-apps/tauri/pull/14031)) Added support to universal app links on macOS with the `plugins > deep-link > desktop > domains` configuration.
|
||||
|
||||
### Enhancements
|
||||
|
||||
- [`94cbd40fc`](https://www.github.com/tauri-apps/tauri/commit/94cbd40fc733e08c0bccd48149d22a0e9c2f1e5c) ([#14223](https://www.github.com/tauri-apps/tauri/pull/14223)) Add support for Android's adaptive and themed icons.
|
||||
- [`b5aa01870`](https://www.github.com/tauri-apps/tauri/commit/b5aa018702bf45dc98297698f9b7d238705865a6) ([#14268](https://www.github.com/tauri-apps/tauri/pull/14268)) Update cargo-mobile2 to 0.21, enhancing error messages and opening Xcode when multiple apps are installed.
|
||||
- [`55453e845`](https://www.github.com/tauri-apps/tauri/commit/55453e8453d927b8197f1ba9f26fd944482938f7) ([#14262](https://www.github.com/tauri-apps/tauri/pull/14262)) Check mismatched versions in `tauri info`
|
||||
- [`1a6627ee7`](https://www.github.com/tauri-apps/tauri/commit/1a6627ee7d085a4e66784e2705254714d68c7244) ([#14122](https://www.github.com/tauri-apps/tauri/pull/14122)) Set a default log level filter when running `tauri add log`.
|
||||
- [`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.
|
||||
- [`f6622a3e3`](https://www.github.com/tauri-apps/tauri/commit/f6622a3e342f5dd5fb3cf6e0f79fb309a10e9b3d) ([#14129](https://www.github.com/tauri-apps/tauri/pull/14129)) Prompt to install the iOS platform if it isn't installed yet.
|
||||
- [`6bbb530fd`](https://www.github.com/tauri-apps/tauri/commit/6bbb530fd5edfc07b180a4f3782b8566872ca3b1) ([#14105](https://www.github.com/tauri-apps/tauri/pull/14105)) Warn if productName is empty when initializing mobile project.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [`19fb6f7cb`](https://www.github.com/tauri-apps/tauri/commit/19fb6f7cb0d702cb2f25f6f2d1e11014d9dada5d) ([#14146](https://www.github.com/tauri-apps/tauri/pull/14146)) Strip Windows-only extensions from the binary path so an Android project initialized on Windows can be used on UNIX systems.
|
||||
- [`19fb6f7cb`](https://www.github.com/tauri-apps/tauri/commit/19fb6f7cb0d702cb2f25f6f2d1e11014d9dada5d) ([#14146](https://www.github.com/tauri-apps/tauri/pull/14146)) Enhance Android build script usage on Windows by attempting to run cmd, bat and exe formats.
|
||||
- [`28a2f9bc5`](https://www.github.com/tauri-apps/tauri/commit/28a2f9bc55f658eb71ef1a970ff9f791346f7682) ([#14101](https://www.github.com/tauri-apps/tauri/pull/14101)) Fix iOS CLI usage after modifying the package name.
|
||||
- [`d2938486e`](https://www.github.com/tauri-apps/tauri/commit/d2938486e9d974debd90c15d7160b8a17bf4d763) ([#14261](https://www.github.com/tauri-apps/tauri/pull/14261)) Replaced the non-standard nerd font character with ` ⱼₛ ` in `tarui info`
|
||||
- [`25e920e16`](https://www.github.com/tauri-apps/tauri/commit/25e920e169db900ca4f07c2bb9eb290e9f9f2c7d) ([#14298](https://www.github.com/tauri-apps/tauri/pull/14298)) Wait for dev server to exit before exiting the CLI when the app is closed on `tauri dev --no-watch`.
|
||||
- [`b0012424c`](https://www.github.com/tauri-apps/tauri/commit/b0012424c5f432debfa42ba145e2672966d5f6d5) ([#14115](https://www.github.com/tauri-apps/tauri/pull/14115)) Resolve local IP address when `tauri.conf.json > build > devUrl` host is `0.0.0.0`.
|
||||
- [`abf7e8850`](https://www.github.com/tauri-apps/tauri/commit/abf7e8850ba41e7173e9e9a3fdd6dfb8f357d72d) ([#14118](https://www.github.com/tauri-apps/tauri/pull/14118)) Fixes mobile project initialization when using `pnpx` or `pnpm dlx`.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `tauri-utils@2.8.0`
|
||||
- Upgraded to `tauri-bundler@2.7.0`
|
||||
|
||||
## \[2.8.4]
|
||||
|
||||
### Enhancements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-cli"
|
||||
version = "2.8.4"
|
||||
version = "2.9.6"
|
||||
authors = ["Tauri Programme within The Commons Conservancy"]
|
||||
edition = "2021"
|
||||
rust-version = "1.77.2"
|
||||
@@ -36,7 +36,7 @@ name = "cargo-tauri"
|
||||
path = "src/main.rs"
|
||||
|
||||
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies]
|
||||
cargo-mobile2 = { version = "0.20.6", default-features = false }
|
||||
cargo-mobile2 = { version = "0.21.1", default-features = false }
|
||||
|
||||
[dependencies]
|
||||
jsonrpsee = { version = "0.24", features = ["server"] }
|
||||
@@ -47,7 +47,7 @@ sublime_fuzzy = "0.7"
|
||||
clap_complete = "4"
|
||||
clap = { version = "4", features = ["derive", "env"] }
|
||||
thiserror = "2"
|
||||
tauri-bundler = { version = "2.6.1", default-features = false, path = "../tauri-bundler" }
|
||||
tauri-bundler = { version = "2.7.5", default-features = false, path = "../tauri-bundler" }
|
||||
colored = "2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = { version = "1", features = ["preserve_order"] }
|
||||
@@ -56,9 +56,9 @@ notify = "8"
|
||||
notify-debouncer-full = "0.6"
|
||||
shared_child = "1"
|
||||
duct = "1.0"
|
||||
toml_edit = { version = "0.23", features = ["serde"] }
|
||||
toml_edit = { version = "0.24", features = ["serde"] }
|
||||
json-patch = "3"
|
||||
tauri-utils = { version = "2.7.0", path = "../tauri-utils", features = [
|
||||
tauri-utils = { version = "2.8.1", path = "../tauri-utils", features = [
|
||||
"isolation",
|
||||
"schema",
|
||||
"config-json5",
|
||||
@@ -66,11 +66,11 @@ tauri-utils = { version = "2.7.0", path = "../tauri-utils", features = [
|
||||
"html-manipulation",
|
||||
] }
|
||||
toml = "0.9"
|
||||
jsonschema = "0.33"
|
||||
jsonschema = { version = "0.33", default-features = false }
|
||||
handlebars = "6"
|
||||
include_dir = "0.7"
|
||||
dirs = "6"
|
||||
minisign = "=0.7.3"
|
||||
minisign = "0.8"
|
||||
base64 = "0.22"
|
||||
ureq = { version = "3", default-features = false, features = ["gzip"] }
|
||||
os_info = "3"
|
||||
@@ -113,6 +113,7 @@ uuid = { version = "1", features = ["v5"] }
|
||||
rand = "0.9"
|
||||
zip = { version = "4", default-features = false, features = ["deflate"] }
|
||||
which = "8"
|
||||
rayon = "1.10"
|
||||
|
||||
[dev-dependencies]
|
||||
insta = "1"
|
||||
@@ -132,7 +133,7 @@ libc = "0.2"
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dependencies]
|
||||
plist = "1"
|
||||
tauri-macos-sign = { version = "2.2.0", path = "../tauri-macos-sign" }
|
||||
tauri-macos-sign = { version = "2.3.2", path = "../tauri-macos-sign" }
|
||||
object = { version = "0.36", default-features = false, features = [
|
||||
"macho",
|
||||
"read_core",
|
||||
|
||||
@@ -33,7 +33,7 @@ These environment variables are inputs to the CLI which may have an equivalent C
|
||||
- See [creating API keys](https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api) for more information.
|
||||
- `API_PRIVATE_KEYS_DIR` — Specify the directory where your AuthKey file is located. See `APPLE_API_KEY`.
|
||||
- `APPLE_API_ISSUER` — Issuer ID. Required if `APPLE_API_KEY` is specified.
|
||||
- `APPLE_API_KEY_PATH` - path to the API key `.p8` file. If not specified, for macOS apps the bundler searches the following directories in sequence for a private key file with the name of 'AuthKey\_<api_key>.p8': './private_keys', '~/private_keys', '~/.private_keys', and '~/.appstoreconnect/private_keys'. **For iOS this variable is required**.
|
||||
- `APPLE_API_KEY_PATH` - path to the API key `.p8` file. If not specified, for macOS apps the bundler searches the following directories in sequence for a private key file with the name of `AuthKey\_<api_key>.p8`: `./private_keys`, `~/private_keys`, `~/.private_keys`, and `~/.appstoreconnect/private_keys`. **For iOS this variable is required**.
|
||||
- `APPLE_SIGNING_IDENTITY` — The identity used to code sign. Overwrites `tauri.conf.json > bundle > macOS > signingIdentity`. If neither are set, it is inferred from `APPLE_CERTIFICATE` when provided.
|
||||
- `APPLE_PROVIDER_SHORT_NAME` — If your Apple ID is connected to multiple teams, you have to specify the provider short name of the team you want to use to notarize your app. Overwrites `tauri.conf.json > bundle > macOS > providerShortName`.
|
||||
- `APPLE_DEVELOPMENT_TEAM` — The team ID used to code sign on iOS. Overwrites `tauri.conf.json > bundle > iOS > developmentTeam`. Can be found in https://developer.apple.com/account#MembershipDetailsCard.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://schema.tauri.app/config/2.8.5",
|
||||
"$id": "https://schema.tauri.app/config/2.9.5",
|
||||
"title": "Config",
|
||||
"description": "The Tauri configuration object.\n It is read from a file where you can define your frontend assets,\n configure the bundler and define a tray icon.\n\n The configuration file is generated by the\n [`tauri init`](https://v2.tauri.app/reference/cli/#init) command that lives in\n your Tauri application source directory (src-tauri).\n\n Once generated, you may modify it at will to customize your Tauri application.\n\n ## File Formats\n\n By default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\n Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.\n The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.\n The TOML file name is `Tauri.toml`.\n\n ## Platform-Specific Configuration\n\n In addition to the default configuration file, Tauri can\n read a platform-specific configuration from `tauri.linux.conf.json`,\n `tauri.windows.conf.json`, `tauri.macos.conf.json`, `tauri.android.conf.json` and `tauri.ios.conf.json`\n (or `Tauri.linux.toml`, `Tauri.windows.toml`, `Tauri.macos.toml`, `Tauri.android.toml` and `Tauri.ios.toml` if the `Tauri.toml` format is used),\n which gets merged with the main configuration object.\n\n ## Configuration Structure\n\n The configuration is composed of the following objects:\n\n - [`app`](#appconfig): The Tauri configuration\n - [`build`](#buildconfig): The build configuration\n - [`bundle`](#bundleconfig): The bundle configurations\n - [`plugins`](#pluginconfig): The plugins configuration\n\n Example tauri.config.json file:\n\n ```json\n {\n \"productName\": \"tauri-app\",\n \"version\": \"0.1.0\",\n \"build\": {\n \"beforeBuildCommand\": \"\",\n \"beforeDevCommand\": \"\",\n \"devUrl\": \"http://localhost:3000\",\n \"frontendDist\": \"../dist\"\n },\n \"app\": {\n \"security\": {\n \"csp\": null\n },\n \"windows\": [\n {\n \"fullscreen\": false,\n \"height\": 600,\n \"resizable\": true,\n \"title\": \"Tauri App\",\n \"width\": 800\n }\n ]\n },\n \"bundle\": {},\n \"plugins\": {}\n }\n ```",
|
||||
"type": "object",
|
||||
@@ -84,6 +84,7 @@
|
||||
"default": {
|
||||
"active": false,
|
||||
"android": {
|
||||
"autoIncrementVersionCode": false,
|
||||
"minSdkVersion": 24
|
||||
},
|
||||
"createUpdaterArtifacts": false,
|
||||
@@ -167,7 +168,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"windows": {
|
||||
"description": "The app windows configuration.\n\n ## Example:\n\n To create a window at app startup\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n If not specified, the window's label (its identifier) defaults to \"main\",\n you can use this label to get the window through\n `app.get_webview_window` in Rust or `WebviewWindow.getByLabel` in JavaScript\n\n When working with multiple windows, each window will need an unique label\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"label\": \"main\", \"width\": 800, \"height\": 600 },\n { \"label\": \"secondary\", \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n You can also set `create` to false and use this config through the Rust APIs\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"create\": false, \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n and use it like this\n\n ```rust\n tauri::Builder::default()\n .setup(|app| {\n tauri::WebviewWindowBuilder::from_config(app.handle(), app.config().app.windows[0])?.build()?;\n Ok(())\n });\n ```",
|
||||
"description": "The app windows configuration.\n\n ## Example:\n\n To create a window at app startup\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n If not specified, the window's label (its identifier) defaults to \"main\",\n you can use this label to get the window through\n `app.get_webview_window` in Rust or `WebviewWindow.getByLabel` in JavaScript\n\n When working with multiple windows, each window will need an unique label\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"label\": \"main\", \"width\": 800, \"height\": 600 },\n { \"label\": \"secondary\", \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n You can also set `create` to false and use this config through the Rust APIs\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"create\": false, \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n and use it like this\n\n ```rust\n tauri::Builder::default()\n .setup(|app| {\n tauri::WebviewWindowBuilder::from_config(app.handle(), &app.config().app.windows[0])?.build()?;\n Ok(())\n });\n ```",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -233,7 +234,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"create": {
|
||||
"description": "Whether Tauri should create this window at app startup or not.\n\n When this is set to `false` you must manually grab the config object via `app.config().app.windows`\n and create it with [`WebviewWindowBuilder::from_config`](https://docs.rs/tauri/2/tauri/webview/struct.WebviewWindowBuilder.html#method.from_config).\n\n ## Example:\n\n ```rust\n tauri::Builder::default()\n .setup(|app| {\n tauri::WebviewWindowBuilder::from_config(app.handle(), app.config().app.windows[0])?.build()?;\n Ok(())\n });\n ```",
|
||||
"description": "Whether Tauri should create this window at app startup or not.\n\n When this is set to `false` you must manually grab the config object via `app.config().app.windows`\n and create it with [`WebviewWindowBuilder::from_config`](https://docs.rs/tauri/2/tauri/webview/struct.WebviewWindowBuilder.html#method.from_config).\n\n ## Example:\n\n ```rust\n tauri::Builder::default()\n .setup(|app| {\n tauri::WebviewWindowBuilder::from_config(app.handle(), &app.config().app.windows[0])?.build()?;\n Ok(())\n });\n ```",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -264,7 +265,7 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"x": {
|
||||
"description": "The horizontal position of the window's top left corner",
|
||||
"description": "The horizontal position of the window's top left corner in logical pixels",
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
@@ -272,7 +273,7 @@
|
||||
"format": "double"
|
||||
},
|
||||
"y": {
|
||||
"description": "The vertical position of the window's top left corner",
|
||||
"description": "The vertical position of the window's top left corner in logical pixels",
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
@@ -280,19 +281,19 @@
|
||||
"format": "double"
|
||||
},
|
||||
"width": {
|
||||
"description": "The window width.",
|
||||
"description": "The window width in logical pixels.",
|
||||
"default": 800.0,
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"height": {
|
||||
"description": "The window height.",
|
||||
"description": "The window height in logical pixels.",
|
||||
"default": 600.0,
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"minWidth": {
|
||||
"description": "The min window width.",
|
||||
"description": "The min window width in logical pixels.",
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
@@ -300,7 +301,7 @@
|
||||
"format": "double"
|
||||
},
|
||||
"minHeight": {
|
||||
"description": "The min window height.",
|
||||
"description": "The min window height in logical pixels.",
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
@@ -308,7 +309,7 @@
|
||||
"format": "double"
|
||||
},
|
||||
"maxWidth": {
|
||||
"description": "The max window width.",
|
||||
"description": "The max window width in logical pixels.",
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
@@ -316,7 +317,7 @@
|
||||
"format": "double"
|
||||
},
|
||||
"maxHeight": {
|
||||
"description": "The max window height.",
|
||||
"description": "The max window height in logical pixels.",
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
@@ -654,13 +655,13 @@
|
||||
],
|
||||
"properties": {
|
||||
"width": {
|
||||
"description": "Horizontal margin in physical unit",
|
||||
"description": "Horizontal margin in physical pixels",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"height": {
|
||||
"description": "Vertical margin in physical unit",
|
||||
"description": "Vertical margin in physical pixels",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
@@ -923,7 +924,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Mica effect that matches the system dark perefence **Windows 11 Only**",
|
||||
"description": "Mica effect that matches the system dark preference **Windows 11 Only**",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"mica"
|
||||
@@ -944,7 +945,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Tabbed effect that matches the system dark perefence **Windows 11 Only**",
|
||||
"description": "Tabbed effect that matches the system dark preference **Windows 11 Only**",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"tabbed"
|
||||
@@ -1298,7 +1299,7 @@
|
||||
"additionalProperties": false
|
||||
},
|
||||
"FsScope": {
|
||||
"description": "Protocol scope definition.\n It is a list of glob patterns that restrict the API access from the webview.\n\n Each pattern can start with a variable that resolves to a system base directory.\n The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,\n `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,\n `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`,\n `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"description": "Protocol scope definition.\n It is a list of glob patterns that restrict the API access from the webview.\n\n Each pattern can start with a variable that resolves to a system base directory.\n The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,\n `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,\n `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$TEMP`,\n `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "A list of paths that are allowed by this scope.",
|
||||
@@ -1993,7 +1994,7 @@
|
||||
"description": "Defines the URL or assets to embed in the application.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "An external URL that should be used as the default application URL.",
|
||||
"description": "An external URL that should be used as the default application URL. No assets are embedded in the app in this case.",
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
@@ -2002,7 +2003,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "An array of files to embed on the app.",
|
||||
"description": "An array of files to embed in the app.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
@@ -2288,6 +2289,7 @@
|
||||
"android": {
|
||||
"description": "Android configuration.",
|
||||
"default": {
|
||||
"autoIncrementVersionCode": false,
|
||||
"minSdkVersion": 24
|
||||
},
|
||||
"allOf": [
|
||||
@@ -2796,7 +2798,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"description": "MSI installer version in the format `major.minor.patch.build` (build is optional).\n\n Because a valid version is required for MSI installer, it will be derived from [`Config::version`] if this field is not set.\n\n The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255.\n The third and foruth fields have a maximum value of 65,535.\n\n See <https://learn.microsoft.com/en-us/windows/win32/msi/productversion> for more info.",
|
||||
"description": "MSI installer version in the format `major.minor.patch.build` (build is optional).\n\n Because a valid version is required for MSI installer, it will be derived from [`Config::version`] if this field is not set.\n\n The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255.\n The third and fourth fields have a maximum value of 65,535.\n\n See <https://learn.microsoft.com/en-us/windows/win32/msi/productversion> for more info.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
@@ -3100,7 +3102,7 @@
|
||||
"description": "Custom Signing Command configuration.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "A string notation of the script to execute.\n\n \"%1\" will be replaced with the path to the binary to be signed.\n\n This is a simpler notation for the command.\n Tauri will split the string with `' '` and use the first element as the command name and the rest as arguments.\n\n If you need to use whitespace in the command or arguments, use the object notation [`Self::ScriptWithOptions`].",
|
||||
"description": "A string notation of the script to execute.\n\n \"%1\" will be replaced with the path to the binary to be signed.\n\n This is a simpler notation for the command.\n Tauri will split the string with `' '` and use the first element as the command name and the rest as arguments.\n\n If you need to use whitespace in the command or arguments, use the object notation [`Self::CommandWithOptions`].",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
@@ -3853,6 +3855,11 @@
|
||||
"format": "uint32",
|
||||
"maximum": 2100000000.0,
|
||||
"minimum": 1.0
|
||||
},
|
||||
"autoIncrementVersionCode": {
|
||||
"description": "Whether to automatically increment the `versionCode` on each build.\n\n - If `true`, the generator will try to read the last `versionCode` from\n `tauri.properties` and increment it by 1 for every build.\n - If `false` or not set, it falls back to `version_code` or semver-derived logic.\n\n Note that to use this feature, you should remove `/tauri.properties` from `src-tauri/gen/android/app/.gitignore` so the current versionCode is committed to the repository.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"cli.js": {
|
||||
"version": "2.8.4",
|
||||
"version": "2.9.6",
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"tauri": "2.8.5",
|
||||
"tauri-build": "2.4.1",
|
||||
"tauri-plugin": "2.4.0"
|
||||
"tauri": "2.9.5",
|
||||
"tauri-build": "2.5.3",
|
||||
"tauri-plugin": "2.5.2"
|
||||
}
|
||||
|
||||
@@ -7,12 +7,7 @@ use std::{collections::HashSet, path::PathBuf};
|
||||
use clap::Parser;
|
||||
use tauri_utils::acl::capability::{Capability, PermissionEntry};
|
||||
|
||||
use crate::{
|
||||
acl::FileFormat,
|
||||
error::ErrorExt,
|
||||
helpers::{app_paths::tauri_dir, prompts},
|
||||
Result,
|
||||
};
|
||||
use crate::{acl::FileFormat, error::ErrorExt, helpers::prompts, Result};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(about = "Create a new permission file")]
|
||||
@@ -37,7 +32,7 @@ pub struct Options {
|
||||
}
|
||||
|
||||
pub fn command(options: Options) -> Result<()> {
|
||||
crate::helpers::app_paths::resolve();
|
||||
let dirs = crate::helpers::app_paths::resolve_dirs();
|
||||
|
||||
let identifier = match options.identifier {
|
||||
Some(i) => i,
|
||||
@@ -111,8 +106,7 @@ pub fn command(options: Options) -> Result<()> {
|
||||
.canonicalize()
|
||||
.fs_context("failed to canonicalize capability file path", o.clone())?,
|
||||
None => {
|
||||
let dir = tauri_dir();
|
||||
let capabilities_dir = dir.join("capabilities");
|
||||
let capabilities_dir = dirs.tauri.join("capabilities");
|
||||
capabilities_dir.join(format!(
|
||||
"{}.{}",
|
||||
capability.identifier,
|
||||
|
||||
@@ -6,7 +6,6 @@ use clap::Parser;
|
||||
|
||||
use crate::{
|
||||
error::{Context, ErrorExt},
|
||||
helpers::app_paths::tauri_dir,
|
||||
Result,
|
||||
};
|
||||
use colored::Colorize;
|
||||
@@ -25,16 +24,17 @@ pub struct Options {
|
||||
}
|
||||
|
||||
pub fn command(options: Options) -> Result<()> {
|
||||
crate::helpers::app_paths::resolve();
|
||||
let dirs = crate::helpers::app_paths::resolve_dirs();
|
||||
|
||||
let acl_manifests_path = tauri_dir()
|
||||
let acl_manifests_path = dirs
|
||||
.tauri
|
||||
.join("gen")
|
||||
.join("schemas")
|
||||
.join("acl-manifests.json");
|
||||
|
||||
if acl_manifests_path.exists() {
|
||||
let plugin_manifest_json = read_to_string(&acl_manifests_path)
|
||||
.fs_context("failed to read plugin manifest", acl_manifests_path.clone())?;
|
||||
.fs_context("failed to read plugin manifest", acl_manifests_path)?;
|
||||
let acl = serde_json::from_str::<BTreeMap<String, Manifest>>(&plugin_manifest_json)
|
||||
.context("failed to parse plugin manifest as JSON")?;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
acl,
|
||||
error::ErrorExt,
|
||||
helpers::{
|
||||
app_paths::{resolve_frontend_dir, tauri_dir},
|
||||
app_paths::{resolve_frontend_dir, Dirs},
|
||||
cargo,
|
||||
npm::PackageManager,
|
||||
},
|
||||
@@ -39,11 +39,11 @@ pub struct Options {
|
||||
}
|
||||
|
||||
pub fn command(options: Options) -> Result<()> {
|
||||
crate::helpers::app_paths::resolve();
|
||||
run(options)
|
||||
let dirs = crate::helpers::app_paths::resolve_dirs();
|
||||
run(options, &dirs)
|
||||
}
|
||||
|
||||
pub fn run(options: Options) -> Result<()> {
|
||||
pub fn run(options: Options, dirs: &Dirs) -> Result<()> {
|
||||
let (plugin, version) = options
|
||||
.plugin
|
||||
.split_once('@')
|
||||
@@ -71,7 +71,6 @@ pub fn run(options: Options) -> Result<()> {
|
||||
}
|
||||
|
||||
let frontend_dir = resolve_frontend_dir();
|
||||
let tauri_dir = tauri_dir();
|
||||
|
||||
let target_str = metadata
|
||||
.desktop_only
|
||||
@@ -90,7 +89,7 @@ pub fn run(options: Options) -> Result<()> {
|
||||
branch: options.branch.as_deref(),
|
||||
rev: options.rev.as_deref(),
|
||||
tag: options.tag.as_deref(),
|
||||
cwd: Some(tauri_dir),
|
||||
cwd: Some(dirs.tauri),
|
||||
target: target_str,
|
||||
})?;
|
||||
|
||||
@@ -117,7 +116,7 @@ pub fn run(options: Options) -> Result<()> {
|
||||
(None, None, None, None) => npm_name,
|
||||
_ => crate::error::bail!("Only one of --tag, --rev and --branch can be specified"),
|
||||
};
|
||||
manager.install(&[npm_spec], tauri_dir)?;
|
||||
manager.install(&[npm_spec], dirs.tauri)?;
|
||||
}
|
||||
|
||||
let _ = acl::permission::add::command(acl::permission::add::Options {
|
||||
@@ -143,7 +142,10 @@ pub fn run(options: Options) -> Result<()> {
|
||||
let plugin_init = format!(".plugin(tauri_plugin_{plugin_snake_case}::{plugin_init_fn})");
|
||||
|
||||
let re = Regex::new(r"(tauri\s*::\s*Builder\s*::\s*default\(\))(\s*)").unwrap();
|
||||
for file in [tauri_dir.join("src/main.rs"), tauri_dir.join("src/lib.rs")] {
|
||||
for file in [
|
||||
dirs.tauri.join("src/main.rs"),
|
||||
dirs.tauri.join("src/lib.rs"),
|
||||
] {
|
||||
let contents =
|
||||
std::fs::read_to_string(&file).fs_context("failed to read Rust entry point", file.clone())?;
|
||||
|
||||
@@ -166,7 +168,7 @@ pub fn run(options: Options) -> Result<()> {
|
||||
log::info!("Running `cargo fmt`...");
|
||||
let _ = Command::new("cargo")
|
||||
.arg("fmt")
|
||||
.current_dir(tauri_dir)
|
||||
.current_dir(dirs.tauri)
|
||||
.status();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::{
|
||||
error::{Context, ErrorExt},
|
||||
helpers::{
|
||||
self,
|
||||
app_paths::{frontend_dir, tauri_dir},
|
||||
config::{get as get_config, ConfigHandle, FrontendDist},
|
||||
app_paths::Dirs,
|
||||
config::{get_config, ConfigMetadata, FrontendDist},
|
||||
},
|
||||
info::plugins::check_mismatched_packages,
|
||||
interface::{rust::get_cargo_target_dir, AppInterface, Interface},
|
||||
@@ -40,7 +40,7 @@ pub struct Options {
|
||||
pub target: Option<String>,
|
||||
/// Space or comma separated list of features to activate
|
||||
#[clap(short, long, action = ArgAction::Append, num_args(0..))]
|
||||
pub features: Option<Vec<String>>,
|
||||
pub features: Vec<String>,
|
||||
/// Space or comma separated list of bundles to package.
|
||||
#[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')]
|
||||
pub bundles: Option<Vec<BundleFormat>>,
|
||||
@@ -82,7 +82,7 @@ pub struct Options {
|
||||
}
|
||||
|
||||
pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
|
||||
crate::helpers::app_paths::resolve();
|
||||
let dirs = crate::helpers::app_paths::resolve_dirs();
|
||||
|
||||
if options.no_sign {
|
||||
log::warn!("--no-sign flag detected: Signing will be skipped.");
|
||||
@@ -99,41 +99,37 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
|
||||
let config = get_config(
|
||||
target,
|
||||
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
|
||||
dirs.tauri,
|
||||
)?;
|
||||
|
||||
let mut interface = AppInterface::new(
|
||||
config.lock().unwrap().as_ref().unwrap(),
|
||||
options.target.clone(),
|
||||
)?;
|
||||
let mut interface = AppInterface::new(&config, options.target.clone(), dirs.tauri)?;
|
||||
|
||||
setup(&interface, &mut options, config.clone(), false)?;
|
||||
setup(&interface, &mut options, &config, &dirs, false)?;
|
||||
|
||||
let config_guard = config.lock().unwrap();
|
||||
let config_ = config_guard.as_ref().unwrap();
|
||||
|
||||
if let Some(minimum_system_version) = &config_.bundle.macos.minimum_system_version {
|
||||
if let Some(minimum_system_version) = &config.bundle.macos.minimum_system_version {
|
||||
std::env::set_var("MACOSX_DEPLOYMENT_TARGET", minimum_system_version);
|
||||
}
|
||||
|
||||
let app_settings = interface.app_settings();
|
||||
let interface_options = options.clone().into();
|
||||
|
||||
let out_dir = app_settings.out_dir(&interface_options)?;
|
||||
let out_dir = app_settings.out_dir(&interface_options, dirs.tauri)?;
|
||||
|
||||
let bin_path = interface.build(interface_options)?;
|
||||
let bin_path = interface.build(interface_options, &dirs)?;
|
||||
|
||||
log::info!(action ="Built"; "application at: {}", tauri_utils::display_path(bin_path));
|
||||
|
||||
let app_settings = interface.app_settings();
|
||||
|
||||
if !options.no_bundle && (config_.bundle.active || options.bundles.is_some()) {
|
||||
if !options.no_bundle && (config.bundle.active || options.bundles.is_some()) {
|
||||
crate::bundle::bundle(
|
||||
&options.into(),
|
||||
verbosity,
|
||||
ci,
|
||||
&interface,
|
||||
&app_settings,
|
||||
config_,
|
||||
&*app_settings,
|
||||
&config,
|
||||
&dirs,
|
||||
&out_dir,
|
||||
)?;
|
||||
}
|
||||
@@ -144,15 +140,14 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
|
||||
pub fn setup(
|
||||
interface: &AppInterface,
|
||||
options: &mut Options,
|
||||
config: ConfigHandle,
|
||||
config: &ConfigMetadata,
|
||||
dirs: &Dirs,
|
||||
mobile: bool,
|
||||
) -> Result<()> {
|
||||
let tauri_path = tauri_dir();
|
||||
|
||||
// TODO: Maybe optimize this to run in parallel in the future
|
||||
// see https://github.com/tauri-apps/tauri/pull/13993#discussion_r2280697117
|
||||
log::info!("Looking up installed tauri packages to check mismatched versions...");
|
||||
if let Err(error) = check_mismatched_packages(frontend_dir(), tauri_path) {
|
||||
if let Err(error) = check_mismatched_packages(dirs.frontend, dirs.tauri) {
|
||||
if options.ignore_version_mismatches {
|
||||
log::error!("{error}");
|
||||
} else {
|
||||
@@ -160,46 +155,47 @@ pub fn setup(
|
||||
}
|
||||
}
|
||||
|
||||
set_current_dir(tauri_path).context("failed to set current directory")?;
|
||||
set_current_dir(dirs.tauri).context("failed to set current directory")?;
|
||||
|
||||
let config_guard = config.lock().unwrap();
|
||||
let config_ = config_guard.as_ref().unwrap();
|
||||
|
||||
let bundle_identifier_source = config_
|
||||
let bundle_identifier_source = config
|
||||
.find_bundle_identifier_overwriter()
|
||||
.unwrap_or_else(|| "tauri.conf.json".into());
|
||||
|
||||
if config_.identifier == "com.tauri.dev" {
|
||||
if config.identifier == "com.tauri.dev" {
|
||||
crate::error::bail!(
|
||||
"You must change the bundle identifier in `{bundle_identifier_source} identifier`. The default value `com.tauri.dev` is not allowed as it must be unique across applications.",
|
||||
);
|
||||
}
|
||||
|
||||
if config_
|
||||
if config
|
||||
.identifier
|
||||
.chars()
|
||||
.any(|ch| !(ch.is_alphanumeric() || ch == '-' || ch == '.'))
|
||||
{
|
||||
crate::error::bail!(
|
||||
"The bundle identifier \"{}\" set in `{} identifier`. The bundle identifier string must contain only alphanumeric characters (A-Z, a-z, and 0-9), hyphens (-), and periods (.).",
|
||||
config_.identifier,
|
||||
bundle_identifier_source
|
||||
"The bundle identifier \"{}\" set in `{bundle_identifier_source:?} identifier`. The bundle identifier string must contain only alphanumeric characters (A-Z, a-z, and 0-9), hyphens (-), and periods (.).",
|
||||
config.identifier,
|
||||
);
|
||||
}
|
||||
|
||||
if config_.identifier.ends_with(".app") {
|
||||
if config.identifier.ends_with(".app") {
|
||||
log::warn!(
|
||||
"The bundle identifier \"{}\" set in `{} identifier` ends with `.app`. This is not recommended because it conflicts with the application bundle extension on macOS.",
|
||||
config_.identifier,
|
||||
bundle_identifier_source
|
||||
"The bundle identifier \"{}\" set in `{bundle_identifier_source:?} identifier` ends with `.app`. This is not recommended because it conflicts with the application bundle extension on macOS.",
|
||||
config.identifier,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(before_build) = config_.build.before_build_command.clone() {
|
||||
helpers::run_hook("beforeBuildCommand", before_build, interface, options.debug)?;
|
||||
if let Some(before_build) = config.build.before_build_command.clone() {
|
||||
helpers::run_hook(
|
||||
"beforeBuildCommand",
|
||||
before_build,
|
||||
interface,
|
||||
options.debug,
|
||||
dirs.frontend,
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(FrontendDist::Directory(web_asset_path)) = &config_.build.frontend_dist {
|
||||
if let Some(FrontendDist::Directory(web_asset_path)) = &config.build.frontend_dist {
|
||||
if !web_asset_path.exists() {
|
||||
let absolute_path = web_asset_path
|
||||
.parent()
|
||||
@@ -224,7 +220,7 @@ pub fn setup(
|
||||
|
||||
// Issue #13287 - Allow the use of target dir inside frontendDist/distDir
|
||||
// https://github.com/tauri-apps/tauri/issues/13287
|
||||
let target_path = get_cargo_target_dir(&options.args)?;
|
||||
let target_path = get_cargo_target_dir(&options.args, dirs.tauri)?;
|
||||
let mut out_folders = Vec::new();
|
||||
if let Ok(web_asset_canonical) = dunce::canonicalize(web_asset_path) {
|
||||
if let Ok(relative_path) = target_path.strip_prefix(&web_asset_canonical) {
|
||||
@@ -252,13 +248,12 @@ pub fn setup(
|
||||
}
|
||||
|
||||
if options.runner.is_none() {
|
||||
options.runner = config_.build.runner.clone();
|
||||
options.runner = config.build.runner.clone();
|
||||
}
|
||||
|
||||
options
|
||||
.features
|
||||
.get_or_insert(Vec::new())
|
||||
.extend(config_.build.features.clone().unwrap_or_default());
|
||||
.extend_from_slice(config.build.features.as_deref().unwrap_or_default());
|
||||
interface.build_options(&mut options.args, &mut options.features, mobile);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -16,8 +16,8 @@ use crate::{
|
||||
error::{Context, ErrorExt},
|
||||
helpers::{
|
||||
self,
|
||||
app_paths::tauri_dir,
|
||||
config::{get as get_config, ConfigMetadata},
|
||||
app_paths::Dirs,
|
||||
config::{get_config, ConfigMetadata},
|
||||
updater_signature,
|
||||
},
|
||||
interface::{AppInterface, AppSettings, Interface},
|
||||
@@ -71,7 +71,7 @@ pub struct Options {
|
||||
pub config: Vec<ConfigValue>,
|
||||
/// Space or comma separated list of features, should be the same features passed to `tauri build` if any.
|
||||
#[clap(short, long, action = ArgAction::Append, num_args(0..))]
|
||||
pub features: Option<Vec<String>>,
|
||||
pub features: Vec<String>,
|
||||
/// Target triple to build against.
|
||||
///
|
||||
/// It must be one of the values outputted by `$rustc --print target-list` or `universal-apple-darwin` for an universal macOS application.
|
||||
@@ -118,7 +118,7 @@ impl From<crate::build::Options> for Options {
|
||||
}
|
||||
|
||||
pub fn command(options: Options, verbosity: u8) -> crate::Result<()> {
|
||||
crate::helpers::app_paths::resolve();
|
||||
let dirs = crate::helpers::app_paths::resolve_dirs();
|
||||
|
||||
let ci = options.ci;
|
||||
|
||||
@@ -131,35 +131,30 @@ pub fn command(options: Options, verbosity: u8) -> crate::Result<()> {
|
||||
let config = get_config(
|
||||
target,
|
||||
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
|
||||
dirs.tauri,
|
||||
)?;
|
||||
|
||||
let interface = AppInterface::new(
|
||||
config.lock().unwrap().as_ref().unwrap(),
|
||||
options.target.clone(),
|
||||
)?;
|
||||
let interface = AppInterface::new(&config, options.target.clone(), dirs.tauri)?;
|
||||
|
||||
let tauri_path = tauri_dir();
|
||||
std::env::set_current_dir(tauri_path).context("failed to set current directory")?;
|
||||
std::env::set_current_dir(dirs.tauri).context("failed to set current directory")?;
|
||||
|
||||
let config_guard = config.lock().unwrap();
|
||||
let config_ = config_guard.as_ref().unwrap();
|
||||
|
||||
if let Some(minimum_system_version) = &config_.bundle.macos.minimum_system_version {
|
||||
if let Some(minimum_system_version) = &config.bundle.macos.minimum_system_version {
|
||||
std::env::set_var("MACOSX_DEPLOYMENT_TARGET", minimum_system_version);
|
||||
}
|
||||
|
||||
let app_settings = interface.app_settings();
|
||||
let interface_options = options.clone().into();
|
||||
|
||||
let out_dir = app_settings.out_dir(&interface_options)?;
|
||||
let out_dir = app_settings.out_dir(&interface_options, dirs.tauri)?;
|
||||
|
||||
bundle(
|
||||
&options,
|
||||
verbosity,
|
||||
ci,
|
||||
&interface,
|
||||
&app_settings,
|
||||
config_,
|
||||
&*app_settings,
|
||||
&config,
|
||||
&dirs,
|
||||
&out_dir,
|
||||
)
|
||||
}
|
||||
@@ -170,8 +165,9 @@ pub fn bundle<A: AppSettings>(
|
||||
verbosity: u8,
|
||||
ci: bool,
|
||||
interface: &AppInterface,
|
||||
app_settings: &std::sync::Arc<A>,
|
||||
app_settings: &A,
|
||||
config: &ConfigMetadata,
|
||||
dirs: &Dirs,
|
||||
out_dir: &Path,
|
||||
) -> crate::Result<()> {
|
||||
let package_types: Vec<PackageType> = if let Some(bundles) = &options.bundles {
|
||||
@@ -198,12 +194,19 @@ pub fn bundle<A: AppSettings>(
|
||||
before_bundle,
|
||||
interface,
|
||||
options.debug,
|
||||
dirs.frontend,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut settings = app_settings
|
||||
.get_bundler_settings(options.clone().into(), config, out_dir, package_types)
|
||||
.get_bundler_settings(
|
||||
options.clone().into(),
|
||||
config,
|
||||
out_dir,
|
||||
package_types,
|
||||
dirs.tauri,
|
||||
)
|
||||
.with_context(|| "failed to build bundler settings")?;
|
||||
settings.set_no_sign(options.no_sign);
|
||||
|
||||
@@ -249,6 +252,11 @@ fn sign_updaters(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if settings.no_sign() {
|
||||
log::warn!("Updater signing is skipped due to --no-sign flag.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// get the public key
|
||||
let pubkey = &update_settings.pubkey;
|
||||
// check if pubkey points to a file...
|
||||
|
||||
@@ -5,11 +5,9 @@
|
||||
use crate::{
|
||||
error::{Context, ErrorExt},
|
||||
helpers::{
|
||||
app_paths::{frontend_dir, tauri_dir},
|
||||
app_paths::Dirs,
|
||||
command_env,
|
||||
config::{
|
||||
get as get_config, reload as reload_config, BeforeDevCommand, ConfigHandle, FrontendDist,
|
||||
},
|
||||
config::{get_config, reload_config, BeforeDevCommand, ConfigMetadata, FrontendDist},
|
||||
},
|
||||
info::plugins::check_mismatched_packages,
|
||||
interface::{AppInterface, ExitReason, Interface},
|
||||
@@ -34,7 +32,7 @@ use std::{
|
||||
mod builtin_dev_server;
|
||||
|
||||
static BEFORE_DEV: OnceLock<Mutex<Arc<SharedChild>>> = OnceLock::new();
|
||||
static KILL_BEFORE_DEV_FLAG: OnceLock<AtomicBool> = OnceLock::new();
|
||||
static KILL_BEFORE_DEV_FLAG: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg(unix)]
|
||||
const KILL_CHILDREN_SCRIPT: &[u8] = include_bytes!("../scripts/kill-children.sh");
|
||||
@@ -57,7 +55,7 @@ pub struct Options {
|
||||
pub target: Option<String>,
|
||||
/// List of cargo features to activate
|
||||
#[clap(short, long, action = ArgAction::Append, num_args(0..))]
|
||||
pub features: Option<Vec<String>>,
|
||||
pub features: Vec<String>,
|
||||
/// Exit on panic
|
||||
#[clap(short, long)]
|
||||
pub exit_on_panic: bool,
|
||||
@@ -99,61 +97,57 @@ pub struct Options {
|
||||
}
|
||||
|
||||
pub fn command(options: Options) -> Result<()> {
|
||||
crate::helpers::app_paths::resolve();
|
||||
let dirs = crate::helpers::app_paths::resolve_dirs();
|
||||
|
||||
let r = command_internal(options);
|
||||
let r = command_internal(options, dirs);
|
||||
if r.is_err() {
|
||||
kill_before_dev_process();
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
fn command_internal(mut options: Options) -> Result<()> {
|
||||
fn command_internal(mut options: Options, dirs: Dirs) -> Result<()> {
|
||||
let target = options
|
||||
.target
|
||||
.as_deref()
|
||||
.map(Target::from_triple)
|
||||
.unwrap_or_else(Target::current);
|
||||
|
||||
let config = get_config(
|
||||
let mut config = get_config(
|
||||
target,
|
||||
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
|
||||
dirs.tauri,
|
||||
)?;
|
||||
|
||||
let mut interface = AppInterface::new(
|
||||
config.lock().unwrap().as_ref().unwrap(),
|
||||
options.target.clone(),
|
||||
)?;
|
||||
let mut interface = AppInterface::new(&config, options.target.clone(), dirs.tauri)?;
|
||||
|
||||
setup(&interface, &mut options, config)?;
|
||||
setup(&interface, &mut options, &mut config, &dirs)?;
|
||||
|
||||
let exit_on_panic = options.exit_on_panic;
|
||||
let no_watch = options.no_watch;
|
||||
interface.dev(options.into(), move |status, reason| {
|
||||
on_app_exit(status, reason, exit_on_panic, no_watch)
|
||||
})
|
||||
interface.dev(
|
||||
&mut config,
|
||||
options.into(),
|
||||
move |status, reason| on_app_exit(status, reason, exit_on_panic, no_watch),
|
||||
&dirs,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHandle) -> Result<()> {
|
||||
let tauri_path = tauri_dir();
|
||||
|
||||
pub fn setup(
|
||||
interface: &AppInterface,
|
||||
options: &mut Options,
|
||||
config: &mut ConfigMetadata,
|
||||
dirs: &Dirs,
|
||||
) -> Result<()> {
|
||||
std::thread::spawn(|| {
|
||||
if let Err(error) = check_mismatched_packages(frontend_dir(), tauri_path) {
|
||||
if let Err(error) = check_mismatched_packages(dirs.frontend, dirs.tauri) {
|
||||
log::error!("{error}");
|
||||
}
|
||||
});
|
||||
|
||||
set_current_dir(tauri_path).context("failed to set current directory")?;
|
||||
set_current_dir(dirs.tauri).context("failed to set current directory")?;
|
||||
|
||||
if let Some(before_dev) = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.build
|
||||
.before_dev_command
|
||||
.clone()
|
||||
{
|
||||
if let Some(before_dev) = config.build.before_dev_command.clone() {
|
||||
let (script, script_cwd, wait) = match before_dev {
|
||||
BeforeDevCommand::Script(s) if s.is_empty() => (None, None, false),
|
||||
BeforeDevCommand::Script(s) => (Some(s), None, false),
|
||||
@@ -161,7 +155,7 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
|
||||
(Some(script), cwd.map(Into::into), wait)
|
||||
}
|
||||
};
|
||||
let cwd = script_cwd.unwrap_or_else(|| frontend_dir().clone());
|
||||
let cwd = script_cwd.unwrap_or_else(|| dirs.frontend.to_owned());
|
||||
if let Some(before_dev) = script {
|
||||
log::info!(action = "Running"; "BeforeDevCommand (`{}`)", before_dev);
|
||||
let mut env = command_env(true);
|
||||
@@ -218,14 +212,13 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
|
||||
let status = child_
|
||||
.wait()
|
||||
.expect("failed to wait on \"beforeDevCommand\"");
|
||||
if !(status.success() || KILL_BEFORE_DEV_FLAG.get().unwrap().load(Ordering::Relaxed)) {
|
||||
if !(status.success() || KILL_BEFORE_DEV_FLAG.load(Ordering::Relaxed)) {
|
||||
log::error!("The \"beforeDevCommand\" terminated with a non-zero status code.");
|
||||
exit(status.code().unwrap_or(1));
|
||||
}
|
||||
});
|
||||
|
||||
BEFORE_DEV.set(Mutex::new(child)).unwrap();
|
||||
KILL_BEFORE_DEV_FLAG.set(AtomicBool::default()).unwrap();
|
||||
|
||||
let _ = ctrlc::set_handler(move || {
|
||||
kill_before_dev_process();
|
||||
@@ -236,45 +229,14 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
|
||||
}
|
||||
|
||||
if options.runner.is_none() {
|
||||
options.runner = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.build
|
||||
.runner
|
||||
.clone();
|
||||
options.runner = config.build.runner.clone();
|
||||
}
|
||||
|
||||
let mut cargo_features = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.build
|
||||
.features
|
||||
.clone()
|
||||
.unwrap_or_default();
|
||||
if let Some(features) = &options.features {
|
||||
cargo_features.extend(features.clone());
|
||||
}
|
||||
let mut cargo_features = config.build.features.clone().unwrap_or_default();
|
||||
cargo_features.extend(options.features.clone());
|
||||
|
||||
let mut dev_url = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.build
|
||||
.dev_url
|
||||
.clone();
|
||||
let frontend_dist = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.build
|
||||
.frontend_dist
|
||||
.clone();
|
||||
let mut dev_url = config.build.dev_url.clone();
|
||||
let frontend_dist = config.build.frontend_dist.clone();
|
||||
if !options.no_dev_server && dev_url.is_none() {
|
||||
if let Some(FrontendDist::Directory(path)) = &frontend_dist {
|
||||
if path.exists() {
|
||||
@@ -297,19 +259,21 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
|
||||
}
|
||||
})));
|
||||
|
||||
reload_config(&options.config.iter().map(|c| &c.0).collect::<Vec<_>>())?;
|
||||
reload_config(
|
||||
config,
|
||||
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
|
||||
dirs.tauri,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !options.no_dev_server_wait {
|
||||
if let Some(url) = dev_url {
|
||||
let host = url
|
||||
.host()
|
||||
.unwrap_or_else(|| panic!("No host name in the URL"));
|
||||
let host = url.host().expect("No host name in the URL");
|
||||
let port = url
|
||||
.port_or_known_default()
|
||||
.unwrap_or_else(|| panic!("No port number in the URL"));
|
||||
.expect("No port number in the URL");
|
||||
let addrs;
|
||||
let addr;
|
||||
let addrs = match host {
|
||||
@@ -352,16 +316,9 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
|
||||
}
|
||||
|
||||
if options.additional_watch_folders.is_empty() {
|
||||
options.additional_watch_folders.extend(
|
||||
config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.build
|
||||
.additional_watch_folders
|
||||
.clone(),
|
||||
);
|
||||
options
|
||||
.additional_watch_folders
|
||||
.extend(config.build.additional_watch_folders.clone());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -380,11 +337,10 @@ pub fn on_app_exit(code: Option<i32>, reason: ExitReason, exit_on_panic: bool, n
|
||||
pub fn kill_before_dev_process() {
|
||||
if let Some(child) = BEFORE_DEV.get() {
|
||||
let child = child.lock().unwrap();
|
||||
let kill_before_dev_flag = KILL_BEFORE_DEV_FLAG.get().unwrap();
|
||||
if kill_before_dev_flag.load(Ordering::Relaxed) {
|
||||
if KILL_BEFORE_DEV_FLAG.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
kill_before_dev_flag.store(true, Ordering::Relaxed);
|
||||
KILL_BEFORE_DEV_FLAG.store(true, Ordering::Relaxed);
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let powershell_path = std::env::var("SYSTEMROOT").map_or_else(
|
||||
|
||||
@@ -155,9 +155,9 @@ fn inject_address(html_bytes: Vec<u8>, address: &SocketAddr) -> Vec<u8> {
|
||||
}
|
||||
|
||||
fn fs_read_scoped(path: PathBuf, scope: &Path) -> crate::Result<Vec<u8>> {
|
||||
let path = dunce::canonicalize(&path).fs_context("failed to canonicalize path", path.clone())?;
|
||||
let path = dunce::canonicalize(&path).fs_context("failed to canonicalize path", path)?;
|
||||
if path.starts_with(scope) {
|
||||
std::fs::read(&path).fs_context("failed to read file", path.clone())
|
||||
std::fs::read(&path).fs_context("failed to read file", &path)
|
||||
} else {
|
||||
crate::error::bail!("forbidden path")
|
||||
}
|
||||
|
||||
@@ -23,6 +23,11 @@ const ENV_TAURI_APP_PATH: &str = "TAURI_APP_PATH";
|
||||
// path to the frontend app directory, usually `<project>/`
|
||||
const ENV_TAURI_FRONTEND_PATH: &str = "TAURI_FRONTEND_PATH";
|
||||
|
||||
pub struct Dirs {
|
||||
pub tauri: &'static Path,
|
||||
pub frontend: &'static Path,
|
||||
}
|
||||
|
||||
static FRONTEND_DIR: OnceLock<PathBuf> = OnceLock::new();
|
||||
static TAURI_DIR: OnceLock<PathBuf> = OnceLock::new();
|
||||
|
||||
@@ -75,21 +80,13 @@ fn lookup<F: Fn(&PathBuf) -> bool>(dir: &Path, checker: F) -> Option<PathBuf> {
|
||||
}
|
||||
|
||||
fn env_tauri_app_path() -> Option<PathBuf> {
|
||||
std::env::var(ENV_TAURI_APP_PATH)
|
||||
.map(PathBuf::from)
|
||||
.ok()?
|
||||
.canonicalize()
|
||||
.ok()
|
||||
.map(|p| dunce::simplified(&p).to_path_buf())
|
||||
let p = PathBuf::from(std::env::var_os(ENV_TAURI_APP_PATH)?);
|
||||
dunce::canonicalize(p).ok()
|
||||
}
|
||||
|
||||
fn env_tauri_frontend_path() -> Option<PathBuf> {
|
||||
std::env::var(ENV_TAURI_FRONTEND_PATH)
|
||||
.map(PathBuf::from)
|
||||
.ok()?
|
||||
.canonicalize()
|
||||
.ok()
|
||||
.map(|p| dunce::simplified(&p).to_path_buf())
|
||||
let p = PathBuf::from(std::env::var_os(ENV_TAURI_FRONTEND_PATH)?);
|
||||
dunce::canonicalize(p).ok()
|
||||
}
|
||||
|
||||
pub fn resolve_tauri_dir() -> Option<PathBuf> {
|
||||
@@ -130,8 +127,8 @@ pub fn resolve_tauri_dir() -> Option<PathBuf> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve() {
|
||||
TAURI_DIR.set(resolve_tauri_dir().unwrap_or_else(|| {
|
||||
pub fn resolve_dirs() -> Dirs {
|
||||
let tauri = TAURI_DIR.get_or_init(|| resolve_tauri_dir().unwrap_or_else(|| {
|
||||
let env_var_name = env_tauri_app_path().is_some().then(|| format!("`{ENV_TAURI_APP_PATH}`"));
|
||||
panic!("Couldn't recognize the {} folder as a Tauri project. It must contain a `{}`, `{}` or `{}` file in any subfolder.",
|
||||
env_var_name.as_deref().unwrap_or("current"),
|
||||
@@ -139,16 +136,11 @@ pub fn resolve() {
|
||||
ConfigFormat::Json5.into_file_name(),
|
||||
ConfigFormat::Toml.into_file_name()
|
||||
)
|
||||
})).expect("tauri dir already resolved");
|
||||
FRONTEND_DIR
|
||||
.set(resolve_frontend_dir().unwrap_or_else(|| tauri_dir().parent().unwrap().to_path_buf()))
|
||||
.expect("app dir already resolved");
|
||||
}
|
||||
|
||||
pub fn tauri_dir() -> &'static PathBuf {
|
||||
TAURI_DIR
|
||||
.get()
|
||||
.expect("app paths not initialized, this is a Tauri CLI bug")
|
||||
}));
|
||||
let frontend = FRONTEND_DIR.get_or_init(|| {
|
||||
resolve_frontend_dir().unwrap_or_else(|| tauri.parent().unwrap().to_path_buf())
|
||||
});
|
||||
Dirs { tauri, frontend }
|
||||
}
|
||||
|
||||
pub fn resolve_frontend_dir() -> Option<PathBuf> {
|
||||
@@ -173,9 +165,3 @@ pub fn resolve_frontend_dir() -> Option<PathBuf> {
|
||||
})
|
||||
.map(|p| p.parent().unwrap().to_path_buf())
|
||||
}
|
||||
|
||||
pub fn frontend_dir() -> &'static PathBuf {
|
||||
FRONTEND_DIR
|
||||
.get()
|
||||
.expect("app paths not initialized, this is a Tauri CLI bug")
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ pub fn cargo_manifest_and_lock(tauri_dir: &Path) -> (Option<CargoManifest>, Opti
|
||||
.ok()
|
||||
.and_then(|manifest_contents| toml::from_str(&manifest_contents).ok());
|
||||
|
||||
let lock: Option<CargoLock> = get_workspace_dir()
|
||||
let lock: Option<CargoLock> = get_workspace_dir(tauri_dir)
|
||||
.ok()
|
||||
.and_then(|p| fs::read_to_string(p.join("Cargo.lock")).ok())
|
||||
.and_then(|s| toml::from_str(&s).ok());
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user