270 lines
8.6 KiB
Rust
270 lines
8.6 KiB
Rust
use crate::{command, dependencies, version};
|
|
use alvr_filesystem::{self as afs, Layout};
|
|
use xshell::{cmd, Shell};
|
|
|
|
pub fn build_server(
|
|
is_release: bool,
|
|
gpl: bool,
|
|
root: Option<String>,
|
|
reproducible: bool,
|
|
experiments: bool,
|
|
local_ffmpeg: bool,
|
|
) {
|
|
let sh = Shell::new().unwrap();
|
|
|
|
let build_layout = Layout::new(&afs::server_build_dir());
|
|
|
|
let build_type = if is_release { "release" } else { "debug" };
|
|
|
|
let mut common_flags = vec![];
|
|
if is_release {
|
|
common_flags.push("--release");
|
|
}
|
|
if reproducible {
|
|
common_flags.push("--locked");
|
|
}
|
|
let common_flags_ref = &common_flags;
|
|
|
|
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);
|
|
|
|
sh.remove_path(&afs::server_build_dir()).unwrap();
|
|
sh.create_dir(&afs::server_build_dir()).unwrap();
|
|
sh.create_dir(&build_layout.openvr_driver_lib_dir())
|
|
.unwrap();
|
|
sh.create_dir(&build_layout.executables_dir).unwrap();
|
|
|
|
if let Some(root) = root {
|
|
sh.set_var("ALVR_ROOT_DIR", root);
|
|
}
|
|
|
|
// build server
|
|
{
|
|
let _push_guard = sh.push_dir(afs::crate_dir("server"));
|
|
cmd!(sh, "cargo build {common_flags_ref...} {gpl_flag...}")
|
|
.run()
|
|
.unwrap();
|
|
|
|
sh.copy_file(
|
|
artifacts_dir.join(afs::dynlib_fname("alvr_server")),
|
|
build_layout.openvr_driver_lib(),
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
// build launcher
|
|
{
|
|
let _push_guard = sh.push_dir(afs::crate_dir("launcher"));
|
|
cmd!(sh, "cargo build {common_flags_ref...}").run().unwrap();
|
|
|
|
sh.copy_file(
|
|
artifacts_dir.join(afs::exec_fname("alvr_launcher")),
|
|
build_layout.launcher_exe(),
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
// copy dependencies
|
|
if cfg!(windows) {
|
|
command::copy_recursive(
|
|
&sh,
|
|
&afs::crate_dir("server").join("cpp/bin/windows"),
|
|
&build_layout.openvr_driver_lib_dir(),
|
|
)
|
|
.unwrap();
|
|
|
|
// copy ffmpeg binaries
|
|
if gpl {
|
|
let bin_dir = &build_layout.openvr_driver_lib_dir();
|
|
sh.create_dir(&bin_dir).unwrap();
|
|
for lib_path in sh
|
|
.read_dir(afs::deps_dir().join("windows/ffmpeg/bin"))
|
|
.unwrap()
|
|
.into_iter()
|
|
.filter(|path| path.file_name().unwrap().to_string_lossy().contains(".dll"))
|
|
{
|
|
sh.copy_file(lib_path.clone(), bin_dir).unwrap();
|
|
}
|
|
}
|
|
} else if cfg!(target_os = "linux") {
|
|
// build compositor wrapper
|
|
let _push_guard = sh.push_dir(afs::crate_dir("vrcompositor_wrapper"));
|
|
cmd!(sh, "cargo build {common_flags_ref...}").run().unwrap();
|
|
sh.create_dir(&build_layout.vrcompositor_wrapper_dir)
|
|
.unwrap();
|
|
sh.copy_file(
|
|
artifacts_dir.join("alvr_vrcompositor_wrapper"),
|
|
build_layout.vrcompositor_wrapper(),
|
|
)
|
|
.unwrap();
|
|
|
|
// build vulkan layer
|
|
let _push_guard = sh.push_dir(afs::crate_dir("vulkan_layer"));
|
|
cmd!(sh, "cargo build {common_flags_ref...}").run().unwrap();
|
|
sh.create_dir(&build_layout.libraries_dir).unwrap();
|
|
sh.copy_file(
|
|
artifacts_dir.join(afs::dynlib_fname("alvr_vulkan_layer")),
|
|
build_layout.vulkan_layer(),
|
|
)
|
|
.unwrap();
|
|
|
|
// copy vulkan layer manifest
|
|
sh.create_dir(&build_layout.vulkan_layer_manifest_dir)
|
|
.unwrap();
|
|
sh.copy_file(
|
|
afs::crate_dir("vulkan_layer").join("layer/alvr_x86_64.json"),
|
|
build_layout.vulkan_layer_manifest(),
|
|
)
|
|
.unwrap();
|
|
|
|
// copy ffmpeg binaries
|
|
if gpl {
|
|
let lib_dir = &build_layout.openvr_driver_root_dir;
|
|
let mut libavcodec_so = std::path::PathBuf::new();
|
|
sh.create_dir(&lib_dir).unwrap();
|
|
let _push_guard = sh.push_dir(&lib_dir);
|
|
for lib_path in sh
|
|
.read_dir(afs::deps_dir().join("linux/ffmpeg/alvr_build/lib"))
|
|
.unwrap()
|
|
.into_iter()
|
|
.filter(|path| path.file_name().unwrap().to_string_lossy().contains(".so."))
|
|
{
|
|
let src_so_file = lib_path.canonicalize().unwrap(); // canonicalize resolves symlinks.
|
|
sh.copy_file(&src_so_file, ".").unwrap();
|
|
// Shell::copy_file does not handle symlinks so we must recreate them.
|
|
if lib_path.is_symlink() {
|
|
assert!(lib_dir.join(src_so_file.file_name().unwrap()).exists());
|
|
let so_file = std::path::Path::new(src_so_file.file_name().unwrap());
|
|
let so_file_symlink = std::path::Path::new(lib_path.file_name().unwrap());
|
|
command::make_symlink(&sh, so_file, so_file_symlink).unwrap();
|
|
}
|
|
let lib_filename = src_so_file.file_name().unwrap();
|
|
if lib_filename.to_string_lossy().starts_with("libavcodec.so") {
|
|
libavcodec_so = src_so_file;
|
|
}
|
|
}
|
|
// copy ffmpeg shared lib dependencies.
|
|
for solib in ["libx264.so", "libx265.so"] {
|
|
let src_libs = dependencies::find_resolved_so_paths(&libavcodec_so, solib);
|
|
if !src_libs.is_empty() {
|
|
let src_lib = src_libs.first().unwrap();
|
|
sh.copy_file(&src_lib, ".").unwrap();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// copy static resources
|
|
{
|
|
// copy dashboard
|
|
command::copy_recursive(
|
|
&sh,
|
|
&afs::workspace_dir().join("dashboard"),
|
|
&build_layout.dashboard_dir(),
|
|
)
|
|
.unwrap();
|
|
|
|
// copy presets
|
|
command::copy_recursive(
|
|
&sh,
|
|
&afs::crate_dir("xtask").join("resources/presets"),
|
|
&build_layout.presets_dir(),
|
|
)
|
|
.ok();
|
|
|
|
// copy driver manifest
|
|
sh.copy_file(
|
|
afs::crate_dir("xtask").join("resources/driver.vrdrivermanifest"),
|
|
&build_layout.openvr_driver_manifest(),
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
// build experiments
|
|
if experiments {
|
|
command::copy_recursive(
|
|
&sh,
|
|
&afs::workspace_dir().join("experiments/gui/resources/languages"),
|
|
&build_layout.static_resources_dir.join("languages"),
|
|
)
|
|
.unwrap();
|
|
|
|
let _push_guard = sh.push_dir(afs::workspace_dir().join("experiments/launcher"));
|
|
cmd!(sh, "cargo build {common_flags_ref...}").run().unwrap();
|
|
sh.copy_file(
|
|
artifacts_dir.join(afs::exec_fname("launcher")),
|
|
build_layout
|
|
.executables_dir
|
|
.join(afs::exec_fname("experimental_launcher")),
|
|
)
|
|
.unwrap();
|
|
}
|
|
}
|
|
|
|
pub fn build_client_lib(is_release: bool) {
|
|
let sh = Shell::new().unwrap();
|
|
|
|
let build_dir = afs::build_dir().join("alvr_client_core");
|
|
sh.create_dir(&build_dir).unwrap();
|
|
|
|
let mut flags = vec![];
|
|
if is_release {
|
|
flags.push("--release");
|
|
}
|
|
let flags_ref = &flags;
|
|
|
|
let _push_guard = sh.push_dir(afs::crate_dir("client_core"));
|
|
|
|
cmd!(
|
|
sh,
|
|
"cargo ndk -t arm64-v8a -p 26 -o {build_dir} build {flags_ref...}"
|
|
)
|
|
.run()
|
|
.unwrap();
|
|
|
|
let out = build_dir.join("alvr_client_core.h");
|
|
cmd!(sh, "cbindgen --output {out}").run().unwrap();
|
|
}
|
|
|
|
pub fn build_quest_client(is_release: bool) {
|
|
let sh = Shell::new().unwrap();
|
|
|
|
build_client_lib(is_release);
|
|
|
|
let is_nightly = version::version().contains("nightly");
|
|
let is_release = if is_nightly { false } else { is_release };
|
|
|
|
let package_type = if is_nightly { "Nightly" } else { "Stable" };
|
|
let build_type = if is_release { "release" } else { "debug" };
|
|
|
|
let build_task = format!("assemble{package_type}{build_type}");
|
|
|
|
let client_dir = afs::workspace_dir().join("android");
|
|
|
|
const ARTIFACT_NAME: &str = "alvr_client_oculus_quest";
|
|
|
|
let _push_guard = sh.push_dir(&client_dir);
|
|
if cfg!(windows) {
|
|
cmd!(sh, "cmd /C gradlew.bat {build_task}").run().unwrap();
|
|
} else {
|
|
cmd!(sh, "bash ./gradlew {build_task}").run().unwrap();
|
|
};
|
|
|
|
sh.create_dir(&afs::build_dir().join(ARTIFACT_NAME))
|
|
.unwrap();
|
|
sh.copy_file(
|
|
client_dir
|
|
.join("app/build/outputs/apk")
|
|
.join(package_type)
|
|
.join(build_type)
|
|
.join(format!("app-{package_type}-{build_type}.apk")),
|
|
afs::build_dir()
|
|
.join(ARTIFACT_NAME)
|
|
.join(format!("{ARTIFACT_NAME}.apk")),
|
|
)
|
|
.unwrap();
|
|
}
|