treewide: add emulator to platform

You can use stdenv.hostPlatform.emulator to get an executable that
runs cross-built binaries. This could be any emulator. For instance,
we use QEMU to emulate Linux targets and Wine to emulate Windows
targets. To work with qemu, we need to support custom targets.

I’ve reworked the cross tests in pkgs/test/cross to use this
functionality.

Also, I’ve used talloc to cross-execute with the emulator. There
appears to be a cross-execute for all waf builds. In the future, it
would be nice to set this for all waf builds.

Adds stdenv.hostPlatform.qemuArch attrbute to get the qemuArch for
each platform.
This commit is contained in:
Matthew Bauer 2018-11-13 16:54:08 -06:00
parent ce6d558c4d
commit 9c8fd41224
5 changed files with 99 additions and 45 deletions

View file

@ -66,6 +66,46 @@ rec {
# uname -r # uname -r
release = null; release = null;
}; };
qemuArch =
if final.isArm then "arm"
else if final.isx86_64 then "x86_64"
else if final.isx86 then "i386"
else {
"powerpc" = "ppc";
"powerpc64" = "ppc64";
"powerpc64le" = "ppc64";
"mips64" = "mips";
"mipsel64" = "mipsel";
}.${final.parsed.cpu.name} or final.parsed.cpu.name;
emulator = pkgs: let
qemu-user = pkgs.qemu.override {
smartcardSupport = false;
spiceSupport = false;
openGLSupport = false;
virglSupport = false;
vncSupport = false;
gtkSupport = false;
sdlSupport = false;
pulseSupport = false;
smbdSupport = false;
seccompSupport = false;
hostCpuTargets = ["${final.qemuArch}-linux-user"];
};
wine-name = "wine${toString final.parsed.cpu.bits}";
wine = (pkgs.winePackagesFor wine-name).minimal;
in
if final.parsed.kernel.name == pkgs.stdenv.hostPlatform.parsed.kernel.name &&
(final.parsed.cpu.name == pkgs.stdenv.hostPlatform.parsed.cpu.name ||
(final.platform.isi686 && pkgs.stdenv.hostPlatform.isx86_64))
then pkgs.runtimeShell
else if final.isWindows
then "${wine}/bin/${wine-name}"
else if final.isLinux && pkgs.stdenv.hostPlatform.isLinux
then "${qemu-user}/bin/qemu-${final.qemuArch}"
else throw "Don't know how to run ${final.config} executables.";
} // mapAttrs (n: v: v final.parsed) inspect.predicates } // mapAttrs (n: v: v final.parsed) inspect.predicates
// args; // args;
in assert final.useAndroidPrebuilt -> final.isAndroid; in assert final.useAndroidPrebuilt -> final.isAndroid;

View file

@ -18,6 +18,10 @@
, virglSupport ? openGLSupport, virglrenderer , virglSupport ? openGLSupport, virglrenderer
, smbdSupport ? false, samba , smbdSupport ? false, samba
, hostCpuOnly ? false , hostCpuOnly ? false
, hostCpuTargets ? (if hostCpuOnly
then (stdenv.lib.optional stdenv.isx86_64 "i386-softmmu"
++ ["${stdenv.hostPlatform.qemuArch}-softmmu"])
else null)
, nixosTestRunner ? false , nixosTestRunner ? false
}: }:
@ -27,11 +31,6 @@ let
+ optionalString pulseSupport "pa," + optionalString pulseSupport "pa,"
+ optionalString sdlSupport "sdl,"; + optionalString sdlSupport "sdl,";
hostCpuTargets = if stdenv.isx86_64 then "i386-softmmu,x86_64-softmmu"
else if stdenv.isi686 then "i386-softmmu"
else if stdenv.isAarch32 then "arm-softmmu"
else if stdenv.isAarch64 then "aarch64-softmmu"
else throw "Don't know how to build a 'hostCpuOnly = true' QEMU";
in in
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
@ -113,7 +112,7 @@ stdenv.mkDerivation rec {
++ optional smartcardSupport "--enable-smartcard" ++ optional smartcardSupport "--enable-smartcard"
++ optional spiceSupport "--enable-spice" ++ optional spiceSupport "--enable-spice"
++ optional usbredirSupport "--enable-usb-redir" ++ optional usbredirSupport "--enable-usb-redir"
++ optional hostCpuOnly "--target-list=${hostCpuTargets}" ++ optional (hostCpuTargets != null) "--target-list=${stdenv.lib.concatStringsSep "," hostCpuTargets}"
++ optional stdenv.isDarwin "--enable-cocoa" ++ optional stdenv.isDarwin "--enable-cocoa"
++ optional stdenv.isLinux "--enable-linux-aio" ++ optional stdenv.isLinux "--enable-linux-aio"
++ optional gtkSupport "--enable-gtk" ++ optional gtkSupport "--enable-gtk"
@ -135,12 +134,13 @@ stdenv.mkDerivation rec {
''; '';
# Add a qemu-kvm wrapper for compatibility/convenience. # Add a qemu-kvm wrapper for compatibility/convenience.
postInstall = postInstall = ''
if stdenv.isx86_64 then ''makeWrapper $out/bin/qemu-system-x86_64 $out/bin/qemu-kvm --add-flags "\$([ -e /dev/kvm ] && echo -enable-kvm)"'' if [ -x $out/bin/qemu-system-${stdenv.hostPlatform.qemuArch} ]; then
else if stdenv.isi686 then ''makeWrapper $out/bin/qemu-system-i386 $out/bin/qemu-kvm --add-flags "\$([ -e /dev/kvm ] && echo -enable-kvm)"'' makeWrapper $out/bin/qemu-system-${stdenv.hostPlatform.qemuArch} \
else if stdenv.isAarch32 then ''makeWrapper $out/bin/qemu-system-arm $out/bin/qemu-kvm --add-flags "\$([ -e /dev/kvm ] && echo -enable-kvm)"'' $out/bin/qemu-kvm \
else if stdenv.isAarch64 then ''makeWrapper $out/bin/qemu-system-aarch64 $out/bin/qemu-kvm --add-flags "\$([ -e /dev/kvm ] && echo -enable-kvm)"'' --add-flags "\$([ -e /dev/kvm ] && echo -enable-kvm)"
else ""; fi
'';
passthru = { passthru = {
qemu-system-i386 = "bin/qemu-system-i386"; qemu-system-i386 = "bin/qemu-system-i386";

View file

@ -1,5 +1,6 @@
{ stdenv, fetchurl, python, pkgconfig, readline, libxslt { stdenv, fetchurl, python, pkgconfig, readline, libxslt
, docbook_xsl, docbook_xml_dtd_42, fixDarwinDylibNames , docbook_xsl, docbook_xml_dtd_42, fixDarwinDylibNames
, buildPackages
}: }:
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
@ -10,10 +11,9 @@ stdenv.mkDerivation rec {
sha256 = "1kk76dyav41ip7ddbbf04yfydb4jvywzi2ps0z2vla56aqkn11di"; sha256 = "1kk76dyav41ip7ddbbf04yfydb4jvywzi2ps0z2vla56aqkn11di";
}; };
nativeBuildInputs = [ pkgconfig fixDarwinDylibNames ]; nativeBuildInputs = [ pkgconfig fixDarwinDylibNames python
buildInputs = [ docbook_xsl docbook_xml_dtd_42 ];
python readline libxslt docbook_xsl docbook_xml_dtd_42 buildInputs = [ readline libxslt ];
];
prePatch = '' prePatch = ''
patchShebangs buildtools/bin/waf patchShebangs buildtools/bin/waf
@ -23,10 +23,14 @@ stdenv.mkDerivation rec {
"--enable-talloc-compat1" "--enable-talloc-compat1"
"--bundled-libraries=NONE" "--bundled-libraries=NONE"
"--builtin-libraries=replace" "--builtin-libraries=replace"
] ++ stdenv.lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
"--cross-compile"
"--cross-execute=${stdenv.hostPlatform.emulator buildPackages}"
]; ];
configurePlatforms = [];
postInstall = '' postInstall = ''
ar q $out/lib/libtalloc.a bin/default/talloc_[0-9]*.o ${stdenv.cc.targetPrefix}ar q $out/lib/libtalloc.a bin/default/talloc_[0-9]*.o
''; '';
meta = with stdenv.lib; { meta = with stdenv.lib; {

View file

@ -1,12 +1,11 @@
{ pkgs, pkgsCross, lib }: { pkgs, lib }:
let let
emulators = { testedSystems = lib.filterAttrs (name: value: let
mingw32 = "WINEDEBUG=-all ${pkgs.winePackages.minimal}/bin/wine"; platform = lib.systems.elaborate value;
mingwW64 = "WINEDEBUG=-all ${pkgs.wineWowPackages.minimal}/bin/wine"; in platform.isLinux || platform.isWindows
# TODO: add some qemu-based emulaltors here ) lib.systems.examples;
};
getExecutable = pkgs: pkgFun: exec: getExecutable = pkgs: pkgFun: exec:
"${pkgFun pkgs}${exec}${pkgs.hostPlatform.extensions.executable}"; "${pkgFun pkgs}${exec}${pkgs.hostPlatform.extensions.executable}";
@ -17,6 +16,10 @@ let
in pkgs.runCommand "test-${pkgName}-${crossPkgs.hostPlatform.config}" { in pkgs.runCommand "test-${pkgName}-${crossPkgs.hostPlatform.config}" {
nativeBuildInputs = [ pkgs.dos2unix ]; nativeBuildInputs = [ pkgs.dos2unix ];
} '' } ''
# Just in case we are using wine, get rid of that annoying extra
# stuff.
export WINEDEBUG=-all
HOME=$(pwd) HOME=$(pwd)
mkdir -p $out mkdir -p $out
@ -44,10 +47,13 @@ let
fi fi
''; '';
in mapMultiPlatformTest = test: lib.mapAttrs (name: system: test rec {
crossPkgs = import pkgs.path {
localSystem = { inherit (pkgs.hostPlatform) config; };
crossSystem = system;
};
lib.mapAttrs (name: emulator: let emulator = crossPkgs.hostPlatform.emulator pkgs;
crossPkgs = pkgsCross.${name};
# Apply some transformation on windows to get dlls in the right # Apply some transformation on windows to get dlls in the right
# place. Unfortunately mingw doesnt seem to be able to do linking # place. Unfortunately mingw doesnt seem to be able to do linking
@ -57,16 +63,13 @@ lib.mapAttrs (name: emulator: let
name = "${pkg.name}-winlinks"; name = "${pkg.name}-winlinks";
paths = [pkg] ++ pkg.buildInputs; paths = [pkg] ++ pkg.buildInputs;
} else pkg; } else pkg;
in { }) testedSystems;
hello = compareTest { in
inherit emulator crossPkgs;
hostPkgs = pkgs;
exec = "/bin/hello";
pkgFun = pkgs: pkgs.hello;
};
file = compareTest { lib.mapAttrs (_: mapMultiPlatformTest) {
file = {platformFun, crossPkgs, emulator}: compareTest {
inherit emulator crossPkgs; inherit emulator crossPkgs;
hostPkgs = pkgs; hostPkgs = pkgs;
exec = "/bin/file"; exec = "/bin/file";
@ -77,4 +80,11 @@ in {
pkgFun = pkgs: platformFun pkgs.file; pkgFun = pkgs: platformFun pkgs.file;
}; };
}) emulators hello = {platformFun, crossPkgs, emulator}: compareTest {
inherit emulator crossPkgs;
hostPkgs = pkgs;
exec = "/bin/hello";
pkgFun = pkgs: pkgs.hello;
};
}

View file

@ -12465,7 +12465,7 @@ with pkgs;
taglib-sharp = callPackage ../development/libraries/taglib-sharp { }; taglib-sharp = callPackage ../development/libraries/taglib-sharp { };
talloc = callPackage ../development/libraries/talloc { talloc = callPackage ../development/libraries/talloc {
python = python2; python = buildPackages.python2;
}; };
tclap = callPackage ../development/libraries/tclap {}; tclap = callPackage ../development/libraries/tclap {};