diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml new file mode 100644 index 0000000..b87b045 --- /dev/null +++ b/.github/workflows/build-nightly.yml @@ -0,0 +1,110 @@ +name: Build Nightly Releases +on: + push: + branches: [master] + +env: + CARGO_TERM_COLOR: always + +jobs: + build-cross: + runs-on: ubuntu-latest + env: + RUST_BACKTRACE: full + strategy: + matrix: + target: + - x86_64-unknown-linux-musl + - aarch64-unknown-linux-musl + + steps: + - uses: actions/checkout@v2 + + - name: Install cross + run: cargo install cross + + - name: Build ${{ matrix.target }} + timeout-minutes: 120 + run: | + compile_target=${{ matrix.target }} + + cd build + ./build-release -t ${{ matrix.target }} $compile_features $compile_compress + + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.target }} + path: build/release/* + + build-unix: + runs-on: ${{ matrix.os }} + env: + RUST_BACKTRACE: full + strategy: + matrix: + os: [macos-latest] + target: + - x86_64-apple-darwin + - aarch64-apple-darwin + steps: + - uses: actions/checkout@v2 + + - name: Install GNU tar + if: runner.os == 'macOS' + run: | + brew install gnu-tar + # echo "::add-path::/usr/local/opt/gnu-tar/libexec/gnubin" + echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH + + - name: Install Rust stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + target: ${{ matrix.target }} + default: true + override: true + + # https://github.com/actions/virtual-environments/issues/2557#issuecomment-769611326 + - if: ${{ matrix.target }} == 'aarch64-apple-darwin' + run: | + sudo xcode-select -s /Applications/Xcode_12.4.app && + sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/* + + - name: Build release + shell: bash + run: | + ./build/build-host-release -t ${{ matrix.target }} + + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.target }} + path: build/release/* + + build-windows: + runs-on: windows-latest + env: + RUSTFLAGS: "-Ctarget-feature=+crt-static" + RUST_BACKTRACE: full + steps: + - uses: actions/checkout@v2 + + - name: Install Rust stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + default: true + override: true + + - name: Build release + run: | + pwsh ./build/build-host-release.ps1 + + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: windows-native + path: build/release/* diff --git a/build/README.md b/build/README.md new file mode 100644 index 0000000..b957c7a --- /dev/null +++ b/build/README.md @@ -0,0 +1,21 @@ +## Build Standalone Binaries + +### Build with `cross` + +- Install [`cross`](https://github.com/rust-embedded/cross) + +```bash +cargo install cross +``` + +- Build with cross + +```bash +cross build --target x86_64-unknown-linux-musl +``` + +### Predefined build routines + +- `build-release`: Build binaries with `cross` and packages outputs into `release` folder +- `build-host-release`: Build binaries with host's Rust toolchain. *NIX shell script +- `build-host-release.ps1`: Build binaries with host's Rust toolchain. PowerShell script diff --git a/build/build-host-release b/build/build-host-release new file mode 100755 index 0000000..8c875f6 --- /dev/null +++ b/build/build-host-release @@ -0,0 +1,95 @@ +#!/bin/bash + +BUILD_TARGET="" +BUILD_FEATURES=() +while getopts "t:f:" opt; do + case $opt in + t) + BUILD_TARGET=$OPTARG + ;; + f) + BUILD_FEATURES+=($OPTARG) + ;; + ?) + echo "Usage: $(basename $0) [-t ] [-f ]" + ;; + esac +done + +BUILD_FEATURES+=${BUILD_EXTRA_FEATURES} + +ROOT_DIR=$( cd $( dirname $0 ) && pwd ) +VERSION=$(grep -E '^version' "${ROOT_DIR}/../Cargo.toml" | awk '{print $3}' | sed 's/"//g') +HOST_TRIPLE=$(rustc -Vv | grep 'host:' | awk '{print $2}') + +echo "Started build release ${VERSION} for ${HOST_TRIPLE} (target: ${BUILD_TARGET}) with features \"${BUILD_FEATURES}\"..." + +if [[ "${BUILD_TARGET}" != "" ]]; then + if [[ "${BUILD_FEATURES}" != "" ]]; then + cargo build --release --features "${BUILD_FEATURES}" --target "${BUILD_TARGET}" + else + cargo build --release --target "${BUILD_TARGET}" + fi +else + if [[ "${BUILD_FEATURES}" != "" ]]; then + cargo build --release --features "${BUILD_FEATURES}" + else + cargo build --release + fi +fi + +if [[ "$?" != "0" ]]; then + exit $?; +fi + +if [[ "${BUILD_TARGET}" == "" ]]; then + BUILD_TARGET=$HOST_TRIPLE +fi + +TARGET_SUFFIX="" +if [[ "${BUILD_TARGET}" == *"-windows-"* ]]; then + TARGET_SUFFIX=".exe" +fi + +TARGETS=("qtun-client${TARGET_SUFFIX}" "qtun-server${TARGET_SUFFIX}") + +RELEASE_FOLDER="${ROOT_DIR}/release" +RELEASE_PACKAGE_NAME="qtun-v${VERSION}.${BUILD_TARGET}" + +mkdir -p "${RELEASE_FOLDER}" + +# Into release folder +if [[ "${BUILD_TARGET}" != "" ]]; then + cd "${ROOT_DIR}/../target/${BUILD_TARGET}/release" +else + cd "${ROOT_DIR}/../target/release" +fi + +if [[ "${BUILD_TARGET}" == *"-windows-"* ]]; then + # For Windows, use zip + + RELEASE_PACKAGE_FILE_NAME="${RELEASE_PACKAGE_NAME}.zip" + RELEASE_PACKAGE_FILE_PATH="${RELEASE_FOLDER}/${RELEASE_PACKAGE_FILE_NAME}" + zip "${RELEASE_PACKAGE_FILE_PATH}" "${TARGETS[@]}" + + # Checksum + cd "${RELEASE_FOLDER}" + shasum -a 256 "${RELEASE_PACKAGE_FILE_NAME}" > "${RELEASE_PACKAGE_FILE_NAME}.sha256" +else + # For others, Linux, OS X, uses tar.xz + + # For Darwin, .DS_Store and other related files should be ignored + if [[ "$(uname -s)" == "Darwin" ]]; then + export COPYFILE_DISABLE=1 + fi + + RELEASE_PACKAGE_FILE_NAME="${RELEASE_PACKAGE_NAME}.tar.xz" + RELEASE_PACKAGE_FILE_PATH="${RELEASE_FOLDER}/${RELEASE_PACKAGE_FILE_NAME}" + tar -cJf "${RELEASE_PACKAGE_FILE_PATH}" "${TARGETS[@]}" + + # Checksum + cd "${RELEASE_FOLDER}" + shasum -a 256 "${RELEASE_PACKAGE_FILE_NAME}" > "${RELEASE_PACKAGE_FILE_NAME}.sha256" +fi + +echo "Finished build release ${RELEASE_PACKAGE_FILE_PATH}" diff --git a/build/build-host-release.ps1 b/build/build-host-release.ps1 new file mode 100644 index 0000000..0678a10 --- /dev/null +++ b/build/build-host-release.ps1 @@ -0,0 +1,59 @@ +#!pwsh +<# + OpenSSL is already installed on windows-latest virtual environment. + If you need OpenSSL, consider install it by: + + choco install openssl +#> +param( + [Parameter(HelpMessage = "extra features")] + [Alias('f')] + [string]$Features +) + +$ErrorActionPreference = "Stop" + +$TargetTriple = (rustc -Vv | Select-String -Pattern "host: (.*)" | ForEach-Object { $_.Matches.Value }).split()[-1] + +Write-Host "Started building release for ${TargetTriple} ..." + +if ([string]::IsNullOrEmpty($Features)) { + cargo build --release +} +else { + cargo build --release --features "${Features}" +} + +if (!$?) { + exit $LASTEXITCODE +} + +$Version = (Select-String -Pattern '^version *= *"([^"]*)"$' -Path "${PSScriptRoot}\..\Cargo.toml" | ForEach-Object { $_.Matches.Value }).split()[-1] +$Version = $Version -replace '"' + +$PackageReleasePath = "${PSScriptRoot}\release" +$PackageName = "shadowsocks-v${Version}.${TargetTriple}.zip" +$PackagePath = "${PackageReleasePath}\${PackageName}" + +Write-Host $Version +Write-Host $PackageReleasePath +Write-Host $PackageName +Write-Host $PackagePath + +Push-Location "${PSScriptRoot}\..\target\release" + +$ProgressPreference = "SilentlyContinue" +New-Item "${PackageReleasePath}" -ItemType Directory -ErrorAction SilentlyContinue +$CompressParam = @{ + LiteralPath = "qtun-client.exe", "qtun-server.exe" + DestinationPath = "${PackagePath}" +} +Compress-Archive @CompressParam + +Write-Host "Created release packet ${PackagePath}" + +$PackageChecksumPath = "${PackagePath}.sha256" +$PackageHash = (Get-FileHash -Path "${PackagePath}" -Algorithm SHA256).Hash +"${PackageHash} ${PackageName}" | Out-File -FilePath "${PackageChecksumPath}" + +Write-Host "Created release packet checksum ${PackageChecksumPath}" diff --git a/build/build-release b/build/build-release new file mode 100755 index 0000000..ada42e8 --- /dev/null +++ b/build/build-release @@ -0,0 +1,124 @@ +#!/bin/bash + +CUR_DIR=$( cd $( dirname $0 ) && pwd ) +VERSION=$(grep -E '^version' ${CUR_DIR}/../Cargo.toml | awk '{print $3}' | sed 's/"//g') + +## Disable macos ACL file +if [[ "$(uname -s)" == "Darwin" ]]; then + export COPYFILE_DISABLE=1 +fi + +targets=() +features=() +use_upx=false + +while getopts "t:f:u" opt; do + case $opt in + t) + targets+=($OPTARG) + ;; + f) + features+=($OPTARG) + ;; + u) + use_upx=true + ;; + ?) + echo "Usage: $(basename $0) [-t ] [-f features] [-u]" + ;; + esac +done + +features+=${EXTRA_FEATURES} + +if [[ "${#targets[@]}" == "0" ]]; then + echo "Specifying compile target with -t " + exit 1 +fi + +if [[ "${use_upx}" = true ]]; then + if [[ -z "$upx" ]] && command -v upx &> /dev/null; then + upx="upx -9" + fi + + if [[ "x$upx" == "x" ]]; then + echo "Couldn't find upx in PATH, consider specifying it with variable \$upx" + exit 1 + fi +fi + + +function build() { + cd "$CUR_DIR/.." + + TARGET=$1 + + RELEASE_DIR="target/${TARGET}/release" + TARGET_FEATURES="${features[@]}" + + if [[ "${TARGET_FEATURES}" != "" ]]; then + echo "* Building ${TARGET} package ${VERSION} with features \"${TARGET_FEATURES}\" ..." + + cross build --target "${TARGET}" \ + --features "${TARGET_FEATURES}" \ + --release + else + echo "* Building ${TARGET} package ${VERSION} ..." + + cross build --target "${TARGET}" \ + --release + fi + + if [[ $? != "0" ]]; then + exit $? + fi + + PKG_DIR="${CUR_DIR}/release" + mkdir -p "${PKG_DIR}" + + if [[ "$TARGET" == *"-linux-"* ]]; then + PKG_NAME="qtun-v${VERSION}.${TARGET}.tar.xz" + PKG_PATH="${PKG_DIR}/${PKG_NAME}" + + cd ${RELEASE_DIR} + + if [[ "${use_upx}" = true ]]; then + # Enable upx for MIPS. + $upx sslocal ssserver ssurl ssmanager #>/dev/null + fi + + echo "* Packaging XZ in ${PKG_PATH} ..." + tar -cJf ${PKG_PATH} \ + "qtun-client" \ + "qtun-server" + + if [[ $? != "0" ]]; then + exit $? + fi + + cd "${PKG_DIR}" + shasum -a 256 "${PKG_NAME}" > "${PKG_NAME}.sha256" + elif [[ "$TARGET" == *"-windows-"* ]]; then + PKG_NAME="qtun-v${VERSION}.${TARGET}.zip" + PKG_PATH="${PKG_DIR}/${PKG_NAME}" + + echo "* Packaging ZIP in ${PKG_PATH} ..." + cd ${RELEASE_DIR} + zip ${PKG_PATH} \ + "qtun-client.exe" \ + "qtun-server.exe" + + if [[ $? != "0" ]]; then + exit $? + fi + + cd "${PKG_DIR}" + shasum -a 256 "${PKG_NAME}" > "${PKG_NAME}.sha256" + fi + + echo "* Done build package ${PKG_NAME}" +} + +for target in "${targets[@]}"; do + build "$target"; +done