From 9a35460d876457dea57c56a3fd13aa1a7c497a8f Mon Sep 17 00:00:00 2001 From: Liam Murphy Date: Mon, 4 Nov 2024 21:36:00 +0400 Subject: [PATCH] fex: add initial package tests --- pkgs/by-name/fe/fex/check-home.patch | 25 +++++++ pkgs/by-name/fe/fex/cross-includes.patch | 21 ++++++ pkgs/by-name/fe/fex/package.nix | 95 ++++++++++++++++++++++-- pkgs/by-name/fe/fex/realpath.patch | 19 +++++ 4 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 pkgs/by-name/fe/fex/check-home.patch create mode 100644 pkgs/by-name/fe/fex/cross-includes.patch create mode 100644 pkgs/by-name/fe/fex/realpath.patch diff --git a/pkgs/by-name/fe/fex/check-home.patch b/pkgs/by-name/fe/fex/check-home.patch new file mode 100644 index 00000000000000..2846873c83d35b --- /dev/null +++ b/pkgs/by-name/fe/fex/check-home.patch @@ -0,0 +1,25 @@ +diff --git a/Source/Common/Config.cpp b/Source/Common/Config.cpp +index 093e11682..fd8143570 100644 +--- a/Source/Common/Config.cpp ++++ b/Source/Common/Config.cpp +@@ -423,17 +423,17 @@ const char* GetHomeDirectory() { + const char* HomeDir = getenv("HOME"); + + // Try to get home directory from uid +- if (!HomeDir) { ++ if (!HomeDir || !FHU::Filesystem::Exists(HomeDir)) { + HomeDir = FindUserHomeThroughUID(); + } + + // try the PWD +- if (!HomeDir) { ++ if (!HomeDir || !FHU::Filesystem::Exists(HomeDir)) { + HomeDir = getenv("PWD"); + } + + // Still doesn't exit? You get local +- if (!HomeDir) { ++ if (!HomeDir || !FHU::Filesystem::Exists(HomeDir)) { + HomeDir = "."; + } + diff --git a/pkgs/by-name/fe/fex/cross-includes.patch b/pkgs/by-name/fe/fex/cross-includes.patch new file mode 100644 index 00000000000000..8de1bd6cbf0acb --- /dev/null +++ b/pkgs/by-name/fe/fex/cross-includes.patch @@ -0,0 +1,21 @@ +diff --git a/Scripts/StructPackVerifier.py b/Scripts/StructPackVerifier.py +index 4716e7976..47a2ef9d9 100755 +--- a/Scripts/StructPackVerifier.py ++++ b/Scripts/StructPackVerifier.py +@@ -656,14 +656,14 @@ def main(): + BaseArgs.append(sys.argv[ArgIndex]) + + args_x86_32 = [ +- "-I/usr/i686-linux-gnu/include", ++ "-I@i686Libs@/include", + "-O2", + "-m32", + "--target=i686-linux-unknown", + ] + + args_x86_64 = [ +- "-I/usr/x86_64-linux-gnu/include", ++ "-I@x86_64Libs@/include", + "-O2", + "--target=x86_64-linux-unknown", + "-D_M_X86_64", diff --git a/pkgs/by-name/fe/fex/package.nix b/pkgs/by-name/fe/fex/package.nix index 923f1164a9132b..874be683a78c35 100644 --- a/pkgs/by-name/fe/fex/package.nix +++ b/pkgs/by-name/fe/fex/package.nix @@ -2,16 +2,18 @@ fetchFromGitHub, lib, llvmPackages, + pkgsCross, + replaceVars, cmake, ninja, pkg-config, - git, + gitMinimal, qt5, python3, - python3Packages, + nasm, }: -llvmPackages.stdenv.mkDerivation rec { +llvmPackages.stdenv.mkDerivation (finalAttrs: rec { pname = "fex"; version = "2410"; @@ -23,15 +25,34 @@ llvmPackages.stdenv.mkDerivation rec { fetchSubmodules = true; }; + patches = [ + # These aren't strictly needed. + # + # This is a workaround to get FEX working within Nix's build sandbox: FEX's + # tests will break without it, but you can fix that with `export HOME=$PWD`. + # + # TODO: upstream this one. + ./check-home.patch + # This is a workaround to get FEX working with NixOS's slightly weird binfmt + # infrastructure. + ./realpath.patch + ] ++ lib.optional finalAttrs.finalPackage.doCheck (replaceVars ./cross-includes.patch { + i686Libs = pkgsCross.gnu32.stdenv.cc.libc_dev; + x86_64Libs = pkgsCross.gnu64.stdenv.cc.libc_dev; + }); + nativeBuildInputs = [ cmake ninja pkg-config - git + gitMinimal qt5.wrapQtAppsHook - python3 - python3Packages.setuptools llvmPackages.bintools + + (python3.withPackages (pythonPackages: with pythonPackages; [ + setuptools + libclang + ])) ]; buildInputs = with qt5; [ @@ -45,10 +66,68 @@ llvmPackages.stdenv.mkDerivation rec { "-DCMAKE_BUILD_TYPE=Release" "-DUSE_LINKER=lld" "-DENABLE_LTO=True" - "-DBUILD_TESTS=False" "-DENABLE_ASSERTIONS=False" + (lib.cmakeBool "BUILD_TESTS" finalAttrs.finalPackage.doCheck) + ]; + + strictDeps = true; + + doCheck = true; + + nativeCheckInputs = [ + nasm + llvmPackages.libcxx + ]; + + checkInputs = [ + llvmPackages.libcxx ]; + preCheck = '' + find \ + ../External/fex-posixtest-bins/conformance \ + ../External/fex-gvisor-tests-bins \ + ../External/fex-gcc-target-tests-bins/64 \ + -type f -executable \ + -exec patchelf \ + --set-interpreter ${pkgsCross.gnu64.stdenv.cc.libc}/lib/ld-linux-x86-64.so.2 \ + '{}' '+' + find ../External/fex-gcc-target-tests-bins/32 -type f -executable \ + -exec patchelf \ + --set-interpreter ${pkgsCross.gnu32.stdenv.cc.libc}/lib/ld-linux.so.2 \ + '{}' '+' + + find ../External/fex-gvisor-tests-bins -type f -executable \ + -exec patchelf --add-rpath ${pkgsCross.gnu64.gcc.cc.lib}/lib '{}' '+' + + # These all seem to fail due to the build sandbox. + echo -n ' + conformance-interfaces-sched_setparam-26-1.test + conformance-interfaces-sigqueue-12-1.test + conformance-interfaces-sigqueue-3-1.test + ' >> ../unittests/POSIX/Known_Failures + + echo -n ' + dev_test + getcpu_host_test + getcpu_test + lseek_test + tuntap_test + write_test + ' >> ../unittests/gvisor-tests/Known_Failures + + # For some reason this test fails in darwin.linux-builder, and passes in a UTM + # VM; paper over the difference by disabling it. + echo 'write_test' >> ../unittests/gvisor-tests/Disabled_Tests + ''; + + # Avoid wrapping anything other than FEXConfig, since the wrapped executables + # don't seem to work when registered as binfmts. + dontWrapQtApps = true; + preFixup = '' + wrapQtApp $out/bin/FEXConfig + ''; + meta = { description = "A fast usermode x86 and x86-64 emulator for Arm64 Linux"; homepage = "https://fex-emu.com/"; @@ -56,4 +135,4 @@ llvmPackages.stdenv.mkDerivation rec { license = lib.licenses.mit; maintainers = with lib.maintainers; [ andre4ik3 ]; }; -} +}) diff --git a/pkgs/by-name/fe/fex/realpath.patch b/pkgs/by-name/fe/fex/realpath.patch new file mode 100644 index 00000000000000..51cf02d426dcaa --- /dev/null +++ b/pkgs/by-name/fe/fex/realpath.patch @@ -0,0 +1,19 @@ +diff --git a/Source/Common/FEXServerClient.cpp b/Source/Common/FEXServerClient.cpp +index 424ecf0a0..501bcbac1 100644 +--- a/Source/Common/FEXServerClient.cpp ++++ b/Source/Common/FEXServerClient.cpp +@@ -209,7 +209,13 @@ int ConnectToAndStartServer(char* InterpreterPath) { + return -1; + } + +- fextl::string FEXServerPath = FHU::Filesystem::ParentPath(InterpreterPath) + "/FEXServer"; ++ char RealInterpreterPathBuf[PATH_MAX]; ++ char *RealInterpreterPath = realpath(InterpreterPath, RealInterpreterPathBuf); ++ if (!RealInterpreterPath) { ++ LogMan::Msg::EFmt("realpath failed"); ++ return -1; ++ } ++ fextl::string FEXServerPath = FHU::Filesystem::ParentPath(RealInterpreterPath) + "/FEXServer"; + // Check if a local FEXServer next to FEXInterpreter exists + // If it does then it takes priority over the installed one + if (!FHU::Filesystem::Exists(FEXServerPath)) {