sigil/packages/genodelabs/default.nix

433 lines
14 KiB
Nix

{ 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 =
# This is where the Genode source tree is defined.
# Must be updated with ./patches/sources.patch.
pkgs.fetchFromGitHub {
owner = "genodelabs";
repo = "genode";
rev = "sculpt-21.03";
hash = "sha256-rbrzhSUXRaL1RhQ2GDBrRTIOt6o0TYhi5GOXjKa71Nc=";
};
genodeSources =
# The Genode source repository after patching.
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 = builtins.substring 0 7 upstreamSources.rev;
src = upstreamSources;
nativeBuildInputs = [ expect gnumake tcl ];
patches = [ ./patches/sources.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 =
# Port versions are taken from the sources to force
# updates of the port fixed-output derivations.
import "${genodeSources}/ports.nix";
preparePort =
# Prepare a "port" of source code declared in the Genode sources.
# This is fragile because breakage can appear when the packages
# used in preparation are updated, but previously successful
# builds will cache.
name:
{ hash ? "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
, patches ? [ ], extraRepos ? [ ], ... }@args:
let
dontUnpack = patches == [ ] && extraRepos == [ ];
version = portVersions.${name} or args.version;
in with buildPackages.buildPackages;
stdenvNoCC.mkDerivation (args // {
name = name + "-port-" + version;
inherit version patches dontUnpack extraRepos;
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 dontUnpack then null else genodeSources;
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_CONTRIB_CACHE=$NIX_BUILD_TOP/contrib/cache
export GENODE_DIR=${if dontUnpack then genodeSources else "$(pwd)"}
for repo in $extraRepos; do
ln -s $repo $GENODE_DIR/repos/
done
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 cache -exec rm -rf {} \; || true
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 -av $CONTRIB_DIR/* $out/
runHook postInstall
'';
dontFixup = true;
});
ports =
# The "ports" mechanism is hardly deterministic, so prepare with
# a pinned nixpkgs revision for a pinned platform for consistency.
lib.mapAttrs preparePort (import ./ports.nix {
pkgs = flake.inputs.nixpkgs.legacyPackages.x86_64-linux // {
inherit (pkgs) genodePackages;
};
});
toolchain =
# Patched GCC build from upstream.
buildPackages.buildPackages.callPackage ./toolchain.nix { };
stdenv' =
# Special stdenv for use within the upstream sources.
# TODO: build with Clang.
pkgs.stdenvAdapters.overrideCC pkgs.stdenv toolchain;
buildUpstream =
# Build from the Genode sources using the least recursive make.
{ 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 from the Genode sources using the depot build system.
# WARNING: buildDepot can produce artifacts with broken linkage
# to their inputs. The Genode depot mechanism links programs and
# libraries to facsimilie stub libraries which are not guaranteed
# to have the same ABI as the current version as the real library.
{ name, apiOnly ? false, portInputs ? [ ], depotInputs ? [ ]
, nativeBuildInputs ? [ ], buildInputs ? [ ], meta ? { }, ... }@extraAttrs:
let
getDepotInputs = lib.concatMap (x:
[ x ] ++ x.passthru.depotInputs
++ (getDepotInputs x.passthru.depotInputs));
depotInputs' = lib.lists.unique (getDepotInputs depotInputs);
portInputs' = portInputs
++ lib.concatMap (builtins.getAttr "portInputs") depotInputs';
self = stdenv'.mkDerivation (extraAttrs // {
pname = name;
inherit (genodeSources) version;
enableParallelBuilding = true;
nativeBuildInputs = with buildPackages.buildPackages;
[ binutils bison flex stdenv.cc tcl which ] ++ nativeBuildInputs
++ lib.optional (!stdenv.hostPlatform.isGenode) erisPatchHook;
buildInputs = buildInputs ++ depotInputs';
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 outputBinDir="''${!outputBin}/bin"
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 "$outputBinDir" {} \;
runHook postInstall
'';
passthru = { inherit portInputs depotInputs; };
meta = { platforms = lib.platforms.genode; } // meta;
});
in self;
makePackages =
# Build everything in ./make-targets.nix.
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
# Build everything in ./depot-targets.nix.
(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
# and 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
'';
};
in makePackages // depotPackages // {
genodeSources =
# Expose genodeSources and tuck some extras in with it.
genodeSources // {
inherit arch buildUpstream buildDepot genodeBase ports specs toolchain;
};
# Builds of the Genode base-systems follow.
# These contain the hardware and kernel specific core program,
# the loader and base-library, and a timer driver.
base-hw-pc = buildUpstream {
name = "base-hw-pc";
outputs = [ "out" "coreObj" "bootstrapObj" ];
KERNEL = "hw";
BOARD = "pc";
targets = [ "bootstrap" "core" "timer" "lib/ld" ];
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
'';
dontErisPatch = true;
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" ];
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
'';
dontErisPatch = true;
meta.platforms = [ "aarch64-genode" ];
};
base-linux = buildUpstream {
name = "base-linux";
KERNEL = "linux";
BOARD = "linux";
targets = [ "core" "timer" "lib/ld" ];
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";
dontErisPatch = true;
};
base-nova = buildUpstream {
name = "base-nova";
outputs = [ "out" "coreObj" ];
KERNEL = "nova";
targets = [ "core" "timer" "lib/ld" ];
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_DIR/bin/core-nova.a $coreObj
'';
dontErisPatch = true;
};
}