qt/bundle -> qt/launcher
- remove more of the old bundling code - handle app icon
|
@ -20,7 +20,6 @@
|
|||
"ftl/usage",
|
||||
"licenses.json",
|
||||
".dmypy.json",
|
||||
"qt/bundle/PyOxidizer",
|
||||
"target",
|
||||
".mypy_cache",
|
||||
"extra",
|
||||
|
|
|
@ -2,4 +2,3 @@
|
|||
py_version=39
|
||||
known_first_party=anki,aqt,tests
|
||||
profile=black
|
||||
extend_skip=qt/bundle
|
||||
|
|
|
@ -18,7 +18,7 @@ mypy_path =
|
|||
ftl,
|
||||
pylib/tools,
|
||||
python
|
||||
exclude = (qt/bundle/PyOxidizer|pylib/anki/_vendor)
|
||||
exclude = (pylib/anki/_vendor)
|
||||
|
||||
[mypy-anki.*]
|
||||
disallow_untyped_defs = True
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
target-version = "py39"
|
||||
extend-exclude = ["qt/bundle"]
|
||||
extend-exclude = []
|
||||
|
|
|
@ -31,8 +31,7 @@
|
|||
"rust-analyzer.rustfmt.extraArgs": ["+nightly"],
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
".bazel/**": true,
|
||||
"qt/bundle/PyOxidizer": true
|
||||
".bazel/**": true
|
||||
},
|
||||
"rust-analyzer.cargo.buildScripts.enable": true,
|
||||
"python.analysis.typeCheckingMode": "off",
|
||||
|
|
418
Cargo.lock
generated
|
@ -292,18 +292,6 @@ version = "1.0.98"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
|
||||
[[package]]
|
||||
name = "apple-bundles"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "716b8a7bacf7325eb3e7a1a7f5ead4da91e1e16d9b56a25edea0e1e4ba21fd8e"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"plist",
|
||||
"simple-file-manifest",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.4.1"
|
||||
|
@ -539,12 +527,6 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.7"
|
||||
|
@ -631,15 +613,6 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.12.0"
|
||||
|
@ -1002,15 +975,6 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cbc"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.20"
|
||||
|
@ -1073,16 +1037,6 @@ dependencies = [
|
|||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.37"
|
||||
|
@ -1839,15 +1793,6 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "des"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "difflib"
|
||||
version = "0.4.0"
|
||||
|
@ -1942,18 +1887,6 @@ dependencies = [
|
|||
"dtoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "duct"
|
||||
version = "0.13.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
"os_pipe",
|
||||
"shared_child",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.5"
|
||||
|
@ -2123,17 +2056,6 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-winsdk"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8cbf17b871570c1f8612b763bac3e86290602bcf5dc3c5ce657e0e1e9071d9e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"winreg 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.5.7"
|
||||
|
@ -2273,16 +2195,6 @@ dependencies = [
|
|||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fsevent-sys"
|
||||
version = "4.1.0"
|
||||
|
@ -3187,20 +3099,6 @@ dependencies = [
|
|||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"hyper 0.14.32",
|
||||
"rustls 0.21.12",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.5"
|
||||
|
@ -3211,13 +3109,13 @@ dependencies = [
|
|||
"http 1.3.1",
|
||||
"hyper 1.6.0",
|
||||
"hyper-util",
|
||||
"rustls 0.23.26",
|
||||
"rustls",
|
||||
"rustls-native-certs",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.2",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
"webpki-roots 0.26.8",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3505,16 +3403,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "intl-memoizer"
|
||||
version = "0.5.2"
|
||||
|
@ -3883,33 +3771,6 @@ dependencies = [
|
|||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "makeapp"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"apple-bundles",
|
||||
"camino",
|
||||
"clap",
|
||||
"glob",
|
||||
"plist",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simple-file-manifest",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "makeexe"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
"clap",
|
||||
"tugger-windows-codesign",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
|
@ -4623,39 +4484,12 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "p12"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4873306de53fe82e7e484df31e1e947d61514b6ea2ed6cd7b45d63006fd9224"
|
||||
dependencies = [
|
||||
"cbc",
|
||||
"cipher",
|
||||
"des",
|
||||
"getrandom 0.2.16",
|
||||
"hmac",
|
||||
"lazy_static",
|
||||
"rc2",
|
||||
"sha1",
|
||||
"yasna",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.2.1"
|
||||
|
@ -4720,15 +4554,6 @@ dependencies = [
|
|||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
|
@ -4923,19 +4748,6 @@ version = "0.3.32"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "plist"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d77244ce2d584cd84f6a15f86195b8c9b2a0dfbfd817c09e0464244091a58ed"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"indexmap",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.7"
|
||||
|
@ -5254,15 +5066,6 @@ dependencies = [
|
|||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.37.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.7"
|
||||
|
@ -5275,7 +5078,7 @@ dependencies = [
|
|||
"quinn-proto",
|
||||
"quinn-udp",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustls 0.23.26",
|
||||
"rustls",
|
||||
"socket2",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
|
@ -5292,9 +5095,9 @@ dependencies = [
|
|||
"bytes",
|
||||
"getrandom 0.3.2",
|
||||
"rand 0.9.1",
|
||||
"ring 0.17.14",
|
||||
"ring",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustls 0.23.26",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"slab",
|
||||
"thiserror 2.0.12",
|
||||
|
@ -5467,27 +5270,6 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rc2"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62c64daa8e9438b84aaae55010a93f396f8e60e3911590fcba770d04643fc1dd"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rcgen"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b"
|
||||
dependencies = [
|
||||
"pem",
|
||||
"ring 0.16.20",
|
||||
"time",
|
||||
"yasna",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reborrow"
|
||||
version = "0.5.5"
|
||||
|
@ -5596,7 +5378,6 @@ dependencies = [
|
|||
"http 0.2.12",
|
||||
"http-body 0.4.6",
|
||||
"hyper 0.14.32",
|
||||
"hyper-rustls 0.24.2",
|
||||
"hyper-tls 0.5.0",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
|
@ -5606,7 +5387,6 @@ dependencies = [
|
|||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls 0.21.12",
|
||||
"rustls-pemfile 1.0.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -5615,14 +5395,12 @@ dependencies = [
|
|||
"system-configuration",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls 0.24.1",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots 0.25.4",
|
||||
"winreg 0.50.0",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5640,7 +5418,7 @@ dependencies = [
|
|||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.6.0",
|
||||
"hyper-rustls 0.27.5",
|
||||
"hyper-rustls",
|
||||
"hyper-tls 0.6.0",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
|
@ -5653,7 +5431,7 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"quinn",
|
||||
"rustls 0.23.26",
|
||||
"rustls",
|
||||
"rustls-native-certs",
|
||||
"rustls-pemfile 2.2.0",
|
||||
"rustls-pki-types",
|
||||
|
@ -5663,7 +5441,7 @@ dependencies = [
|
|||
"sync_wrapper 1.0.2",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls 0.26.2",
|
||||
"tokio-rustls",
|
||||
"tokio-socks",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
|
@ -5673,25 +5451,10 @@ dependencies = [
|
|||
"wasm-bindgen-futures",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
"webpki-roots 0.26.8",
|
||||
"webpki-roots",
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"spin 0.5.2",
|
||||
"untrusted 0.7.1",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
|
@ -5702,7 +5465,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"getrandom 0.2.16",
|
||||
"libc",
|
||||
"untrusted 0.9.0",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
|
@ -5855,18 +5618,6 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring 0.17.14",
|
||||
"rustls-webpki 0.101.7",
|
||||
"sct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.26"
|
||||
|
@ -5874,9 +5625,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"ring 0.17.14",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki 0.103.1",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
@ -5920,25 +5671,15 @@ dependencies = [
|
|||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.101.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
|
||||
dependencies = [
|
||||
"ring 0.17.14",
|
||||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
|
||||
dependencies = [
|
||||
"ring 0.17.14",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted 0.9.0",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -6012,16 +5753,6 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
|
||||
dependencies = [
|
||||
"ring 0.17.14",
|
||||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
|
@ -6233,16 +5964,6 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shared_child"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
|
@ -6258,12 +5979,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple-file-manifest"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dd19be0257552dd56d1bb6946f89f193c6e5b9f13cc9327c4bc84a357507c74"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.11"
|
||||
|
@ -6337,12 +6052,6 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
|
@ -6824,23 +6533,13 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
|
||||
dependencies = [
|
||||
"rustls 0.21.12",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
|
||||
dependencies = [
|
||||
"rustls 0.23.26",
|
||||
"rustls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
|
@ -7038,58 +6737,6 @@ version = "0.2.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "tugger-common"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f90d950380afdb1a6bbe74f29485a04e821869dfad11f5929ff1c5b1dac09d02"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"fs2",
|
||||
"glob",
|
||||
"hex",
|
||||
"log",
|
||||
"once_cell",
|
||||
"reqwest 0.11.27",
|
||||
"sha2",
|
||||
"tempfile",
|
||||
"url",
|
||||
"zip 0.6.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tugger-windows"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9f181ac4fc7f8facfd418824d13045cd068ee73de44319a6116868c22789782"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"duct",
|
||||
"find-winsdk",
|
||||
"glob",
|
||||
"once_cell",
|
||||
"semver",
|
||||
"tugger-common",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tugger-windows-codesign"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed3f09f8bdace495373cec3fc607bc39f00720a984ba82e310cc9382462fd364"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"duct",
|
||||
"log",
|
||||
"p12",
|
||||
"rcgen",
|
||||
"time",
|
||||
"tugger-common",
|
||||
"tugger-windows",
|
||||
"yasna",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.21.0"
|
||||
|
@ -7290,12 +6937,6 @@ version = "0.2.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
|
@ -7566,12 +7207,6 @@ dependencies = [
|
|||
"string_cache_codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.25.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.8"
|
||||
|
@ -8233,16 +7868,6 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.50.0"
|
||||
|
@ -8346,15 +7971,6 @@ dependencies = [
|
|||
"lzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yasna"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
|
||||
dependencies = [
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.7.5"
|
||||
|
|
|
@ -12,9 +12,7 @@ members = [
|
|||
"build/runner",
|
||||
"ftl",
|
||||
"pylib/rsbridge",
|
||||
"qt/bundle/launcher",
|
||||
"qt/bundle/mac",
|
||||
"qt/bundle/win",
|
||||
"qt/launcher",
|
||||
"rslib",
|
||||
"rslib/i18n",
|
||||
"rslib/io",
|
||||
|
|
|
@ -371,11 +371,7 @@ fn build_wheel(build: &mut Build) -> Result<()> {
|
|||
}
|
||||
|
||||
fn check_python(build: &mut Build) -> Result<()> {
|
||||
python_format(
|
||||
build,
|
||||
"qt",
|
||||
inputs![glob!("qt/**/*.py", "qt/bundle/PyOxidizer/**")],
|
||||
)?;
|
||||
python_format(build, "qt", inputs![glob!("qt/**/*.py")])?;
|
||||
|
||||
build.add_action(
|
||||
"check:pytest:aqt",
|
||||
|
|
|
@ -1,445 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use std::env;
|
||||
|
||||
use anyhow::Result;
|
||||
use ninja_gen::action::BuildAction;
|
||||
use ninja_gen::archives::download_and_extract;
|
||||
use ninja_gen::archives::empty_manifest;
|
||||
use ninja_gen::archives::with_exe;
|
||||
use ninja_gen::archives::OnlineArchive;
|
||||
use ninja_gen::archives::Platform;
|
||||
use ninja_gen::build::BuildProfile;
|
||||
use ninja_gen::cargo::CargoBuild;
|
||||
use ninja_gen::cargo::RustOutput;
|
||||
use ninja_gen::git::SyncSubmodule;
|
||||
use ninja_gen::glob;
|
||||
use ninja_gen::input::BuildInput;
|
||||
use ninja_gen::inputs;
|
||||
use ninja_gen::python::PythonEnvironment;
|
||||
use ninja_gen::Build;
|
||||
use ninja_gen::Utf8Path;
|
||||
|
||||
use crate::anki_version;
|
||||
use crate::platform::overriden_python_target_platform;
|
||||
use crate::platform::overriden_rust_target_triple;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum DistKind {
|
||||
Standard,
|
||||
}
|
||||
|
||||
impl DistKind {
|
||||
fn folder_name(&self) -> &'static str {
|
||||
match self {
|
||||
DistKind::Standard => "std",
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
match self {
|
||||
DistKind::Standard => "standard",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_bundle(_build: &mut Build) -> Result<()> {
|
||||
// install into venv
|
||||
// setup_primary_venv(build)?;
|
||||
// install_anki_wheels(build)?;
|
||||
|
||||
// // bundle venv into output binary + extra_files
|
||||
// build_pyoxidizer(build)?;
|
||||
// build_artifacts(build)?;
|
||||
// build_binary(build)?;
|
||||
|
||||
// // package up outputs with Qt/other deps
|
||||
// download_dist_folder_deps(build)?;
|
||||
// build_dist_folder(build, DistKind::Standard)?;
|
||||
|
||||
// build_packages(build)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn targetting_macos_arm() -> bool {
|
||||
cfg!(all(target_os = "macos", target_arch = "aarch64"))
|
||||
&& overriden_python_target_platform().is_none()
|
||||
}
|
||||
|
||||
const WIN_AUDIO: OnlineArchive = OnlineArchive {
|
||||
url: "https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2022-02-09/audio-win-amd64.tar.gz",
|
||||
sha256: "0815a601baba05e03bc36b568cdc2332b1cf4aa17125fc33c69de125f8dd687f",
|
||||
};
|
||||
|
||||
const MAC_ARM_AUDIO: OnlineArchive = OnlineArchive {
|
||||
url: "https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2022-05-26/audio-mac-arm64.tar.gz",
|
||||
sha256: "f6c4af9be59ae1c82a16f5c6307f13cbf31b49ad7b69ce1cb6e0e7b403cfdb8f",
|
||||
};
|
||||
|
||||
const MAC_AMD_AUDIO: OnlineArchive = OnlineArchive {
|
||||
url: "https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2022-05-26/audio-mac-amd64.tar.gz",
|
||||
sha256: "ecbb3c878805cdd58b1a0b8e3fd8c753b8ce3ad36c8b5904a79111f9db29ff42",
|
||||
};
|
||||
|
||||
const MAC_ARM_QT6: OnlineArchive = OnlineArchive {
|
||||
url: "https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2024-02-29/pyqt6.6-mac-arm64.tar.zst",
|
||||
sha256: "9b2ade4ae9b80506689062845e83e8c60f7fa9843545bf7bb2d11d3e2f105878",
|
||||
};
|
||||
|
||||
const MAC_AMD_QT6: OnlineArchive = OnlineArchive {
|
||||
url: "https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2024-02-29/pyqt6.6-mac-amd64.tar.zst",
|
||||
sha256: "dbd0871e4da22820d1fa9ab29220d631467d1178038dcab4b15169ad7f499b1b",
|
||||
};
|
||||
|
||||
const LINUX_QT_PLUGINS: OnlineArchive = OnlineArchive {
|
||||
url: "https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2023-05-02/qt-plugins-linux-amd64.tar.gz",
|
||||
sha256: "66bb568aca7242bc55ad419bf5c96755ca15d2a743e1c3a09cba8b83230b138b",
|
||||
};
|
||||
|
||||
const NSIS_PLUGINS: OnlineArchive = OnlineArchive {
|
||||
url: "https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2023-05-19/nsis.tar.zst",
|
||||
sha256: "6133f730ece699de19714d0479c73bc848647d277e9cc80dda9b9ebe532b40a8",
|
||||
};
|
||||
|
||||
fn download_dist_folder_deps(build: &mut Build) -> Result<()> {
|
||||
let mut bundle_deps = vec![":wheels"];
|
||||
if cfg!(windows) {
|
||||
download_and_extract(build, "win_amd64_audio", WIN_AUDIO, empty_manifest())?;
|
||||
download_and_extract(build, "nsis_plugins", NSIS_PLUGINS, empty_manifest())?;
|
||||
bundle_deps.extend([":extract:win_amd64_audio", ":extract:nsis_plugins"]);
|
||||
} else if cfg!(target_os = "macos") {
|
||||
if targetting_macos_arm() {
|
||||
download_and_extract(build, "mac_arm_audio", MAC_ARM_AUDIO, empty_manifest())?;
|
||||
download_and_extract(build, "mac_arm_qt6", MAC_ARM_QT6, empty_manifest())?;
|
||||
bundle_deps.extend([":extract:mac_arm_audio", ":extract:mac_arm_qt6"]);
|
||||
} else {
|
||||
download_and_extract(build, "mac_amd_audio", MAC_AMD_AUDIO, empty_manifest())?;
|
||||
download_and_extract(build, "mac_amd_qt6", MAC_AMD_QT6, empty_manifest())?;
|
||||
bundle_deps.extend([":extract:mac_amd_audio", ":extract:mac_amd_qt6"]);
|
||||
}
|
||||
} else {
|
||||
download_and_extract(
|
||||
build,
|
||||
"linux_qt_plugins",
|
||||
LINUX_QT_PLUGINS,
|
||||
empty_manifest(),
|
||||
)?;
|
||||
bundle_deps.extend([":extract:linux_qt_plugins"]);
|
||||
}
|
||||
build.add_dependency(
|
||||
"bundle:deps",
|
||||
inputs![bundle_deps
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<_>>()],
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct Venv {
|
||||
label: &'static str,
|
||||
path_without_builddir: &'static str,
|
||||
}
|
||||
|
||||
impl Venv {
|
||||
fn label_as_target(&self, suffix: &str) -> String {
|
||||
format!(":{}{suffix}", self.label)
|
||||
}
|
||||
}
|
||||
|
||||
const PRIMARY_VENV: Venv = Venv {
|
||||
label: "bundle:pyenv",
|
||||
path_without_builddir: "bundle/pyenv",
|
||||
};
|
||||
|
||||
// fn setup_primary_venv(build: &mut Build) -> Result<()> {
|
||||
// let mut qt6_reqs = inputs![
|
||||
// "python/requirements.bundle.txt",
|
||||
// "python/requirements.qt6_6.txt",
|
||||
// ];
|
||||
// if cfg!(windows) {
|
||||
// qt6_reqs = inputs![qt6_reqs, "python/requirements.win.txt"];
|
||||
// }
|
||||
// build.add_action(
|
||||
// PRIMARY_VENV.label,
|
||||
// PythonEnvironment {
|
||||
// venv_folder: PRIMARY_VENV.path_without_builddir,
|
||||
// base_requirements_txt: "python/requirements.base.txt".into(),
|
||||
// requirements_txt: qt6_reqs,
|
||||
// extra_binary_exports: &[],
|
||||
// },
|
||||
// )?;
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
struct InstallAnkiWheels {
|
||||
venv: Venv,
|
||||
}
|
||||
|
||||
impl BuildAction for InstallAnkiWheels {
|
||||
fn command(&self) -> &str {
|
||||
"$pip install --force-reinstall --no-deps $in"
|
||||
}
|
||||
|
||||
fn files(&mut self, build: &mut impl ninja_gen::build::FilesHandle) {
|
||||
build.add_inputs("pip", inputs![self.venv.label_as_target(":pip")]);
|
||||
build.add_inputs("in", inputs![":wheels"]);
|
||||
build.add_output_stamp("bundle/wheels.stamp");
|
||||
}
|
||||
}
|
||||
|
||||
fn install_anki_wheels(build: &mut Build) -> Result<()> {
|
||||
build.add_action(
|
||||
"bundle:add_wheels:qt6",
|
||||
InstallAnkiWheels { venv: PRIMARY_VENV },
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_pyoxidizer(build: &mut Build) -> Result<()> {
|
||||
let offline_build = env::var("OFFLINE_BUILD").is_ok();
|
||||
|
||||
build.add_action(
|
||||
"bundle:pyoxidizer:repo",
|
||||
SyncSubmodule {
|
||||
path: "qt/bundle/PyOxidizer",
|
||||
offline_build,
|
||||
},
|
||||
)?;
|
||||
let target =
|
||||
overriden_rust_target_triple().unwrap_or_else(|| Platform::current().as_rust_triple());
|
||||
let output_bin = format!("bundle/rust/{target}/release/pyoxidizer",);
|
||||
build.add_action(
|
||||
"bundle:pyoxidizer:bin",
|
||||
CargoBuild {
|
||||
inputs: inputs![
|
||||
":bundle:pyoxidizer:repo",
|
||||
"out/env",
|
||||
glob!["qt/bundle/PyOxidizer/**"]
|
||||
],
|
||||
// can't use ::Binary() here, as we're in a separate workspace
|
||||
outputs: &[RustOutput::Data("bin", &with_exe(&output_bin))],
|
||||
target: Some(target),
|
||||
extra_args: &format!(
|
||||
"--manifest-path={} --target-dir={} -p pyoxidizer",
|
||||
"qt/bundle/PyOxidizer/Cargo.toml", "$builddir/bundle/rust"
|
||||
),
|
||||
release_override: Some(BuildProfile::Release),
|
||||
},
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct BuildArtifacts {}
|
||||
|
||||
impl BuildAction for BuildArtifacts {
|
||||
fn command(&self) -> &str {
|
||||
"$runner build-artifacts $bundle_root $pyoxidizer_bin"
|
||||
}
|
||||
|
||||
fn files(&mut self, build: &mut impl ninja_gen::build::FilesHandle) {
|
||||
build.add_inputs("pyoxidizer_bin", inputs![":bundle:pyoxidizer:bin"]);
|
||||
build.add_inputs("", inputs![PRIMARY_VENV.label_as_target("")]);
|
||||
build.add_inputs("", inputs![":bundle:add_wheels:qt6", glob!["qt/bundle/**"]]);
|
||||
build.add_variable("bundle_root", "$builddir/bundle");
|
||||
build.add_outputs_ext(
|
||||
"pyo3_config",
|
||||
vec!["bundle/artifacts/pyo3-build-config-file.txt"],
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
fn check_output_timestamps(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn build_artifacts(build: &mut Build) -> Result<()> {
|
||||
build.add_action("bundle:artifacts", BuildArtifacts {})
|
||||
}
|
||||
|
||||
struct BuildBundle {}
|
||||
|
||||
impl BuildAction for BuildBundle {
|
||||
fn command(&self) -> &str {
|
||||
"$runner build-bundle-binary"
|
||||
}
|
||||
|
||||
fn files(&mut self, build: &mut impl ninja_gen::build::FilesHandle) {
|
||||
build.add_inputs("", inputs![":bundle:artifacts", glob!["qt/bundle/**"]]);
|
||||
build.add_outputs(
|
||||
"",
|
||||
vec![RustOutput::Binary("anki").path(
|
||||
Utf8Path::new("$builddir/bundle/rust"),
|
||||
Some(
|
||||
overriden_rust_target_triple()
|
||||
.unwrap_or_else(|| Platform::current().as_rust_triple()),
|
||||
),
|
||||
// our pyoxidizer bin uses lto on the release profile
|
||||
BuildProfile::Release,
|
||||
)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_binary(build: &mut Build) -> Result<()> {
|
||||
build.add_action("bundle:binary", BuildBundle {})
|
||||
}
|
||||
|
||||
struct BuildDistFolder {
|
||||
kind: DistKind,
|
||||
deps: BuildInput,
|
||||
}
|
||||
|
||||
impl BuildAction for BuildDistFolder {
|
||||
fn command(&self) -> &str {
|
||||
"$runner build-dist-folder $kind $out_folder "
|
||||
}
|
||||
|
||||
fn files(&mut self, build: &mut impl ninja_gen::build::FilesHandle) {
|
||||
build.add_inputs("", &self.deps);
|
||||
build.add_variable("kind", self.kind.name());
|
||||
let folder = match self.kind {
|
||||
DistKind::Standard => "bundle/std",
|
||||
};
|
||||
build.add_outputs("out_folder", vec![folder]);
|
||||
build.add_outputs("stamp", vec![format!("{folder}.stamp")]);
|
||||
}
|
||||
|
||||
fn check_output_timestamps(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn build_dist_folder(build: &mut Build, kind: DistKind) -> Result<()> {
|
||||
let deps = inputs![":bundle:deps", ":bundle:binary", glob!["qt/bundle/**"]];
|
||||
let group = match kind {
|
||||
DistKind::Standard => "bundle:folder:std",
|
||||
};
|
||||
build.add_action(group, BuildDistFolder { kind, deps })
|
||||
}
|
||||
|
||||
fn build_packages(build: &mut Build) -> Result<()> {
|
||||
if cfg!(windows) {
|
||||
build_windows_installers(build)
|
||||
} else if cfg!(target_os = "macos") {
|
||||
build_mac_app(build, DistKind::Standard)?;
|
||||
build_dmgs(build)
|
||||
} else {
|
||||
build_tarball(build, DistKind::Standard)
|
||||
}
|
||||
}
|
||||
|
||||
struct BuildTarball {
|
||||
kind: DistKind,
|
||||
}
|
||||
|
||||
impl BuildAction for BuildTarball {
|
||||
fn command(&self) -> &str {
|
||||
"chmod -R a+r $folder && tar -I '$zstd' --transform $transform -cf $tarball -C $folder ."
|
||||
}
|
||||
|
||||
fn files(&mut self, build: &mut impl ninja_gen::build::FilesHandle) {
|
||||
let input_folder_name = self.kind.folder_name();
|
||||
let input_folder_target = format!(":bundle:folder:{input_folder_name}");
|
||||
let input_folder_path = format!("$builddir/bundle/{input_folder_name}");
|
||||
|
||||
let version = anki_version();
|
||||
let qt = match self.kind {
|
||||
DistKind::Standard => "qt6",
|
||||
};
|
||||
let output_folder_base = format!("anki-{version}-linux-{qt}");
|
||||
let output_tarball = format!("bundle/package/{output_folder_base}.tar.zst");
|
||||
|
||||
build.add_inputs("", inputs![input_folder_target]);
|
||||
build.add_variable("zstd", "zstd -c --long -T0 -18");
|
||||
build.add_variable("transform", format!("s%^.%{output_folder_base}%S"));
|
||||
build.add_variable("folder", input_folder_path);
|
||||
build.add_outputs("tarball", vec![output_tarball]);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_tarball(build: &mut Build, kind: DistKind) -> Result<()> {
|
||||
let name = kind.folder_name();
|
||||
build.add_action(format!("bundle:package:{name}"), BuildTarball { kind })
|
||||
}
|
||||
|
||||
struct BuildWindowsInstallers {}
|
||||
|
||||
impl BuildAction for BuildWindowsInstallers {
|
||||
fn command(&self) -> &str {
|
||||
"cargo run -p makeexe --target-dir=out/rust -- $version $src_root $bundle_root $out"
|
||||
}
|
||||
|
||||
fn files(&mut self, build: &mut impl ninja_gen::build::FilesHandle) {
|
||||
let version = anki_version();
|
||||
let outputs = ["qt6"].iter().map(|qt| {
|
||||
let output_base = format!("anki-{version}-windows-{qt}");
|
||||
format!("bundle/package/{output_base}.exe")
|
||||
});
|
||||
|
||||
build.add_inputs("", inputs![":bundle:folder:std"]);
|
||||
build.add_variable("version", &version);
|
||||
build.add_variable("bundle_root", "$builddir/bundle");
|
||||
build.add_outputs("out", outputs);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_windows_installers(build: &mut Build) -> Result<()> {
|
||||
build.add_action("bundle:package", BuildWindowsInstallers {})
|
||||
}
|
||||
|
||||
struct BuildMacApp {
|
||||
kind: DistKind,
|
||||
}
|
||||
|
||||
impl BuildAction for BuildMacApp {
|
||||
fn command(&self) -> &str {
|
||||
"cargo run -p makeapp --target-dir=out/rust -- build-app $version $kind $stamp"
|
||||
}
|
||||
|
||||
fn files(&mut self, build: &mut impl ninja_gen::build::FilesHandle) {
|
||||
let folder_name = self.kind.folder_name();
|
||||
build.add_inputs("", inputs![format!(":bundle:folder:{folder_name}")]);
|
||||
build.add_variable("version", anki_version());
|
||||
build.add_variable("kind", self.kind.name());
|
||||
build.add_outputs("stamp", vec![format!("bundle/app/{folder_name}.stamp")]);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_mac_app(build: &mut Build, kind: DistKind) -> Result<()> {
|
||||
build.add_action(format!("bundle:app:{}", kind.name()), BuildMacApp { kind })
|
||||
}
|
||||
|
||||
struct BuildDmgs {}
|
||||
|
||||
impl BuildAction for BuildDmgs {
|
||||
fn command(&self) -> &str {
|
||||
"cargo run -p makeapp --target-dir=out/rust -- build-dmgs $dmgs"
|
||||
}
|
||||
|
||||
fn files(&mut self, build: &mut impl ninja_gen::build::FilesHandle) {
|
||||
let version = anki_version();
|
||||
let platform = if targetting_macos_arm() {
|
||||
"apple"
|
||||
} else {
|
||||
"intel"
|
||||
};
|
||||
let qt = &["qt6"][..];
|
||||
let dmgs = qt
|
||||
.iter()
|
||||
.map(|qt| format!("bundle/dmg/anki-{version}-mac-{platform}-{qt}.dmg"));
|
||||
|
||||
build.add_inputs("", inputs![":bundle:app"]);
|
||||
build.add_outputs("dmgs", dmgs);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_dmgs(build: &mut Build) -> Result<()> {
|
||||
build.add_action("bundle:dmg", BuildDmgs {})
|
||||
}
|
60
build/configure/src/launcher.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use std::env;
|
||||
|
||||
use anyhow::Result;
|
||||
use ninja_gen::action::BuildAction;
|
||||
use ninja_gen::archives::download_and_extract;
|
||||
use ninja_gen::archives::empty_manifest;
|
||||
use ninja_gen::archives::with_exe;
|
||||
use ninja_gen::archives::OnlineArchive;
|
||||
use ninja_gen::archives::Platform;
|
||||
use ninja_gen::build::BuildProfile;
|
||||
use ninja_gen::cargo::CargoBuild;
|
||||
use ninja_gen::cargo::RustOutput;
|
||||
use ninja_gen::command::RunCommand;
|
||||
use ninja_gen::git::SyncSubmodule;
|
||||
use ninja_gen::glob;
|
||||
use ninja_gen::hashmap;
|
||||
use ninja_gen::input::BuildInput;
|
||||
use ninja_gen::inputs;
|
||||
use ninja_gen::python::PythonEnvironment;
|
||||
use ninja_gen::Build;
|
||||
use ninja_gen::Utf8Path;
|
||||
|
||||
use crate::anki_version;
|
||||
use crate::platform::overriden_python_target_platform;
|
||||
use crate::platform::overriden_rust_target_triple;
|
||||
|
||||
pub fn setup_uv_universal(build: &mut Build) -> Result<()> {
|
||||
build.add_action(
|
||||
"launcher:uv_universal",
|
||||
RunCommand {
|
||||
command: "/usr/bin/lipo",
|
||||
args: "-create -output $out $arm_bin $x86_bin",
|
||||
inputs: hashmap! {
|
||||
"arm_bin" => inputs![":extract:uv:bin"],
|
||||
"x86_bin" => inputs![":extract:uv_mac_x86:bin"],
|
||||
},
|
||||
outputs: hashmap! {
|
||||
"out" => vec!["launcher/uv"],
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn build_launcher(build: &mut Build) -> Result<()> {
|
||||
setup_uv_universal(build)?;
|
||||
download_and_extract(build, "nsis_plugins", NSIS_PLUGINS, empty_manifest())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
const NSIS_PLUGINS: OnlineArchive = OnlineArchive {
|
||||
url: "https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2023-05-19/nsis.tar.zst",
|
||||
sha256: "6133f730ece699de19714d0479c73bc848647d277e9cc80dda9b9ebe532b40a8",
|
||||
};
|
|
@ -2,7 +2,7 @@
|
|||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
mod aqt;
|
||||
mod bundle;
|
||||
mod launcher;
|
||||
mod platform;
|
||||
mod pylib;
|
||||
mod python;
|
||||
|
@ -13,13 +13,12 @@ use std::env;
|
|||
|
||||
use anyhow::Result;
|
||||
use aqt::build_and_check_aqt;
|
||||
use bundle::build_bundle;
|
||||
use launcher::build_launcher;
|
||||
use ninja_gen::glob;
|
||||
use ninja_gen::inputs;
|
||||
use ninja_gen::protobuf::check_proto;
|
||||
use ninja_gen::protobuf::setup_protoc;
|
||||
use ninja_gen::python::setup_uv;
|
||||
use ninja_gen::python::setup_uv_universal;
|
||||
use ninja_gen::Build;
|
||||
use platform::overriden_python_target_platform;
|
||||
use pylib::build_pylib;
|
||||
|
@ -62,8 +61,7 @@ fn main() -> Result<()> {
|
|||
build_and_check_aqt(build)?;
|
||||
|
||||
if env::var("OFFLINE_BUILD").is_err() {
|
||||
setup_uv_universal(build)?;
|
||||
build_bundle(build)?;
|
||||
build_launcher(build)?;
|
||||
}
|
||||
|
||||
setup_sphinx(build)?;
|
||||
|
|
|
@ -12,7 +12,6 @@ use crate::archives::download_and_extract;
|
|||
use crate::archives::with_exe;
|
||||
use crate::archives::OnlineArchive;
|
||||
use crate::archives::Platform;
|
||||
use crate::command::RunCommand;
|
||||
use crate::hash::simple_hash;
|
||||
use crate::input::BuildInput;
|
||||
use crate::inputs;
|
||||
|
@ -286,20 +285,3 @@ impl BuildAction for PythonTest {
|
|||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_uv_universal(build: &mut Build) -> Result<()> {
|
||||
build.add_action(
|
||||
"bundle:uv_universal",
|
||||
RunCommand {
|
||||
command: "/usr/bin/lipo",
|
||||
args: "-create -output $out $arm_bin $x86_bin",
|
||||
inputs: hashmap! {
|
||||
"arm_bin" => inputs![":extract:uv:bin"],
|
||||
"x86_bin" => inputs![":extract:uv_mac_x86:bin"],
|
||||
},
|
||||
outputs: hashmap! {
|
||||
"out" => vec!["bundle/uv"],
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::Args;
|
||||
|
||||
use crate::run::run_command;
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct BuildArtifactsArgs {
|
||||
bundle_root: Utf8PathBuf,
|
||||
pyoxidizer_bin: String,
|
||||
}
|
||||
|
||||
pub fn build_artifacts(args: BuildArtifactsArgs) {
|
||||
// build.rs doesn't declare inputs from venv, so we need to force a rebuild to
|
||||
// ensure changes to our libs/the venv get included
|
||||
let artifacts = args.bundle_root.join("artifacts");
|
||||
if artifacts.exists() {
|
||||
fs::remove_dir_all(&artifacts).unwrap();
|
||||
}
|
||||
let bundle_root = args.bundle_root.canonicalize_utf8().unwrap();
|
||||
let build_folder = bundle_root.join("build");
|
||||
if build_folder.exists() {
|
||||
fs::remove_dir_all(&build_folder).unwrap();
|
||||
}
|
||||
|
||||
run_command(
|
||||
Command::new(&args.pyoxidizer_bin)
|
||||
.args([
|
||||
"--system-rust",
|
||||
"run-build-script",
|
||||
"qt/bundle/build.rs",
|
||||
"--var",
|
||||
"venv",
|
||||
"out/bundle/pyenv",
|
||||
"--var",
|
||||
"build",
|
||||
build_folder.as_str(),
|
||||
])
|
||||
.env("CARGO_MANIFEST_DIR", "qt/bundle")
|
||||
.env("CARGO_TARGET_DIR", "out/bundle/rust")
|
||||
.env("PROFILE", "release")
|
||||
.env("OUT_DIR", &artifacts)
|
||||
.env("TARGET", env!("TARGET"))
|
||||
.env("SDKROOT", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
|
||||
.env("MACOSX_DEPLOYMENT_TARGET", macos_deployment_target())
|
||||
.env("CARGO_BUILD_TARGET", env!("TARGET")),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn macos_deployment_target() -> &'static str {
|
||||
if env!("TARGET") == "x86_64-apple-darwin" {
|
||||
"10.13.4"
|
||||
} else {
|
||||
"11"
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
use anki_process::CommandExt;
|
||||
use camino::Utf8Path;
|
||||
use camino::Utf8PathBuf;
|
||||
|
||||
use super::artifacts::macos_deployment_target;
|
||||
use crate::run::run_command;
|
||||
|
||||
pub fn build_bundle_binary() {
|
||||
let mut features = String::from("build-mode-prebuilt-artifacts");
|
||||
if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
|
||||
features.push_str(",global-allocator-jemalloc,allocator-jemalloc");
|
||||
}
|
||||
|
||||
let mut command = Command::new("cargo");
|
||||
command
|
||||
.args([
|
||||
"build",
|
||||
"--manifest-path=qt/bundle/Cargo.toml",
|
||||
"--target-dir=out/bundle/rust",
|
||||
"--release",
|
||||
"--no-default-features",
|
||||
])
|
||||
.arg(format!("--features={features}"))
|
||||
.env(
|
||||
"DEFAULT_PYTHON_CONFIG_RS",
|
||||
// included in main.rs, so relative to qt/bundle/src
|
||||
"../../../out/bundle/artifacts/",
|
||||
)
|
||||
.env(
|
||||
"PYO3_CONFIG_FILE",
|
||||
Utf8Path::new("out/bundle/artifacts/pyo3-build-config-file.txt")
|
||||
.canonicalize_utf8()
|
||||
.unwrap(),
|
||||
)
|
||||
.env("MACOSX_DEPLOYMENT_TARGET", macos_deployment_target())
|
||||
.env("SDKROOT", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
|
||||
.env("CARGO_BUILD_TARGET", env!("TARGET"));
|
||||
if env!("TARGET") == "x86_64-apple-darwin" {
|
||||
let xcode_path = Command::run_with_output(["xcode-select", "-p"]).unwrap();
|
||||
let ld_classic = Utf8PathBuf::from(xcode_path.stdout.trim())
|
||||
.join("Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-classic");
|
||||
if ld_classic.exists() {
|
||||
// work around XCode 15's default linker not supporting macOS 10.15-12.
|
||||
command.env("RUSTFLAGS", format!("-Clink-arg=-fuse-ld={ld_classic}"));
|
||||
}
|
||||
}
|
||||
run_command(&mut command);
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
|
||||
use camino::Utf8Path;
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::Args;
|
||||
use clap::ValueEnum;
|
||||
|
||||
use crate::paths::absolute_msys_path;
|
||||
use crate::paths::unix_path;
|
||||
use crate::run::run_command;
|
||||
|
||||
#[derive(Clone, Copy, ValueEnum, Debug)]
|
||||
enum DistKind {
|
||||
Standard,
|
||||
Alternate,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct BuildDistFolderArgs {
|
||||
kind: DistKind,
|
||||
folder_root: Utf8PathBuf,
|
||||
}
|
||||
|
||||
pub fn build_dist_folder(args: BuildDistFolderArgs) {
|
||||
let BuildDistFolderArgs { kind, folder_root } = args;
|
||||
fs::create_dir_all(&folder_root).unwrap();
|
||||
// Start with Qt, as it's the largest, and we use --delete to ensure there are
|
||||
// no stale files in lib/. Skipped on macOS as Qt is handled later.
|
||||
if !cfg!(target_os = "macos") {
|
||||
copy_qt_from_venv(kind, &folder_root);
|
||||
}
|
||||
clean_top_level_files(&folder_root);
|
||||
copy_binary_and_pylibs(&folder_root);
|
||||
if cfg!(target_os = "linux") {
|
||||
copy_linux_extras(kind, &folder_root);
|
||||
} else if cfg!(windows) {
|
||||
copy_windows_extras(&folder_root);
|
||||
}
|
||||
fs::write(folder_root.with_extension("stamp"), b"").unwrap();
|
||||
}
|
||||
|
||||
fn copy_qt_from_venv(kind: DistKind, folder_root: &Utf8Path) {
|
||||
let python39 = if cfg!(windows) { "" } else { "python3.9/" };
|
||||
let qt_root = match kind {
|
||||
DistKind::Standard => {
|
||||
folder_root.join(format!("../pyenv/lib/{python39}site-packages/PyQt6"))
|
||||
}
|
||||
DistKind::Alternate => {
|
||||
folder_root.join(format!("../pyenv-qt5/lib/{python39}site-packages/PyQt5"))
|
||||
}
|
||||
};
|
||||
let src_path = absolute_msys_path(&qt_root);
|
||||
let lib_path = folder_root.join("lib");
|
||||
fs::create_dir_all(&lib_path).unwrap();
|
||||
let dst_path = with_slash(absolute_msys_path(&lib_path));
|
||||
run_command(Command::new("rsync").args([
|
||||
"-a",
|
||||
"--delete",
|
||||
"--exclude-from",
|
||||
"qt/bundle/qt.exclude",
|
||||
&src_path,
|
||||
&dst_path,
|
||||
]));
|
||||
}
|
||||
|
||||
fn copy_linux_extras(kind: DistKind, folder_root: &Utf8Path) {
|
||||
// add README, installer, etc
|
||||
run_command(Command::new("rsync").args(["-a", "qt/bundle/lin/", &with_slash(folder_root)]));
|
||||
|
||||
// add extra IME plugins from download
|
||||
let lib_path = folder_root.join("lib");
|
||||
let src_path = folder_root
|
||||
.join("../../extracted/linux_qt_plugins")
|
||||
.join(match kind {
|
||||
DistKind::Standard => "qt6",
|
||||
DistKind::Alternate => "qt5",
|
||||
});
|
||||
let dst_path = lib_path.join(match kind {
|
||||
DistKind::Standard => "PyQt6/Qt6/plugins",
|
||||
DistKind::Alternate => "PyQt5/Qt5/plugins",
|
||||
});
|
||||
run_command(Command::new("rsync").args(["-a", &with_slash(src_path), &with_slash(dst_path)]));
|
||||
}
|
||||
|
||||
fn copy_windows_extras(folder_root: &Utf8Path) {
|
||||
run_command(Command::new("rsync").args([
|
||||
"-a",
|
||||
"out/extracted/win_amd64_audio/",
|
||||
&with_slash(folder_root),
|
||||
]));
|
||||
}
|
||||
|
||||
fn clean_top_level_files(folder_root: &Utf8Path) {
|
||||
let mut to_remove = vec![];
|
||||
for entry in fs::read_dir(folder_root).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
if entry.file_name() == "lib" {
|
||||
continue;
|
||||
} else {
|
||||
to_remove.push(entry.path());
|
||||
}
|
||||
}
|
||||
for path in to_remove {
|
||||
if path.is_dir() {
|
||||
fs::remove_dir_all(path).unwrap()
|
||||
} else {
|
||||
fs::remove_file(path).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn with_slash<P>(path: P) -> String
|
||||
where
|
||||
P: AsRef<str>,
|
||||
{
|
||||
format!("{}/", path.as_ref())
|
||||
}
|
||||
|
||||
fn copy_binary_and_pylibs(folder_root: &Utf8Path) {
|
||||
let binary = folder_root
|
||||
.join("../rust")
|
||||
.join(env!("TARGET"))
|
||||
.join("release")
|
||||
.join(if cfg!(windows) { "anki.exe" } else { "anki" });
|
||||
let extra_files = folder_root
|
||||
.join("../build")
|
||||
.join(env!("TARGET"))
|
||||
.join("release/resources/extra_files");
|
||||
run_command(Command::new("rsync").args([
|
||||
"-a",
|
||||
"--exclude",
|
||||
"PyQt6",
|
||||
// misleading, as it misses the GPL PyQt, and our Rust/JS
|
||||
// dependencies
|
||||
"--exclude",
|
||||
"COPYING.txt",
|
||||
&unix_path(&binary),
|
||||
&with_slash(unix_path(&extra_files)),
|
||||
&with_slash(unix_path(folder_root)),
|
||||
]));
|
||||
let google_py = if cfg!(windows) {
|
||||
folder_root.join("../pyenv/lib/site-packages/google")
|
||||
} else {
|
||||
folder_root.join("../pyenv/lib/python3.9/site-packages/google")
|
||||
};
|
||||
run_command(Command::new("rsync").args([
|
||||
"-a",
|
||||
&unix_path(&google_py),
|
||||
&with_slash(unix_path(&folder_root.join("lib"))),
|
||||
]));
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
pub mod artifacts;
|
||||
pub mod binary;
|
||||
pub mod folder;
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
mod archive;
|
||||
mod build;
|
||||
mod bundle;
|
||||
mod paths;
|
||||
mod pyenv;
|
||||
mod rsync;
|
||||
|
@ -19,11 +18,6 @@ use archive::archive_command;
|
|||
use archive::ArchiveArgs;
|
||||
use build::run_build;
|
||||
use build::BuildArgs;
|
||||
use bundle::artifacts::build_artifacts;
|
||||
use bundle::artifacts::BuildArtifactsArgs;
|
||||
use bundle::binary::build_bundle_binary;
|
||||
use bundle::folder::build_dist_folder;
|
||||
use bundle::folder::BuildDistFolderArgs;
|
||||
use clap::Parser;
|
||||
use clap::Subcommand;
|
||||
use pyenv::setup_pyenv;
|
||||
|
@ -48,9 +42,6 @@ enum Command {
|
|||
Rsync(RsyncArgs),
|
||||
Run(RunArgs),
|
||||
Build(BuildArgs),
|
||||
BuildArtifacts(BuildArtifactsArgs),
|
||||
BuildBundleBinary,
|
||||
BuildDistFolder(BuildDistFolderArgs),
|
||||
#[clap(subcommand)]
|
||||
Archive(ArchiveArgs),
|
||||
}
|
||||
|
@ -62,9 +53,6 @@ fn main() -> Result<()> {
|
|||
Command::Rsync(args) => rsync_files(args),
|
||||
Command::Yarn(args) => setup_yarn(args),
|
||||
Command::Build(args) => run_build(args),
|
||||
Command::BuildArtifacts(args) => build_artifacts(args),
|
||||
Command::BuildBundleBinary => build_bundle_binary(),
|
||||
Command::BuildDistFolder(args) => build_dist_folder(args),
|
||||
Command::Archive(args) => archive_command(args)?,
|
||||
};
|
||||
Ok(())
|
||||
|
|
|
@ -16,8 +16,3 @@ pub fn absolute_msys_path(path: &Utf8Path) -> String {
|
|||
// and \ -> /
|
||||
format!("/{drive}/{}", path[7..].replace('\\', "/"))
|
||||
}
|
||||
|
||||
/// Converts backslashes to forward slashes
|
||||
pub fn unix_path(path: &Utf8Path) -> String {
|
||||
path.as_str().replace('\\', "/")
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Define output path
|
||||
OUTPUT_DIR="../../out/bundle"
|
||||
APP_BUNDLE="$OUTPUT_DIR/Anki.app"
|
||||
|
||||
# Build rust binary in debug mode
|
||||
cargo build -p launcher
|
||||
(cd ../.. && ./ninja bundle:uv_universal)
|
||||
|
||||
# Ensure output directory exists
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
# Remove existing app bundle
|
||||
rm -rf "$APP_BUNDLE"
|
||||
|
||||
# Create app bundle structure
|
||||
mkdir -p "$APP_BUNDLE/Contents/MacOS" "$APP_BUNDLE/Contents/Resources"
|
||||
|
||||
# Copy binaries
|
||||
TARGET_DIR=${CARGO_TARGET_DIR:-target}
|
||||
cp $TARGET_DIR/debug/launcher "$APP_BUNDLE/Contents/MacOS/"
|
||||
cp "$OUTPUT_DIR/uv" "$APP_BUNDLE/Contents/MacOS/"
|
||||
|
||||
# Copy support files
|
||||
cp launcher/Info.plist "$APP_BUNDLE/Contents/"
|
||||
cp launcher/pyproject.toml "$APP_BUNDLE/Contents/Resources/"
|
||||
|
||||
# Codesign
|
||||
for i in "$APP_BUNDLE/Contents/MacOS/uv" "$APP_BUNDLE/Contents/MacOS/launcher" "$APP_BUNDLE"; do
|
||||
codesign --force -vvvv -o runtime -s "Developer ID Application:" \
|
||||
--entitlements $c/desktop/anki/qt/bundle/mac/entitlements.python.xml \
|
||||
"$i"
|
||||
done
|
||||
|
||||
# Check
|
||||
codesign -vvv "$APP_BUNDLE"
|
||||
spctl -a "$APP_BUNDLE"
|
||||
|
||||
# Mark as quarantined
|
||||
#xattr -w com.apple.quarantine "0181;$(date +%s);Safari;" "$APP_BUNDLE"
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
[package]
|
||||
name = "makeapp"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
publish = false
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
apple-bundles.workspace = true
|
||||
camino.workspace = true
|
||||
clap.workspace = true
|
||||
glob.workspace = true
|
||||
plist.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
simple-file-manifest.workspace = true
|
||||
walkdir.workspace = true
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::bail;
|
||||
use anyhow::Result;
|
||||
use camino::Utf8Path;
|
||||
use camino::Utf8PathBuf;
|
||||
|
||||
const CODESIGN_ARGS: &[&str] = &["-vvvv", "-o", "runtime", "-s", "Developer ID Application:"];
|
||||
|
||||
pub fn codesign_python_libs(bundle_dir: &Utf8PathBuf) -> Result<()> {
|
||||
for entry in glob::glob(bundle_dir.join("Contents/MacOS/lib/**/*.so").as_str())? {
|
||||
let entry = entry?;
|
||||
let entry = Utf8PathBuf::from_path_buf(entry).unwrap();
|
||||
codesign_file(&entry, &[])?;
|
||||
}
|
||||
codesign_file(&bundle_dir.join("Contents/MacOS/libankihelper.dylib"), &[])
|
||||
}
|
||||
|
||||
pub fn codesign_app(bundle_dir: &Utf8PathBuf) -> Result<()> {
|
||||
codesign_file(
|
||||
bundle_dir,
|
||||
&["--entitlements", "qt/bundle/mac/entitlements.python.xml"],
|
||||
)
|
||||
}
|
||||
|
||||
fn codesign_file(path: &Utf8Path, extra_args: &[&str]) -> Result<()> {
|
||||
if env::var("ANKI_CODESIGN").is_ok() {
|
||||
let status = Command::new("codesign")
|
||||
.args(CODESIGN_ARGS)
|
||||
.args(extra_args)
|
||||
.arg(path.as_str())
|
||||
.status()?;
|
||||
if !status.success() {
|
||||
bail!("codesign failed");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use camino::Utf8Path;
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::Args;
|
||||
|
||||
use crate::notarize::wait_then_staple_app;
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct BuildDmgsArgs {
|
||||
qt6_dmg: Utf8PathBuf,
|
||||
qt5_dmg: Option<Utf8PathBuf>,
|
||||
}
|
||||
|
||||
pub fn make_dmgs(args: BuildDmgsArgs) -> Result<()> {
|
||||
let root = Utf8Path::new("out/bundle/app");
|
||||
let mut variants = vec![("std", args.qt6_dmg)];
|
||||
if let Some(alt) = args.qt5_dmg {
|
||||
variants.push(("alt", alt));
|
||||
}
|
||||
|
||||
for (variant, dmg) in variants {
|
||||
let app = root.join(variant).join("Anki.app");
|
||||
if std::env::var("ANKI_CODESIGN").is_ok() {
|
||||
let uuid = fs::read_to_string(app.with_extension("uuid")).context("read uuid")?;
|
||||
wait_then_staple_app(&app, uuid)?;
|
||||
}
|
||||
|
||||
make_dmg(&app, &dmg)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_dmg(app_folder: &Utf8Path, dmg: &Utf8Path) -> Result<()> {
|
||||
assert!(
|
||||
Command::new("qt/bundle/mac/dmg/build.sh")
|
||||
.args([app_folder.parent().unwrap().as_str(), dmg.as_str()])
|
||||
.status()
|
||||
.context("dmg")?
|
||||
.success(),
|
||||
"dmg"
|
||||
);
|
||||
Ok(())
|
||||
}
|
|
@ -1,239 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
#![cfg(unix)]
|
||||
|
||||
//! Munge the output of PyOxidizer into a macOS app bundle, and combine it
|
||||
//! with our other runtime dependencies.
|
||||
|
||||
mod codesign;
|
||||
mod dmg;
|
||||
mod notarize;
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::os::unix::prelude::PermissionsExt;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::bail;
|
||||
use anyhow::Result;
|
||||
use apple_bundles::MacOsApplicationBundleBuilder;
|
||||
use camino::Utf8Path;
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::Parser;
|
||||
use clap::Subcommand;
|
||||
use clap::ValueEnum;
|
||||
use codesign::codesign_app;
|
||||
use codesign::codesign_python_libs;
|
||||
use dmg::make_dmgs;
|
||||
use dmg::BuildDmgsArgs;
|
||||
use notarize::notarize_app;
|
||||
use plist::Value;
|
||||
use simple_file_manifest::FileEntry;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
#[derive(Clone, ValueEnum)]
|
||||
enum DistKind {
|
||||
Standard,
|
||||
Alternate,
|
||||
}
|
||||
|
||||
impl DistKind {
|
||||
fn folder_name(&self) -> &'static str {
|
||||
match self {
|
||||
DistKind::Standard => "std",
|
||||
DistKind::Alternate => "alt",
|
||||
}
|
||||
}
|
||||
|
||||
fn input_folder(&self) -> Utf8PathBuf {
|
||||
Utf8Path::new("out/bundle").join(self.folder_name())
|
||||
}
|
||||
|
||||
fn output_folder(&self) -> Utf8PathBuf {
|
||||
Utf8Path::new("out/bundle/app")
|
||||
.join(self.folder_name())
|
||||
.join("Anki.app")
|
||||
}
|
||||
|
||||
fn macos_min(&self) -> &str {
|
||||
match self {
|
||||
DistKind::Standard => {
|
||||
if env::var("MAC_X86").is_ok() {
|
||||
"11"
|
||||
} else {
|
||||
"12"
|
||||
}
|
||||
}
|
||||
DistKind::Alternate => "10.13.4",
|
||||
}
|
||||
}
|
||||
|
||||
fn qt_repo(&self) -> &Utf8Path {
|
||||
Utf8Path::new(match self {
|
||||
DistKind::Standard => {
|
||||
if cfg!(target_arch = "aarch64") && env::var("MAC_X86").is_err() {
|
||||
"out/extracted/mac_arm_qt6"
|
||||
} else {
|
||||
"out/extracted/mac_amd_qt6"
|
||||
}
|
||||
}
|
||||
DistKind::Alternate => "out/extracted/mac_amd_qt5",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
BuildApp {
|
||||
version: String,
|
||||
kind: DistKind,
|
||||
stamp: Utf8PathBuf,
|
||||
},
|
||||
BuildDmgs(BuildDmgsArgs),
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
match Cli::parse().command {
|
||||
Commands::BuildApp {
|
||||
version,
|
||||
kind,
|
||||
stamp,
|
||||
} => {
|
||||
let plist = get_plist(&version);
|
||||
make_app(kind, plist, &stamp)
|
||||
}
|
||||
Commands::BuildDmgs(args) => make_dmgs(args),
|
||||
}
|
||||
}
|
||||
|
||||
fn make_app(kind: DistKind, mut plist: plist::Dictionary, stamp: &Utf8Path) -> Result<()> {
|
||||
let input_folder = kind.input_folder();
|
||||
let output_folder = kind.output_folder();
|
||||
let output_variant = output_folder.parent().unwrap();
|
||||
if output_variant.exists() {
|
||||
fs::remove_dir_all(output_variant)?;
|
||||
}
|
||||
fs::create_dir_all(&output_folder)?;
|
||||
|
||||
let mut builder = MacOsApplicationBundleBuilder::new("Anki")?;
|
||||
plist.insert(
|
||||
"LSMinimumSystemVersion".into(),
|
||||
Value::from(kind.macos_min()),
|
||||
);
|
||||
builder.set_info_plist_from_dictionary(plist)?;
|
||||
builder.add_file_resources("Assets.car", &include_bytes!("../icon/Assets.car")[..])?;
|
||||
|
||||
for entry in WalkDir::new(&input_folder)
|
||||
.into_iter()
|
||||
.map(Result::unwrap)
|
||||
.filter(|e| !e.file_type().is_dir())
|
||||
{
|
||||
let path = entry.path();
|
||||
let entry = FileEntry::try_from(path)?;
|
||||
let relative_path = path.strip_prefix(&input_folder)?;
|
||||
let path_str = relative_path.to_str().unwrap();
|
||||
if path_str.contains("libankihelper") {
|
||||
builder.add_file_macos("libankihelper.dylib", entry)?;
|
||||
} else if path_str.contains("aqt/data")
|
||||
|| path_str.contains("certifi")
|
||||
|| path_str.contains("google/protobuf")
|
||||
{
|
||||
builder.add_file_resources(relative_path.strip_prefix("lib").unwrap(), entry)?;
|
||||
} else {
|
||||
if path_str.contains("__pycache__") {
|
||||
continue;
|
||||
}
|
||||
builder.add_file_macos(relative_path, entry)?;
|
||||
}
|
||||
}
|
||||
|
||||
builder.files().materialize_files(&output_folder)?;
|
||||
fix_rpath(output_folder.join("Contents/MacOS/anki"))?;
|
||||
codesign_python_libs(&output_folder)?;
|
||||
copy_in_audio(&output_folder)?;
|
||||
copy_in_qt(&output_folder, kind)?;
|
||||
codesign_app(&output_folder)?;
|
||||
fixup_perms(&output_folder)?;
|
||||
notarize_app(&output_folder)?;
|
||||
fs::write(stamp, b"")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The bundle builder writes some files without world read/execute perms,
|
||||
/// which prevents them from being opened by a non-admin user.
|
||||
fn fixup_perms(dir: &Utf8Path) -> Result<()> {
|
||||
let status = Command::new("find")
|
||||
.arg(dir)
|
||||
.args(["-not", "-perm", "-a=r", "-exec", "chmod", "a+r", "{}", ";"])
|
||||
.status()?;
|
||||
if !status.success() {
|
||||
bail!("error setting perms");
|
||||
}
|
||||
fs::set_permissions(
|
||||
dir.join("Contents/MacOS/anki"),
|
||||
PermissionsExt::from_mode(0o755),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Copy everything at the provided path into the Contents/ folder of our app.
|
||||
fn extend_app_contents(source: &Utf8Path, target_dir: &Utf8Path) -> Result<()> {
|
||||
let status = Command::new("rsync")
|
||||
.arg("-a")
|
||||
.arg(format!("{}/", source.as_str()))
|
||||
.arg(target_dir)
|
||||
.status()?;
|
||||
if !status.success() {
|
||||
bail!("error syncing {source:?}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_in_audio(bundle_dir: &Utf8Path) -> Result<()> {
|
||||
println!("Copying in audio...");
|
||||
|
||||
let src_folder = Utf8Path::new(
|
||||
if cfg!(target_arch = "aarch64") && env::var("MAC_X86").is_err() {
|
||||
"out/extracted/mac_arm_audio"
|
||||
} else {
|
||||
"out/extracted/mac_amd_audio"
|
||||
},
|
||||
);
|
||||
extend_app_contents(src_folder, &bundle_dir.join("Contents/Resources"))
|
||||
}
|
||||
|
||||
fn copy_in_qt(bundle_dir: &Utf8Path, kind: DistKind) -> Result<()> {
|
||||
println!("Copying in Qt...");
|
||||
extend_app_contents(kind.qt_repo(), &bundle_dir.join("Contents"))
|
||||
}
|
||||
|
||||
fn fix_rpath(exe_path: Utf8PathBuf) -> Result<()> {
|
||||
let status = Command::new("install_name_tool")
|
||||
.arg("-add_rpath")
|
||||
.arg("@executable_path/../Frameworks")
|
||||
.arg(exe_path.as_str())
|
||||
.status()?;
|
||||
assert!(status.success());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_plist(anki_version: &str) -> plist::Dictionary {
|
||||
let reader = std::io::Cursor::new(include_bytes!("Info.plist"));
|
||||
let mut plist = Value::from_reader(reader)
|
||||
.unwrap()
|
||||
.into_dictionary()
|
||||
.unwrap();
|
||||
plist.insert(
|
||||
"CFBundleShortVersionString".into(),
|
||||
Value::from(anki_version),
|
||||
);
|
||||
plist
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::bail;
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use camino::Utf8Path;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct NotarySubmitOutput {
|
||||
id: String,
|
||||
}
|
||||
|
||||
pub fn notarize_app(output_folder: &Utf8Path) -> Result<()> {
|
||||
if env::var("ANKI_CODESIGN").is_err() {
|
||||
return Ok(());
|
||||
}
|
||||
if env::var("ANKI_NO_NOTARIZE").is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
let zip_file = output_folder.with_extension("zip");
|
||||
assert!(
|
||||
Command::new("ditto")
|
||||
.args([
|
||||
"-c",
|
||||
"-k",
|
||||
"--keepParent",
|
||||
output_folder.as_str(),
|
||||
zip_file.as_str(),
|
||||
])
|
||||
.status()
|
||||
.unwrap()
|
||||
.success(),
|
||||
"zip build"
|
||||
);
|
||||
let output = Command::new("xcrun")
|
||||
.args([
|
||||
"notarytool",
|
||||
"submit",
|
||||
zip_file.as_str(),
|
||||
"-f",
|
||||
"json",
|
||||
"-p",
|
||||
"default",
|
||||
])
|
||||
.output()
|
||||
.expect("notarytool");
|
||||
if !output.status.success() {
|
||||
panic!(
|
||||
"notarytool submit failed: {} {}",
|
||||
String::from_utf8_lossy(&output.stderr),
|
||||
String::from_utf8_lossy(&output.stdout)
|
||||
)
|
||||
}
|
||||
let output: NotarySubmitOutput = match serde_json::from_slice(&output.stdout) {
|
||||
Ok(out) => out,
|
||||
Err(err) => panic!(
|
||||
"unable to parse notary output: {err} {} {}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
),
|
||||
};
|
||||
let uuid_path = output_folder.with_extension("uuid");
|
||||
fs::write(uuid_path, output.id).expect("write uuid");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct NotaryWaitOutput {
|
||||
status: String,
|
||||
}
|
||||
|
||||
pub fn wait_then_staple_app(app: &Utf8Path, uuid: String) -> Result<()> {
|
||||
let output = Command::new("xcrun")
|
||||
.args(["notarytool", "wait", &uuid, "-p", "default", "-f", "json"])
|
||||
.output()
|
||||
.context("notary wait")?;
|
||||
let output: NotaryWaitOutput = serde_json::from_slice(&output.stdout)
|
||||
.with_context(|| String::from_utf8_lossy(&output.stderr).to_string())?;
|
||||
if output.status != "Accepted" {
|
||||
bail!("unexpected status: {}", output.status);
|
||||
}
|
||||
|
||||
assert!(
|
||||
Command::new("xcrun")
|
||||
.args(["stapler", "staple", app.as_str()])
|
||||
.status()
|
||||
.context("staple")?
|
||||
.success(),
|
||||
"staple"
|
||||
);
|
||||
|
||||
// clean up temporary files
|
||||
fs::remove_file(app.with_extension("zip")).context("app.zip")?;
|
||||
fs::remove_file(app.with_extension("uuid")).context("app.uuid")?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
[package]
|
||||
name = "makeexe"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
publish = false
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
camino.workspace = true
|
||||
clap.workspace = true
|
||||
tugger-windows-codesign.workspace = true
|
||||
walkdir.workspace = true
|
|
@ -1,153 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::fs;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::bail;
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use camino::Utf8Path;
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::Parser;
|
||||
use tugger_windows_codesign::CodeSigningCertificate;
|
||||
use tugger_windows_codesign::SigntoolSign;
|
||||
use tugger_windows_codesign::SystemStore;
|
||||
use tugger_windows_codesign::TimestampServer;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
version: String,
|
||||
bundle_root: Utf8PathBuf,
|
||||
qt6_setup_path: Utf8PathBuf,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
let src_win_folder = Utf8Path::new("qt/bundle/win");
|
||||
let std_dist_folder = args.bundle_root.join("std");
|
||||
// folder->installer
|
||||
let dists = [(&std_dist_folder, &args.qt6_setup_path)];
|
||||
|
||||
for (folder, _) in dists {
|
||||
fs::copy(
|
||||
src_win_folder.join("anki-console.bat"),
|
||||
folder.join("anki-console.bat"),
|
||||
)
|
||||
.context("anki-console")?;
|
||||
}
|
||||
|
||||
println!("--- Build uninstaller");
|
||||
build_installer(
|
||||
&args.bundle_root,
|
||||
&std_dist_folder,
|
||||
&args.qt6_setup_path,
|
||||
&args.version,
|
||||
true,
|
||||
)
|
||||
.context("uninstaller")?;
|
||||
|
||||
// sign the anki.exe and uninstaller.exe in std
|
||||
println!("--- Sign binaries");
|
||||
codesign([
|
||||
&std_dist_folder.join("anki.exe"),
|
||||
&std_dist_folder.join("uninstall.exe"),
|
||||
])?;
|
||||
|
||||
println!("--- Build manifest");
|
||||
for (folder, _) in dists {
|
||||
build_manifest(folder).context("manifest")?;
|
||||
}
|
||||
|
||||
for (folder, installer) in dists {
|
||||
println!("--- Build {}", installer);
|
||||
build_installer(&args.bundle_root, folder, installer, &args.version, false)?;
|
||||
}
|
||||
|
||||
println!("--- Sign installers");
|
||||
codesign(dists.iter().map(|tup| tup.1))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_installer(
|
||||
bundle_root: &Utf8Path,
|
||||
dist_folder: &Utf8Path,
|
||||
installer: &Utf8Path,
|
||||
version: &str,
|
||||
uninstaller: bool,
|
||||
) -> Result<()> {
|
||||
let rendered_nsi = include_str!("../anki.template.nsi")
|
||||
.replace("@@SRC@@", dist_folder.as_str())
|
||||
.replace("@@INSTALLER@@", installer.as_str())
|
||||
.replace("@@VERSION@@", version);
|
||||
let rendered_nsi_path = bundle_root.join("anki.nsi");
|
||||
fs::write(&rendered_nsi_path, rendered_nsi).context("anki.nsi")?;
|
||||
fs::write(
|
||||
bundle_root.join("fileassoc.nsh"),
|
||||
include_str!("../fileassoc.nsh"),
|
||||
)?;
|
||||
fs::copy(
|
||||
"out/extracted/nsis_plugins/nsProcess.dll",
|
||||
bundle_root.join("nsProcess.dll"),
|
||||
)?;
|
||||
let mut cmd = Command::new("c:/program files (x86)/nsis/makensis.exe");
|
||||
cmd.arg("-V3");
|
||||
if uninstaller {
|
||||
cmd.arg("-DWRITE_UNINSTALLER");
|
||||
};
|
||||
if option_env!("RELEASE").is_none() {
|
||||
cmd.arg("-DNO_COMPRESS");
|
||||
}
|
||||
cmd.arg(rendered_nsi_path);
|
||||
let status = cmd.status()?;
|
||||
if !status.success() {
|
||||
bail!("makensis failed");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn codesign(paths: impl IntoIterator<Item = impl AsRef<Path>>) -> Result<()> {
|
||||
if option_env!("ANKI_CODESIGN").is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
let cert = CodeSigningCertificate::Sha1Thumbprint(
|
||||
SystemStore::My,
|
||||
"dccfc6d312fc0432197bb7be951478e5866eebf8".into(),
|
||||
);
|
||||
let mut sign = SigntoolSign::new(cert);
|
||||
sign.file_digest_algorithm("sha256")
|
||||
.timestamp_server(TimestampServer::Rfc3161(
|
||||
"http://time.certum.pl".into(),
|
||||
"sha256".into(),
|
||||
))
|
||||
.verbose();
|
||||
paths.into_iter().for_each(|path| {
|
||||
sign.sign_file(path);
|
||||
});
|
||||
sign.run()
|
||||
}
|
||||
|
||||
fn build_manifest(base_path: &Utf8Path) -> Result<()> {
|
||||
let mut buf = vec![];
|
||||
for entry in WalkDir::new(base_path)
|
||||
.min_depth(1)
|
||||
.sort_by_file_name()
|
||||
.into_iter()
|
||||
{
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
let relative_path = path.strip_prefix(base_path)?;
|
||||
write!(
|
||||
&mut buf,
|
||||
"{}\r\n",
|
||||
relative_path.to_str().context("relative_path utf8")?
|
||||
)?;
|
||||
}
|
||||
fs::write(base_path.join("anki.install-manifest"), buf)?;
|
||||
Ok(())
|
||||
}
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
41
qt/launcher/mac/build.sh
Executable file
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Define output path
|
||||
OUTPUT_DIR="../../../out/launcher"
|
||||
APP_LAUNCHER="$OUTPUT_DIR/Anki.app"
|
||||
|
||||
# Build rust binary in debug mode
|
||||
cargo build -p launcher
|
||||
(cd ../../.. && ./ninja launcher:uv_universal)
|
||||
|
||||
# Ensure output directory exists
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
# Remove existing app launcher
|
||||
rm -rf "$APP_LAUNCHER"
|
||||
|
||||
# Create app launcher structure
|
||||
mkdir -p "$APP_LAUNCHER/Contents/MacOS" "$APP_LAUNCHER/Contents/Resources"
|
||||
|
||||
# Copy binaries
|
||||
TARGET_DIR=${CARGO_TARGET_DIR:-target}
|
||||
cp $TARGET_DIR/debug/launcher "$APP_LAUNCHER/Contents/MacOS/"
|
||||
cp "$OUTPUT_DIR/uv" "$APP_LAUNCHER/Contents/MacOS/"
|
||||
|
||||
# Copy support files
|
||||
cp Info.plist "$APP_LAUNCHER/Contents/"
|
||||
cp icon/Assets.car "$APP_LAUNCHER/Contents/Resources/"
|
||||
cp ../pyproject.toml "$APP_LAUNCHER/Contents/Resources/"
|
||||
|
||||
# Codesign
|
||||
for i in "$APP_LAUNCHER/Contents/MacOS/uv" "$APP_LAUNCHER/Contents/MacOS/launcher" "$APP_LAUNCHER"; do
|
||||
codesign --force -vvvv -o runtime -s "Developer ID Application:" \
|
||||
--entitlements entitlements.python.xml \
|
||||
"$i"
|
||||
done
|
||||
|
||||
# Check
|
||||
codesign -vvv "$APP_LAUNCHER"
|
||||
spctl -a "$APP_LAUNCHER"
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 362 B After Width: | Height: | Size: 362 B |
Before Width: | Height: | Size: 358 KiB After Width: | Height: | Size: 358 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
|
@ -29,8 +29,6 @@ const NONSTANDARD_HEADER: &[&str] = &[
|
|||
"./python/write_wheel.py",
|
||||
"./qt/aqt/mpv.py",
|
||||
"./qt/aqt/winpaths.py",
|
||||
"./qt/bundle/build.rs",
|
||||
"./qt/bundle/src/main.rs",
|
||||
];
|
||||
|
||||
const IGNORED_FOLDERS: &[&str] = &[
|
||||
|
@ -38,7 +36,6 @@ const IGNORED_FOLDERS: &[&str] = &[
|
|||
"./node_modules",
|
||||
"./qt/aqt/forms",
|
||||
"./tools/workspace-hack",
|
||||
"./qt/bundle/PyOxidizer",
|
||||
"./target",
|
||||
".mypy_cache",
|
||||
"./extra",
|
||||
|
|