AppImage linux releases (#1181)
* AppImage build * AppImage workflow * use appimagetool bundled with linuxdeploy * add appimage update info * Deploy ffmpeg deps /w linuxdeploy * change dependencies in gh actions * fix non-gpl builds * simplify server build script, set-up for potential future ffmpeg static linking work
This commit is contained in:
parent
871c6d348a
commit
0c4bd7d8d6
|
@ -133,16 +133,16 @@ jobs:
|
|||
RUST_BACKTRACE: 1
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential pkg-config nasm libva-dev libdrm-dev libvulkan-dev libx264-dev libx265-dev cmake libasound2-dev libjack-jackd2-dev libgtk-3-dev libunwind-dev libffmpeg-nvenc-dev nvidia-cuda-toolkit
|
||||
sudo apt-get install build-essential pkg-config nasm libva-dev libdrm-dev libvulkan-dev libx264-dev libx265-dev cmake libasound2-dev libjack-jackd2-dev libxrandr-dev libunwind-dev libffmpeg-nvenc-dev nvidia-cuda-toolkit
|
||||
cp packaging/deb/cuda.pc /usr/share/pkgconfig
|
||||
cargo xtask prepare-deps --platform linux
|
||||
|
||||
|
||||
- name: Build and package ALVR (.tar.gz)
|
||||
id: build
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
run: |
|
||||
cargo xtask package-server
|
||||
cargo xtask package-server --local-ffmpeg
|
||||
|
||||
- name: Upload server for Linux
|
||||
uses: actions/upload-release-asset@v1
|
||||
|
@ -154,12 +154,12 @@ jobs:
|
|||
asset_name: alvr_server_linux.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
|
||||
- name: Build and package ALVR portable (.tar.gz)
|
||||
- name: Build and package ALVR portable (.AppImage)
|
||||
id: build_portable
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
run: |
|
||||
cargo xtask package-server --gpl
|
||||
cargo xtask package-server --gpl --appimage --zsync
|
||||
|
||||
- name: Upload portable server for Linux
|
||||
uses: actions/upload-release-asset@v1
|
||||
|
@ -167,9 +167,19 @@ jobs:
|
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.prepare_release.outputs.upload_url }}
|
||||
asset_path: ./build/alvr_server_linux.tar.gz
|
||||
asset_name: alvr_server_linux_portable.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
asset_path: ./build/ALVR-x86_64.AppImage
|
||||
asset_name: ALVR-x86_64.AppImage
|
||||
asset_content_type: application/appimage
|
||||
|
||||
- name: Upload portable server for Linux (zsync)
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.prepare_release.outputs.upload_url }}
|
||||
asset_path: ./build/ALVR-x86_64.AppImage.zsync
|
||||
asset_name: ALVR-x86_64.AppImage.zsync
|
||||
asset_content_type: application/appimage
|
||||
|
||||
build_android_client:
|
||||
# Windows latest has Rust, Android NDK and LLVM already installed.
|
||||
|
|
|
@ -47,7 +47,7 @@ jobs:
|
|||
RUST_BACKTRACE: 1
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install build-essential pkg-config nasm libva-dev libdrm-dev libvulkan-dev libx264-dev libx265-dev cmake libasound2-dev libjack-jackd2-dev libgtk-3-dev libunwind-dev
|
||||
sudo apt install build-essential pkg-config nasm libva-dev libdrm-dev libvulkan-dev libx264-dev libx265-dev cmake libasound2-dev libjack-jackd2-dev libxrandr-dev libunwind-dev
|
||||
cargo xtask prepare-deps --platform linux --no-nvidia
|
||||
|
||||
- name: Build crates
|
||||
|
|
|
@ -10,7 +10,8 @@ rust-version = "1.58"
|
|||
crate-type = ["cdylib"]
|
||||
|
||||
[features]
|
||||
gpl = []
|
||||
gpl = ["local_ffmpeg"]
|
||||
local_ffmpeg = []
|
||||
|
||||
[dependencies]
|
||||
alvr_audio = { path = "../audio" }
|
||||
|
|
|
@ -2,23 +2,32 @@
|
|||
use pkg_config;
|
||||
use std::{env, path::PathBuf};
|
||||
|
||||
// this code must be executed BEFORE the actual cpp build when using bundled ffmpeg,
|
||||
// as it adds definitions and include flags
|
||||
// but AFTER the build in other cases because linker flags must appear after.
|
||||
#[cfg(target_os = "linux")]
|
||||
fn do_ffmpeg_pkg_config(build: &mut cc::Build) {
|
||||
let ffmpeg_path = alvr_filesystem::deps_dir().join("linux/ffmpeg");
|
||||
let alvr_build = if cfg!(feature = "gpl") {
|
||||
"alvr_build"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let ffmpeg_build_dir = ffmpeg_path.join(alvr_build);
|
||||
fn get_ffmpeg_path() -> PathBuf {
|
||||
let ffmpeg_path = alvr_filesystem::deps_dir()
|
||||
.join(if cfg!(target_os = "linux") {
|
||||
"linux"
|
||||
} else {
|
||||
"windows"
|
||||
})
|
||||
.join("ffmpeg");
|
||||
|
||||
#[cfg(feature = "gpl")]
|
||||
if cfg!(target_os = "linux") {
|
||||
ffmpeg_path.join("alvr_build")
|
||||
} else {
|
||||
ffmpeg_path
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "local_ffmpeg")]
|
||||
fn do_ffmpeg_config(build: &mut cc::Build) {
|
||||
let ffmpeg_path = get_ffmpeg_path();
|
||||
|
||||
assert!(ffmpeg_path.join("include").exists());
|
||||
build.include(ffmpeg_path.join("include"));
|
||||
|
||||
#[cfg(all(feature = "gpl", target_os = "linux"))]
|
||||
{
|
||||
assert!(ffmpeg_path.exists());
|
||||
let ffmpeg_pkg_path = ffmpeg_build_dir.join("lib/pkgconfig/");
|
||||
let ffmpeg_pkg_path = ffmpeg_path.join("lib").join("pkgconfig");
|
||||
assert!(ffmpeg_pkg_path.exists());
|
||||
|
||||
let ffmpeg_pkg_path = ffmpeg_pkg_path.to_string_lossy().to_string();
|
||||
|
@ -28,17 +37,14 @@ fn do_ffmpeg_pkg_config(build: &mut cc::Build) {
|
|||
format!("{ffmpeg_pkg_path}:{old}")
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
let pkg = pkg_config::Config::new()
|
||||
.cargo_metadata(cfg!(not(feature = "gpl")))
|
||||
.to_owned();
|
||||
let avutil = pkg.probe("libavutil").unwrap();
|
||||
let avfilter = pkg.probe("libavfilter").unwrap();
|
||||
let avcodec = pkg.probe("libavcodec").unwrap();
|
||||
let swscale = pkg.probe("libswscale").unwrap();
|
||||
let pkg = pkg_config::Config::new().cargo_metadata(false).to_owned();
|
||||
|
||||
let avutil = pkg.probe("libavutil").unwrap();
|
||||
let avfilter = pkg.probe("libavfilter").unwrap();
|
||||
let avcodec = pkg.probe("libavcodec").unwrap();
|
||||
let swscale = pkg.probe("libswscale").unwrap();
|
||||
|
||||
if cfg!(feature = "gpl") {
|
||||
build
|
||||
.define("AVCODEC_MAJOR", avcodec.version.split(".").next().unwrap())
|
||||
.define("AVUTIL_MAJOR", avutil.version.split(".").next().unwrap())
|
||||
|
@ -48,9 +54,6 @@ fn do_ffmpeg_pkg_config(build: &mut cc::Build) {
|
|||
)
|
||||
.define("SWSCALE_MAJOR", swscale.version.split(".").next().unwrap());
|
||||
|
||||
assert!(ffmpeg_build_dir.join("include").exists());
|
||||
build.include(ffmpeg_build_dir.join("include"));
|
||||
|
||||
// activate dlopen for libav libraries
|
||||
build
|
||||
.define("LIBRARY_LOADER_AVCODEC_LOADER_H_DLOPEN", None)
|
||||
|
@ -62,20 +65,35 @@ fn do_ffmpeg_pkg_config(build: &mut cc::Build) {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(all(windows, feature = "gpl"))]
|
||||
fn do_ffmpeg_windows_config(build: &mut cc::Build) {
|
||||
let ffmpeg_dir = alvr_filesystem::deps_dir().join("windows/ffmpeg");
|
||||
fn do_ffmpeg_config_post() {
|
||||
if cfg!(feature = "local_ffmpeg") {
|
||||
// TODO: cfg!(feature = "gpl") - switch to static linking
|
||||
let kind = if false { "static" } else { "dylib" };
|
||||
|
||||
build.include(format!("{}/include", ffmpeg_dir.to_string_lossy()));
|
||||
let ffmpeg_path = get_ffmpeg_path();
|
||||
let ffmpeg_lib_path = ffmpeg_path.join("lib");
|
||||
assert!(ffmpeg_lib_path.exists());
|
||||
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}/lib",
|
||||
ffmpeg_dir.to_string_lossy()
|
||||
);
|
||||
println!("cargo:rustc-link-lib=avcodec");
|
||||
println!("cargo:rustc-link-lib=avutil");
|
||||
println!("cargo:rustc-link-lib=avfilter");
|
||||
println!("cargo:rustc-link-lib=swscale");
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
ffmpeg_lib_path.to_string_lossy()
|
||||
);
|
||||
|
||||
println!("cargo:rustc-link-lib={}=avutil", kind);
|
||||
println!("cargo:rustc-link-lib={}=avfilter", kind);
|
||||
println!("cargo:rustc-link-lib={}=avcodec", kind);
|
||||
println!("cargo:rustc-link-lib={}=swscale", kind);
|
||||
} else {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let pkg = pkg_config::Config::new().to_owned();
|
||||
|
||||
pkg.probe("libavutil").unwrap();
|
||||
pkg.probe("libavfilter").unwrap();
|
||||
pkg.probe("libavcodec").unwrap();
|
||||
pkg.probe("libswscale").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -135,19 +153,15 @@ fn main() {
|
|||
// #[cfg(debug_assertions)]
|
||||
// build.define("ALVR_DEBUG_LOG", None);
|
||||
|
||||
#[cfg(all(target_os = "linux", feature = "gpl"))]
|
||||
do_ffmpeg_pkg_config(&mut build);
|
||||
#[cfg(feature = "local_ffmpeg")]
|
||||
do_ffmpeg_config(&mut build);
|
||||
|
||||
#[cfg(all(windows, feature = "gpl"))]
|
||||
{
|
||||
do_ffmpeg_windows_config(&mut build);
|
||||
build.define("ALVR_GPL", None);
|
||||
}
|
||||
build.define("ALVR_GPL", None);
|
||||
|
||||
build.compile("bindings");
|
||||
|
||||
#[cfg(all(target_os = "linux", not(feature = "gpl")))]
|
||||
do_ffmpeg_pkg_config(&mut build);
|
||||
do_ffmpeg_config_post();
|
||||
|
||||
bindgen::builder()
|
||||
.clang_arg("-xc++")
|
||||
|
|
|
@ -8,6 +8,7 @@ pub fn build_server(
|
|||
root: Option<String>,
|
||||
reproducible: bool,
|
||||
experiments: bool,
|
||||
local_ffmpeg: bool,
|
||||
) {
|
||||
let sh = Shell::new().unwrap();
|
||||
|
||||
|
@ -24,7 +25,9 @@ pub fn build_server(
|
|||
}
|
||||
let common_flags_ref = &common_flags;
|
||||
|
||||
let gpl_flag = gpl.then(|| vec!["--features", "gpl"]).unwrap_or_default();
|
||||
let gpl_flag = (gpl || local_ffmpeg)
|
||||
.then(|| vec!["--features", if gpl { "gpl" } else { "local_ffmpeg" }])
|
||||
.unwrap_or_default();
|
||||
|
||||
let artifacts_dir = afs::target_dir().join(build_type);
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@ FLAGS:
|
|||
--release Optimized build without debug info. For build subcommands
|
||||
--gpl Bundle GPL libraries. For build subcommands
|
||||
--experiments Build unfinished features. For build subcommands
|
||||
--local-ffmpeg Use local build of ffmpeg in non GPL build. For build subcommands
|
||||
--appimage Package as AppImage. For package-server subcommand
|
||||
--zsync For --appimage, create .zsync update file and build AppImage with embedded update information. For package-server subcommand
|
||||
--nightly Append nightly tag to versions. For bump subcommand
|
||||
--no-rebuild Do not rebuild the server with run-server
|
||||
--ci Do some CI related tweaks. Depends on the other flags and subcommand
|
||||
|
@ -167,6 +170,11 @@ fn main() {
|
|||
let no_rebuild = args.contains("--no-rebuild");
|
||||
let for_ci = args.contains("--ci");
|
||||
|
||||
let appimage = args.contains("--appimage");
|
||||
let zsync = args.contains("--zsync");
|
||||
|
||||
let local_ffmpeg = args.contains("--local-ffmpeg");
|
||||
|
||||
let platform: Option<String> = args.opt_value_from_str("--platform").unwrap();
|
||||
let version: Option<String> = args.opt_value_from_str("--version").unwrap();
|
||||
let root: Option<String> = args.opt_value_from_str("--root").unwrap();
|
||||
|
@ -191,16 +199,27 @@ fn main() {
|
|||
dependencies::build_android_deps(for_ci);
|
||||
}
|
||||
}
|
||||
"build-server" => build::build_server(is_release, gpl, None, false, experiments),
|
||||
"build-server" => {
|
||||
build::build_server(is_release, gpl, None, false, experiments, local_ffmpeg)
|
||||
}
|
||||
"build-client" => build::build_quest_client(is_release),
|
||||
"build-client-lib" => build::build_client_lib(is_release),
|
||||
"run-server" => {
|
||||
if !no_rebuild {
|
||||
build::build_server(is_release, gpl, None, false, experiments);
|
||||
build::build_server(
|
||||
is_release,
|
||||
gpl,
|
||||
None,
|
||||
false,
|
||||
experiments,
|
||||
local_ffmpeg,
|
||||
);
|
||||
}
|
||||
run_server();
|
||||
}
|
||||
"package-server" => packaging::package_server(root, gpl),
|
||||
"package-server" => {
|
||||
packaging::package_server(root, gpl, local_ffmpeg, appimage, zsync)
|
||||
}
|
||||
"package-client" => build::build_quest_client(true),
|
||||
"package-client-lib" => packaging::package_client_lib(),
|
||||
"clean" => clean(),
|
||||
|
|
|
@ -44,10 +44,16 @@ fn build_windows_installer() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn package_server(root: Option<String>, gpl: bool) {
|
||||
pub fn package_server(
|
||||
root: Option<String>,
|
||||
gpl: bool,
|
||||
local_ffmpeg: bool,
|
||||
appimage: bool,
|
||||
zsync: bool,
|
||||
) {
|
||||
let sh = Shell::new().unwrap();
|
||||
|
||||
build::build_server(true, gpl, root, true, false);
|
||||
build::build_server(true, gpl, root, true, false, local_ffmpeg);
|
||||
|
||||
// Add licenses
|
||||
let licenses_dir = afs::server_build_dir().join("licenses");
|
||||
|
@ -92,9 +98,92 @@ pub fn package_server(root: Option<String>, gpl: bool) {
|
|||
build_windows_installer();
|
||||
} else {
|
||||
command::targz(&sh, &afs::server_build_dir()).unwrap();
|
||||
|
||||
if appimage {
|
||||
server_appimage(true, gpl, zsync).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn server_appimage(release: bool, gpl: bool, update: bool) -> Result<(), xshell::Error> {
|
||||
let sh = Shell::new().unwrap();
|
||||
|
||||
let appdir = &afs::build_dir().join("ALVR.AppDir");
|
||||
let bin = &afs::build_dir().join("alvr_server_linux");
|
||||
|
||||
let icon = &afs::workspace_dir().join("resources/alvr.png");
|
||||
let desktop = &afs::workspace_dir().join("packaging/freedesktop/alvr.desktop");
|
||||
|
||||
let linuxdeploy = &afs::build_dir().join("linuxdeploy-x86_64.AppImage");
|
||||
|
||||
if !sh.path_exists(&linuxdeploy) {
|
||||
command::download(&sh, "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage", &linuxdeploy).ok();
|
||||
}
|
||||
cmd!(&sh, "chmod a+x {linuxdeploy}").run().ok();
|
||||
|
||||
if sh.path_exists(&appdir) {
|
||||
sh.remove_path(&appdir).ok();
|
||||
}
|
||||
|
||||
cmd!(&sh, "{linuxdeploy} --appdir={appdir}").run().ok();
|
||||
|
||||
sh.cmd("sh")
|
||||
.arg("-c")
|
||||
.arg(format!(
|
||||
"cp -r {}/* {}/usr",
|
||||
bin.to_string_lossy(),
|
||||
appdir.to_string_lossy()
|
||||
))
|
||||
.run()
|
||||
.ok();
|
||||
|
||||
sh.set_var("ARCH", "x86_64");
|
||||
sh.set_var("OUTPUT", "ALVR-x86_64.AppImage");
|
||||
|
||||
if release {
|
||||
let version = version::version();
|
||||
sh.set_var("VERSION", &version);
|
||||
|
||||
if update {
|
||||
let repo = if version.contains("nightly") {
|
||||
"ALVR-nightly"
|
||||
} else {
|
||||
"ALVR"
|
||||
};
|
||||
sh.set_var(
|
||||
"UPDATE_INFORMATION",
|
||||
format!("gh-releases-zsync|alvr-org|{repo}|latest|ALVR-x86_64.AppImage.zsync"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sh.set_var("VERBOSE", "1");
|
||||
sh.set_var("NO_APPSTREAM", "1");
|
||||
// Faster decompression (gzip) or smaller AppImage size (xz)?
|
||||
// sh.set_var("APPIMAGE_COMP", "xz"); // Currently uses gzip compression, will take effect when linuxdeploy updates.
|
||||
|
||||
sh.change_dir(&afs::build_dir());
|
||||
let mut cmd = cmd!(&sh, "{linuxdeploy} --appdir={appdir} -i{icon} -d{desktop} --deploy-deps-only={appdir}/usr/lib64/alvr/bin/linux64/driver_alvr_server.so --deploy-deps-only={appdir}/usr/lib64/libalvr_vulkan_layer.so --output appimage");
|
||||
|
||||
if gpl {
|
||||
for lib_path in sh
|
||||
.read_dir(appdir.join("usr/lib64/alvr"))
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.filter(|path| path.file_name().unwrap().to_string_lossy().contains(".so."))
|
||||
{
|
||||
let file_name = lib_path.file_name().unwrap().to_string_lossy();
|
||||
if file_name.contains("libx264.so") || file_name.contains("libx265.so") {
|
||||
sh.remove_path(lib_path).ok();
|
||||
} else {
|
||||
cmd = cmd.arg(format!("--deploy-deps-only={}", lib_path.to_string_lossy()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmd.run()
|
||||
}
|
||||
|
||||
pub fn package_client_lib() {
|
||||
let sh = Shell::new().unwrap();
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
Loading…
Reference in New Issue