fix: macOS nightly-release (#105)

* Add script to package libs

* Install gstreamer on macOS CI

* Add cargo packager to macOS

* Install cargo-packager on macos

* Update version env variable

* Move step order

* Update artifact path

* Add develop installer

* Use fallback path instead

* Move env variable to build steps instead

* Manually export instead

* Move dylib to framework instead

* Try ad-hoc codesign

* Try frameworks

* Test custom package script

* Update dmg version

* Add rpath in build script

* Add entitlements

* Cleanup

* Revert CI condition for packaging
This commit is contained in:
Ngo Iok Ui (Wu Yu Wei)
2024-08-05 12:30:17 +09:00
committed by GitHub
parent b25660f062
commit 2da3ed2c1b
5 changed files with 143 additions and 8 deletions

View File

@@ -127,6 +127,7 @@ jobs:
uses: dsherret/rust-toolchain-file@v1
- name: Install Rust toolchain for packager
if: ${{ github.event_name == 'schedule' }}
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
@@ -148,6 +149,7 @@ jobs:
uses: Mozilla-Actions/sccache-action@v0.0.4
- name: Install Cargo Packager
if: ${{ github.event_name == 'schedule' }}
run: cargo +stable install cargo-packager
- name: Build
@@ -196,6 +198,12 @@ jobs:
- name: Install Rust
uses: dsherret/rust-toolchain-file@v1
- name: Install Rust toolchain for packager
if: ${{ github.event_name == 'schedule' }}
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- name: Install Python
uses: actions/setup-python@v5
with:
@@ -203,30 +211,48 @@ jobs:
- name: Install dependencies
run: |
brew install cmake pkg-config
brew install cmake
python -m pip install mako
curl https://gstreamer.freedesktop.org/data/pkg/osx/1.24.6/gstreamer-1.0-1.24.6-universal.pkg -o runtime.pkg
sudo installer -pkg runtime.pkg -target /
curl https://gstreamer.freedesktop.org/data/pkg/osx/1.24.6/gstreamer-1.0-devel-1.24.6-universal.pkg -o develop.pkg
sudo installer -pkg develop.pkg -target /
- name: Run sccache-cache
uses: Mozilla-Actions/sccache-action@v0.0.4
- name: Install Cargo Packager
if: ${{ github.event_name == 'schedule' }}
run: cargo +stable install cargo-packager
- name: Build
run: |
export PATH="/Library/Frameworks/GStreamer.framework/Versions/1.0/bin${PATH:+:$PATH}"
export DYLD_LIBRARY_PATH="/Library/Frameworks/GStreamer.framework/Versions/1.0/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
cargo build --release
# - name: Test
# run: |
# cargo test --release
- name: Tar Binary
- name: Bundle
if: ${{ github.event_name == 'schedule' }}
run: tar -czvf verso-${{ matrix.platform.target }}.tar.gz -C ./target/release/ verso
run: |
export PATH="/Library/Frameworks/GStreamer.framework/Versions/1.0/bin${PATH:+:$PATH}"
export DYLD_LIBRARY_PATH="/Library/Frameworks/GStreamer.framework/Versions/1.0/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
cargo packager --release
- name: Fetch Verso version
if: ${{ github.event_name == 'schedule' }}
run: |
echo "VERSO_VERSION=$(cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | select(.name == "verso") | .version')" >> $GITHUB_ENV
- name: Upload artifact
if: ${{ github.event_name == 'schedule' }}
uses: actions/upload-artifact@v4
with:
name: verso-${{ matrix.platform.target }}
path: verso-${{ matrix.platform.target }}.tar.gz
name: verso_${{ env.VERSO_VERSION }}_${{ matrix.platform.arch }}
path: target/release/verso_${{ env.VERSO_VERSION }}_${{ matrix.platform.arch }}.dmg
build-result:
name: Build Result

View File

@@ -18,12 +18,13 @@ name = "verso"
product-name = "verso"
identifier = "org.versotile.verso"
version = "0.0.1"
before-each-package-command = "cargo build --release --features packager"
before-each-package-command = "python etc/package_libs.py"
resources = [
"resources",
"icons",
"target/release/build/**/libEGL.dll",
"target/release/build/**/libGLESv2.dll",
"target/release/lib",
]
icons = ["icons/icon256x256.png", "icons/icon.ico"]

View File

@@ -94,9 +94,11 @@ But please understand we don't triage any build issue without flatpak or nix set
Nightly releases built with CrabNebula Cloud can be found at [releases](https://web.crabnebula.cloud/verso/verso-nightly/releases).
> Packages are unsigned currently. If you have problem opening the app on macOS, try `xattr -d com.apple.quarantine /Applications/verso.app` after installation.
## Future Work
- Multiwindow support.
- Enable multiprocess mode.
- Enable sandobx in all platforms.
- Enable `Gstreamer` feature and remove `brew install harfbuzz` in README.
- Enable sandbox in all platforms.
- Enable `Gstreamer` feature.

View File

@@ -8,4 +8,7 @@ fn main() {
apple: { any(target_os = "ios", target_os = "macos") },
linux: { all(unix, not(apple), not(android)) },
}
#[cfg(all(feature = "packager", target_os = "macos"))]
println!("cargo:rustc-link-arg=-Wl,-rpath,@executable_path/../Resources/lib");
}

103
etc/package_libs.py Normal file
View File

@@ -0,0 +1,103 @@
import os
import os.path as path
import shutil
import subprocess
import sys
def otool(s):
o = subprocess.Popen(['/usr/bin/otool', '-L', s], stdout=subprocess.PIPE)
for line in map(lambda s: s.decode('ascii'), o.stdout):
if line[0] == '\t':
yield line.split(' ', 1)[0][1:]
def install_name_tool(binary, *args):
try:
subprocess.check_call(['install_name_tool', *args, binary])
except subprocess.CalledProcessError as e:
print("install_name_tool exited with return value %d" % e.returncode)
def change_link_name(binary, old, new):
install_name_tool(binary, '-change', old, f"@executable_path/{new}")
def is_system_library(lib):
return lib.startswith("/System/Library") or lib.startswith("/usr/lib") or ".asan." in lib
def is_relocatable_library(lib):
return lib.startswith("@rpath/")
def change_non_system_libraries_path(libraries, relative_path, binary):
for lib in libraries:
if is_system_library(lib) or is_relocatable_library(lib):
continue
new_path = path.join(relative_path, path.basename(lib))
change_link_name(binary, lib, new_path)
def resolve_rpath(lib, rpath_root):
if not is_relocatable_library(lib):
return lib
rpaths = ['', '../', 'gstreamer-1.0/']
for rpath in rpaths:
full_path = rpath_root + lib.replace('@rpath/', rpath)
if path.exists(full_path):
return path.normpath(full_path)
raise Exception("Unable to satisfy rpath dependency: " + lib)
def copy_dependencies(binary_path, lib_path, gst_lib_dir):
relative_path = path.relpath(lib_path, path.dirname(binary_path)) + "/"
# Update binary libraries
binary_dependencies = set(otool(binary_path))
change_non_system_libraries_path(binary_dependencies, relative_path, binary_path)
# Update dependencies libraries
need_checked = binary_dependencies
checked = set()
while need_checked:
checking = set(need_checked)
need_checked = set()
for f in checking:
# No need to check these for their dylibs
if is_system_library(f):
continue
full_path = resolve_rpath(f, gst_lib_dir)
need_relinked = set(otool(full_path))
new_path = path.join(lib_path, path.basename(full_path))
if not path.exists(new_path):
shutil.copyfile(full_path, new_path)
change_non_system_libraries_path(need_relinked, relative_path, new_path)
need_checked.update(need_relinked)
checked.update(checking)
need_checked.difference_update(checked)
def package_gstreamer_dylibs(bin):
gst_root = "/Library/Frameworks/GStreamer.framework/Versions/1.0"
lib_dir = path.join(path.dirname(bin), "lib")
if os.path.exists(lib_dir):
shutil.rmtree(lib_dir)
os.mkdir(lib_dir)
try:
copy_dependencies(bin, lib_dir, path.join(gst_root, 'lib', ''))
except Exception as e:
print("ERROR: could not package required dylibs")
print(e)
return False
return True
if __name__ == '__main__':
try:
subprocess.check_call(['cargo', 'build', '--release', '--features', 'packager'])
except subprocess.CalledProcessError as e:
print("cargo build exited with return value %d" % e.returncode)
if sys.platform == "darwin":
binary = "./target/release/verso"
package_gstreamer_dylibs(binary)