mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Add Linux Arm64 support
This commit is contained in:
@@ -10,6 +10,7 @@ indent_style = space
|
||||
# ReSharper properties
|
||||
resharper_csharp_wrap_after_invocation_lpar = true
|
||||
resharper_csharp_wrap_arguments_style = chop_if_long
|
||||
resharper_indent_raw_literal_string = indent
|
||||
|
||||
# MSBuild files
|
||||
[*.{csproj,targets,props}]
|
||||
@@ -138,6 +139,19 @@ dotnet_diagnostic.il3000.severity = error
|
||||
dotnet_diagnostic.il3001.severity = error
|
||||
dotnet_diagnostic.il3002.severity = error
|
||||
dotnet_diagnostic.il3003.severity = error
|
||||
|
||||
# Resharper
|
||||
resharper_place_accessorholder_attribute_on_same_line = false
|
||||
resharper_place_accessor_attribute_on_same_line = false
|
||||
resharper_place_event_attribute_on_same_line = false
|
||||
resharper_place_field_attribute_on_same_line = false
|
||||
resharper_place_method_attribute_on_same_line = false
|
||||
resharper_place_property_attribute_on_same_line = false
|
||||
resharper_place_record_field_attribute_on_same_line = false
|
||||
resharper_place_type_attribute_on_same_line = false
|
||||
csharp_max_attribute_length_for_same_line = 0
|
||||
|
||||
|
||||
###############################
|
||||
# VB Coding Conventions #
|
||||
###############################
|
||||
|
||||
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@@ -17,16 +17,15 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: dotnet/nbgv@master
|
||||
with:
|
||||
setAllVars: true
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "rust-test-${{ matrix.os }}"
|
||||
workspaces: "src/Rust -> target"
|
||||
- name: Install cargo-llvm-cov
|
||||
uses: taiki-e/install-action@cargo-llvm-cov
|
||||
- name: Install NBGV
|
||||
run: dotnet tool install -g nbgv
|
||||
if: startsWith(matrix.os, 'macos-')
|
||||
continue-on-error: true
|
||||
- name: Test Rust
|
||||
working-directory: src/Rust
|
||||
run: cargo llvm-cov ${{ matrix.rust_flags }} --cobertura --output-path ../../test/coverage.rust.${{ matrix.os }}.xml
|
||||
@@ -42,6 +41,9 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: dotnet/nbgv@master
|
||||
with:
|
||||
setAllVars: true
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "rust-build-windows"
|
||||
@@ -70,20 +72,33 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: dotnet/nbgv@master
|
||||
id: nbgv
|
||||
with:
|
||||
setAllVars: true
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "rust-build-linux"
|
||||
workspaces: "src/Rust -> target"
|
||||
- name: Build Rust
|
||||
- name: Build Rust (x64)
|
||||
working-directory: src/Rust
|
||||
run: |
|
||||
cargo build --release --target x86_64-unknown-linux-gnu
|
||||
cp ./target/x86_64-unknown-linux-gnu/release/update ./target/release/UpdateNix
|
||||
cp ./target/x86_64-unknown-linux-gnu/release/update ./target/release/UpdateNix_x64
|
||||
- name: Build Rust (arm64)
|
||||
working-directory: src/Rust
|
||||
env:
|
||||
CROSS_NuGetPackageVersion: ${{ steps.nbgv.outputs.NuGetPackageVersion }}
|
||||
run: |
|
||||
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
|
||||
cargo binstall cross --no-confirm
|
||||
cross build --release --target aarch64-unknown-linux-gnu
|
||||
cp ./target/aarch64-unknown-linux-gnu/release/update ./target/release/UpdateNix_arm64
|
||||
- name: Upload Rust Build Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: rust-ubuntu-latest
|
||||
path: src/Rust/target/release/UpdateNix
|
||||
path: src/Rust/target/release/UpdateNix*
|
||||
- name: Cancel workflow if failed
|
||||
uses: andymckay/cancel-action@0.4
|
||||
if: ${{ failure() }}
|
||||
@@ -97,13 +112,13 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: dotnet/nbgv@master
|
||||
with:
|
||||
setAllVars: true
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "rust-build-${{ matrix.os }}"
|
||||
workspaces: "src/Rust -> target"
|
||||
- name: Install NBGV
|
||||
run: dotnet tool install -g nbgv
|
||||
continue-on-error: true
|
||||
- name: Build Rust
|
||||
working-directory: src/Rust
|
||||
run: |
|
||||
@@ -170,10 +185,6 @@ jobs:
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nuget-
|
||||
- name: Install NBGV
|
||||
run: dotnet tool install -g nbgv
|
||||
if: ${{ matrix.os == 'macos-latest' }}
|
||||
continue-on-error: true
|
||||
- name: Install FUSE
|
||||
run: |
|
||||
sudo add-apt-repository universe
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
<None Include="..\Rust\target\release\setup.exe" Pack="true" PackagePath="vendor" />
|
||||
<None Include="..\Rust\target\release\stub.exe" Pack="true" PackagePath="vendor" />
|
||||
<None Include="..\Rust\target\release\UpdateMac" Pack="true" PackagePath="vendor" />
|
||||
<None Include="..\Rust\target\release\UpdateNix" Pack="true" PackagePath="vendor" />
|
||||
<None Include="..\Rust\target\release\UpdateNix_x64" Pack="true" PackagePath="vendor" />
|
||||
<None Include="..\Rust\target\release\UpdateNix_arm64" Pack="true" PackagePath="vendor" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
5
src/Rust/Cross.toml
Normal file
5
src/Rust/Cross.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
pre-build = [
|
||||
"dpkg --add-architecture $CROSS_DEB_ARCH",
|
||||
"apt-get update && apt-get install -y libssl-dev:$CROSS_DEB_ARCH",
|
||||
]
|
||||
@@ -1,6 +1,7 @@
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use semver;
|
||||
use std::process::Command;
|
||||
use std::env;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
extern crate winres;
|
||||
@@ -12,9 +13,7 @@ fn main() {
|
||||
#[cfg(target_os = "windows")]
|
||||
delay_load();
|
||||
|
||||
let ver_output = Command::new("nbgv").args(&["get-version", "-v", "NuGetPackageVersion"]).output().expect("Failed to execute nbgv get-version");
|
||||
let version = String::from_utf8(ver_output.stdout).expect("Unable to convert ngbv output to string");
|
||||
let version = version.trim();
|
||||
let version = get_package_version();
|
||||
let ver = semver::Version::parse(&version).expect("Unable to parse ngbv output as semver version");
|
||||
let ver: u64 = ver.major << 48 | ver.minor << 32 | ver.patch << 16;
|
||||
let desc = format!("Velopack {}", version);
|
||||
@@ -28,13 +27,32 @@ fn main() {
|
||||
.set_version_info(winres::VersionInfo::FILEVERSION, ver)
|
||||
.set("CompanyName", "Velopack")
|
||||
.set("ProductName", "Velopack")
|
||||
.set("ProductVersion", version)
|
||||
.set("ProductVersion", &version)
|
||||
.set("FileDescription", &desc)
|
||||
.set("LegalCopyright", "Caelan Sayler (c) 2023, Velopack Ltd. (c) 2024")
|
||||
.compile()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn get_package_version() -> String {
|
||||
if let Ok(version) = env::var("NuGetPackageVersion") {
|
||||
// NuGetPackageVersion is set, return it trimmed
|
||||
return version.trim().to_string();
|
||||
} else if let Ok(version) = env::var("NBGV_NuGetPackageVersion") {
|
||||
// NBGV_NuGetPackageVersion is set, return it trimmed
|
||||
return version.trim().to_string();
|
||||
} else if let Ok(version) = env::var("CROSS_NuGetPackageVersion") {
|
||||
// NBGV_NuGetPackageVersion is set, return it trimmed
|
||||
return version.trim().to_string();
|
||||
} else if env::var("CI").is_ok() {
|
||||
// CI is set, NuGetPackageVersion should be set always in CI
|
||||
panic!("Error: NuGetPackageVersion must be set in CI");
|
||||
} else {
|
||||
// CI is not set, return "v0.0.0-local"
|
||||
return "0.0.0-local".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn delay_load() {
|
||||
delay_load_exe("update");
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use anyhow::Result;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, strum::IntoStaticStr)]
|
||||
pub enum RuntimeArch {
|
||||
X86,
|
||||
@@ -86,7 +84,7 @@ type IsWow64Process2Fn = unsafe extern "system" fn(
|
||||
) -> windows::Win32::Foundation::BOOL;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
unsafe fn is_wow64_process2(handle: windows::Win32::Foundation::HANDLE) -> Result<u16> {
|
||||
unsafe fn is_wow64_process2(handle: windows::Win32::Foundation::HANDLE) -> anyhow::Result<u16> {
|
||||
use windows::Win32::Foundation::TRUE;
|
||||
use windows::Win32::System::SystemInformation::IMAGE_FILE_MACHINE;
|
||||
|
||||
|
||||
@@ -35,18 +35,18 @@ public class LinuxPackCommandRunner : PackageBuilder<LinuxPackOptions>
|
||||
: Options.Categories.TrimEnd(';');
|
||||
|
||||
File.WriteAllText(appRunPath, $$"""
|
||||
#!/bin/sh
|
||||
if [ ! -z "$APPIMAGE" ] && [ ! -z "$APPDIR" ]; then
|
||||
MD5=$(echo -n "file://$APPIMAGE" | md5sum | cut -d' ' -f1)
|
||||
cp "$APPDIR/{{iconFilename}}" "$HOME/.cache/thumbnails/normal/$MD5.png" >/dev/null 2>&1
|
||||
cp "$APPDIR/{{iconFilename}}" "$HOME/.cache/thumbnails/large/$MD5.png" >/dev/null 2>&1
|
||||
xdg-icon-resource forceupdate >/dev/null 2>&1
|
||||
fi
|
||||
HERE="$(dirname "$(readlink -f "${0}")")"
|
||||
export PATH="${HERE}"/usr/bin/:"${PATH}"
|
||||
EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1 | sed 's/\\s/ /g')
|
||||
exec "${EXEC}" "$@"
|
||||
""".Replace("\r", ""));
|
||||
#!/bin/sh
|
||||
if [ ! -z "$APPIMAGE" ] && [ ! -z "$APPDIR" ]; then
|
||||
MD5=$(echo -n "file://$APPIMAGE" | md5sum | cut -d' ' -f1)
|
||||
cp "$APPDIR/{{iconFilename}}" "$HOME/.cache/thumbnails/normal/$MD5.png" >/dev/null 2>&1
|
||||
cp "$APPDIR/{{iconFilename}}" "$HOME/.cache/thumbnails/large/$MD5.png" >/dev/null 2>&1
|
||||
xdg-icon-resource forceupdate >/dev/null 2>&1
|
||||
fi
|
||||
HERE="$(dirname "$(readlink -f "${0}")")"
|
||||
export PATH="${HERE}"/usr/bin/:"${PATH}"
|
||||
EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1 | sed 's/\\s/ /g')
|
||||
exec "${EXEC}" "$@"
|
||||
""".Replace("\r", ""));
|
||||
Chmod.ChmodFileAsExecutable(appRunPath);
|
||||
|
||||
var mainExeName = Options.EntryExecutableName ?? Options.PackId;
|
||||
@@ -59,23 +59,28 @@ exec "${EXEC}" "$@"
|
||||
mainExeName = mainExeName.Replace(" ", "\\s");
|
||||
|
||||
File.WriteAllText(Path.Combine(dir.FullName, Options.PackId + ".desktop"), $"""
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name={Options.PackTitle ?? Options.PackId}
|
||||
Comment={Options.PackTitle ?? Options.PackId} {Options.PackVersion}
|
||||
Icon={Options.PackId}
|
||||
Exec={mainExeName}
|
||||
StartupWMClass={Options.PackId}
|
||||
Categories={categories};
|
||||
""".Replace("\r", ""));
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name={Options.PackTitle ?? Options.PackId}
|
||||
Comment={Options.PackTitle ?? Options.PackId} {Options.PackVersion}
|
||||
Icon={Options.PackId}
|
||||
Exec={mainExeName}
|
||||
StartupWMClass={Options.PackId}
|
||||
Categories={categories};
|
||||
""".Replace("\r", ""));
|
||||
|
||||
// copy existing app files
|
||||
CopyFiles(new DirectoryInfo(packDir), bin, progress, true);
|
||||
}
|
||||
|
||||
Options.TargetRuntime.Architecture = Options.TargetRuntime.HasArchitecture
|
||||
? Options.TargetRuntime.Architecture
|
||||
: GetMachineForBinary(MainExePath);
|
||||
|
||||
|
||||
// velopack required files
|
||||
File.WriteAllText(Path.Combine(bin.FullName, "sq.version"), GenerateNuspecContent());
|
||||
File.Copy(HelperFile.GetUpdatePath(RuntimeOs.Linux), Path.Combine(bin.FullName, "UpdateNix"), true);
|
||||
File.Copy(HelperFile.GetUpdatePath(Options.TargetRuntime, Log), Path.Combine(bin.FullName, "UpdateNix"), true);
|
||||
progress(100);
|
||||
return Task.FromResult(dir.FullName);
|
||||
}
|
||||
@@ -91,10 +96,7 @@ Categories={categories};
|
||||
protected override Task CreatePortablePackage(Action<int> progress, string packDir, string outputPath)
|
||||
{
|
||||
progress(-1);
|
||||
var machine = Options.TargetRuntime.HasArchitecture
|
||||
? Options.TargetRuntime.Architecture
|
||||
: GetMachineForBinary(MainExePath);
|
||||
AppImageTool.CreateLinuxAppImage(packDir, outputPath, machine, Log);
|
||||
AppImageTool.CreateLinuxAppImage(packDir, outputPath, Options.TargetRuntime.Architecture, Log);
|
||||
PortablePackagePath = outputPath;
|
||||
progress(100);
|
||||
return Task.CompletedTask;
|
||||
@@ -126,4 +128,4 @@ Categories={categories};
|
||||
progress(-1); // there is only one "file", so progress will not work
|
||||
return base.CreateDeltaPackage(progress, releasePkg, prevReleasePkg, outputPkg, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class OsxPackCommandRunner : PackageBuilder<OsxPackOptions>
|
||||
var structure = new OsxStructureBuilder(dir.FullName);
|
||||
var macosdir = structure.MacosDirectory;
|
||||
File.WriteAllText(Path.Combine(macosdir, "sq.version"), GenerateNuspecContent());
|
||||
File.Copy(HelperFile.GetUpdatePath(RuntimeOs.OSX), Path.Combine(macosdir, "UpdateMac"), true);
|
||||
File.Copy(HelperFile.GetUpdatePath(Options.TargetRuntime, Log), Path.Combine(macosdir, "UpdateMac"), true);
|
||||
|
||||
foreach (var f in Directory.GetFiles(macosdir, "*", SearchOption.AllDirectories)) {
|
||||
if (BinDetect.IsMachOImage(f)) {
|
||||
|
||||
@@ -46,7 +46,7 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions>
|
||||
packDir = dir.FullName;
|
||||
|
||||
var updatePath = Path.Combine(TempDir.FullName, "Update.exe");
|
||||
File.Copy(HelperFile.GetUpdatePath(RuntimeOs.Windows), updatePath, true);
|
||||
File.Copy(HelperFile.GetUpdatePath(Options.TargetRuntime, Log), updatePath, true);
|
||||
|
||||
// check for and delete clickonce manifest
|
||||
var clickonceManifests = Directory.EnumerateFiles(packDir, "*.application")
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System.Runtime.Versioning;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Velopack.Packaging;
|
||||
|
||||
public static class HelperFile
|
||||
{
|
||||
public static string GetUpdateExeName(RuntimeOs os)
|
||||
private static string GetUpdateExeName(RID target, ILogger log)
|
||||
{
|
||||
switch (os) {
|
||||
switch (target.BaseRID) {
|
||||
case RuntimeOs.Windows:
|
||||
return FindHelperFile("update.exe");
|
||||
#if DEBUG
|
||||
@@ -16,16 +17,25 @@ public static class HelperFile
|
||||
return FindHelperFile("update");
|
||||
#else
|
||||
case RuntimeOs.Linux:
|
||||
return FindHelperFile("UpdateNix");
|
||||
if (!target.HasArchitecture) {
|
||||
log.Warn("No architecture specified with --runtime, defaulting to x64. If this was not intended please specify via the --runtime parameter");
|
||||
return FindHelperFile("UpdateNix_x64");
|
||||
}
|
||||
|
||||
return target.Architecture switch {
|
||||
RuntimeCpu.arm64 => FindHelperFile("UpdateNix_arm64"),
|
||||
RuntimeCpu.x64 => FindHelperFile("UpdateNix_x64"),
|
||||
_ => throw new PlatformNotSupportedException($"Update binary is not available for this platform ({target}).")
|
||||
};
|
||||
case RuntimeOs.OSX:
|
||||
return FindHelperFile("UpdateMac");
|
||||
#endif
|
||||
default:
|
||||
throw new PlatformNotSupportedException("Update binary is not available for this platform.");
|
||||
}
|
||||
|
||||
throw new PlatformNotSupportedException($"Update binary is not available for this platform ({target}).");
|
||||
}
|
||||
|
||||
public static string GetUpdatePath(RuntimeOs os) => FindHelperFile(GetUpdateExeName(os));
|
||||
public static string GetUpdatePath(RID target, ILogger log) => FindHelperFile(GetUpdateExeName(target, log));
|
||||
|
||||
public static string GetZstdPath()
|
||||
{
|
||||
@@ -73,7 +83,7 @@ public static class HelperFile
|
||||
}
|
||||
}
|
||||
|
||||
private static List<string> _searchPaths = new List<string>();
|
||||
private static readonly List<string> _searchPaths = new List<string>();
|
||||
|
||||
static HelperFile()
|
||||
{
|
||||
@@ -123,4 +133,4 @@ public static class HelperFile
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,6 @@ public abstract class PackageBuilder<T> : ICommand<T>
|
||||
var packId = options.PackId;
|
||||
var packDirectory = options.PackDirectory;
|
||||
var packVersion = options.PackVersion;
|
||||
var semVer = SemanticVersion.Parse(packVersion);
|
||||
|
||||
// check that entry exe exists
|
||||
var mainExeName = options.EntryExecutableName ?? options.PackId;
|
||||
|
||||
Reference in New Issue
Block a user