[ENG-270, ENG-213] Stabilize release pipeline (#768)

* Attempt at building our own ffmpeg dylibs for macOS
 - Create dockerfile to setup osxcross and required host dependencies for cross-compiling ffmpeg for macOS
 - Create script to setup required macOS dependencies and build ffmpeg for both x86_64 and aarch64

* Improve dockerfile to better use docker's cache
 - Attempt at fixing arm64 build (still not there yet)

* ARM64 sucessfully compiles \o/
 - Use clang for everything (e.g. linker, assembler, ...)
 - Remove -lc++ because it is now handled internally thanks to a patch
 - Apply 3 open PRs to osxcross as external patches to solve some of our problems
 - PR 180 reduces the macports dependencies size by prefering non universal libs for x88
 - PR 314 adds the -lc++ flag for macOS SDKs >= 11.1
 - PR 379 fix macports pulling incorrects deps for SDK11 and adds support for SDK13 (future proofing, as it does nothing for us rigth now)

* Fix relink and copy logic in ffmpeg build script
 - Ensure ffmpeg and dependencies dylibs are correctly relinked and copied over to the output directory
 - Copy includes from ffmpeg and dependencies to allow for dev building against these dylibs
 - Set up symlinks for all dylibs to the common `lib` directory
 - Remove superfluous linker and compiler options
 - Add `-headerpad_max_install_names` linker option to accommodate the required relink changes
 - Remove `--disable-fft` for the arm64 build, as it doesn't seem to be required nowadays
 - Allow `swresample` and `avdevices` to be compiled as they seem to be expected to exist by `ffmpeg-sys-next`
 - Disable ffmpeg program compilation
 - Fix dylibs id to match their new expected location
 - Fix ffmpeg dylibs inter-linkage not being updated
 - Add custom patch for osxcross macports to load already downloaded files from cache
 - Remove the requirement for specifying the darwin version in the Dockerfile
 - Enable docker cache for macports
 - Move arm min macOS version ARG to the top

* Attempt at building ffmpeg with github actions
 - Split osxcross setup into it's own Dockerfile to allow exporting it as a image to Dockerhub
 - Create a github action to build ffmpeg
 - Add osxcross patch for PR 372 for future proofing (Add support for macOS SDK 13.1)

* Remove incompatible step name

* Change FFMPEG_VERSION to string to avoid yaml weird type casting

* Start to use our ffmpeg build in the macOS
 - Adjust the macOS setup script to download our ffmpeg build, also replace installing protobuf compiler from brew with grabbing it from it's own repository
 - Some misc improvement to the *nix setup script
 - Fix ffmpeg build script not copying static libs (for when we may want to statically link ffmpeg)
 - Fix ffmpeg build script not taking into acount possible libraries that are multiple paths deep in /lib
 - Update CI to actions/checkout@v3, v2 is deprecated
 - Update ffmpeg build CI to not xz the artifacts, as github already zips it anyway

* Fix macOS setup not finding the ffmpeg artifact due to a jq script mistake
 - Comment out embeeding static libs in ffmpeg artifact for now, as they take too much space
 - Remove incorrect dockerfile settings from editorconfig

* Fix protobuf download in macOS
 - Fix Framework directory creation not following script's dir but cwd
 - Improve download logic to avoid being rate limited on failures
 - Return to using xz for ffmpeg build, as it saves quite a bit of space

* Replace `OSTYPE` with `$(uname)` for a more standardized way to check which os is running
 - Fix mobile check using `==` instead of `=` in test command

* Fix syntax error in bash 3.x (which is the default in macOS)
 - Fix jq not downloading all deps and being placed in the incorrect directory

* Fix incorrect install_name_tool arguments
 - Remove leading './' when referencing ffmpeg libs during build

* Fix protoc not being executable
 - Fix some error messages

* jq throw input when it is invalid
 - Enable debug log in setup script when running in CI

* Add a dev.js build script for desktop app
 - Remove dll copy from setup-system.ps1, now done by dev.js
 - Minor rework to build.js to improve signals and stdio handling

* Configure cargo to use FFMPEG_DIR and PROTOC envvars on macOS

* Pass GITHUB_TOKEN to macOS setup script in CI

* Replace simple curl with gh_curl in github request

* Fix some ctrl+c/ctrl+v typos

* Add missing ffmpeg deps
 - Fix missing symlinks for ffmpeg libs in the output_dir/libs
 - Change arm64 minimum macOS target to 11.2 due to libbrotli only being available precompiled to this version
 - Add more options to ffmpeg configure in an attempt to reduce its size + improve performance

* Rework ffmpeg build script to create a FFMpeg.framework instead of loose dylibs
 - Disable unused postproc and enabled missing required protocols in ffmpeg configuration
 - Adjust Dockerfile and setup-script to handle the new FFMpeg.framework

* Fix setup script incorrect linking logic for FFMpeg.framework

* Forgot to remote the leading path in the lib/header linking logic for FFMpeg.framework

* Enable size optimization for ffmpeg
 - Remove Frameworks directory before setting it up in setup-system.sh

* Revert lib id to use `@executable_path/../Frameworks/` instead of `@rpath`
 - `@rpath` breaks dev builds
 - Add logic to create less versioned versions of dylibs in setup-system script, due to it being required for compiling ffmpeg-sys-next (not required during runtime, just for compilation)
 - Add scripts/deps to gitignore

* Fix ffmpeg build script not copying unversioned symlinks to FFMpeg.framework
 - Remove unecessary unversioned symlink logic from setup-system
 - Add new build scripts for dev and prod that setup the environment and tauri to correctly point to FFMpeg.framework
 - Rework windows setup-system script to follow the same logic as in macOS setup-system

* Attempt at fixing windows setup script
 - Add powershell editorconfig

* Attempt to fix Windows CI

* Fix some mistakes in the build scripts
 - Replace toml lib with something more used and maybe better?
 - Attempt to fix Windows CI

* Fix some more problems with the build script

* Another attempt at fixing windows CI

* Some more fixes for the windows setup script

* Add build.js step to release CI
 - Implement patch only mode for build.js when running under CI
 - Implement appeding extra env in cargo config in env.js
 - Only run windows dlls copy in dev in env.js
 - Another attempt at fixing windows CI

* Maybe this will make the windows CI happy?

* Windows CI why dont you work, whyyy?

* Try to apease the Windows CI Gods
 - Disable updater build in macOS, due to tauri-apps/tauri#3933

* Fix build.js extra env vars
 - Uncomment parts of setup-system.ps1 to check if it keeps working

* Uncomment another section and see if windows CI will complain

* uncomment some more of setup-system.ps1

* Use Start-Process for robocopy instead of executing it directly
 - Only raise an error if robocopy exists with a status code >=8
 - Revert build.js macOS specific bundles change
 - Disable updater for now

* Remove updater from cargo.toml

* Add -PassThru to Start-Process to ensure we get and Process obj back

* Comment out more of updater

* Improve documentation for both of the docker containers
 - Fix a harcoded install_name_tool call in the ffmpeg-build-macos.sh script

* Configure tauri to copy ffmpeg dlls to windows prod version
 - Fix windows dlls copy on dev
 - Stop replacing tauri.conf.json, except on CI, for prod builds and use a tauri.conf.patch.json for any required changes
 - Don't unset macOSPrivateApi on prod build, we need it for the transparent background
 - Fix dev.js not exiting when the spawned command was over

* Fix windows not find protoc
 - Fix missing import in env.js

* Fix Windows Dlls copy logic for prod build
 - Fix dev script failing due to missing env
 - Implement error handler to spawned process

* Format + Fix pnpm-lock

* Fix video thumb generation failing on Windows due to bad path to CString conversion logic

* Fix mobile build
 - Greatly improve windows setup-script error handling
 - Install LLVM with winget instead of downloading exe from github

* Improve CI a bit
 - Fix mobile CI not using github token to avoid being rate limited

* Fix pnpm not accesible to actions/setup-node

* Skip pnpm check on CI

* Fix pnpm skip not working
 - Fix pnpm cache check missing a step

* Only lock action to major versions

* CI really doesn't like running robocopy directly

* Attempt to build our own patched tauri bundler

* Trigger new workflow

* Fix attempt for patched tauri action tests
 - Disable cache for patched tauri action
 - Enable package publishing for patched tauri action

* Attempt fix patched tauri publish

* Remove commented code from patched tauri workflow
 - Replace deprecated `actions-rs/toolchain` with `dtolnay/rust-toolchain`

* Fix url patching logic for publishing step of patched tauri package

* Fix prepublishOnly command for patched tauri package

* Adjust patched tauri package package.json

* Also patch the specific os/arch sub packages

* Instruct napi to stop doing github releases

* Patch package.json befor build

* Re-enable updater
 - Patch tauri cli to workaround a tauri bug that prevented use from bundling frameworks in the updater
 - Update tauri/api to 1.3 and tauri/cli 1.3.1
 - Add target triple in the release artifacts name
 - Use ubuntu-20.04 instead of ubuntu-latest
 - Configure release workflow to build to all supported platforms
 - Replace `tauri-apps/tauri-action` with simply calling `pnpm desktop build`
 - Simplify tauri-patched-cli-js to only build the required macOS binaries
 - Unify build.js and dev.js in a tauri.js build script, which now acts as an all around wrapper for the tauri/cli

* Restore incorrectly removed step from `tauri-patched-cli-js`

* Disable auto-run of tauri-patched-cli-js
 - Update setup-system.sh with the latest tauri-patched-cli-js artifacts

* Forgot to mkdir bin

* Fix pnpm-lock.yaml not being up to date
 - Remove pnpm deps caching

* Fix variable name conflict

* Enable the updater build conditionally
 - Enable release workflow to test it

* Fix artifacts not being published
 - Change macOS on arm64 minimumSystemVersion to 11.2
 - Commented out rust cache to check if this is the culprit to the low memory problem on windows runner
 - Add some debug log to tauri.js

* Fix release workflow artifact uploading

* Specify which bundles to build on each platform
 - Attempt fix apple arm build
 - Don't include internal deb archives in linux updater artifact

* Attempt to fix apple arm build
 - Fix dmg background not applying

* Fix incorrect semver usage

* Patch swift-rs to see if that fix apple arm64 release build

* Update swift-rs submodule
 - Remove unused deps lodash.merge

* Configure so only release workflow runs without cache
 - Improve tauri.js logs

* Ignore `crates/swift-rs`

* Revert "Ignore `crates/swift-rs`"
- Remove `crates/swift-rs` before running `cargo fmt`

This reverts commit 851bd84373.

* Github CI input/output are always string
 - Attempt to fix Windows Clippy

* Fix CI syntax error

* Fix mobile CI
 - Disable pnpm deps caching
 - Disable rust targets caching on Windows
 - Configure cache factory to run for all targets

* Remove `crates/swift-rs`

* Attempt fix Mobile CI
 - Enable cache factory run in pull_request to test it
 - Specific more path for the CI run to ignore
 - Specify path that will trigger the cache factory run
 - Some cleanup in the setup-pnpm action

* Remove restore-cache options
 - Add prefix key to cache-factory
 - Fix LLVM cache-hit check
 - Add libheif to FFMpeg.framework

* Remove submodule clone from actions

* Add fake deps to ffmpeg build dockerfile
 - Fake install deps that aren't really necessary to build ffmpeg
 - Fail ffmpeg build script if it can't find a macports deps
 - Copy libheif headers to Framework

* Remove automatic trigger for relase and pull request trigger for cache-factory actions

* Remove pnpm setup from Cache factory
 - Cache factory is exclusivly for rust deps caching, no need to setup Node and pnpm with it

* Re-enabled fail-fast in Github CI
This commit is contained in:
Vítor Vasconcellos 2023-05-15 18:02:56 +00:00 committed by GitHub
parent 61e4088d8a
commit cf482f5621
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 2089 additions and 796 deletions

3
.cargo/README.md Normal file
View file

@ -0,0 +1,3 @@
## Attention
Make sure to execute the `setup-system` script after any modification to `cargo.toml`.

View file

@ -71,3 +71,14 @@ indent_style = space
# http://yaml.org/spec/1.2/2009-07-21/spec.html#id2576668
[*.{yaml,yml}]
indent_style = space
# Shell
# https://google.github.io/styleguide/shell.xml#Indentation
[*.{bash,sh,zsh}]
indent_style = space
# PowerShell
# https://poshcode.gitbook.io/powershell-practice-and-style/style-guide/code-layout-and-formatting
[*.{ps1,psd1,psm1}]
indent_size = 4
indent_style = space

View file

@ -1,15 +0,0 @@
name: Cache Rust Dependencies
description: Caches Rust dependencies
inputs:
save-cache:
description: Whether to save the Rust cache
required: false
default: 'false'
runs:
using: 'composite'
steps:
- name: Cache Rust Dependencies
uses: Swatinem/rust-cache@v2
with:
shared-key: rust-deps
save-if: ${{ inputs.save-cache }}

View file

@ -1,17 +0,0 @@
name: Generate Prisma client
description: Generates the Prisma client, using a cached value if one is available
runs:
using: 'composite'
steps:
- name: Cache Prisma codegen
id: cache-prisma
uses: actions/cache@v3
with:
path: ./core/src/prisma*.rs
key: prisma-0-${{ runner.os }}-${{ hashFiles('./core/prisma/*', './crates/sync-generator/*', './Cargo.toml') }}
- name: Generate Prisma client
working-directory: core
if: steps.cache-prisma.outputs.cache-hit != 'true'
shell: bash
run: cargo run -p prisma-cli --bin prisma -- generate

View file

@ -1,6 +1,8 @@
name: Publish artifacts
description: Publishes artifacts after CI process
inputs:
target:
description: target triples for built artifact
profile:
description: "'debug' or 'release'"
runs:
@ -12,57 +14,44 @@ runs:
export GITHUB_SHA_SHORT=$(git rev-parse --short "$GITHUB_SHA")
echo "GITHUB_SHA_SHORT=$GITHUB_SHA_SHORT" >> $GITHUB_ENV
- name: Set AppImage file permissions
if: matrix.platform == 'ubuntu-latest'
shell: bash
run: |
chmod +x target/${{ inputs.profile }}/bundle/appimage/spacedrive*.AppImage
- name: Publish artifacts (AppImage)
if: matrix.platform == 'ubuntu-latest'
- name: Publish artifacts (Linux - AppImage)
if: ${{ matrix.settings.host == 'ubuntu-20.04' }}
uses: actions/upload-artifact@v3
with:
name: Spacedrive-AppImage-${{ env.GITHUB_SHA_SHORT }}
path: target/${{ inputs.profile }}/bundle/appimage/*.AppImage
name: Spacedrive-AppImage-${{ inputs.target }}-${{ env.GITHUB_SHA_SHORT }}
path: target/${{ inputs.target }}/${{ inputs.profile }}/bundle/appimage/*.AppImage
if-no-files-found: error
- name: Publish artifacts (deb)
if: matrix.platform == 'ubuntu-latest'
- name: Publish artifacts (Debian - deb)
if: ${{ matrix.settings.host == 'ubuntu-20.04' }}
uses: actions/upload-artifact@v3
with:
name: Spacedrive-deb-${{ env.GITHUB_SHA_SHORT }}
path: target/${{ inputs.profile }}/bundle/deb/*.deb
name: Spacedrive-deb-${{ inputs.target }}-${{ env.GITHUB_SHA_SHORT }}
path: target/${{ inputs.target }}/${{ inputs.profile }}/bundle/deb/*.deb
if-no-files-found: error
# - name: Publish artifacts (server)
# if: matrix.platform == 'ubuntu-latest'
# uses: actions/upload-artifact@v3
# with:
# name: Spacedrive-server-${{ env.GITHUB_SHA_SHORT }}
# path: ./target/${{ inputs.profile }}/server
- name: Publish artifacts (Windows)
if: matrix.platform == 'windows-latest'
- name: Publish artifacts (Windows - msi)
if: ${{ matrix.settings.host == 'windows-latest' }}
uses: actions/upload-artifact@v3
with:
name: Spacedrive-Windows-${{ env.GITHUB_SHA_SHORT }}
path: target\${{ inputs.profile }}\bundle\msi\*.msi
name: Spacedrive-Windows-msi-${{ inputs.target }}-${{ env.GITHUB_SHA_SHORT }}
path: target/${{ inputs.target }}/${{ inputs.profile }}/bundle/msi/*.msi
if-no-files-found: error
- name: Set app file permissions
if: matrix.platform == 'macos-latest'
shell: bash
run: |
chmod +x target/${{ inputs.profile }}/bundle/macos/*.app/Contents/MacOS/Spacedrive
- name: Publish artifacts (macOS)
if: matrix.platform == 'macos-latest'
- name: Publish artifacts (macOS - dmg)
if: ${{ matrix.settings.host == 'macos-latest' }}
uses: actions/upload-artifact@v3
with:
name: Spacedrive-macOS-${{ env.GITHUB_SHA_SHORT }}
path: target/${{ inputs.profile }}/bundle/macos/*.app
name: Spacedrive-macOS-dmg-${{ inputs.target }}-${{ env.GITHUB_SHA_SHORT }}
path: target/${{ inputs.target }}/${{ inputs.profile }}/bundle/dmg/*.dmg
if-no-files-found: error
- name: Publish updater binaries
uses: actions/upload-artifact@v3
with:
name: Spacedrive-Updaters-${{ env.GITHUB_SHA_SHORT }}
name: Spacedrive-Updaters-${{ inputs.target }}-${{ env.GITHUB_SHA_SHORT }}
path: |
target/${{ inputs.profile }}/bundle/*/*.tar.gz*
target/${{ inputs.profile }}/bundle/*/*.zip*
target/${{ inputs.target }}/${{ inputs.profile }}/bundle/**/*.tar.gz*
target/${{ inputs.target }}/${{ inputs.profile }}/bundle/**/*.zip*
!target/**/deb/**/*.tar.gz
if-no-files-found: error

View file

@ -34,14 +34,14 @@ runs:
docker push $IMAGE_NAME:$IMAGE_TAG
- name: Tag & push image as latest staging image
if: github.event_name != 'release'
if: ${{ github.event_name != 'release' }}
shell: bash
run: |
docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:staging
docker push $IMAGE_NAME:staging
- name: Tag & push image as latest production image
if: github.event_name == 'release'
if: ${{ github.event_name == 'release' }}
shell: bash
run: |
docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:production

25
.github/actions/setup-pnpm/action.yml vendored Normal file
View file

@ -0,0 +1,25 @@
name: Setup Node.js, pnpm and dependencies
description: Setup Node.js, pnpm and dependencies
inputs:
token:
description: Github token
required: false
default: ''
runs:
using: 'composite'
steps:
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 8.x.x
- name: Install Node.js
uses: actions/setup-node@v3
with:
token: ${{ inputs.token }}
check-latest: true
node-version-file: '.nvmrc'
- name: Install pnpm deps
shell: ${{ runner.os == 'Windows' && 'powershell' || 'bash' }}
run: pnpm i --frozen-lockfile

51
.github/actions/setup-rust/action.yaml vendored Normal file
View file

@ -0,0 +1,51 @@
name: Setup Rust and Prisma
description: Setup Rust and Prisma
inputs:
targets:
description: Comma-separated list of target triples to install for this toolchain
required: false
save-cache:
description: Whether to save the Rust cache
required: false
default: 'false'
runs:
using: 'composite'
steps:
- name: Install Rust
id: toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ inputs.targets }}
toolchain: stable
components: clippy, rustfmt
- name: Cache Rust Dependencies
uses: Swatinem/rust-cache@v2
with:
key: ${{ inputs.targets }}
save-if: ${{ inputs.save-cache }}
prefix-key: "v0"
shared-key: rust-deps
# Windows is having disk related problems with target caching
cache-targets: ${{ runner.os != 'Windows' }}
- name: Restore cached Prisma codegen
id: cache-prisma-restore
uses: actions/cache/restore@v3
with:
key: prisma-0-${{ runner.os }}-${{ hashFiles('./core/prisma/*', './crates/sync-generator/*', './Cargo.toml') }}
path: ./core/src/prisma*.rs
- name: Generate Prisma client
working-directory: core
if: ${{ steps.cache-prisma-restore.outputs.cache-hit != 'true' }}
shell: bash
run: cargo run -p prisma-cli --bin prisma -- generate
- name: Save Prisma codegen
id: cache-prisma-save
if: ${{ inputs.save-cache == 'true' }}
uses: actions/cache/save@v3
with:
key: ${{ steps.cache-prisma-restore.outputs.cache-primary-key }}
path: ./core/src/prisma*.rs

64
.github/actions/setup-system/action.yml vendored Normal file
View file

@ -0,0 +1,64 @@
name: Setup System and Rust
description: Setup System and Rust
inputs:
token:
description: Github token
required: false
default: ''
targets:
description: Comma-separated list of target triples to install for this toolchain
required: false
setup-arg:
description: Argument for the system setup script
required: false
default: ''
save-cache:
description: Whether to save the System cache
required: false
default: 'false'
runs:
using: 'composite'
steps:
- name: Restore cached LLVM and Clang
if: ${{ runner.os == 'Windows' }}
id: cache-llvm-restore
uses: actions/cache/restore@v3
with:
key: llvm-15
path: C:/Program Files/LLVM
- name: Install LLVM and Clang
if: ${{ runner.os == 'Windows' }}
uses: KyleMayes/install-llvm-action@v1
with:
cached: ${{ steps.cache-llvm-restore.outputs.cache-hit }}
version: '15'
- name: Save LLVM and Clang
if: ${{ runner.os == 'Windows' && inputs.save-cache == 'true' }}
id: cache-llvm-save
uses: actions/cache/save@v3
with:
key: ${{ steps.cache-llvm-restore.outputs.cache-primary-key }}
path: C:/Program Files/LLVM
- name: Setup Rust and Dependencies
uses: ./.github/actions/setup-rust
with:
targets: ${{ inputs.targets }}
save-cache: ${{ inputs.save-cache }}
- name: Run 'setup-system.sh' script
shell: bash
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
run: ./.github/scripts/setup-system.sh ${{ inputs.setup-arg }}
env:
TARGET: ${{ inputs.targets }}
GITHUB_TOKEN: ${{ inputs.token }}
- name: Run 'setup-system.ps1' script
shell: powershell
if: ${{ runner.os == 'Windows' }}
run: ./.github/scripts/setup-system.ps1
env:
GITHUB_TOKEN: ${{ inputs.token }}

View file

@ -1,61 +0,0 @@
name: Setup
description: Sets up runner, Rust and pnpm
inputs:
token:
description: Github token
required: false
default: ''
save-cache:
description: Whether to save the Rust cache
required: false
default: 'false'
runs:
using: 'composite'
steps:
- name: Install Rust
id: toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
components: clippy, rustfmt
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 8.x.x
run_install: false
- name: Cache LLVM and Clang
if: runner.os == 'Windows'
id: cache-llvm
uses: actions/cache@v3
with:
path: C:/Program Files/LLVM
key: llvm-15
- name: Install LLVM and Clang
if: runner.os == 'Windows'
uses: KyleMayes/install-llvm-action@v1
with:
version: '15'
cached: ${{ steps.cache-llvm.outputs.cache-hit }}
- name: Cache Rust deps
uses: ./.github/actions/cache-rust-deps
with:
save-cache: ${{ inputs.save-cache }}
- name: Run 'setup-system.sh' script
shell: bash
if: runner.os == 'Linux' || runner.os == 'macOS'
run: ./.github/scripts/setup-system.sh
- name: Run 'setup-system.ps1' script
shell: powershell
if: runner.os == 'Windows'
run: ./.github/scripts/setup-system.ps1
env:
GITHUB_TOKEN: ${{ inputs.token }}
- name: Generate Prisma client
uses: ./.github/actions/generate-prisma-client

65
.github/scripts/ffmpeg-macos/Dockerfile vendored Normal file
View file

@ -0,0 +1,65 @@
ARG FAKE_DEPS="python311 perl5.34 gdk-pixbuf2 xorg-libsm xorg-libX11" \
FFMPEG_DEPS="aom bzip2 fontconfig freetype fribidi lame libgsm libheif libogg libopus libpng \
libtheora libvidstab libvorbis libvpx-devel lzo2 openjpeg rav1e soxr svt-av1 twolame webp x264 \
x265 XviD xz zimg zlib" \
FFMPEG_VERSION=6.0
FROM vvasconcellos/osxcross:12.3-50e86eb-1 as base
# Download ffmpeg
ARG FFMPEG_VERSION
ADD "https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz" ./
RUN tar -xf ffmpeg-${FFMPEG_VERSION}.tar.xz && rm ffmpeg-${FFMPEG_VERSION}.tar.xz
WORKDIR /srv/ffmpeg-${FFMPEG_VERSION}
COPY ./ffmpeg-build-macos.sh ./
# ---
FROM base as x86_64
# Fake Install macOS dependencies not required to build ffmpeg
ARG FAKE_DEPS
# hadolint ignore=SC2086
RUN osxcross-macports fake-install $FAKE_DEPS
# Install macOS dependencies required to build ffmpeg
ARG FFMPEG_DEPS
# hadolint ignore=SC2086
RUN --mount=type=cache,id=macports-x86_64,target=/opt/osxcross/macports/cache \
osxcross-macports install $FFMPEG_DEPS
# Build ffmpeg
RUN ./ffmpeg-build-macos.sh x86_64 "$MACOSX_SDK"
# ---
FROM base as aarch64
# https://ffmpeg.org/pipermail/ffmpeg-user/2016-January/030202.html
ADD https://raw.githubusercontent.com/yuvi/gas-preprocessor/master/gas-preprocessor.pl /usr/local/bin/
RUN chmod +x /usr/local/bin/gas-preprocessor.pl
# Update min macOS version for arm64
# libbrotli macports precompiled binaries are only available for macOS 11.2+
ENV OSX_VERSION_MIN="11.2" \
MACOSX_DEPLOYMENT_TARGET="11.2"
# Fake Install macOS dependencies not required to build ffmpeg
ARG FAKE_DEPS
# hadolint ignore=SC2086
RUN osxcross-macports fake-install --arm64 $FAKE_DEPS
# Install macOS dependencies required to build ffmpeg
ARG FFMPEG_DEPS
# hadolint ignore=SC2086
RUN --mount=type=cache,id=macports-arm64,target=/opt/osxcross/macports/cache \
osxcross-macports install --arm64 $FFMPEG_DEPS
# Build ffmpeg
RUN ./ffmpeg-build-macos.sh aarch64 "$MACOSX_SDK"
# ---
FROM scratch
COPY --from=x86_64 /FFMpeg.framework /ffmpeg/x86_64/FFMpeg.framework
COPY --from=aarch64 /FFMpeg.framework /ffmpeg/aarch64/FFMpeg.framework

25
.github/scripts/ffmpeg-macos/README.md vendored Normal file
View file

@ -0,0 +1,25 @@
# FFMpeg.framework
## Build instructions
To build `FFMpeg.framework` a `docker` or `podman` installation is required.
It is recomended to enable [`BuildKit`](https://docs.docker.com/build/buildkit/#getting-started) in docker.
Just run the following inside this directory:
```sh
$> docker build -o . .
```
or
```sh
$> podman build -o . .
```
After some time (it takes aroung 15min in Github CI) a directory named `ffmpeg` will show up with both a `x86_64` and `arm64` directory inside,
both will have a `FFMpeg.framework` for their respective architecture.
### How does the build process work?
The `FFMpeg.framework` is built inside an Alpine Linux container that contains a copy of [`osxcross`](https://github.com/tpoechtrager/osxcross), which is a cross toolchain that enables building native macOS binaries on Linux. Most of the build process is similar to how you would do it in macOS. The main advantage of using `osxcross` is that it handles the configuration for both `x86` and `arm64` and all the required compiling tools without the need for Xcode and with a more direct and easier managment of macOS SDKs. Any required macOS dependencies are handled by a MacPorts-compatible package manager.

View file

@ -0,0 +1,345 @@
#!/usr/bin/env bash
# This script builds ffmpeg for macOS using osxcross.
# This script is heavly influenced by:
# https://github.com/FFmpeg/FFmpeg/blob/ea3d24bbe3c58b171e55fe2151fc7ffaca3ab3d2/configure
# https://github.com/GerardSoleCa/macports-ports/blob/6f646dfaeb58ccb4a8b877df1ae4eecc4650fac7/multimedia/ffmpeg-upstream/Portfile
# https://github.com/arthenica/ffmpeg-kit/blob/47f85fa9ea3f8c34f3c817b87d8667b61b87d0bc/scripts/apple/ffmpeg.sh
# https://github.com/zimbatm/ffmpeg-static/blob/3206c0d74cd129c2ddfc3e928dcd3ea317d54857/build.sh
set -euox pipefail
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <target-arch> <macos-version>" >&2
exit 1
fi
if [ -z "$MACOSX_DEPLOYMENT_TARGET" ]; then
echo "You must set MACOSX_DEPLOYMENT_TARGET first." >&2
exit 1
fi
ARCH="$1"
MACOS_VERSION="$2"
set -- # Clear command line arguments
if [ "$ARCH" = "x86_64" ]; then
TARGET_CPU="x86_64"
TARGET_ARCH="x86_64"
set -- --enable-x86asm
elif [ "$ARCH" = "aarch64" ]; then
TARGET_CPU="armv8"
TARGET_ARCH="aarch64"
set -- --enable-neon --enable-asm
else
echo "Unsupported architecture: $ARCH" >&2
exit 1
fi
# Get darwin version and build compiler triple
DARWIN_VERSION="$(basename "$(realpath "$(command -v "oa64-clang")")" | awk -F- '{print $3}')"
TRIPLE="${ARCH}-apple-${DARWIN_VERSION}"
# Check macOS clang exists
if ! CC="$(command -v "${TRIPLE}-clang" 2>/dev/null)"; then
echo "${TRIPLE}-clang not found" >&2
exit 1
fi
export CC
# Get osxcross root directory
_osxcross_root="$(dirname "$(dirname "$CC")")"
# Check macports root exists
_macports_root="${_osxcross_root}/macports/pkgs/opt/local"
if ! [ -d "$_macports_root" ]; then
echo "macports root not found: $_macports_root" >&2
exit 1
fi
# Check SDK exists
_sdk="${_osxcross_root}/SDK/MacOSX${MACOS_VERSION}.sdk"
if ! [ -d "$_sdk" ]; then
echo "Invalid MacOS version: $MACOS_VERSION" >&2
exit 1
fi
# Gather all SDK libs
_skd_libs="$(
while IFS= read -r -d '' _lib; do
_lib="${_lib#"${_sdk}/usr/lib/"}"
_lib="${_lib%.*}"
printf '%s.dylib\n' "$_lib"
done < <(find "${_sdk}/usr/lib" \( -name '*.tbd' -o -name '*.dylib' \) -print0) \
| sort -u
)"
# Change cwd to the script directory (which should be ffmpeg source root)
CDPATH='' cd -- "$(dirname -- "$0")"
# Save FFmpeg version
FFMPEG_VERSION="$(xargs printf '%s' <VERSION)"
# Create a tmp TARGET_DIR
TARGET_DIR="$(mktemp -d -t ffmpeg-macos-XXXXXXXXXX)"
trap 'rm -rf "$TARGET_DIR"' EXIT
# Configure FFMpeg.
# NOTICE: This isn't autotools
# TODO: Metal suport is disabled because no open source toolchain is available for it
# TODO: Maybe try macOS own metal compiler under darling? https://github.com/darlinghq/darling/issues/326
./configure \
--nm="${TRIPLE}-nm" \
--ar="${TRIPLE}-ar" \
--as="$CC" \
--ld="$CC" \
--cc="$CC" \
--cxx="${TRIPLE}-clang++" \
--arch="${ARCH}" \
--objcc="$CC" \
--strip="${TRIPLE}-strip" \
--dep-cc="$CC" \
--sysroot="$_sdk" \
--cross-prefix="${TRIPLE}-" \
--ranlib="${TRIPLE}-ranlib" \
--prefix="${TARGET_DIR}" \
--arch="${TARGET_ARCH}" \
--cpu="${TARGET_CPU}" \
--target-os=darwin \
--pkg-config="${TRIPLE}-pkg-config" \
--pkg-config-flags="--static" \
--extra-ldflags="-Bstatic -headerpad_max_install_names" \
--extra-ldexeflags="-Bstatic" \
--extra-cxxflags="-xc++-header" \
--disable-alsa \
--disable-cuda \
--disable-cuvid \
--disable-debug \
--disable-doc \
--disable-htmlpages \
--disable-indevs \
--disable-libjack \
--disable-libopencore-amrnb \
--disable-libopencore-amrwb \
--disable-libpulse \
--disable-libxcb \
--disable-libxcb-shape \
--disable-libxcb-shm \
--disable-libxcb-xfixes \
--disable-manpages \
--disable-metal \
--disable-neon-clobber-test \
--disable-network \
--disable-nvdec \
--disable-nvenc \
--disable-openssl \
--disable-outdevs \
--disable-podpages \
--disable-postproc \
--disable-programs \
--disable-schannel \
--disable-sdl2 \
--disable-securetransport \
--disable-sndio \
--disable-static \
--disable-txtpages \
--disable-v4l2-m2m \
--disable-vaapi \
--disable-vdpau \
--disable-vulkan \
--disable-xlib \
--disable-xmm-clobber-test \
--enable-appkit \
--enable-audiotoolbox \
--enable-avcodec \
--enable-avfilter \
--enable-avformat \
--enable-avfoundation \
--enable-bzlib \
--enable-coreimage \
--enable-cross-compile \
--enable-fontconfig \
--enable-gpl \
--enable-iconv \
--enable-inline-asm \
--enable-libaom \
--enable-libfreetype \
--enable-libfribidi \
--enable-libgsm \
--enable-libmp3lame \
--enable-libopenjpeg \
--enable-libopus \
--enable-librav1e \
--enable-libsoxr \
--enable-libsvtav1 \
--enable-libtheora \
--enable-libtwolame \
--enable-libvorbis \
--enable-libvpx \
--enable-libwebp \
--enable-libx264 \
--enable-libx265 \
--enable-libxvid \
--enable-libzimg \
--enable-lto \
--enable-lzma \
--enable-opencl \
--enable-opengl \
--enable-optimizations \
--enable-pic \
--enable-postproc \
--enable-pthreads \
--enable-small \
--enable-shared \
--enable-swscale \
--enable-version3 \
--enable-videotoolbox \
--enable-zlib \
"$@"
make -j"$(nproc)" install
# Create FFMpeg.framework
# https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
# Create the framework basic directory structure
_framework="FFMpeg.framework"
mkdir -p "/${_framework}/Versions/A/"{Headers,Resources,Libraries}
# Copy licenses to Framework
_framework_docs="/${_framework}/Versions/A/Resources/English.lproj/Documentation"
mkdir -p "$_framework_docs"
# FFMpeg license
cp -avt "$_framework_docs" COPYING* LICENSE*
# Dependency licenses which are not covered by FFMpeg licenses
(cd "${_macports_root}/share/doc" \
&& cp -avt "$_framework_docs" --parents \
zimg/COPYING \
webp/COPYING \
libpng/LICENSE \
libvorbis/COPYING \
freetype/LICENSE.TXT \
fontconfig/COPYING)
# libvorbis, libogg and libtheora share the same license
ln -s libvorbis "${_framework_docs}/libogg"
ln -s libvorbis "${_framework_docs}/libtheora"
# Create required framework symlinks
ln -s A "/${_framework}/Versions/Current"
ln -s Versions/Current/Headers "/${_framework}/Headers"
ln -s Versions/Current/Resources "/${_framework}/Resources"
ln -s Versions/Current/Libraries "/${_framework}/Libraries"
# Framework Info.plist (based on macOS internal OpenGL.framework Info.plist)
cat <<EOF >"/${_framework}/Versions/Current/Resources/Info.plist"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>FFMpeg</string>
<key>CFBundleGetInfoString</key>
<string>FFMpeg ${FFMPEG_VERSION}</string>
<key>CFBundleIdentifier</key>
<string>com.spacedrive.ffmpeg</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>FFMpeg</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>${FFMPEG_VERSION}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${FFMPEG_VERSION}</string>
</dict>
</plist>
EOF
# Process FFMpeg libraries to be compatible with the Framework structure
cd "$TARGET_DIR/lib"
# Move all symlinks of ffmpeg libraries to Framework
while IFS= read -r -d '' _lib; do
# Copy symlinks to the output directory
cp -Ppv "$_lib" "/${_framework}/Libraries/${_lib#./}"
rm "$_lib"
done < <(find . -type l -print0)
# Populate queue with ffmpeg libraries
set -- # Clear command line arguments
while IFS= read -r -d '' _lib; do
set -- "$@" "${_lib#./}"
done < <(find . -name '*.dylib' -print0)
# Copy all symlinks of libheif libraries to Framework
while IFS= read -r -d '' _lib; do
# Copy symlinks to the output directory
cp -Ppv "$_lib" "/${_framework}/Libraries/${_lib#"${_macports_root}/lib/"}"
done < <(find "${_macports_root}/lib" -type l \( -name 'libheif.*' -a -name '*.dylib' \) -print0)
# Copy libheif to cwd and add it to queue
while IFS= read -r -d '' _lib; do
_lib_rel="${_lib#"${_macports_root}/lib/"}"
cp -Lpv "$_lib" "./${_lib_rel}"
set -- "$@" "${_lib_rel}"
done < <(find "${_macports_root}/lib" -type f \( -name 'libheif.*' -a -name '*.dylib' \) -print0)
while [ $# -gt 0 ]; do
# Loop through each of the library's dependencies
for _dep in $("${TRIPLE}-otool" -L "$1" | tail -n+2 | awk '{print $1}'); do
case "$_dep" in
# FFMpeg inter dependency
"${TARGET_DIR}/lib/"*)
_linker_path="@loader_path/${_dep#"${TARGET_DIR}/lib/"}"
;;
# Macports dependency (/opt/local/lib means it was installed by Macports)
/opt/local/lib/*)
_dep_rel="${_dep#/opt/local/lib/}"
# Check if the macports dependency is already included in the macOS SDK
if [ -n "$(comm -12 <(printf "%s" "$_dep_rel") <(printf "%s" "$_skd_libs"))" ]; then
# Relink libs already included in macOS SDK
_linker_path="/usr/lib/${_dep_rel}"
else
_linker_path="@loader_path/${_dep_rel}"
if ! [ -e "${_macports_root}/lib/${_dep_rel}" ]; then
echo "Missing macports dependency: ${_dep_rel}"
exit 1
elif ! { [ -f "$_dep_rel" ] || [ -e "/${_framework}/Libraries/${_dep_rel}" ]; }; then
# Copy dependency to the current directory if this is the first time we see it
cp -Lpv "${_macports_root}/lib/${_dep_rel}" "./${_dep_rel}"
# Add it to the queue to have it's own dependencies processed
set -- "$@" "$_dep_rel"
fi
fi
;;
*) # Ignore system libraries
continue
;;
esac
# Change the dependency linker path to make it compatible with an .app bundle
"${TRIPLE}-install_name_tool" -change "$_dep" "$_linker_path" "$1"
done
# Update the library's own id
"${TRIPLE}-install_name_tool" -id "@executable_path/../Frameworks/${_framework}/Libraries/${1}" "$1"
# Copy the library to framework
cp -Lpv "$1" "/${_framework}/Libraries/${1}"
# Remove library from queue
shift
done
# Copy all libheif headers to framework
cp -av "${_macports_root}/include/libheif" "/${_framework}/Headers/"
# Copy all FFMPEG headers to framework
cp -av "${TARGET_DIR}/include/"* "/${_framework}/Headers/"

51
.github/scripts/osxcross/180.diff vendored Normal file
View file

@ -0,0 +1,51 @@
diff --git a/tools/osxcross-macports b/tools/osxcross-macports
index f008a8d..725fac1 100755
--- a/tools/osxcross-macports
+++ b/tools/osxcross-macports
@@ -306,20 +306,34 @@ getPkgUrl()
verboseMsg " $p"
done
- local pkg=$(echo "$pkgs" | \
- grep "$pkgname-$pkgversion" | grep $OSXVERSION | grep $ARCH | \
- uniq | tail -n1)
- if [ -z "$pkg" ]; then
+ local allpkgs="$pkgs"
+ if [ $ARCH != "i386-x86_64" ]; then
+ pkgs=$(echo "$pkgs" | grep -v universal)
+ fi
+
+ while [ -z "$pkg" ] && [ -n "$pkgs" ]; do
pkg=$(echo "$pkgs" | \
- grep "$pkgname-$pkgversion" | grep $OSXVERSION | grep "noarch" | \
+ grep "$pkgname-$pkgversion" | grep $OSXVERSION | grep $ARCH | \
uniq | tail -n1)
- fi
- if [ -z "$pkg" ]; then
- pkg=$(echo "$pkgs" | grep $OSXVERSION | grep $ARCH | uniq | tail -n1)
- fi
- if [ -z "$pkg" ]; then
- pkg=$(echo "$pkgs" | grep $OSXVERSION | grep "noarch" | uniq | tail -n1)
- fi
+ if [ -z "$pkg" ]; then
+ pkg=$(echo "$pkgs" | \
+ grep "$pkgname-$pkgversion" | grep $OSXVERSION | grep "noarch" | \
+ uniq | tail -n1)
+ fi
+ if [ -z "$pkg" ]; then
+ pkg=$(echo "$pkgs" | grep $OSXVERSION | grep $ARCH | uniq | tail -n1)
+ fi
+ if [ -z "$pkg" ]; then
+ pkg=$(echo "$pkgs" | grep $OSXVERSION | grep "noarch" | uniq | tail -n1)
+ fi
+
+ if [ $ARCH != "i386-x86_64" ]; then
+ pkgs="$allpkgs"
+ allpkgs=""
+ else
+ pkgs=""
+ fi
+ done
verboseMsg " selected: $pkg"

41
.github/scripts/osxcross/181.diff vendored Normal file
View file

@ -0,0 +1,41 @@
diff --git a/tools/osxcross-macports b/tools/osxcross-macports
index f008a8d..23dd68d 100755
--- a/tools/osxcross-macports
+++ b/tools/osxcross-macports
@@ -181,7 +181,7 @@ selectMirror()
}
function download()
-{
+(
local uri=$1
local filename
@@ -191,6 +191,18 @@ function download()
filename=$(basename $1)
fi
+ # Remove file if any error occurs during download
+ trap 'rm -f "$filename"' ERR
+
+ # Return if file already exists in cache
+ case "$filename" in
+ "$CACHE"*)
+ if [ -e "$filename" ]; then
+ return
+ fi
+ ;;
+ esac
+
if command -v curl &>/dev/null; then
## cURL ##
local curl_opts="-L -C - "
@@ -220,7 +232,7 @@ function download()
echo "Required dependency 'curl or wget' not installed" 1>&2
exit 1
fi
-}
+)
getFileStdout()
{

15
.github/scripts/osxcross/314.diff vendored Normal file
View file

@ -0,0 +1,15 @@
diff --git a/wrapper/target.cpp b/wrapper/target.cpp
index 82bf65c40..a81ce97b7 100644
--- a/wrapper/target.cpp
+++ b/wrapper/target.cpp
@@ -741,6 +741,10 @@ bool Target::setup() {
(stdlib == StdLib::libstdcxx && usegcclibs)) {
fargs.push_back("-nostdinc++");
fargs.push_back("-Qunused-arguments");
+
+ if ((SDKOSNum >= OSVersion(11, 1)) && (stdlib == StdLib::libcxx)) {
+ fargs.push_back("-lc++");
+ }
}
if (stdlib == StdLib::libstdcxx && usegcclibs && targetarch.size() < 2 &&

11
.github/scripts/osxcross/372.diff vendored Normal file
View file

@ -0,0 +1,11 @@
diff --git a/build.sh b/build.sh
index eeab219ac..14b9137b5 100755
--- a/build.sh
+++ b/build.sh
@@ -50,6 +50,7 @@ case $SDK_VERSION in
12.3*) TARGET=darwin21.4; X86_64H_SUPPORTED=1; I386_SUPPORTED=0; ARM_SUPPORTED=1; NEED_TAPI_SUPPORT=1; OSX_VERSION_MIN_INT=10.9; ;;
12.4*) TARGET=darwin21.5; X86_64H_SUPPORTED=1; I386_SUPPORTED=0; ARM_SUPPORTED=1; NEED_TAPI_SUPPORT=1; OSX_VERSION_MIN_INT=10.9; ;;
13.0*) TARGET=darwin22; X86_64H_SUPPORTED=1; I386_SUPPORTED=0; ARM_SUPPORTED=1; NEED_TAPI_SUPPORT=1; OSX_VERSION_MIN_INT=10.9; ;;
+ 13.1*) TARGET=darwin22.2; X86_64H_SUPPORTED=1; I386_SUPPORTED=0; ARM_SUPPORTED=1; NEED_TAPI_SUPPORT=1; OSX_VERSION_MIN_INT=10.9; ;;
*) echo "Unsupported SDK"; exit 1 ;;
esac

15
.github/scripts/osxcross/379.diff vendored Normal file
View file

@ -0,0 +1,15 @@
diff --git a/tools/osxcross-macports b/tools/osxcross-macports
index f008a8da7..3e87735b8 100755
--- a/tools/osxcross-macports
+++ b/tools/osxcross-macports
@@ -81,8 +81,9 @@ case $MACOSX_DEPLOYMENT_TARGET in
10.14* ) OSXVERSION="darwin_18" ;;
10.15* ) OSXVERSION="darwin_19" ;;
10.16* ) OSXVERSION="darwin_20" ;;
- 11.* ) OSXVERSION="darwin_21" ;;
+ 11.* ) OSXVERSION="darwin_20" ;;
12.* ) OSXVERSION="darwin_21" ;;
+ 13.* ) OSXVERSION="darwin_22" ;;
* ) unsupportedDepTarget ;;
esac

67
.github/scripts/osxcross/Dockerfile vendored Normal file
View file

@ -0,0 +1,67 @@
ARG MACOS_VERSION=12.3 \
MACOS_MIN_VERSION=10.15 \
# aarch64 requires a higher min macOS version to build ffmpeg
ARM64_MACOS_MIN_VERSION=11.0
FROM alpine:3.17 as base
WORKDIR /srv
# Host dependencies, required to build osxcross, gcc for macOS and ffmpeg. ~1GiB
# hadolint ignore=DL3018
RUN --mount=type=cache,target=/var/cache/apk ln -vs /var/cache/apk /etc/apk/cache && apk add --update \
bash bsd-compat-headers build-base bzip2-dev clang15 cmake curl git gmp-dev libc++-dev libc-dev libuuid libxml2-dev \
llvm15-dev llvm15-static mpc1-dev mpfr-dev musl-fts-dev openssl openssl-dev perl python3 xz yasm zlib-dev
# Download osxcross, use a specific commit to avoid breaking changes and allow docker to cache it
ADD https://github.com/tpoechtrager/osxcross/archive/50e86eb.zip /srv/osxcross.zip
RUN unzip osxcross.zip && mv osxcross-* osxcross && rm osxcross.zip
WORKDIR /srv/osxcross/tarballs
# Download MacOS SDK
ARG MACOS_VERSION
ENV MACOSX_SDK="$MACOS_VERSION"
ADD "https://github.com/joseluisq/macosx-sdks/releases/download/${MACOS_VERSION}/MacOSX${MACOS_VERSION}.sdk.tar.xz" ./
# Setupt osxcross environment variables
ARG MACOS_MIN_VERSION ARM64_MACOS_MIN_VERSION
ENV PATH="$PATH:/opt/osxcross/bin" \
UNATTENDED=yes \
OSXCROSS_MP_INC=1 \
OSX_VERSION_MIN="$MACOS_MIN_VERSION" \
MACOSX_DEPLOYMENT_TARGET="$MACOS_MIN_VERSION" \
MACOSX_ARM64_DEPLOYMENT_TARGET="$ARM64_MACOS_MIN_VERSION"
WORKDIR /srv/osxcross
# Some important patches from unmerged PRs
# PR 180 code needed to be updated to work with the latest osxcross
# 181 is not related to the 181 PR. It's just custom code that needed to be patched after 180 and before 379
COPY 180.diff 181.diff 314.diff 372.diff 379.diff ./
RUN set -eux; for patch in *.diff; do patch -p1 < "$patch"; done
# Build osxcross
RUN set -eux; export TARGET_DIR=/opt/osxcross \
&& \
./build.sh \
&& \
./build_compiler_rt.sh \
&& \
# Ugly workaround for linker not finding the macOS SDK's Framework directory
ln -fs "${TARGET_DIR}/SDK/MacOSX${MACOS_VERSION}.sdk/System" '/System' \
&& \
./cleanup.sh
WORKDIR /srv
# Setup macports
RUN osxcross-macports --help
LABEL org.opencontainers.image.title="alpine-osxcross" \
# Version is macOS SDK version + osxcross commit hash
org.opencontainers.image.version="12.3-50e86eb" \
org.opencontainers.image.authors="Vítor Vasconcellos <vasconcellos.dev@gmail.com>, Spacedrive <support@spacedrive.com>" \
org.opencontainers.image.revision="1" \
org.opencontainers.image.licenses="GPL-2.0" \
org.opencontainers.image.description="macOS cross toolchain configured inside Alpine Linux"

5
.github/scripts/osxcross/README.md vendored Normal file
View file

@ -0,0 +1,5 @@
# OSXCross container
This container is currently available at https://hub.docker.com/r/vvasconcellos/osxcross.
It is based on alpine 3.17, with the most commom build depencies installed, and a built version of [`osxcross`](https://github.com/tpoechtrager/osxcross) plus the macOS SDK 12.3 (Monterey) targetting a minimum compatibility of macOS 10.15 (Catalina) for x86_64 and macOS 11.0 (BigSur) for arm64.

View file

@ -3,102 +3,93 @@ $ErrorActionPreference = if ($env:CI) { 'Stop' } else { 'Inquire' }
Set-StrictMode -Version Latest
function Reset-Path {
$env:Path = [System.Environment]::ExpandEnvironmentVariables(
[System.Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' + [System.Environment]::GetEnvironmentVariable('Path', 'User')
)
}
function Set-EnvVar($variable, $value = $null) {
if ($null -ne $value) {
[System.Environment]::SetEnvironmentVariable($variable, $value, 'User')
if ($env:CI -and ($variable -ne 'Path')) {
# If running in CI, we need to use GITHUB_ENV instead of the normal env variables
Add-Content $env:GITHUB_ENV "$variable=$value`n"
}
}
# The following is needed to make the environment variable available to the current PowerShell process
if ($variable -eq 'Path') {
Reset-Path
} else {
[System.Environment]::SetEnvironmentVariable(
$variable, [System.Environment]::GetEnvironmentVariable($variable, 'User'), 'Process'
)
}
$env:Path = [System.Environment]::ExpandEnvironmentVariables(
[System.Environment]::GetEnvironmentVariable('Path', 'Machine') +
[IO.Path]::PathSeparator +
[System.Environment]::GetEnvironmentVariable('Path', 'User')
)
}
# Verify if environment is Windows 64-bit and if the user is an administrator
if ((-not [string]::IsNullOrEmpty($env:PROCESSOR_ARCHITEW6432)) -or (
"$env:PROCESSOR_ARCHITECTURE" -eq 'ARM64'
) -or (
-not [System.Environment]::Is64BitOperatingSystem
# Powershell >= 6 is cross-platform, check if running on Windows
) -or (($PSVersionTable.PSVersion.Major -ge 6) -and (-not $IsWindows))
"$env:PROCESSOR_ARCHITECTURE" -eq 'ARM64'
) -or (
-not [System.Environment]::Is64BitOperatingSystem
# Powershell >= 6 is cross-platform, check if running on Windows
) -or (($PSVersionTable.PSVersion.Major -ge 6) -and (-not $IsWindows))
) {
$ErrorActionPreference = 'Continue'
Write-Host # There is no oficial ffmpeg binaries for Windows 32 or ARM
if (Test-Path "$($env:WINDIR)\SysNative\WindowsPowerShell\v1.0\powershell.exe" -PathType Leaf) {
throw 'You are using PowerShell (32-bit), please re-run in PowerShell (64-bit)'
} else {
throw 'This script is only supported on Windows 64-bit'
}
Exit 1
$ErrorActionPreference = 'Continue'
Write-Host # There is no oficial ffmpeg binaries for Windows 32 or ARM
if (Test-Path "$($env:WINDIR)\SysNative\WindowsPowerShell\v1.0\powershell.exe" -PathType Leaf) {
throw 'You are using PowerShell (32-bit), please re-run in PowerShell (64-bit)'
} else {
throw 'This script is only supported on Windows 64-bit'
}
Exit 1
} elseif (
-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
) {
# Start a new PowerShell process with administrator privileges and set the working directory to the directory where the script is located
Start-Process -Wait -FilePath 'PowerShell.exe' -Verb RunAs -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Definition)`"" -WorkingDirectory "$PSScriptRoot"
# NOTICE: Any modified environment variables should be reloaded here, so the user doesn't have to restart the shell after running the script
Reset-Path
Set-EnvVar('PROTOC')
Set-EnvVar('FFMPEG_DIR')
Exit
# Start a new PowerShell process with administrator privileges and set the working directory to the directory where the script is located
$proc = Start-Process -PassThru -Wait -FilePath 'PowerShell.exe' -Verb RunAs -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Definition)`"" -WorkingDirectory "$PSScriptRoot"
# Reset path so the user doesn't have to restart the shell to use the tools installed by this script
Reset-Path
Exit $proc.ExitCode
}
function Exit-WithError($err, $help = $null) {
if ($null -ne $help) {
Write-Host
Write-Host $help -ForegroundColor DarkRed
}
throw $err
Exit 1
if ($null -ne $help) {
Write-Host
Write-Host $help -ForegroundColor DarkRed
}
throw $err
Exit 1
}
function Add-DirectoryToPath($directory) {
if ($env:Path.Split(';') -notcontains $directory) {
Set-EnvVar 'Path' "$($env:Path);$directory"
if ($env:CI) {
# If running in CI, we need to use GITHUB_PATH instead of the normal PATH env variables
Add-Content $env:GITHUB_PATH "$directory`n"
}
}
Reset-Path
Reset-Path
if ($env:Path.Split([IO.Path]::PathSeparator) -notcontains $directory) {
[System.Environment]::SetEnvironmentVariable(
'Path',
[System.Environment]::GetEnvironmentVariable('Path', 'User') + [IO.Path]::PathSeparator + $directory,
'User'
)
if ($env:CI) {
# If running in CI, we need to use GITHUB_PATH instead of the normal PATH env variables
Add-Content $env:GITHUB_PATH "$directory`n"
}
}
Reset-Path
}
function Invoke-RestMethodGithub {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$Uri,
[string]$Method = 'GET',
[hashtable]$Headers = @{},
[string]$UserAgent = 'PowerShell'
)
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Uri,
[string]$Method = 'GET',
[hashtable]$Headers = @{},
[string]$UserAgent = 'PowerShell'
)
if (![string]::IsNullOrEmpty($env:GITHUB_TOKEN)) {
$headers.Add("Authorization", "Bearer $($env:GITHUB_TOKEN)")
}
$headers.Add('Accept', 'application/vnd.github+json')
$headers.Add('X-GitHub-Api-Version', '2022-11-28')
$params = @{
Uri = $Uri
Method = $Method
Headers = $Headers
UserAgent = $UserAgent
}
if (![string]::IsNullOrEmpty($env:GITHUB_TOKEN)) {
$headers.Add('Authorization', "Bearer $($env:GITHUB_TOKEN)")
}
Invoke-RestMethod @params
$params = @{
Uri = $Uri
Method = $Method
Headers = $Headers
UserAgent = $UserAgent
}
Invoke-RestMethod @params
}
# Reset PATH to ensure the script doesn't read any stale entries
# Reset PATH to ensure the script doesn't have stale Path entries
Reset-Path
# Get temp folder
@ -106,16 +97,19 @@ $temp = [System.IO.Path]::GetTempPath()
# Get project dir (get grandparent dir from script location: <PROJECT_ROOT>\.github\scripts)
$projectRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
$packageJson = Get-Content -Raw -Path "$projectRoot\package.json" | ConvertFrom-Json
# Pnpm
$pnpm_major = '8'
# Valid winget exit status
$wingetValidExit = 0, -1978335189, -1978335153, -1978335135
# Currently LLVM >= 16 is not supported due to incompatibilities with ffmpeg-sys-next
# See https://github.com/spacedriveapp/spacedrive/issues/677
$llvm_major = '15'
$llvmVersion = [Version]'15.0.7'
# Change CWD to project root
Set-Location $projectRoot
Remove-Item -Force -ErrorAction SilentlyContinue -Path "$projectRoot\.cargo\config"
Remove-Item -Force -ErrorAction SilentlyContinue -Path "$projectRoot\target\Frameworks" -Recurse
Write-Host 'Spacedrive Development Environment Setup' -ForegroundColor Magenta
Write-Host @"
@ -125,259 +119,262 @@ To set up your machine for Spacedrive development, this script will do the follo
2) Install Edge Webview 2
3) Install Rust and Cargo
4) Install Rust tools
5) Install Node.js, npm and pnpm $pnpm_major
6) Install LLVM $llvm_major (compiler for ffmpeg-rust)
7) Download protbuf compiler and set the PROTOC environment variable
8) Download ffmpeg and set the FFMPEG_DIR environment variable
5) Install Node.js, npm and pnpm
6) Install LLVM $llvmVersion (compiler for ffmpeg-rust)
7) Download the protbuf compiler
8) Download a compatible ffmpeg build
"@
# Check connectivity to GitHub
$ProgressPreference = 'SilentlyContinue'
if (-not ((Test-NetConnection -ComputerName 'github.com' -Port 80).TcpTestSucceeded)) {
throw "Can't connect to github, maybe internet is down?"
}
$ProgressPreference = 'Continue'
# Install C++ build tools and Rust
# GitHub Actions already has all of this installed
# Install System dependencies (GitHub Actions already has all of those installed)
if (-not $env:CI) {
if (-not (Get-Command winget -ea 0)) {
Exit-WithError 'winget not available' @'
if (-not (Get-Command winget -ea 0)) {
Exit-WithError 'winget not available' @'
Follow the instructions here to install winget:
https://learn.microsoft.com/windows/package-manager/winget/
'@
}
}
Write-Host
Write-Host 'Installing Visual Studio Build Tools...' -ForegroundColor Yellow
Write-Host 'This will take some time as it involves downloading several gigabytes of data....' -ForegroundColor Cyan
# Force install because BuildTools is itself an installer for multiple packages, so let itself decide if it need to install anythin or not
winget install --exact --no-upgrade --accept-source-agreements --force --disable-interactivity --id Microsoft.VisualStudio.2022.BuildTools --override '--wait --quiet --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended'
# Check connectivity to GitHub
$ProgressPreference = 'SilentlyContinue'
if (-not ((Test-NetConnection -ComputerName 'github.com' -Port 80).TcpTestSucceeded)) {
Exit-WithError "Can't connect to github, check your internet connection and run this script again"
}
$ProgressPreference = 'Continue'
Write-Host
Write-Host 'Installing Edge Webview 2...' -ForegroundColor Yellow
try {
# This is normally already available, but on some early Windows 10 versions it isn't
winget install --exact --no-upgrade --accept-source-agreements --disable-interactivity --id Microsoft.EdgeWebView2Runtime
} catch {}
Write-Host
Read-Host 'Press Enter to continue'
Write-Host
Write-Host 'Installing Rust and Cargo...' -ForegroundColor Yellow
try {
winget install --exact --no-upgrade --accept-source-agreements --disable-interactivity --id Rustlang.Rustup
Reset-Path # Reset Path to ensure that cargo is available to the command bellow
} catch {}
Write-Host
Write-Host 'Installing Visual Studio Build Tools...' -ForegroundColor Yellow
Write-Host 'This will take some time as it involves downloading several gigabytes of data....' -ForegroundColor Cyan
# Force install because BuildTools is itself a package manager, so let it decide if something needs to be installed or not
winget install -e --accept-source-agreements --force --disable-interactivity --id Microsoft.VisualStudio.2022.BuildTools `
--override '--wait --quiet --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended'
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
Exit-WithError 'Failed to install Visual Studio Build Tools'
} else {
$LASTEXITCODE = 0
}
Write-Host
Write-Host 'Installing Rust tools' -ForegroundColor Yellow
cargo install cargo-watch
Write-Host
Write-Host 'Installing Edge Webview 2...' -ForegroundColor Yellow
# This is normally already available, but on some early Windows 10 versions it isn't
winget install -e --accept-source-agreements --disable-interactivity --id Microsoft.EdgeWebView2Runtime
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
Exit-WithError 'Failed to install Edge Webview 2'
} else {
$LASTEXITCODE = 0
}
Write-Host
Write-Host 'Installing Rust and Cargo...' -ForegroundColor Yellow
winget install -e --accept-source-agreements --disable-interactivity --id Rustlang.Rustup
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
Exit-WithError 'Failed to install Rust and Cargo'
} else {
$LASTEXITCODE = 0
}
Write-Host
Write-Host 'Installing NodeJS...' -ForegroundColor Yellow
# Check if Node.JS is already installed and if it's compatible with the project
$currentNode = Get-Command node -ea 0
$currentNodeVersion = if (-not $currentNode) { $null } elseif ($currentNode.Version) { $currentNode.Version } elseif ((node --version) -match '(?sm)(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
$enginesNodeVersion = if ($packageJson.engines.node -match '(?sm)(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
if ($currentNodeVersion -and $enginesNodeVersion -and $currentNodeVersion.CompareTo($enginesNodeVersion) -lt 0) {
Exit-WithError "Current Node.JS version: $currentNodeVersion (required: $enginesNodeVersion)" `
'Uninstall the current version of Node.JS and run this script again'
}
# Install Node.JS
winget install -e --accept-source-agreements --disable-interactivity --id OpenJS.NodeJS
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
Exit-WithError 'Failed to install NodeJS'
} else {
$LASTEXITCODE = 0
}
# Add NodeJS to the PATH
Add-DirectoryToPath "$env:SystemDrive\Program Files\nodejs"
Write-Host
Write-Host 'Checking for LLVM...' -ForegroundColor Yellow
# Check if LLVM is already installed and if it's compatible with the project
$currentLLVMVersion = if ("$(winget list -e --disable-interactivity --id LLVM.LLVM)" -match '(?sm)LLVM.LLVM\s+(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
if ($currentLLVMVersion -and $currentLLVMVersion.Major -gt $llvmVersion.Major) {
Exit-WithError "Current LLVM version: $currentLLVMVersion (required: $llvmVersion)" `
'Uninstall the current version of LLVM and run this script again'
}
# Install LLVM
winget install -e --accept-source-agreements --disable-interactivity --id LLVM.LLVM --version "$llvmVersion"
if (-not ($wingetValidExit -contains $LASTEXITCODE)) {
Exit-WithError 'Failed to install NodeJS'
} else {
$LASTEXITCODE = 0
}
# Add LLVM to the PATH
Add-DirectoryToPath "$env:SystemDrive\Program Files\LLVM\bin"
# Reset Path to ensure that executable installed above are available to rest of the script
Reset-Path
Write-Host
Write-Host 'Installing Rust MSVC Toolchain...' -ForegroundColor Yellow
rustup toolchain install stable-msvc
if ($LASTEXITCODE -ne 0) {
Exit-WithError 'Failed to install Rust MSVC Toolchain'
}
Write-Host
Write-Host 'Installing Rust tools...' -ForegroundColor Yellow
cargo install cargo-watch
if ($LASTEXITCODE -ne 0) {
Exit-WithError 'Failed to install Rust tools'
}
Write-Host
Write-Host 'Installing for pnpm...' -ForegroundColor Yellow
# Check if pnpm is already installed and if it's compatible with the project
$currentPnpmVersion = if (-not (Get-Command pnpm -ea 0)) { $null } elseif ((pnpm --version) -match '(?sm)(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
$enginesPnpmVersion = if ($packageJson.engines.pnpm -match '(?sm)(\d+(\.\d+)*)') { [Version]$matches[1] } else { $null }
if (-not $currentPnpmVersion) {
# Remove possible remaining envvars from old pnpm installation
[System.Environment]::SetEnvironmentVariable('PNPM_HOME', $null, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('PNPM_HOME', $null, [System.EnvironmentVariableTarget]::User)
# Install pnpm
npm install -g "pnpm@latest-$($enginesPnpmVersion.Major)"
if ($LASTEXITCODE -ne 0) {
Exit-WithError 'Failed to install pnpm'
}
# Add NPM global modules to the PATH
if (Test-Path "$env:APPDATA\npm" -PathType Container) {
Add-DirectoryToPath "$env:APPDATA\npm"
}
} elseif ($currentPnpmVersion -and $enginesPnpmVersion -and $currentPnpmVersion.CompareTo($enginesPnpmVersion) -lt 0) {
Exit-WithError "Current pnpm version: $currentPnpmVersion (required: $enginesPnpmVersion)" `
'Uninstall the current version of pnpm and run this script again'
}
}
# Create target folder, continue if already exists
New-Item -Force -ErrorAction SilentlyContinue -ItemType Directory -Path "$projectRoot\target\Frameworks" | Out-Null
# --
Write-Host
Write-Host 'Checking for pnpm...' -ForegroundColor Yellow
if ($env:CI) {
# The CI has pnpm installed already
Write-Host 'Running with CI, skipping pnpm install.' -ForegroundColor Green
}if ((Get-Command pnpm -ea 0) -and (pnpm --version | Select-Object -First 1) -match "^$pnpm_major\." ) {
Write-Host "pnpm $pnpm_major is installed." -ForegroundColor Green
} else {
# Check for pnpm installed with standalone installer
if (($null -ne $env:PNPM_HOME) -and (Test-Path "$env:PNPM_HOME/pnpm.exe" -PathType Leaf)) {
Exit-WithError 'You have a incompatible version of pnpm installed, please remove it and run this script again' @'
Follow the instructions here to uninstall pnpm:
https://pnpm.io/uninstall
'@
} else {
# Remove possible remaining envvars from old pnpm installation
[System.Environment]::SetEnvironmentVariable('PNPM_HOME', $null, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('PNPM_HOME', $null, [System.EnvironmentVariableTarget]::User)
}
Write-Host 'Retrieving protobuf version...' -ForegroundColor Yellow
if (-not $env:CI) {
Write-Host 'Installing NodeJS...' -ForegroundColor Yellow
try {
winget install --exact --no-upgrade --accept-source-agreements --disable-interactivity --id OpenJS.NodeJS
# Add NodeJS to the PATH
Add-DirectoryToPath "$env:SystemDrive\Program Files\nodejs"
} catch {}
}
$filename = $null
$downloadUri = $null
$releasesUri = 'https://api.github.com/repos/protocolbuffers/protobuf/releases'
$filenamePattern = '*-win64.zip'
Write-Host 'Installing pnpm...'
npm install -g "pnpm@latest-$pnpm_major"
# Add NPM global modules to the PATH
if (Test-Path "$env:APPDATA\npm" -PathType Container) {
Add-DirectoryToPath "$env:APPDATA\npm"
}
}
Write-Host
Write-Host 'Checking for LLVM...' -ForegroundColor Yellow
if ($env:CI) {
# The CI has LLVM installed already
Write-Host 'Running with CI, skipping LLVM install.' -ForegroundColor Green
} elseif (
(Get-Command clang -ea 0) -and (
(clang --version | Select-String -Pattern 'version\s+(\d+)' | ForEach-Object { $_.Matches.Groups[1].Value }) -eq "$llvm_major"
)
) {
Write-Host "LLVM $llvm_major is installed." -ForegroundColor Green
} else {
$downloadUri = $null
$releasesUri = 'https://api.github.com/repos/llvm/llvm-project/releases'
$llvmVersion = "LLVM $llvm_major*"
$filenamePattern = '*-win64.exe'
Write-Host "Downloading LLVM $llvm_major installer..." -ForegroundColor Yellow
$releases = Invoke-RestMethodGithub -Uri $releasesUri
$downloadUri = $releases | ForEach-Object {
if ($_.name -like $llvmVersion) {
$_.assets | Where-Object { $_.name -like $filenamePattern } | Select-Object -ExpandProperty 'browser_download_url'
}
} | Select-Object -First 1
if ($null -eq $downloadUri) {
Exit-WithError "Couldn't find a LLVM installer for version: $llvm_major"
}
$oldUninstaller = "$env:SystemDrive\Program Files\LLVM\Uninstall.exe"
if (Test-Path $oldUninstaller -PathType Leaf) {
Exit-WithError 'You have a incompatible version of LLVM installed' 'Uninstall the current version of LLVM and run this script again'
}
Start-BitsTransfer -TransferType Download -Source $downloadUri -Destination "$temp\llvm.exe"
Write-Host "Installing LLVM $llvm_major" -ForegroundColor Yellow
Write-Host 'This may take a while and will have no visual feedback, please wait...' -ForegroundColor Cyan
Start-Process -FilePath "$temp\llvm.exe" -Verb RunAs -ArgumentList '/S' -Wait -ErrorAction Stop
Add-DirectoryToPath "$env:SystemDrive\Program Files\LLVM\bin"
Remove-Item "$temp\llvm.exe"
}
Write-Host
Write-Host 'Checking for protobuf compiler...' -ForegroundColor Yellow
$protocVersion = $null
if (($null -ne $env:PROTOC) -and (Test-Path $env:PROTOC -PathType Leaf)) {
$protocVersion = &"$env:PROTOC" --version 2>&1 | Out-String
}
if ($protocVersion) {
Write-Host 'protobuf compiler is installed.' -ForegroundColor Green
} else {
$filename = $null
$downloadUri = $null
$releasesUri = 'https://api.github.com/repos/protocolbuffers/protobuf/releases'
$filenamePattern = '*-win64.zip'
Write-Host 'Downloading protobuf compiler...' -ForegroundColor Yellow
$releases = Invoke-RestMethodGithub -Uri $releasesUri
for ($i = 0; $i -lt $releases.Count; $i++) {
$release = $releases[$i]
foreach ($asset in $release.assets) {
if ($asset.name -like $filenamePattern) {
$releases = Invoke-RestMethodGithub -Uri $releasesUri
for ($i = 0; $i -lt $releases.Count; $i++) {
$release = $releases[$i]
foreach ($asset in $release.assets) {
if ($asset.name -like $filenamePattern) {
$filename = $asset.name
$downloadUri = $asset.browser_download_url
$i = $releases.Count
break
}
}
}
if (-not ($filename -and $downloadUri)) {
Exit-WithError "Couldn't find a protobuf compiler installer"
}
$foldername = "$env:LOCALAPPDATA\$([System.IO.Path]::GetFileNameWithoutExtension($fileName))"
New-Item -Path $foldername -ItemType Directory -ErrorAction SilentlyContinue
Write-Host 'Dowloading protobuf zip...' -ForegroundColor Yellow
Start-BitsTransfer -TransferType Download -Source $downloadUri -Destination "$temp\protobuf.zip"
Write-Host 'Expanding protobuf zip...' -ForegroundColor Yellow
Expand-Archive "$temp\protobuf.zip" $foldername -ErrorAction SilentlyContinue
Remove-Item "$temp\protobuf.zip"
Write-Host 'Setting PROTOC environment variable...' -ForegroundColor Yellow
Set-EnvVar 'PROTOC' "$foldername\bin\protoc.exe"
Add-DirectoryToPath "$foldername\bin"
}
}
}
Write-Host
Write-Host 'Update cargo packages...' -ForegroundColor Yellow
# Run first time to ensure packages are up to date
cargo metadata --format-version 1 > $null
if (-not ($filename -and $downloadUri)) {
Exit-WithError "Couldn't find a protobuf compiler installer"
}
Write-Host 'Dowloading protobuf zip...' -ForegroundColor Yellow
Start-BitsTransfer -TransferType Download -Source $downloadUri -Destination "$temp\protobuf.zip"
Write-Host 'Expanding protobuf zip...' -ForegroundColor Yellow
Expand-Archive "$temp\protobuf.zip" "$projectRoot\target\Frameworks" -Force
Remove-Item -Force -ErrorAction SilentlyContinue -Path "$temp\protobuf.zip"
# --
Write-Host
Write-Host 'Checking for ffmpeg build...' -ForegroundColor Yellow
Write-Host 'Retrieving ffmpeg version...' -ForegroundColor Yellow
# Run first to update packages
cargo metadata --format-version 1 | Out-Null
# Get ffmpeg-sys-next version
$ffmpegVersion = (cargo metadata --format-version 1 | ConvertFrom-Json).packages.dependencies | Where-Object {
$_.name -like 'ffmpeg-sys-next'
$_.name -like 'ffmpeg-sys-next'
} | Select-Object -ExpandProperty 'req' | ForEach-Object {
$_ -replace '[~^<>=!*]+', ''
$_ -replace '[~^<>=!*]+', ''
} | Sort-Object -Unique | Select-Object -Last 1
if (($null -ne $env:FFMPEG_DIR) -and (
$ffmpegVersion.StartsWith(
(($env:FFMPEG_DIR.split('\') | Where-Object { $_ -like 'ffmpeg-*' }) -replace 'ffmpeg-(\d+(\.\d+)*).*', '$1'),
[System.StringComparison]::InvariantCulture
)
)
) {
Write-Host 'ffmpeg is installed.' -ForegroundColor Green
} else {
$filename = $null
$downloadUri = $null
$releasesUri = 'https://api.github.com/repos/GyanD/codexffmpeg/releases'
$filenamePattern = '*-full_build-shared.zip'
# Downloads a build of ffmpeg from GitHub compatible with the declared ffmpeg-sys-next version
$releases = Invoke-RestMethodGithub -Uri $releasesUri
$version = $ffmpegVersion
while (-not ($filename -and $downloadUri) -and $version) {
for ($i = 0; $i -lt $releases.Count; $i++) {
$release = $releases[$i]
if ($release.tag_name -eq $version) {
foreach ($asset in $release.assets) {
if ($asset.name -like $filenamePattern) {
$filename = $asset.name
$downloadUri = $asset.browser_download_url
$i = $releases.Count
break
}
}
}
}
$version = $version -replace '\.?\d+$'
}
if (-not ($filename -and $downloadUri)) {
Exit-WithError "Couldn't find a ffmpeg installer for version: $ffmpegVersion"
}
$foldername = "$env:LOCALAPPDATA\$([System.IO.Path]::GetFileNameWithoutExtension($fileName))"
Write-Host 'Dowloading ffmpeg zip...' -ForegroundColor Yellow
Start-BitsTransfer -TransferType Download -Source $downloadUri -Destination "$temp\ffmpeg.zip"
Write-Host 'Expanding ffmpeg zip...' -ForegroundColor Yellow
# FFmpeg zip contains a subdirectory with the same name as the zip file
Expand-Archive "$temp\ffmpeg.zip" $env:LOCALAPPDATA -ErrorAction SilentlyContinue
Remove-Item "$temp\ffmpeg.zip"
Write-Host 'Setting FFMPEG_DIR environment variable...' -ForegroundColor Yellow
Set-EnvVar 'FFMPEG_DIR' "$foldername"
Add-DirectoryToPath "$foldername\bin"
if ($LASTEXITCODE -ne 0) {
Exit-WithError 'Failed to get ffmpeg-sys-next version'
}
Write-Host
Write-Host 'Copying Required .dll files...' -ForegroundColor Yellow
# Create target\debug folder, continue if already exists
New-Item -Path $projectRoot\target\debug -ItemType Directory -ErrorAction SilentlyContinue
# Copies all .dll required for rust-ffmpeg to target\debug folder
Get-ChildItem "$env:FFMPEG_DIR\bin" -Recurse -Filter *.dll | Copy-Item -Destination "$projectRoot\target\debug"
$filename = $null
$downloadUri = $null
$releasesUri = 'https://api.github.com/repos/GyanD/codexffmpeg/releases'
$filenamePattern = '*-full_build-shared.zip'
Write-Host
Write-Host 'Your machine has been setup for Spacedrive development!' -ForegroundColor Green
Write-Host 'You will need to re-run this script if there are rust dependencies changes or you use `pnpm clean` or `cargo clean`!' -ForegroundColor Red
if (-not $env:CI) { Read-Host 'Press Enter to continue' }
# Downloads a build of ffmpeg from GitHub compatible with the declared ffmpeg-sys-next version
$releases = Invoke-RestMethodGithub -Uri $releasesUri
$version = $ffmpegVersion
while (-not ($filename -and $downloadUri) -and $version) {
for ($i = 0; $i -lt $releases.Count; $i++) {
$release = $releases[$i]
if ($release.tag_name -eq $version) {
foreach ($asset in $release.assets) {
if ($asset.name -like $filenamePattern) {
$filename = $asset.name
$downloadUri = $asset.browser_download_url
$i = $releases.Count
break
}
}
}
}
$version = $version -replace '\.?\d+$'
}
if (-not ($filename -and $downloadUri)) {
Exit-WithError "Couldn't find a ffmpeg installer for version: $ffmpegVersion"
}
Write-Host 'Dowloading ffmpeg zip...' -ForegroundColor Yellow
Start-BitsTransfer -TransferType Download -Source $downloadUri -Destination "$temp\ffmpeg.zip"
Write-Host 'Expanding ffmpeg zip...' -ForegroundColor Yellow
# FFmpeg zip contains a subdirectory with the same name as the zip file
Expand-Archive -Force -Path "$temp\ffmpeg.zip" -DestinationPath "$temp"
Remove-Item -Force -ErrorAction SilentlyContinue -Path "$temp\ffmpeg.zip"
$ffmpegDir = "$temp\$([System.IO.Path]::GetFileNameWithoutExtension($fileName))"
$proc = Start-Process -PassThru -Wait -FilePath 'Robocopy.exe' -Verb RunAs -ArgumentList `
"`"$ffmpegDir`" `"$projectRoot\target\Frameworks`" /E /NS /NC /NFL /NDL /NP /NJH /NJS"
# https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy#exit-return-codes
if ($proc.ExitCode -ge 8) {
Exit-WithError 'Failed to copy ffmpeg files'
}
Remove-Item -Force -ErrorAction SilentlyContinue -Recurse -Path "$ffmpegDir"
@(
'[env]',
"PROTOC = `"$("$projectRoot\target\Frameworks\bin\protoc" -replace '\\', '\\')`"",
"FFMPEG_DIR = `"$("$projectRoot\target\Frameworks" -replace '\\', '\\')`"",
'',
(Get-Content "$projectRoot\.cargo\config.toml" -Encoding utf8)
) | Out-File -Force -Encoding utf8 -FilePath "$projectRoot\.cargo\config"
if (-not $env:CI) {
Write-Host
Write-Host 'Your machine has been setup for Spacedrive development!' -ForegroundColor Green
Write-Host 'You will need to re-run this script if there are rust dependencies changes or you use `pnpm clean` or `cargo clean`!' -ForegroundColor Red
Write-Host
Read-Host 'Press Enter to continue'
}
if ($LASTEXITCODE -ne 0) {
Exit-WithError "Something went wrong, exit code: $LASTEXITCODE"
}

View file

@ -2,13 +2,55 @@
set -euo pipefail
function log_err() {
echo "$@" >&2
if [ "${CI:-}" = "true" ]; then
set -x
fi
SYSNAME="$(uname)"
FFMPEG_VERSION='6.0'
err() {
for _line in "$@"; do
echo "$@" >&2
done
exit 1
}
function script_failure() {
log_err "An error occurred $(if [ -n "${1:-}" ]; then echo "on line $1"; else echo "(unknown)"; fi)."
log_err "Setup failed."
has() {
if [ "$#" -ne 1 ]; then
err "Usage: has <command>"
fi
command -v "$1" >/dev/null 2>&1
}
_gh_url="https://api.github.com/repos"
_sd_gh_path='spacedriveapp/spacedrive'
gh_curl() {
if [ "$#" -ne 1 ]; then
err "Usage: gh_curl <api_route>"
fi
url="$1"
# Required headers for GitHub API
set -- -LSs -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28"
# Add authorization header if GITHUB_TOKEN is set, to avoid being rate limited
if [ -n "${GITHUB_TOKEN:-}" ]; then
set -- "$@" -H "Authorization: Bearer $GITHUB_TOKEN"
fi
curl "$@" "$url"
}
script_failure() {
if [ -n "${1:-}" ]; then
_line="on line $1"
else
_line="(unknown)"
fi
err "An error occurred $_line." "Setup failed."
}
trap 'script_failure ${LINENO:-}' ERR
@ -16,181 +58,333 @@ trap 'script_failure ${LINENO:-}' ERR
echo "Setting up this system for Spacedrive development."
echo
if ! command -v cargo >/dev/null; then
log_err "Rust was not found. Ensure the 'rustc' and 'cargo' binaries are in your \$PATH."
exit 1
# Change CWD to the directory of this script
CDPATH='' cd -- "$(dirname -- "$0")"
_script_path="$(pwd -P)"
_cargo_config="${_script_path}/../../.cargo"
rm -rf "$_cargo_config/config"
if ! has cargo; then
err 'Rust was not found.' \
"Ensure the 'rustc' and 'cargo' binaries are in your \$PATH." \
'https://rustup.rs'
fi
if [ "${SPACEDRIVE_SKIP_PNPM_CHECK:-'false'}" != "true" ]; then
echo "Checking for pnpm..."
if [ "${CI:-}" != "true" ] && [ "${spacedrive_skip_pnpm_check:-}" != "true" ]; then
echo "checking for pnpm..."
if ! command -v pnpm >/dev/null; then
log_err "pnpm was not found. Ensure the 'pnpm' command is in your \$PATH."
log_err 'You MUST use pnpm for this project; yarn and npm are not allowed.'
exit 1
else
echo "Found pnpm!"
fi
if ! has pnpm; then
err 'pnpm was not found.' \
"Ensure the 'pnpm' command is in your \$PATH." \
'You must use pnpm for this project; yarn and npm are not allowed.' \
'https://pnpm.io/installation'
else
echo "found pnpm!"
fi
else
echo "Skipping pnpm check."
echo "Skipping pnpm check."
fi
if [ "${CI:-}" != "true" ]; then
echo "Installing Rust tools"
cargo install cargo-watch
echo "Installing Rust tools"
cargo install cargo-watch
fi
echo
if [ "${1:-}" == "mobile" ]; then
echo "Setting up for mobile development."
if [ "${1:-}" = "mobile" ]; then
echo "Setting up for mobile development."
# iOS targets
if [[ $OSTYPE == "darwin"* ]]; then
echo "Checking for Xcode..."
if ! /usr/bin/xcodebuild -version >/dev/null; then
log_err "Xcode was not detected."
log_err "Please ensure Xcode is installed and try again."
exit 1
fi
# iOS targets
if [ "$SYSNAME" = "Darwin" ]; then
echo "Checking for Xcode..."
if ! /usr/bin/xcodebuild -version >/dev/null; then
err "Xcode was not detected." \
"Please ensure Xcode is installed and try again."
fi
echo "Installing iOS targets for Rust..."
echo "Installing iOS targets for Rust..."
rustup target add aarch64-apple-ios
rustup target add aarch64-apple-ios-sim
rustup target add x86_64-apple-ios # for CI
fi
rustup target add aarch64-apple-ios
rustup target add aarch64-apple-ios-sim
rustup target add x86_64-apple-ios # for CI
fi
# Android requires python
if ! command -v python3 >/dev/null; then
log_err "python3 command could not be found. This is required for Android mobile development."
log_err "Ensure python3 is available in your \$PATH and try again."
exit 1
fi
# Android requires python
if ! command -v python3 >/dev/null; then
err 'python3 was not found.' \
'This is required for Android mobile development.' \
"Ensure 'python3' is available in your \$PATH and try again."
fi
# Android targets
echo "Setting up Android targets for Rust..."
# Android targets
echo "Setting up Android targets for Rust..."
rustup target add armv7-linux-androideabi # for arm
rustup target add aarch64-linux-android # for arm64
rustup target add i686-linux-android # for x86
rustup target add x86_64-linux-android # for x86_64
rustup target add x86_64-unknown-linux-gnu # for linux-x86-64
rustup target add aarch64-apple-darwin # for darwin arm64 (if you have an M1 Mac)
rustup target add x86_64-apple-darwin # for darwin x86_64 (if you have an Intel Mac)
rustup target add x86_64-pc-windows-gnu # for win32-x86-64-gnu
rustup target add x86_64-pc-windows-msvc # for win32-x86-64-msvc
rustup target add armv7-linux-androideabi # for arm
rustup target add aarch64-linux-android # for arm64
rustup target add i686-linux-android # for x86
rustup target add x86_64-linux-android # for x86_64
rustup target add x86_64-unknown-linux-gnu # for linux-x86-64
rustup target add aarch64-apple-darwin # for darwin arm64 (if you have an M1 Mac)
rustup target add x86_64-apple-darwin # for darwin x86_64 (if you have an Intel Mac)
rustup target add x86_64-pc-windows-gnu # for win32-x86-64-gnu
rustup target add x86_64-pc-windows-msvc # for win32-x86-64-msvc
echo "Done setting up mobile targets."
echo
echo "Done setting up mobile targets."
echo
fi
if [[ $OSTYPE == "linux-gnu"* ]]; then
if command -v apt-get >/dev/null; then
echo "Detected apt!"
echo "Installing dependencies with apt..."
if [ "$SYSNAME" = "Linux" ]; then
if has apt-get; then
echo "Detected apt!"
echo "Installing dependencies with apt..."
# Tauri dependencies
DEBIAN_TAURI_DEPS="libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev"
# Tauri dependencies
DEBIAN_TAURI_DEPS="libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev patchelf"
# FFmpeg dependencies
DEBIAN_FFMPEG_DEPS="libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev ffmpeg"
# FFmpeg dependencies
DEBIAN_FFMPEG_DEPS="libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev ffmpeg"
# Webkit2gtk requires gstreamer plugins for video playback to work
DEBIAN_VIDEO_DEPS="gstreamer1.0-libav gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly"
# Webkit2gtk requires gstreamer plugins for video playback to work
DEBIAN_VIDEO_DEPS="gstreamer1.0-libav gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly"
# Bindgen dependencies - it's used by a dependency of Spacedrive
DEBIAN_BINDGEN_DEPS="pkg-config clang"
# Bindgen dependencies - it's used by a dependency of Spacedrive
DEBIAN_BINDGEN_DEPS="pkg-config clang"
# Protobuf compiler
DEBIAN_LIBP2P_DEPS="protobuf-compiler"
# Protobuf compiler
DEBIAN_LIBP2P_DEPS="protobuf-compiler"
sudo apt-get -y update
sudo apt-get -y install ${SPACEDRIVE_CUSTOM_APT_FLAGS:-} $DEBIAN_TAURI_DEPS $DEBIAN_FFMPEG_DEPS $DEBIAN_BINDGEN_DEPS $DEBIAN_LIBP2P_DEPS $DEBIAN_VIDEO_DEPS
elif command -v pacman >/dev/null; then
echo "Detected pacman!"
echo "Installing dependencies with pacman..."
sudo apt-get -y update
sudo apt-get -y install ${SPACEDRIVE_CUSTOM_APT_FLAGS:-} $DEBIAN_TAURI_DEPS $DEBIAN_FFMPEG_DEPS $DEBIAN_BINDGEN_DEPS $DEBIAN_LIBP2P_DEPS $DEBIAN_VIDEO_DEPS
elif has pacman; then
echo "Detected pacman!"
echo "Installing dependencies with pacman..."
# Tauri deps https://tauri.studio/guides/getting-started/setup/linux#1-system-dependencies
ARCH_TAURI_DEPS="webkit2gtk base-devel curl wget openssl appmenu-gtk-module gtk3 libappindicator-gtk3 librsvg libvips"
# Tauri deps https://tauri.studio/guides/getting-started/setup/linux#1-system-dependencies
ARCH_TAURI_DEPS="webkit2gtk base-devel curl wget openssl appmenu-gtk-module gtk3 libappindicator-gtk3 librsvg libvips patchelf"
# Webkit2gtk requires gstreamer plugins for video playback to work
ARCH_VIDEO_DEPS="gst-libav gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly"
# Webkit2gtk requires gstreamer plugins for video playback to work
ARCH_VIDEO_DEPS="gst-libav gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly"
# FFmpeg dependencies
ARCH_FFMPEG_DEPS="ffmpeg"
# FFmpeg dependencies
ARCH_FFMPEG_DEPS="ffmpeg"
# Bindgen dependencies - it's used by a dependency of Spacedrive
ARCH_BINDGEN_DEPS="clang"
# Bindgen dependencies - it's used by a dependency of Spacedrive
ARCH_BINDGEN_DEPS="clang"
# Protobuf compiler - https://github.com/archlinux/svntogit-packages/blob/packages/protobuf/trunk/PKGBUILD provides `libprotoc`
ARCH_LIBP2P_DEPS="protobuf"
# Protobuf compiler - https://github.com/archlinux/svntogit-packages/blob/packages/protobuf/trunk/PKGBUILD provides `libprotoc`
ARCH_LIBP2P_DEPS="protobuf"
sudo pacman -Sy
sudo pacman -S --needed $ARCH_TAURI_DEPS $ARCH_FFMPEG_DEPS $ARCH_BINDGEN_DEPS $ARCH_LIBP2P_DEPS $ARCH_VIDEO_DEPS
elif command -v dnf >/dev/null; then
echo "Detected dnf!"
echo "Installing dependencies with dnf..."
sudo pacman -Sy --needed $ARCH_TAURI_DEPS $ARCH_FFMPEG_DEPS $ARCH_BINDGEN_DEPS $ARCH_LIBP2P_DEPS $ARCH_VIDEO_DEPS
elif has dnf; then
echo "Detected dnf!"
echo "Installing dependencies with dnf..."
# `webkit2gtk4.0-devel` also provides `webkit2gtk3-devel`, it's just under a different package in fedora versions >= 37.
# https://koji.fedoraproject.org/koji/packageinfo?tagOrder=-blocked&packageID=26162#taglist
# https://packages.fedoraproject.org/pkgs/webkitgtk/webkit2gtk4.0-devel/fedora-38.html#provides
FEDORA_37_TAURI_WEBKIT="webkit2gtk4.0-devel"
FEDORA_36_TAURI_WEBKIT="webkit2gtk3-devel"
# `webkit2gtk4.0-devel` also provides `webkit2gtk3-devel`, it's just under a different package in fedora versions >= 37.
# https://koji.fedoraproject.org/koji/packageinfo?tagOrder=-blocked&packageID=26162#taglist
# https://packages.fedoraproject.org/pkgs/webkitgtk/webkit2gtk4.0-devel/fedora-38.html#provides
FEDORA_37_TAURI_WEBKIT="webkit2gtk4.0-devel"
FEDORA_36_TAURI_WEBKIT="webkit2gtk3-devel"
# Tauri dependencies
# openssl is manually declared here as i don't think openssl and openssl-devel are actually dependant on eachother
# openssl also has a habit of being missing from some of my fresh Fedora installs - i've had to install it at least twice
FEDORA_TAURI_DEPS="openssl-devel curl wget libappindicator-gtk3 librsvg2-devel"
# Tauri dependencies
# openssl is manually declared here as i don't think openssl and openssl-devel are actually dependant on eachother
# openssl also has a habit of being missing from some of my fresh Fedora installs - i've had to install it at least twice
FEDORA_TAURI_DEPS="openssl-devel curl wget libappindicator-gtk3 librsvg2-devel patchelf"
# required for building the openssl-sys crate
FEDORA_OPENSSL_SYS_DEPS="perl-FindBin perl-File-Compare perl-IPC-Cmd perl-File-Copy"
# required for building the openssl-sys crate
FEDORA_OPENSSL_SYS_DEPS="perl-FindBin perl-File-Compare perl-IPC-Cmd perl-File-Copy"
# FFmpeg dependencies
FEDORA_FFMPEG_DEPS="ffmpeg ffmpeg-devel"
# FFmpeg dependencies
FEDORA_FFMPEG_DEPS="ffmpeg ffmpeg-devel"
# Webkit2gtk requires gstreamer plugins for video playback to work
FEDORA_VIDEO_DEPS="gstreamer1-plugin-libav gstreamer1-plugins-base gstreamer1-plugins-good gstreamer1-plugins-good-extras gstreamer1-plugins-bad-free gstreamer1-plugins-bad-free-extras gstreamer1-plugins-ugly-free"
# Webkit2gtk requires gstreamer plugins for video playback to work
FEDORA_VIDEO_DEPS="gstreamer1-plugin-libav gstreamer1-plugins-base gstreamer1-plugins-good gstreamer1-plugins-good-extras gstreamer1-plugins-bad-free gstreamer1-plugins-bad-free-extras gstreamer1-plugins-ugly-free"
# Bindgen dependencies - it's used by a dependency of Spacedrive
FEDORA_BINDGEN_DEPS="clang"
# Bindgen dependencies - it's used by a dependency of Spacedrive
FEDORA_BINDGEN_DEPS="clang"
# Protobuf compiler
FEDORA_LIBP2P_DEPS="protobuf-compiler"
# Protobuf compiler
FEDORA_LIBP2P_DEPS="protobuf-compiler"
sudo dnf update
if ! sudo dnf install $FEDORA_37_TAURI_WEBKIT && ! sudo dnf install $FEDORA_36_TAURI_WEBKIT; then
err 'We were unable to install the webkit2gtk4.0-devel/webkit2gtk3-devel package.' \
'Please open an issue if you feel that this is incorrect.' \
'https://github.com/spacedriveapp/spacedrive/issues'
fi
if ! sudo dnf install $FEDORA_37_TAURI_WEBKIT && ! sudo dnf install $FEDORA_36_TAURI_WEBKIT; then
log_err "We were unable to install the webkit2gtk4.0-devel/webkit2gtk3-devel package. Please open an issue if you feel that this is incorrect. https://github.com/spacedriveapp/spacedrive/issues"
exit 1
fi
if ! sudo dnf install $FEDORA_FFMPEG_DEPS; then
err 'We were unable to install the FFmpeg and FFmpeg-devel packages.' \
'This is likely because the RPM Fusion free repository is not enabled.' \
'https://docs.fedoraproject.org/en-US/quick-docs/setup_rpmfusion'
fi
if ! sudo dnf install $FEDORA_FFMPEG_DEPS; then
log_err "We were unable to install the FFmpeg and FFmpeg-devel packages. This is likely because the RPM Fusion free repository is not enabled. https://docs.fedoraproject.org/en-US/quick-docs/setup_rpmfusion/"
exit 1
fi
sudo dnf install $FEDORA_TAURI_DEPS $FEDORA_BINDGEN_DEPS $FEDORA_LIBP2P_DEPS $FEDORA_VIDEO_DEPS
sudo dnf group install "C Development Tools and Libraries"
else
err "Your Linux distro '$(lsb_release -s -d)' is not supported by this script." \
'We would welcome a PR or some help adding your OS to this script:' \
'https://github.com/spacedriveapp/spacedrive/issues'
fi
elif [ "$SYSNAME" = "Darwin" ]; then
# Location for installing script dependencies
_deps_dir="${_script_path}/deps"
mkdir -p "$_deps_dir"
PATH="$PATH:${_deps_dir}"
export PATH
sudo dnf install $FEDORA_TAURI_DEPS $FEDORA_BINDGEN_DEPS $FEDORA_LIBP2P_DEPS $FEDORA_VIDEO_DEPS
sudo dnf group install "C Development Tools and Libraries"
else
log_err "Your Linux distro '$(lsb_release -s -d)' is not supported by this script. We would welcome a PR or some help adding your OS to this script. https://github.com/spacedriveapp/spacedrive/issues"
exit 1
fi
elif [[ $OSTYPE == "darwin"* ]]; then
if ! command -v brew >/dev/null; then
log_err "Homebrew was not found. Please install it using the instructions at https://brew.sh and try again."
exit 1
fi
_arch="$(uname -m)"
echo "Installing Homebrew dependencies..."
if ! has jq; then
echo "Download jq build..."
BREW_FFMPEG_DEPS="ffmpeg"
BREW_LIBP2P_DEPS="protobuf"
# Determine the machine's architecture
case "$_arch" in
x86_64)
_jq_url='https://packages.macports.org/jq/jq-1.6_4.darwin_19.x86_64.tbz2'
_oniguruma6_url='https://packages.macports.org/oniguruma6/oniguruma6-6.9.8_0.darwin_19.x86_64.tbz2'
;;
arm64)
_jq_url='https://packages.macports.org/jq/jq-1.6_4.darwin_20.arm64.tbz2'
_oniguruma6_url='https://packages.macports.org/oniguruma6/oniguruma6-6.9.8_0.darwin_20.arm64.tbz2'
;;
*)
err "Unsupported architecture: $_arch"
;;
esac
brew install -q $BREW_FFMPEG_DEPS $BREW_LIBP2P_DEPS
# Download the latest jq binary and deps from macports
curl -LSs "$_jq_url" | tar -xjOf - ./opt/local/bin/jq >"${_deps_dir}/jq"
curl -LSs "$_oniguruma6_url" | tar -xjOf - ./opt/local/lib/libonig.5.dylib >"${_deps_dir}/libonig.5.dylib"
# Make the binaries executable
chmod +x "$_deps_dir"/*
# Make jq look for deps in the same directory
install_name_tool -change '/opt/local/lib/libonig.5.dylib' '@executable_path/libonig.5.dylib' "${_deps_dir}/jq"
fi
# Create frameworks directory to put Spacedrive dependencies
_frameworks_dir="${_script_path}/../../target/Frameworks"
rm -rf "$_frameworks_dir"
mkdir -p "${_frameworks_dir}/"{bin,lib,include}
_frameworks_dir="$(CDPATH='' cd -- "$_frameworks_dir" && pwd -P)"
exec 3>&1 # Copy stdout to fd 3.
echo "Download ffmpeg build..."
_page=1
while [ $_page -gt 0 ]; do
# TODO: Filter only actions triggered by the main branch
_success=$(gh_curl "${_gh_url}/${_sd_gh_path}/actions/workflows/ffmpeg.yml/runs?page=${_page}&per_page=100&status=success" \
| jq -r '. as $raw | .workflow_runs | if length == 0 then error("Error: \($raw)") else .[] | .artifacts_url end' \
| while IFS= read -r _artifacts_url; do
if _artifact_path="$(
gh_curl "$_artifacts_url" \
| jq --arg version "$FFMPEG_VERSION" --arg arch "$(
if [ "${TARGET:-}" = 'aarch64-apple-darwin' ]; then
echo 'arm64'
else
echo "$_arch"
fi
)" -r \
'. as $raw | .artifacts | if length == 0 then error("Error: \($raw)") else .[] | select(.name == "ffmpeg-\($version)-\($arch)") | "suites/\(.workflow_run.id)/artifacts/\(.id)" end'
)"; then
# nightly.link is a workaround for the lack of a public GitHub API to download artifacts from a workflow run
# https://github.com/actions/upload-artifact/issues/51
# TODO: Use Github's private API when running on CI
if curl -LSs "https://nightly.link/${_sd_gh_path}/${_artifact_path}" | tar -xOf- | XZ_OPT='-T0' tar -xJf- -C "$_frameworks_dir"; then
printf 'yes'
exit
fi
echo "Failed to ffmpeg artifiact release, trying again in 1sec..." >&3
sleep 1
fi
done)
if [ "${_success:-}" = 'yes' ]; then
break
fi
_page=$((_page + 1))
echo "ffmpeg artifact not found, trying again in 1sec..."
sleep 1
done
# Symlink the FFMpeg.framework libs to the lib directory
for _lib in "${_frameworks_dir}/FFMpeg.framework/Libraries/"*; do
_lib="${_lib#"${_frameworks_dir}/FFMpeg.framework/Libraries/"}"
ln -s "../FFMpeg.framework/Libraries/${_lib}" "${_frameworks_dir}/lib/${_lib}"
done
# Symlink the FFMpeg.framework headers to the include directory
for _header in "${_frameworks_dir}/FFMpeg.framework/Headers/"*; do
_header="${_header#"${_frameworks_dir}/FFMpeg.framework/Headers/"}"
ln -s "../FFMpeg.framework/Headers/${_header}" "${_frameworks_dir}/include/${_header}"
done
# Workaround while https://github.com/tauri-apps/tauri/pull/3934 is not merged
echo "Download patched tauri cli.js build..."
case "$_arch" in
x86_64)
_artifact_url="https://nightly.link/${_sd_gh_path}/actions/artifacts/687573480.zip"
;;
arm64)
_artifact_url="https://nightly.link/${_sd_gh_path}/actions/artifacts/687573479.zip"
;;
*)
err "Unsupported architecture: $_arch"
;;
esac
curl -LSs "$_artifact_url" | tar -xf- -C "${_frameworks_dir}/bin"
echo "Download protobuf build"
_page=1
while [ $_page -gt 0 ]; do
_success=$(gh_curl "${_gh_url}/protocolbuffers/protobuf/releases?page=${_page}&per_page=100" \
| jq --arg arch "$(
if [ "$_arch" = 'arm64' ]; then
echo 'aarch_64'
else
echo 'x86_64'
fi
)" -r \
'. as $raw | if length == 0 then error("Error: \($raw)") else .[] | select(.prerelease | not) | .assets[] | select(.name | endswith("osx-\($arch).zip")) | .browser_download_url end' \
| while IFS= read -r _asset_url; do
if curl -LSs "${_asset_url}" | tar -xf - -C "$_frameworks_dir"; then
printf 'yes'
exit
fi
echo "Failed to download protobuf release, trying again in 1sec..." >&3
sleep 1
done)
if [ "${_success:-}" = 'yes' ]; then
break
fi
_page=$((_page + 1))
echo "protobuf release not found, trying again in 1sec..."
sleep 1
done
# Ensure all binaries are executable
chmod +x "$_frameworks_dir"/bin/*
cat <<EOF >"${_cargo_config}/config"
[env]
PROTOC = "${_frameworks_dir}/bin/protoc"
FFMPEG_DIR = "${_frameworks_dir}"
$(cat "${_cargo_config}/config.toml")
EOF
else
log_err "Your OS ($OSTYPE) is not supported by this script. We would welcome a PR or some help adding your OS to this script. https://github.com/spacedriveapp/spacedrive/issues"
exit 1
err "Your OS ($SYSNAME) is not supported by this script." \
'We would welcome a PR or some help adding your OS to this script.' \
'https://github.com/spacedriveapp/spacedrive/issues'
fi
echo "Your machine has been successfully set up for Spacedrive development."

View file

@ -5,26 +5,58 @@ name: Cache Factory
on:
push:
paths:
- 'Cargo.lock'
- '.github/scripts/setup-system.sh'
- '.github/scripts/setup-system.ps1'
- '.github/workflows/cache-factory.yaml'
- '.github/actions/**/*.yml'
- '.github/actions/**/*.yaml'
- '**/build.rs'
- 'core/prisma/**'
branches:
- main
# Cancel previous runs of the same workflow on the same branch.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
make_cache:
name: 'Make Cache'
runs-on: ${{ matrix.platform }}
strategy:
fail-fast: true
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
settings:
- host: macos-latest
target: x86_64-apple-darwin
- host: macos-latest
target: aarch64-apple-darwin
- host: windows-latest
target: x86_64-pc-windows-msvc
# - host: windows-latest
# target: aarch64-pc-windows-msvc
- host: ubuntu-20.04
target: x86_64-unknown-linux-gnu
# - host: ubuntu-20.04
# target: x86_64-unknown-linux-musl
# - host: ubuntu-20.04
# target: aarch64-unknown-linux-gnu
# - host: ubuntu-20.04
# target: aarch64-unknown-linux-musl
# - host: ubuntu-20.04
# target: armv7-unknown-linux-gnueabihf
name: 'Make Cache'
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v3
- name: Checkout repository
uses: actions/checkout@v3
- uses: ./.github/actions/setup
- name: Setup System and Rust
uses: ./.github/actions/setup-system
with:
token: ${{ secrets.GITHUB_TOKEN }}
targets: ${{ matrix.settings.target }}
save-cache: 'true'
- name: Compile (debug)

View file

@ -4,11 +4,33 @@ on:
push:
branches:
- main
pull_request:
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
- '.cspell/**'
- '.vscode/**'
- '.github/CODEOWNERS'
- '.github/FUNDING.yml'
- '.github/ISSUE_TEMPLATE/**'
- '.github/scripts/osxcross/**'
- '.github/scripts/ffmpeg-macos/**'
- '.gitattributes'
- 'cspell.config.yaml'
pull_request:
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
- '.cspell/**'
- '.vscode/**'
- '.github/CODEOWNERS'
- '.github/FUNDING.yml'
- '.github/ISSUE_TEMPLATE/**'
- '.github/scripts/osxcross/**'
- '.github/scripts/ffmpeg-macos/**'
- '.gitattributes'
- 'cspell.config.yaml'
workflow_dispatch:
env:
@ -22,70 +44,43 @@ concurrency:
jobs:
typescript:
name: TypeScript
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install pnpm
uses: pnpm/action-setup@v2.2.2
- name: Setup Node.js, pnpm and dependencies
uses: ./.github/actions/setup-pnpm
with:
version: 8.x.x
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
- name: Install pnpm dependencies
run: pnpm i --frozen-lockfile
token: ${{ secrets.GITHUB_TOKEN }}
- name: Perform typechecks
run: pnpm typecheck
eslint:
name: ESLint
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install pnpm
uses: pnpm/action-setup@v2.2.2
- name: Setup Node.js, pnpm and dependencies
uses: ./.github/actions/setup-pnpm
with:
version: 8.x.x
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
- name: Install pnpm dependencies
run: pnpm i --frozen-lockfile
token: ${{ secrets.GITHUB_TOKEN }}
- name: Perform linting
run: pnpm lint
rustfmt:
name: Rust Formatting
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt
- name: Cache Rust deps
uses: ./.github/actions/cache-rust-deps
- name: Generate Prisma client
uses: ./.github/actions/generate-prisma-client
- name: Setup Rust and Prisma
uses: ./.github/actions/setup-rust
- name: Run rustfmt
run: cargo fmt --all -- --check
@ -95,34 +90,34 @@ jobs:
runs-on: ${{ matrix.platform }}
strategy:
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
platform: [ubuntu-20.04, macos-latest, windows-latest]
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup
uses: ./.github/actions/setup
- name: Setup System and Rust
uses: ./.github/actions/setup-system
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Run Clippy
uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --all-features
token: ${{ secrets.GITHUB_TOKEN }}
# test:
# name: Test (${{ matrix.platform }})
# runs-on: ${{ matrix.platform }}
# strategy:
# matrix:
# platform: [ubuntu-latest, macos-latest, windows-latest]
# platform: [ubuntu-20.04, macos-latest, windows-latest]
# steps:
# - name: Checkout repository
# uses: actions/checkout@v3
#
# - name: Setup
# uses: ./.github/actions/setup
#
# - name: Test
# run: cargo test --workspace --all-features

66
.github/workflows/ffmpeg.yml vendored Normal file
View file

@ -0,0 +1,66 @@
name: Build ffmpeg
on:
push:
paths:
- '.github/workflows/ffmpeg.yml'
- '.github/scripts/ffmpeg-macos/**'
branches:
- main
pull_request:
paths:
- '.github/workflows/ffmpeg.yml'
- '.github/scripts/ffmpeg-macos/**'
workflow_dispatch:
# Cancel previous runs of the same workflow on the same branch.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
FFMPEG_VERSION: '6.0'
jobs:
build-ffmpeg-macos:
name: Build ffmpeg for macos
runs-on: ubuntu-20.04
defaults:
run:
shell: bash
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
install: true
platforms: linux/amd64
driver-opts: |
image=moby/buildkit:master
network=host
- name: Build ffmpeg
run: |
set -euxo pipefail
cd .github/scripts/ffmpeg-macos
docker build --build-arg FFMPEG_VERSION=$FFMPEG_VERSION -o . .
export XZ_OPT='-T0 -9'
tar -cJf "ffmpeg-${FFMPEG_VERSION}-x86_64.tar.xz" -C ffmpeg/x86_64 .
tar -cJf "ffmpeg-${FFMPEG_VERSION}-arm64.tar.xz" -C ffmpeg/aarch64 .
rm -rf ffmpeg
- name: Publish ffmpeg x86_64
uses: actions/upload-artifact@v3
with:
name: ffmpeg-${{ env.FFMPEG_VERSION }}-x86_64
path: .github/scripts/ffmpeg-macos/ffmpeg-${{ env.FFMPEG_VERSION }}-x86_64.tar.xz
if-no-files-found: error
- name: Publish ffmpeg arm64
uses: actions/upload-artifact@v3
with:
name: ffmpeg-${{ env.FFMPEG_VERSION }}-arm64
path: .github/scripts/ffmpeg-macos/ffmpeg-${{ env.FFMPEG_VERSION }}-arm64.tar.xz
if-no-files-found: error

View file

@ -32,64 +32,43 @@ jobs:
# steps:
# - name: Checkout repository
# uses: actions/checkout@v3
#
# - name: Setup Java JDK
# uses: actions/setup-java@v3.10.0
# with:
# java-version: '18'
# distribution: 'temurin'
# - name: Install pnpm
# uses: pnpm/action-setup@v2.2.2
#
# - name: Setup Node.js, pnpm and dependencies
# uses: ./.github/actions/setup-pnpm
# with:
# version: 8.x.x
# - name: Install Node.js
# uses: actions/setup-node@v3
# token: ${{ secrets.GITHUB_TOKEN }}
#
# - name: Setup System and Rust
# uses: ./.github/actions/setup-system
# with:
# node-version: 18
# cache: 'pnpm'
# - name: Install Rust stable
# uses: actions-rs/toolchain@v1
# with:
# toolchain: stable
# profile: minimal
# - name: Cache Rust deps
# uses: Swatinem/rust-cache@v2
# with:
# save-if: ${{ inputs.save-cache }} == "true"
# - name: Run 'setup-system.sh' script
# shell: bash
# run: ./.github/scripts/setup-system.sh mobile
# - name: Generate Prisma client
# uses: ./.github/actions/generate-prisma-client
# - name: Install pnpm dependencies
# run: pnpm i --frozen-lockfile
# token: ${{ secrets.GITHUB_TOKEN }}
# setup-arg: mobile
#
# - name: Setup Android SDK Tools
# uses: android-actions/setup-android@v2.0.2
#
# - name: Cache NDK
# uses: actions/cache@v3
# with:
# path: ${{ env.ANDROID_HOME }}/ndk/23.1.7779620
# key: ndk-23.1.7779620
#
# - name: Install NDK
# run: echo "y" | sudo ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install "ndk;23.1.7779620"
#
# - name: Cache Gradle
# uses: gradle/gradle-build-action@v2
#
# - name: Build Android
# working-directory: ./apps/mobile/android
# run: chmod +x ./gradlew && ./gradlew assembleRelease -PreactNativeArchitectures=x86_64 --no-daemon
#
# - name: Cache AVD
# uses: actions/cache@v3
# id: avd-cache
@ -98,9 +77,9 @@ jobs:
# ~/.android/avd/*
# ~/.android/adb*
# key: avd-30
#
# - name: Generate AVD Snapshot
# if: steps.avd-cache.outputs.cache-hit != 'true'
# if: ${{ steps.avd-cache.outputs.cache-hit != 'true' }}
# uses: ReactiveCircus/android-emulator-runner@v2.28.0
# with:
# arch: x86_64
@ -113,13 +92,13 @@ jobs:
# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
# disable-animations: false
# script: echo "Generated AVD snapshot."
#
# - name: Install Maestro
# run: |
# # workaround for https://github.com/mobile-dev-inc/maestro/issues/877
# export MAESTRO_VERSION=1.21.3; curl -Ls "https://get.maestro.mobile.dev" | bash
# echo "$HOME/.maestro/bin" >> $GITHUB_PATH
#
# - name: Run Tests
# uses: ReactiveCircus/android-emulator-runner@v2.28.0
# with:
@ -145,41 +124,20 @@ jobs:
uses: actions/checkout@v3
- name: Install Xcode
uses: maxim-lobanov/setup-xcode@v1.5.1
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Install pnpm
uses: pnpm/action-setup@v2.2.2
- name: Setup Node.js, pnpm and dependencies
uses: ./.github/actions/setup-pnpm
with:
version: 8.x.x
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Node.js
uses: actions/setup-node@v3
- name: Setup System and Rust
uses: ./.github/actions/setup-system
with:
node-version: 18
cache: 'pnpm'
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
- name: Cache Rust deps
uses: Swatinem/rust-cache@v2
with:
save-if: ${{ inputs.save-cache }} == "true"
- name: Run 'setup-system.sh' script
shell: bash
run: ./.github/scripts/setup-system.sh mobile
- name: Generate Prisma client
uses: ./.github/actions/generate-prisma-client
- name: Install pnpm dependencies
run: pnpm i --frozen-lockfile
token: ${{ secrets.GITHUB_TOKEN }}
setup-arg: mobile
- name: Cache Pods
uses: actions/cache@v3
@ -203,7 +161,7 @@ jobs:
run: |
curl -Ls "https://get.maestro.mobile.dev" | bash
brew tap facebook/fb
brew install facebook/fb/idb-companion
brew install facebook/fb/idb-companion
echo "$HOME/.maestro/bin" >> $GITHUB_PATH
- name: Run Simulator

View file

@ -1,39 +1,64 @@
name: Release
on:
push:
branches:
- main
workflow_dispatch:
# NOTE: For Linux builds, we can only build with Ubuntu. It should be the oldest base system we intend to support. See PR-759 & https://tauri.app/v1/guides/building/linux for reference.
jobs:
desktop-main:
name: Desktop - Main (${{ matrix.platform }})
runs-on: ${{ matrix.platform }}
strategy:
fail-fast: true
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
settings:
- host: macos-latest
target: x86_64-apple-darwin
bundles: dmg
- host: macos-latest
target: aarch64-apple-darwin
bundles: dmg
- host: windows-latest
target: x86_64-pc-windows-msvc
bundles: msi
# - host: windows-latest
# target: aarch64-pc-windows-msvc
- host: ubuntu-20.04
target: x86_64-unknown-linux-gnu
bundles: deb,appimage
# - host: ubuntu-20.04
# target: x86_64-unknown-linux-musl
# - host: ubuntu-20.04
# target: aarch64-unknown-linux-gnu
# - host: ubuntu-20.04
# target: aarch64-unknown-linux-musl
# - host: ubuntu-20.04
# target: armv7-unknown-linux-gnueabihf
name: Desktop - Main ${{ matrix.settings.target }}
runs-on: ${{ matrix.settings.host }}
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup
uses: ./.github/actions/setup
- name: Setup Node.js, pnpm and dependencies
uses: ./.github/actions/setup-pnpm
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install pnpm dependencies
run: pnpm i --frozen-lockfile
- name: Setup System and Rust
uses: ./.github/actions/setup-system
with:
token: ${{ secrets.GITHUB_TOKEN }}
targets: ${{ matrix.settings.target }}
- name: Build
uses: tauri-apps/tauri-action@dev
run: |
pnpm desktop build --ci -v --target ${{ matrix.settings.target }} --bundles ${{ matrix.settings.bundles }},updater
env:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
with:
projectPath: apps/desktop
- name: Publish Artifacts
uses: ./.github/actions/publish-artifacts
with:
target: ${{ matrix.settings.target }}
profile: release

View file

@ -0,0 +1,69 @@
# Copyright 2019-2023 Tauri Programme within The Commons Conservancy
# SPDX-License-Identifier: Apache-2.0
# SPDX-License-Identifier: MIT
name: publish cli.js
env:
DEBUG: napi:*
APP_NAME: cli
MACOSX_DEPLOYMENT_TARGET: '10.13'
on:
workflow_dispatch:
defaults:
run:
working-directory: tooling/cli/node/
jobs:
build:
strategy:
fail-fast: true
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
architecture: x64
build: |
yarn build:release --features rustls
strip -x *.node
- host: macos-latest
target: aarch64-apple-darwin
build: |
yarn build:release --features rustls --target=aarch64-apple-darwin
strip -x *.node
name: stable - ${{ matrix.settings.target }} - node@16
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v3
with:
repository: 'dceddia/tauri'
ref: 'dd32f97335a6105b134e70dad02d269e49a75b56'
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 16
check-latest: true
architecture: ${{ matrix.settings.architecture }}
- name: Install
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.settings.target }}
toolchain: stable
- name: Install dependencies
run: yarn install --ignore-scripts --frozen-lockfile --registry https://registry.npmjs.org --network-timeout 300000
- name: Build
run: ${{ matrix.settings.build }}
shell: bash
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: bindings-${{ matrix.settings.target }}
path: tooling/cli/node/${{ env.APP_NAME }}.*.node
if-no-files-found: error

4
.gitignore vendored
View file

@ -25,6 +25,7 @@ packages/*/data
apps/*/data
apps/*/stats.html
apps/releases/.vscode
apps/desktop/src-tauri/tauri.conf.patch.json
docs/public/*.st
docs/public/*.toml
dev.db
@ -73,3 +74,6 @@ dev.db-journal
.swiftpm
/core/migration_test
sd_init.json
.cargo/config
.github/scripts/deps

View file

@ -43,7 +43,6 @@ This project uses [Cargo](https://doc.rust-lang.org/cargo/getting-started/instal
- This will install FFmpeg and any other required dependencies for Spacedrive to build.
- For Windows users run using PowerShell: `.\.github\scripts\setup-system.ps1`
- This will install pnpm, LLVM, FFmpeg and any other required dependencies for Spacedrive to build.
- Ensure you run it like documented above as it expects it is executed from the root of the repository.
- `pnpm i`
- `pnpm prep` - Runs all necessary codegen & builds required dependencies.
@ -68,6 +67,8 @@ If you are having issues ensure you are using the following versions of Rust and
- Rust version: **1.68.2**
- Node version: **18**
After clearing out your build artifacts with either `pnpm clean`, `git clean` or `cargo clean`, it is required to re-run the `setup-system` script.
Be sure to read the [guidelines](https://spacedrive.com/docs/developers/prerequisites/guidelines) to make sure your code is a similar style to ours.
##### Mobile app

3
Cargo.lock generated
View file

@ -7750,8 +7750,7 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "swift-rs"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05e51d6f2b5fff4808614f429f8a7655ac8bcfe218185413f3a60c508482c2d6"
source = "git+https://github.com/Brendonovich/swift-rs?rev=973c22215734d1d5b97c496601d658371e537ece#973c22215734d1d5b97c496601d658371e537ece"
dependencies = [
"base64 0.21.0",
"serde",

View file

@ -47,3 +47,5 @@ mdns-sd = { git = "https://github.com/oscartbeaumont/mdns-sd", rev = "45515a98e9
rspc = { git = "https://github.com/oscartbeaumont/rspc", rev = "799eec5df7533edf331f41d3f1be03de07e038d7" }
httpz = { git = "https://github.com/oscartbeaumont/httpz", rev = "a5185f2ed2fdefeb2f582dce38a692a1bf76d1d6" }
swift-rs = { git = "https://github.com/Brendonovich/swift-rs", rev = "973c22215734d1d5b97c496601d658371e537ece" }

View file

@ -6,10 +6,9 @@
"private": true,
"scripts": {
"vite": "vite",
"dev": "tauri dev",
"dev": "node ./src-tauri/scripts/tauri.js dev",
"dev-vite": "vite --clearScreen=false --mode development",
"tauri": "tauri",
"build": "node ./src-tauri/build.js",
"build": "node ./src-tauri/scripts/tauri.js build",
"dmg": "open ../../target/release/bundle/dmg/",
"typecheck": "tsc -b",
"lint": "eslint src --cache"
@ -21,21 +20,23 @@
"@sd/interface": "workspace:*",
"@sd/ui": "workspace:*",
"@tanstack/react-query": "^4.24.4",
"@tauri-apps/api": "1.2.0",
"@tauri-apps/api": "1.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "6.9.0",
"vite-plugin-html": "^3.2.0"
},
"devDependencies": {
"@iarna/toml": "^2.2.5",
"@sd/config": "workspace:*",
"@tauri-apps/cli": "1.2.3",
"@tauri-apps/cli": "1.3.1",
"@types/babel-core": "^6.25.7",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^2.1.0",
"react-devtools": "^4.27.2",
"sass": "^1.55.0",
"semver": "^7.5.0",
"typescript": "^4.8.4",
"vite": "^4.0.4",
"vite-plugin-svgr": "^2.2.1",

View file

@ -9,7 +9,7 @@ default-run = "spacedrive"
edition = "2021"
[dependencies]
tauri = { version = "1.3.0", features = ["api-all", "linux-protocol-headers", "macos-private-api", "updater"] }
tauri = { version = "1.3.0", features = ["api-all", "linux-protocol-headers", "macos-private-api"] }
rspc = { workspace = true, features = ["tauri"] }
httpz = { workspace = true, features = ["axum", "tauri"] } # TODO: The `axum` feature should be only enabled on Linux but this currently can't be done: https://github.com/rust-lang/cargo/issues/1197
sd-core = { path = "../../../core", features = ["ffmpeg", "location-watcher"] }
@ -36,4 +36,5 @@ tauri-build = { version = "1.3.0", features = [] }
[features]
default = ["custom-protocol"]
updater = ["tauri/updater"]
custom-protocol = ["tauri/custom-protocol"]

View file

@ -1,13 +0,0 @@
const path = require('path');
const { spawn } = require('child_process');
process.env.BACKGROUND_FILE = path.join(__dirname, './dmg-background.png');
process.env.BACKGROUND_FILE_NAME = path.basename(process.env.BACKGROUND_FILE);
process.env.BACKGROUND_CLAUSE = `set background picture of opts to file ".background:${process.env.BACKGROUND_FILE_NAME}"`;
const child = spawn('pnpm', ['tauri', 'build']);
child.stdout.on('data', (data) => console.log(data.toString()));
child.stderr.on('data', (data) => console.error(data.toString()));
child.on('exit', (code) => {
if (code !== 0) console.log(`Child exited with code ${code}`);
});

View file

@ -0,0 +1,9 @@
const path = require('node:path');
const platform = /^(msys|cygwin)$/.test(process.env.OSTYPE ?? '') ? 'win32' : process.platform;
module.exports = {
platform,
workspace: path.resolve(__dirname, '../../../../'),
setupScript: `.github/scripts/${platform === 'win32' ? 'setup-system.ps1' : 'setup-system.sh'}`
};

View file

@ -0,0 +1,72 @@
const fs = require('node:fs');
const path = require('node:path');
const toml = require('@iarna/toml');
const { platform, workspace, setupScript } = require('./const.js');
const cargoConfig = path.resolve(workspace, '.cargo/config');
const cargoConfigTempl = path.resolve(workspace, '.cargo/config.toml');
module.exports.setupFFMpegDlls = function setupDlls(FFMPEG_DIR, dev = false) {
const ffmpegBinDir = path.join(FFMPEG_DIR, 'bin');
const ffmpegDlls = fs.readdirSync(ffmpegBinDir).filter((file) => file.endsWith('.dll'));
let targetDir = path.join(workspace, 'apps/desktop/src-tauri');
if (dev) {
targetDir = path.join(workspace, 'target/debug');
// Ensure the target/debug directory exists
fs.mkdirSync(targetDir, { recursive: true });
}
// Copy all DLLs from the $FFMPEG_DIR/bin to targetDir
for (const dll of ffmpegDlls)
fs.copyFileSync(path.join(ffmpegBinDir, dll), path.join(targetDir, dll));
return ffmpegDlls;
};
module.exports.setupPlatformEnv = function setupEnv() {
const env = {};
if (platform === 'darwin' || platform === 'win32') {
env.PROTOC = path.join(
workspace,
'target/Frameworks/bin',
platform === 'win32' ? 'protoc.exe' : 'protoc'
);
env.FFMPEG_DIR = path.join(workspace, 'target/Frameworks');
// Check if env.PROTOC is not empty and that the value is a valid path pointing to an existing file
if (!(env.PROTOC && fs.existsSync(env.PROTOC) && fs.statSync(env.PROTOC).isFile())) {
console.error(`The path to protoc is invalid: ${env.PROTOC}`);
console.error(`Did you ran the setup script: ${setupScript}?`);
process.exit(1);
}
// Check if env.FFMPEG_DIR is not empty and that the value is a valid path pointing to an existing directory
if (
!(
env.FFMPEG_DIR &&
fs.existsSync(env.FFMPEG_DIR) &&
fs.statSync(env.FFMPEG_DIR).isDirectory()
)
) {
console.error(`The path to ffmpeg is invalid: ${env.FFMPEG_DIR}`);
console.error(`Did you ran the setup script: ${setupScript}?`);
process.exit(1);
}
// Update cargo config with the new env variables
const cargoConf = toml.parse(fs.readFileSync(cargoConfigTempl, { encoding: 'binary' }));
cargoConf.env = {
...(cargoConf.env ?? {}),
...(env ?? {}),
PROTOC: env.PROTOC,
FFMPEG_DIR: env.FFMPEG_DIR
};
fs.writeFileSync(cargoConfig, toml.stringify(cargoConf));
}
return env;
};

View file

@ -0,0 +1,30 @@
const { spawn } = require('node:child_process');
module.exports.spawn = (command, args) => {
if (typeof command !== 'string' || command.length === 0)
throw new Error('Command must be a string and not empty');
if (args == null) args = [];
else if (!Array.isArray(args) || args.some((arg) => typeof arg !== 'string'))
throw new Error('Args must be an array of strings');
return new Promise((resolve, reject) => {
const child = spawn(command, args, { shell: true, stdio: 'inherit' });
process.on('SIGTERM', () => child.kill('SIGTERM'));
process.on('SIGINT', () => child.kill('SIGINT'));
process.on('SIGBREAK', () => child.kill('SIGBREAK'));
process.on('SIGHUP', () => child.kill('SIGHUP'));
child.on('error', (error) => {
console.error(error);
reject(1);
});
child.on('exit', (code, signal) => {
if (code === null) code = signal === 'SIGINT' ? 0 : 1;
if (code === 0) {
resolve();
} else {
reject(code);
}
});
});
};

View file

@ -0,0 +1,151 @@
const fs = require('node:fs');
const path = require('node:path');
const semver = require('semver');
const { spawn } = require('./spawn.js');
const { platform, workspace, setupScript } = require('./const.js');
const { setupFFMpegDlls, setupPlatformEnv } = require('./env.js');
const toRemove = [];
const [_, __, ...args] = process.argv;
if (args.length === 0) args.push('build');
const tauriConf = JSON.parse(
fs.readFileSync(path.resolve(__dirname, '..', 'tauri.conf.json'), 'utf-8')
);
switch (args[0]) {
case 'dev': {
const env = setupPlatformEnv();
if (platform === 'win32') setupFFMpegDlls(env.FFMPEG_DIR, true);
break;
}
case 'build': {
if (args.findIndex((e) => e === '-c' || e === '--config') !== -1) {
throw new Error('Custom tauri build config is not supported.');
}
const targets = args
.filter((_, index, args) => {
if (index === 0) return false;
const previous = args[index - 1];
return previous === '-t' || previous === '--target';
})
.flatMap((target) => target.split(','));
const env = setupPlatformEnv();
const tauriPatch = {
build: { features: [] },
tauri: { bundle: { macOS: {} }, updater: {} }
};
if (process.env.TAURI_PRIVATE_KEY) {
console.log('Tauri Private Key detected, enabling updater');
tauriPatch.build.features.push('updater');
tauriPatch.tauri.updater.active = true;
}
switch (platform) {
case 'darwin': {
// Workaround while https://github.com/tauri-apps/tauri/pull/3934 is not merged
const cliNode =
process.arch === 'arm64' ? 'cli.darwin-arm64.node' : 'cli.darwin-x64.node';
const tauriCliPatch = path.join(workspace, 'target/Frameworks/bin/', cliNode);
if (!fs.existsSync(tauriCliPatch)) {
throw new Error(
`Tauri cli patch not found at ${path.relative(
workspace,
tauriCliPatch
)}. Did you run the setup script: ${setupScript}?`
);
}
const tauriBin = path.join(
workspace,
'node_modules/@tauri-apps',
cliNode.replace(/\.[^.]+$/, '').replace(/\./g, '-'),
cliNode
);
if (!fs.existsSync(tauriBin)) {
throw new Error('tauri bin not found at ${tauriBin}. Did you run `pnpm i`?');
}
console.log(
`WORKAROUND tauri-apps/tauri#3933: Replace ${path.relative(
workspace,
tauriBin
)} -> ${path.relative(workspace, tauriCliPatch)}`
);
fs.copyFileSync(tauriCliPatch, tauriBin);
// ARM64 support was added in macOS 11, but we need at least 11.2 due to our ffmpeg build
let macOSMinimumVersion = tauriConf?.tauri?.bundle?.macOS?.minimumSystemVersion;
let macOSArm64MinimumVersion = '11.2';
if (
(targets.includes('aarch64-apple-darwin') ||
(targets.length === 0 && process.arch === 'arm64')) &&
(macOSMinimumVersion == null ||
semver.lt(
semver.coerce(macOSMinimumVersion),
semver.coerce(macOSArm64MinimumVersion)
))
) {
macOSMinimumVersion = macOSArm64MinimumVersion;
console.log(
`aarch64-apple-darwin target detected, setting minimum system version to ${macOSMinimumVersion}`
);
}
if (macOSMinimumVersion) {
process.env.MACOSX_DEPLOYMENT_TARGET = macOSMinimumVersion;
tauriPatch.tauri.bundle.macOS.minimumSystemVersion = macOSMinimumVersion;
}
// Point tauri to our ffmpeg framework
tauriPatch.tauri.bundle.macOS.frameworks = [
path.join(workspace, 'target/Frameworks/FFMpeg.framework')
];
// Configure DMG background
process.env.BACKGROUND_FILE = path.resolve(__dirname, '..', 'dmg-background.png');
process.env.BACKGROUND_FILE_NAME = path.basename(process.env.BACKGROUND_FILE);
process.env.BACKGROUND_CLAUSE = `set background picture of opts to file ".background:${process.env.BACKGROUND_FILE_NAME}"`;
break;
}
case 'win32':
// Point tauri to the ffmpeg DLLs
tauriPatch.tauri.bundle.resources = setupFFMpegDlls(env.FFMPEG_DIR);
toRemove.push(
...tauriPatch.tauri.bundle.resources.map((file) =>
path.join(workspace, 'apps/desktop/src-tauri', file)
)
);
break;
}
const tauriPatchConf = path.resolve(__dirname, '..', 'tauri.conf.patch.json');
fs.writeFileSync(tauriPatchConf, JSON.stringify(tauriPatch, null, 2));
toRemove.push(tauriPatchConf);
args.splice(1, 0, '-c', tauriPatchConf);
}
}
let code = 0;
spawn('pnpm', ['tauri', ...args])
.catch((exitCode) => {
code = exitCode;
console.error(`tauri ${args[0]} failed with exit code ${exitCode}`);
console.error(
`If you got an error related to FFMpeg or Protoc/Protobuf you may need to run ${setupScript}`
);
})
.finally(() => {
for (const file of toRemove)
try {
fs.unlinkSync(file);
} catch (e) {}
process.exit(code);
});

View file

@ -83,6 +83,7 @@ async fn main() -> tauri::Result<()> {
let app = app
.setup(|app| {
#[cfg(feature = "updater")]
tauri::updater::builder(app.handle()).should_install(|_current, _latest| true);
let app = app.handle();

View file

@ -47,7 +47,7 @@
}
},
"updater": {
"active": true,
"active": false,
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEZBMURCMkU5NEU3NDAyOEMKUldTTUFuUk82YklkK296dlkxUGkrTXhCT3ZMNFFVOWROcXNaS0RqWU1kMUdRV2tDdFdIS0Y3YUsK",
"endpoints": [
"https://releases-6oxwxxryr-spacedrive.vercel.app/{{target}}/{{arch}}/{{current_version}}"

View file

@ -1,23 +1,24 @@
#! /bin/zsh
#!/usr/bin/env zsh
set -e
TARGET_DIRECTORY=../../../target
__dirname="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)"
TARGET_DIRECTORY="$(CDPATH='' cd -- "${__dirname}/../../../target" && pwd)"
CARGO_FLAGS=
if [[ $CONFIGURATION != "Debug" ]]; then
CARGO_FLAGS=--release
export CARGO_FLAGS
fi
export PROTOC="${TARGET_DIRECTORY}/Frameworks/bin/protoc"
# TODO: Also do this for non-Apple Silicon Macs
if [[ $SPACEDRIVE_CI == "1" ]]; then
# Required for CI
export PATH="$HOME/.cargo/bin:$PATH"
export PROTOC=/usr/local/bin/protoc
cargo build -p sd-mobile-ios --target x86_64-apple-ios
if [[ $PLATFORM_NAME = "iphonesimulator" ]]
then
lipo -create -output $TARGET_DIRECTORY/libsd_mobile_ios-iossim.a $TARGET_DIRECTORY/x86_64-apple-ios/debug/libsd_mobile_ios.a
@ -27,9 +28,6 @@ if [[ $SPACEDRIVE_CI == "1" ]]; then
exit 0
fi
# Required for M1 Mac builds (?)
export PROTOC=/opt/homebrew/bin/protoc
if [[ $PLATFORM_NAME = "iphonesimulator" ]]
then
cargo build -p sd-mobile-ios --target aarch64-apple-ios-sim

View file

@ -4,26 +4,19 @@ use std::path::Path;
pub(crate) fn from_path(path: impl AsRef<Path>) -> Result<CString, ThumbnailerError> {
let path = path.as_ref();
let path_str = path.as_os_str();
#[cfg(unix)]
{
use std::os::unix::ffi::OsStrExt;
CString::new(path.as_os_str().as_bytes())
CString::new(path_str.as_bytes())
.map_err(|_| ThumbnailerError::PathConversion(path.to_path_buf()))
}
#[cfg(windows)]
#[cfg(not(unix))]
{
use std::os::windows::ffi::OsStrExt;
CString::from_vec_with_nul(
path.as_os_str()
.encode_wide()
.chain(Some(0))
.flat_map(|b| {
let b = b.to_ne_bytes();
b.first().copied().into_iter().chain(b.get(1).copied())
})
.collect::<Vec<u8>>(),
)
.map_err(|_| ThumbnailerError::PathConversion(path.to_path_buf()))
path_str
.to_str()
.and_then(|str| CString::new(str.as_bytes()).ok())
.ok_or(ThumbnailerError::PathConversion(path.to_path_buf()))
}
}

View file

@ -1,6 +1,14 @@
#[cfg(target_os = "macos")]
use std::env;
fn main() {
#[cfg(target_os = "macos")]
swift_rs::SwiftLinker::new("10.15")
.with_package("sd-macos", "./")
.link()
{
let deployment_target =
env::var("MACOSX_DEPLOYMENT_TARGET").unwrap_or_else(|_| String::from("10.15"));
swift_rs::SwiftLinker::new(deployment_target.as_str())
.with_package("sd-macos", "./")
.link()
}
}

View file

@ -1,7 +1,7 @@
{
"private": true,
"scripts": {
"prep": "pnpm gen:prisma && cargo test -p sd-core api::tests::test_and_export_rspc_bindings -- --exact",
"prep": "pnpm gen:prisma && pnpm codegen",
"build": "turbo run build",
"landing-web": "turbo run dev --parallel --filter=@sd/landing --filter=@sd/web",
"gen:migrations": "cd core && cargo prisma migrate dev",

View file

@ -51,7 +51,7 @@ importers:
version: 0.0.0-main-799eec5d
'@rspc/tauri':
specifier: '=0.0.0-main-799eec5d'
version: 0.0.0-main-799eec5d(@tauri-apps/api@1.2.0)
version: 0.0.0-main-799eec5d(@tauri-apps/api@1.3.0)
'@sd/client':
specifier: workspace:*
version: link:../../packages/client
@ -65,8 +65,8 @@ importers:
specifier: ^4.24.4
version: 4.29.5(react-dom@18.2.0)(react-native@0.71.3)(react@18.2.0)
'@tauri-apps/api':
specifier: 1.2.0
version: 1.2.0
specifier: 1.3.0
version: 1.3.0
react:
specifier: ^18.2.0
version: 18.2.0
@ -80,12 +80,15 @@ importers:
specifier: ^3.2.0
version: 3.2.0(vite@4.3.5)
devDependencies:
'@iarna/toml':
specifier: ^2.2.5
version: 2.2.5
'@sd/config':
specifier: workspace:*
version: link:../../packages/config
'@tauri-apps/cli':
specifier: 1.2.3
version: 1.2.3
specifier: 1.3.1
version: 1.3.1
'@types/babel-core':
specifier: ^6.25.7
version: 6.25.7
@ -104,6 +107,9 @@ importers:
sass:
specifier: ^1.55.0
version: 1.62.1
semver:
specifier: ^7.5.0
version: 7.5.0
typescript:
specifier: ^4.8.4
version: 4.9.5
@ -3392,6 +3398,10 @@ packages:
/@humanwhocodes/object-schema@1.2.1:
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
/@iarna/toml@2.2.5:
resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==}
dev: true
/@icons-pack/react-simple-icons@5.11.0(react@18.2.0):
resolution: {integrity: sha512-hFJ4Q4JcYe/wQUab+gIug1BONjBUelaUVFYsZ1FKv5CEX/fP56qGet4CPmx18BqDhxrOehidYNlLyGppXL9/7w==}
peerDependencies:
@ -5287,13 +5297,13 @@ packages:
react: 18.2.0
dev: false
/@rspc/tauri@0.0.0-main-799eec5d(@tauri-apps/api@1.2.0):
/@rspc/tauri@0.0.0-main-799eec5d(@tauri-apps/api@1.3.0):
resolution: {integrity: sha512-1EQiAfDqDe0iV/CoSadw58EasA/finfoXx0h4odZx+mUVlkV6CUd9QC03EtTrXPoA6MrjA+oWKbBP/2wj/CrHg==}
peerDependencies:
'@tauri-apps/api': ^1.2.0
dependencies:
'@rspc/client': 0.0.0-main-799eec5d
'@tauri-apps/api': 1.2.0
'@tauri-apps/api': 1.3.0
dev: false
/@rushstack/eslint-patch@1.2.0:
@ -6854,13 +6864,13 @@ packages:
engines: {node: '>=12'}
dev: false
/@tauri-apps/api@1.2.0:
resolution: {integrity: sha512-lsI54KI6HGf7VImuf/T9pnoejfgkNoXveP14pVV7XarrQ46rOejIVJLFqHI9sRReJMGdh2YuCoI3cc/yCWCsrw==}
/@tauri-apps/api@1.3.0:
resolution: {integrity: sha512-AH+3FonkKZNtfRtGrObY38PrzEj4d+1emCbwNGu0V2ENbXjlLHMZQlUh+Bhu/CRmjaIwZMGJ3yFvWaZZgTHoog==}
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
dev: false
/@tauri-apps/cli-darwin-arm64@1.2.3:
resolution: {integrity: sha512-phJN3fN8FtZZwqXg08bcxfq1+X1JSDglLvRxOxB7VWPq+O5SuB8uLyssjJsu+PIhyZZnIhTGdjhzLSFhSXfLsw==}
/@tauri-apps/cli-darwin-arm64@1.3.1:
resolution: {integrity: sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@ -6868,8 +6878,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-darwin-x64@1.2.3:
resolution: {integrity: sha512-jFZ/y6z8z6v4yliIbXKBXA7BJgtZVMsITmEXSuD6s5+eCOpDhQxbRkr6CA+FFfr+/r96rWSDSgDenDQuSvPAKw==}
/@tauri-apps/cli-darwin-x64@1.3.1:
resolution: {integrity: sha512-fKcAUPVFO3jfDKXCSDGY0MhZFF/wDtx3rgFnogWYu4knk38o9RaqRkvMvqJhLYPuWaEM5h6/z1dRrr9KKCbrVg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@ -6877,8 +6887,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm-gnueabihf@1.2.3:
resolution: {integrity: sha512-C7h5vqAwXzY0kRGSU00Fj8PudiDWFCiQqqUNI1N+fhCILrzWZB9TPBwdx33ZfXKt/U4+emdIoo/N34v3TiAOmQ==}
/@tauri-apps/cli-linux-arm-gnueabihf@1.3.1:
resolution: {integrity: sha512-+4H0dv8ltJHYu/Ma1h9ixUPUWka9EjaYa8nJfiMsdCI4LJLNE6cPveE7RmhZ59v9GW1XB108/k083JUC/OtGvA==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
@ -6886,8 +6896,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm64-gnu@1.2.3:
resolution: {integrity: sha512-buf1c8sdkuUzVDkGPQpyUdAIIdn5r0UgXU6+H5fGPq/Xzt5K69JzXaeo6fHsZEZghbV0hOK+taKV4J0m30UUMQ==}
/@tauri-apps/cli-linux-arm64-gnu@1.3.1:
resolution: {integrity: sha512-Pj3odVO1JAxLjYmoXKxcrpj/tPxcA8UP8N06finhNtBtBaxAjrjjxKjO4968KB0BUH7AASIss9EL4Tr0FGnDuw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@ -6895,8 +6905,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm64-musl@1.2.3:
resolution: {integrity: sha512-x88wPS9W5xAyk392vc4uNHcKBBvCp0wf4H9JFMF9OBwB7vfd59LbQCFcPSu8f0BI7bPrOsyHqspWHuFL8ojQEA==}
/@tauri-apps/cli-linux-arm64-musl@1.3.1:
resolution: {integrity: sha512-tA0JdDLPFaj42UDIVcF2t8V0tSha40rppcmAR/MfQpTCxih6399iMjwihz9kZE1n4b5O4KTq9GliYo50a8zYlQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@ -6904,8 +6914,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-x64-gnu@1.2.3:
resolution: {integrity: sha512-ZMz1jxEVe0B4/7NJnlPHmwmSIuwiD6ViXKs8F+OWWz2Y4jn5TGxWKFg7DLx5OwQTRvEIZxxT7lXHi5CuTNAxKg==}
/@tauri-apps/cli-linux-x64-gnu@1.3.1:
resolution: {integrity: sha512-FDU+Mnvk6NLkqQimcNojdKpMN4Y3W51+SQl+NqG9AFCWprCcSg62yRb84751ujZuf2MGT8HQOfmd0i77F4Q3tQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@ -6913,8 +6923,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-x64-musl@1.2.3:
resolution: {integrity: sha512-B/az59EjJhdbZDzawEVox0LQu2ZHCZlk8rJf85AMIktIUoAZPFbwyiUv7/zjzA/sY6Nb58OSJgaPL2/IBy7E0A==}
/@tauri-apps/cli-linux-x64-musl@1.3.1:
resolution: {integrity: sha512-MpO3akXFmK8lZYEbyQRDfhdxz1JkTBhonVuz5rRqxwA7gnGWHa1aF1+/2zsy7ahjB2tQ9x8DDFDMdVE20o9HrA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@ -6922,8 +6932,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-win32-ia32-msvc@1.2.3:
resolution: {integrity: sha512-ypdO1OdC5ugNJAKO2m3sb1nsd+0TSvMS9Tr5qN/ZSMvtSduaNwrcZ3D7G/iOIanrqu/Nl8t3LYlgPZGBKlw7Ng==}
/@tauri-apps/cli-win32-ia32-msvc@1.3.1:
resolution: {integrity: sha512-9Boeo3K5sOrSBAZBuYyGkpV2RfnGQz3ZhGJt4hE6P+HxRd62lS6+qDKAiw1GmkZ0l1drc2INWrNeT50gwOKwIQ==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
@ -6931,8 +6941,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-win32-x64-msvc@1.2.3:
resolution: {integrity: sha512-CsbHQ+XhnV/2csOBBDVfH16cdK00gNyNYUW68isedmqcn8j+s0e9cQ1xXIqi+Hue3awp8g3ImYN5KPepf3UExw==}
/@tauri-apps/cli-win32-x64-msvc@1.3.1:
resolution: {integrity: sha512-wMrTo91hUu5CdpbElrOmcZEoJR4aooTG+fbtcc87SMyPGQy1Ux62b+ZdwLvL1sVTxnIm//7v6QLRIWGiUjCPwA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@ -6940,20 +6950,20 @@ packages:
dev: true
optional: true
/@tauri-apps/cli@1.2.3:
resolution: {integrity: sha512-erxtXuPhMEGJPBtnhPILD4AjuT81GZsraqpFvXAmEJZ2p8P6t7MVBifCL8LznRknznM3jn90D3M8RNBP3wcXTw==}
/@tauri-apps/cli@1.3.1:
resolution: {integrity: sha512-o4I0JujdITsVRm3/0spfJX7FcKYrYV1DXJqzlWIn6IY25/RltjU6qbC1TPgVww3RsRX63jyVUTcWpj5wwFl+EQ==}
engines: {node: '>= 10'}
hasBin: true
optionalDependencies:
'@tauri-apps/cli-darwin-arm64': 1.2.3
'@tauri-apps/cli-darwin-x64': 1.2.3
'@tauri-apps/cli-linux-arm-gnueabihf': 1.2.3
'@tauri-apps/cli-linux-arm64-gnu': 1.2.3
'@tauri-apps/cli-linux-arm64-musl': 1.2.3
'@tauri-apps/cli-linux-x64-gnu': 1.2.3
'@tauri-apps/cli-linux-x64-musl': 1.2.3
'@tauri-apps/cli-win32-ia32-msvc': 1.2.3
'@tauri-apps/cli-win32-x64-msvc': 1.2.3
'@tauri-apps/cli-darwin-arm64': 1.3.1
'@tauri-apps/cli-darwin-x64': 1.3.1
'@tauri-apps/cli-linux-arm-gnueabihf': 1.3.1
'@tauri-apps/cli-linux-arm64-gnu': 1.3.1
'@tauri-apps/cli-linux-arm64-musl': 1.3.1
'@tauri-apps/cli-linux-x64-gnu': 1.3.1
'@tauri-apps/cli-linux-x64-musl': 1.3.1
'@tauri-apps/cli-win32-ia32-msvc': 1.3.1
'@tauri-apps/cli-win32-x64-msvc': 1.3.1
dev: true
/@testing-library/dom@8.20.0: