diff --git a/alvr/server_openvr/Cargo.toml b/alvr/server_openvr/Cargo.toml index 498dca0902..e373af6c75 100644 --- a/alvr/server_openvr/Cargo.toml +++ b/alvr/server_openvr/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["cdylib"] [features] gpl = [] # Enable for FFmpeg support on Windows. Always enabled on Linux +nix = [] [dependencies] alvr_common.workspace = true diff --git a/alvr/server_openvr/build.rs b/alvr/server_openvr/build.rs index 11e5a5a222..1c6ea8d513 100644 --- a/alvr/server_openvr/build.rs +++ b/alvr/server_openvr/build.rs @@ -1,5 +1,19 @@ use std::{env, path::PathBuf}; +#[cfg(feature = "nix")] +fn get_ffmpeg_path() -> PathBuf { + pkg_config::Config::new() + .probe("libavcodec") + .unwrap() + .to_owned() + .include_paths + .pop() + .unwrap() + .parent() + .unwrap() + .to_path_buf() +} +#[cfg(not(feature = "nix"))] fn get_ffmpeg_path() -> PathBuf { let ffmpeg_path = alvr_filesystem::deps_dir() .join(if cfg!(target_os = "linux") { diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..a0d8cd9a5b --- /dev/null +++ b/flake.lock @@ -0,0 +1,100 @@ +{ + "nodes": { + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1762238689, + "narHash": "sha256-35sTZMb1Y6mct8cmMPYF50YGETTwfq0xOsFCXtoG6Io=", + "owner": "nix-community", + "repo": "fenix", + "rev": "0f94d1e67ea9ef983a9b5caf9c14bc52ae2eac44", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flakeUtils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1762111121, + "narHash": "sha256-4vhDuZ7OZaZmKKrnDpxLZZpGIJvAeMtK6FKLJYUtAdw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b3d51a0365f6695e7dd5cdf3e180604530ed33b4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "fenix": "fenix", + "flakeUtils": "flakeUtils", + "nixpkgs": "nixpkgs" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1762201112, + "narHash": "sha256-Mf3by5z6ptXId0EZ/QVD8md5fyNfgcDIfZbxoxCYItI=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "132d3338f4526b5c71046e5dc7ddf800e279daf4", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..2142af39a9 --- /dev/null +++ b/flake.nix @@ -0,0 +1,223 @@ +{ + description = "Stream VR games from your PC to your headset via Wi-Fi"; + + inputs = { + self.submodules = true; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flakeUtils.url = "github:numtide/flake-utils"; # TODO use upstream nix utils + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { + self, + nixpkgs, + flakeUtils, + fenix, + }: + flakeUtils.lib.eachDefaultSystem ( + system: + with nixpkgs.legacyPackages.${system}; + let + buildPackages = [ + alsa-lib + libclang + ffmpeg + ffmpeg.dev + jack2 + git + llvmPackages.libclang + openssl + pipewire + pipewire.dev + pkg-config + rustToolchain + rustPlatform.bindgenHook + llvmPackages.bintools + vulkan-headers + vulkan-loader + ]; + + dependencyPackages = [ + brotli + celt + ffmpeg + gccStdenv.cc # g++ for vrcompositor_wrapper + gccStdenv.cc.cc.lib # crti.o and friends + lame + libdrm + libglvnd + libogg + libpng + libtheora + libunwind + libva + libvdpau + libxkbcommon + nasm + openssl + pipewire + soxr + stdenv.cc.cc.lib + libva-vdpau-driver + vulkan-headers + vulkan-headers + vulkan-loader + wayland + x264 + xorg.libX11 + xorg.libXcursor + xorg.libXi + xorg.libXrandr + xvidcore + bzip2 + gmp + ]; + + nvidiaPackages = with cudaPackages; [ + cuda_cudart + cuda_nvcc + libnpp + ]; + + androidComposition = androidenv.composeAndroidPackages { + minPlatformVersion = "28"; + maxPlatformVersion = "32"; + abiVersions = [ + "armeabi-v7a" + "arm64-v8a" + "x86-64" + ]; + includeNDK = true; + includeSystemImages = false; + includeEmulator = false; + }; + + rustToolchain = + with fenix.packages.${system}; + combine [ + stable.toolchain + targets."armv7-linux-androideabi".stable.rust-std + targets."aarch64-linux-android".stable.rust-std + targets."x86_64-linux-android".stable.rust-std + ]; + + devShell = + { stdenv, nvidia }: + (mkShell.override { + stdenv = stdenv; + }) + { + LIBCLANG_PATH = "${libclang.lib}/lib"; + buildInputs = + buildPackages + ++ dependencyPackages + ++ (lib.optionals nvidia nvidiaPackages) + ++ [ + androidComposition.androidsdk + watchexec + ]; + JAVA_HOME = "${pkgs.jdk.home}"; + ANDROID_HOME = "${androidComposition.androidsdk}/libexec/android-sdk"; + ANDROID_NDK_ROOT = "${androidComposition.androidsdk}/libexec/android-sdk/ndk-bundle"; + NIX_CFLAGS_COMPILE = toString [ + "-lbrotlicommon" + "-lbrotlidec" + "-lcrypto" + "-lpng" + "-lssl" + ]; + + RUSTFLAGS = toString [ + "-C link-self-contained=-linker" + (map (a: "-C link-arg=${a}") [ + "-Wl,--push-state,--no-as-needed" + "-lEGL" + "-lwayland-client" + "-lxkbcommon" + "-Wl,--pop-state" + ]) + ]; + RUST_BACKTRACE = "1"; + }; + in + { + packages.default = pkgs.rustPlatform.buildRustPackage rec { + pname = "alvr"; + LIBCLANG_PATH = "${libclang.lib}/lib"; + env.NIX_CFLAGS_COMPILE = toString [ + "-lbrotlicommon" + "-lbrotlidec" + "-lcrypto" + "-lpng" + "-lssl" + ]; + RUSTFLAGS = toString [ + "-C link-self-contained=-linker" + (map (a: "-C link-args=${a}") [ + "-Wl,--push-state,--no-as-needed" + "-lEGL" + "-lwayland-client" + "-lxkbcommon" + "-Wl,--pop-state" + ]) + ]; + cargoBuildFlags = [ + "--workspace" + "--exclude alvr_xtask" + ]; + buildNoDefaultFeatures = true; + buildFeatures = [ "nix" ]; + version = "21.0.0-master"; # TODO Change to the release + doCheck = false; # TODO Broken right now + src = ./.; + RUST_BACKTRACE = "full"; + nativeBuildInputs = buildPackages; + buildInputs = buildPackages ++ dependencyPackages; + cargoLock = { + lockFile = ./Cargo.lock; + outputHashes = { + "openxr-0.18.0" = "sha256-v8sY9PROrqzkpuq3laIn2hPaX+DY7Fbca6i/Xiacd1g="; + "settings-schema-0.2.0" = "sha256-luEdAKDTq76dMeo5kA+QDTHpRMFUg3n0qvyQ7DkId0k="; + }; + }; + postInstall = '' + install -Dm755 ${src}/alvr/xtask/resources/alvr.desktop $out/share/applications/alvr.desktop + install -Dm644 ${src}/resources/ALVR-Icon.svg $out/share/icons/hicolor/scalable/apps/alvr.svg + + # Install SteamVR driver + mkdir -p $out/{libexec,lib/alvr,share} + cp -r ./build/alvr_streamer_linux/lib64/. $out/lib + cp -r ./build/alvr_streamer_linux/libexec/. $out/libexec + cp -r ./build/alvr_streamer_linux/share/. $out/share + ln -s $out/lib $out/lib64 + ''; + # TODO FIX that it needs to run the below command. + postBuild = '' + # Build SteamVR driver ("streamer") + cargo xtask build-streamer --release + ''; + meta = { + description = "Stream VR games from your PC to your headset via Wi-Fi"; + homepage = "https://github.com/alvr-org/ALVR/"; + changelog = "https://github.com/alvr-org/ALVR/releases/tag/v${version}"; + license = lib.licenses.mit; + mainProgram = "alvr_dashboard"; + }; + }; + formatter = pkgs.nixfmt-tree; + devShells.default = devShell { + stdenv = clangStdenv; + nvidia = false; + }; + # TODO BROKEN + #devShells.nvidia = devShell { + # stdenv = clangStdenv; + # nvidia = true; + #}; + } + ); +}