{ flake, pkgs }: let inherit (pkgs) lib buildPackages targetPackages; platform = pkgs.targetPlatform; arch = with platform; if isx86_64 then "x86_64" else if isAarch64 then "arm_v8a" else throw "unknown Genode arch for platform ${platform.system}"; upstreamSources = flake.inputs.genode; genodeSources = # The Genode source repository let toolPrefix = if platform.isx86 then "genode-x86-" else if platform.isAarch64 then "genode-aarch64-" else throw "unknown tool prefix for Genode arch ${arch}"; in with buildPackages; stdenvNoCC.mkDerivation { pname = "genode-sources"; version = upstreamSources.lastModifiedDate; src = upstreamSources; nativeBuildInputs = [ expect gnumake tcl ]; patches = [ ./patches/binary-labels.patch ./patches/label-fail.patch ]; configurePhase = '' patchShebangs ./tool substituteInPlace repos/base/etc/tools.conf \ --replace "/usr/local/genode/tool/19.05/bin/" "" substituteInPlace tool/check_abi \ --replace "exec nm" "exec ${toolPrefix}nm" ''; buildPhase = '' echo { >> ports.nix find repos/*/ports -name '*.hash' | while read hashFile do echo " $(basename --suffix=.hash $hashFile) = \"$(cut -c -6 $hashFile)\";" >> ports.nix done echo } >> ports.nix ''; installPhase = "cp -a . $out"; }; portVersions = import "${genodeSources}/ports.nix"; preparePort = # Prepare a "port" of source code declared in the Genode sources name: { hash ? "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" , patches ? [ ], ... }@args: let havePatches = patches != [ ]; version = portVersions.${name}; in with buildPackages.buildPackages; stdenvNoCC.mkDerivation (args // { name = name + "-port-" + version; inherit version patches; preferLocalBuild = true; outputHashMode = "recursive"; outputHash = hash; GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt"; VERBOSE = ""; # need to build in verbose mode because errors are hidden impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ "GIT_PROXY_COMMAND" "SOCKS_SERVER" ]; src = if havePatches then genodeSources else null; dontUnpack = !havePatches; dontConfigure = true; nativeBuildInputs = [ bison flex gitMinimal glibc glibcLocales wget which ] ++ (args.nativeBuildInputs or [ ]); buildPhase = # ignore the port hash, its only for the inputs '' runHook preBuild export CONTRIB_DIR=$NIX_BUILD_TOP/contrib export GENODE_DIR=${if havePatches then "$(pwd)" else genodeSources} mkdir $CONTRIB_DIR $GENODE_DIR/tool/ports/prepare_port ${name} CHECK_HASH=no runHook postBuild ''; installPhase = # strip non-deterministic and extra artifacts '' runHook preInstall chmod -R +w $CONTRIB_DIR/* find $CONTRIB_DIR/* -name .git -exec rm -rf {} \; || true find $CONTRIB_DIR/* -name .svn -exec rm -rf {} \; || true find $CONTRIB_DIR/* -name '*.t?z' -exec rm -rf {} \; || true find $CONTRIB_DIR/* -name '*.tar.*' -exec rm -rf {} \; || true find $CONTRIB_DIR/* -name '*.zip' -exec rm -rf {} \; || true mkdir $out cp -a $CONTRIB_DIR/* $out/ runHook postInstall ''; dontFixup = true; }); ports = lib.mapAttrs preparePort (import ./ports.nix { pkgs = flake.inputs.nixpkgs.legacyPackages.x86_64-linux; }); # The "ports" mechanism is hardly deterministic, so prepare with # a pinned nixpkgs revision for a pinned platform. toolchain = buildPackages.buildPackages.callPackage ./toolchain.nix { }; stdenv' = pkgs.stdenvAdapters.overrideCC pkgs.stdenv toolchain; buildUpstream = # Build from the Genode sources { name, targets, portInputs ? [ ], nativeBuildInputs ? [ ], patches ? [ ] , enableParallelBuilding ? true, meta ? { }, ... }@extraAttrs: let havePatches = patches != [ ]; in stdenv'.mkDerivation (extraAttrs // { pname = name; inherit (genodeSources) version; inherit targets patches enableParallelBuilding; src = if havePatches then genodeSources else null; dontUnpack = !havePatches; nativeBuildInputs = with buildPackages; [ binutils bison flex stdenv.cc tcl which ] ++ nativeBuildInputs; configurePhase = let linkPorts = toString (builtins.map (drv: " ln -sv ${drv}/* $CONTRIB_DIR/;") portInputs); in '' runHook preConfigure export CONTRIB_DIR=$NIX_BUILD_TOP/contrib export BUILD_DIR=$(pwd)/build export GENODE_DIR=${if havePatches then "$(pwd)" else genodeSources} $GENODE_DIR/tool/create_builddir ${arch} substituteInPlace $BUILD_DIR/etc/build.conf \ --replace "#REPOSITORIES" "REPOSITORIES" mkdir $CONTRIB_DIR; ${linkPorts} runHook postConfigure ''; STRIP_TARGET_CMD = "cp $< $@"; makeFlags = [ "-C build" "VERBOSE=" ] ++ targets; installPhase = '' runHook preInstall find build/bin -name '*.xsd' -delete find build/bin -follow -type f -name '*.lib.so' \ -exec install -Dt "''${!outputLib}/lib" {} \; -delete find build/bin -follow -type f -executable \ -exec install -Dt "''${!outputBin}/bin" {} \; runHook postInstall ''; meta = { platforms = lib.platforms.genode; } // meta; }); buildDepot = # Build a Depot target from the Genode sources { name, apiOnly ? false, portInputs ? [ ], nativeBuildInputs ? [ ] , buildInputs ? [ ], meta ? { }, ... }@extraAttrs: stdenv'.mkDerivation (extraAttrs // { pname = name; inherit (genodeSources) version; enableParallelBuilding = true; nativeBuildInputs = with buildPackages.buildPackages; [ binutils bison flex stdenv.cc tcl which ] ++ nativeBuildInputs; src = genodeSources; # The genode source tree must be copied to the build directory # because the depot tool must modify the source tree as it runs. configurePhase = let copyPorts = # wasteful copy toString (builtins.map (drv: " cp -r ${drv}/* $CONTRIB_DIR/;") portInputs); in '' runHook preConfigure export GENODE_DIR=$(pwd) export CONTRIB_DIR=$GENODE_DIR/contrib export DEPOT_DIR=$GENODE_DIR/depot mkdir -p $CONTRIB_DIR; ${copyPorts} chmod +rwX -R . runHook postConfigure ''; STRIP_TARGET_CMD = "cp $< $@"; # defer strip until fixup phase makefile = "tool/depot/create"; makeFlags = [ "genodelabs/bin/${arch}/${name}" # by default the build system will refuse to be useful "FORCE=1" "KEEP_BUILD_DIR=1" "UPDATE_VERSIONS=1" "VERBOSE=" ]; installPhase = '' runHook preInstall rm -r depot/genodelabs/bin/${arch}/${name}/*\.build local outputLibDir="''${!outputLib}/lib" find depot/genodelabs/bin/${arch}/${name} -name '*.lib.so' \ -exec install -Dt "$outputLibDir" {} \; -delete if [ -d "$outputLibDir" ]; then pushd "$outputLibDir" for src in *.lib.so; do dst=$src dst="''${dst#lib}" dst="''${dst%.lib.so}" ln -s "$src" lib"$dst".so done popd fi find depot/genodelabs/bin/${arch}/${name} -executable \ -exec install -Dt "''${!outputBin}/bin" {} \; runHook postInstall ''; meta = { platforms = lib.platforms.genode; } // meta; }); makePackages = let overrides = import ./make-targets.nix { inherit (pkgs) buildPackages genodePackages; inherit ports; }; in lib.attrsets.mapAttrs (name: value: (buildUpstream ({ inherit name; } // value))) overrides; depotPackages = lib.attrsets.mapAttrs (name: value: (buildDepot ({ inherit name; } // value))) (import ./depot-targets.nix { inherit (pkgs) genodePackages; inherit ports; buildPackages = buildPackages.buildPackages; }); specs = with platform; [ ] ++ lib.optional is32bit "32bit" ++ lib.optional is64bit "64bit" ++ lib.optional isAarch32 "arm" ++ lib.optional isAarch64 "arm_64" ++ lib.optional isRiscV "riscv" ++ lib.optional isx86 "x86" ++ lib.optional isx86_32 "x86_32" ++ lib.optional isx86_64 "x86_64"; genodeBase = # A package containing the Genode C++ headers, a stub ld.lib.so and vfs.lib.so buildUpstream { name = "base"; targets = [ "LIB=vfs" ]; postInstall = # The actual ld.lib.so is kernel specific # so ship the stubbed library for linking '' cp $BUILD_DIR/var/libcache/ld/ld.abi.so $out/ld.lib.so mkdir -p $out/include cp -r --no-preserve=mode \ $GENODE_DIR/repos/base/include/* \ $GENODE_DIR/repos/os/include/* \ $GENODE_DIR/repos/demo/include/* \ $GENODE_DIR/repos/gems/include/* \ $out/include/ for spec in ${toString specs}; do dir=$out/include/spec/$spec if [ -d $dir ]; then cp -r $dir/* $out/include/ fi done rm -rf $out/include/spec cp -r $GENODE_DIR/repos/base/src/ld $out/ld ''; }; basePatches = [ ./patches/cxx-align.patch ./patches/core-diag.patch ./patches/ld-ro.patch ]; in makePackages // depotPackages // { genodeSources = genodeSources // { inherit arch buildUpstream buildDepot genodeBase ports specs toolchain; }; base-hw-pc = buildUpstream { name = "base-hw-pc"; outputs = [ "out" "coreObj" "bootstrapObj" ]; KERNEL = "hw"; BOARD = "pc"; targets = [ "bootstrap" "core" "timer" "lib/ld" ]; patches = basePatches; postInstall = '' mv $out/lib/ld-hw.lib.so $out/lib/ld.lib.so mv $out/bin/hw_timer_drv $out/bin/timer_drv install build/bin/core-hw-pc.o $coreObj install build/bin/bootstrap-hw-pc.o $bootstrapObj ''; meta.platforms = [ "x86_64-genode" ]; }; base-hw-virt_qemu = buildUpstream { name = "base-hw-virt_qemu"; outputs = [ "out" "coreObj" "bootstrapObj" ]; KERNEL = "hw"; BOARD = "virt_qemu"; targets = [ "bootstrap" "core" "timer" "lib/ld" ]; patches = basePatches; postInstall = '' mv $out/lib/ld-hw.lib.so $out/lib/ld.lib.so mv $out/bin/hw_timer_drv $out/bin/timer_drv install build/bin/core-hw-virt_qemu.o $coreObj install build/bin/bootstrap-hw-virt_qemu.o $bootstrapObj ''; meta.platforms = [ "aarch64-genode" ]; }; base-linux = buildUpstream { name = "base-linux"; KERNEL = "linux"; BOARD = "linux"; targets = [ "core" "timer" "lib/ld" ]; patches = basePatches; postInstall = '' mv $out/lib/ld-linux.lib.so $out/lib/ld.lib.so mv $out/bin/linux_timer_drv $out/bin/timer_drv ''; HOST_INC_DIR = buildPackages.glibc.dev + "/include"; }; base-nova = buildUpstream { name = "base-nova"; outputs = [ "out" "coreObj" ]; KERNEL = "nova"; targets = [ "core" "timer" "lib/ld" ]; patches = basePatches; postInstall = '' mv $out/lib/ld-nova.lib.so $out/lib/ld.lib.so mv $out/bin/nova_timer_drv $out/bin/timer_drv install build/bin/core-nova.o $coreObj ''; }; }