cc-wrapper: make machine configuration configurable

It is useful to make these dynamic and not bake them into gcc. This
means we don’t have to rebuild gcc to change these values. Instead, we
will pass cflags to gcc based on platform values. This was already
done hackily for android gcc (which is multi-target), but not for our
own gccs which are single target.

To accomplish this, we need to add a few things:

- add ‘arch’ to cpu
- add NIX_CFLAGS_COMPILE_BEFORE flag (goes before args)
- set -march everywhere
- set mcpu, mfpu, mmode, and mtune based on targetPlatform.gcc flags

cc-wrapper: only set -march when it is in the cpu type

Some architectures don’t have a good mapping of -march. For instance
POWER architecture doesn’t support the -march flag at all!

https://gcc.gnu.org/onlinedocs/gcc/RS_002f6000-and-PowerPC-Options.html#RS_002f6000-and-PowerPC-Options
This commit is contained in:
Matthew Bauer 2019-04-09 14:21:54 -04:00
parent 799fa4d404
commit d180cb9850
5 changed files with 64 additions and 51 deletions

View file

@ -69,24 +69,24 @@ rec {
cpuTypes = with significantBytes; setTypes types.openCpuType {
arm = { bits = 32; significantByte = littleEndian; family = "arm"; };
armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; version = "5"; };
armv6m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; };
armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; };
armv7a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; };
armv7r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; };
armv7m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; };
armv7l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; };
armv8a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; };
armv8r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; };
armv8m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; };
aarch64 = { bits = 64; significantByte = littleEndian; family = "arm"; version = "8"; };
aarch64_be = { bits = 64; significantByte = bigEndian; family = "arm"; version = "8"; };
armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; version = "5"; arch = "armv5t"; };
armv6m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; arch = "armv6-m"; };
armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; arch = "armv6"; };
armv7a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-a"; };
armv7r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-r"; };
armv7m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-m"; };
armv7l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7"; };
armv8a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
armv8r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
armv8m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-m"; };
aarch64 = { bits = 64; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
aarch64_be = { bits = 64; significantByte = bigEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
i386 = { bits = 32; significantByte = littleEndian; family = "x86"; };
i486 = { bits = 32; significantByte = littleEndian; family = "x86"; };
i586 = { bits = 32; significantByte = littleEndian; family = "x86"; };
i686 = { bits = 32; significantByte = littleEndian; family = "x86"; };
x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; };
i386 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i386"; };
i486 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i486"; };
i586 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i586"; };
i686 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i686"; };
x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; arch = "x86-64"; };
mips = { bits = 32; significantByte = bigEndian; family = "mips"; };
mipsel = { bits = 32; significantByte = littleEndian; family = "mips"; };

View file

@ -6,6 +6,7 @@
var_templates_list=(
NIX+CFLAGS_COMPILE
NIX+CFLAGS_COMPILE_BEFORE
NIX+CFLAGS_LINK
NIX+CXXSTDLIB_COMPILE
NIX+CXXSTDLIB_LINK
@ -43,5 +44,9 @@ if [ -e @out@/nix-support/cc-ldflags ]; then
NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/cc-ldflags)"
fi
if [ -e @out@/nix-support/cc-cflags-before ]; then
NIX_@infixSalt@_CFLAGS_COMPILE_BEFORE="$(< @out@/nix-support/cc-cflags-before) $NIX_@infixSalt@_CFLAGS_COMPILE_BEFORE"
fi
# That way forked processes will not extend these environment variables again.
export NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET=1

View file

@ -135,7 +135,7 @@ source @out@/nix-support/add-hardening.sh
# Add the flags for the C compiler proper.
extraAfter=($NIX_@infixSalt@_CFLAGS_COMPILE)
extraBefore=(${hardeningCFlags[@]+"${hardeningCFlags[@]}"})
extraBefore=(${hardeningCFlags[@]+"${hardeningCFlags[@]}"} $NIX_@infixSalt@_CFLAGS_COMPILE_BEFORE)
if [ "$dontLink" != 1 ]; then

View file

@ -279,24 +279,51 @@ stdenv.mkDerivation {
export hardening_unsupported_flags="${builtins.concatStringsSep " " (cc.hardeningUnsupportedFlags or [])}"
''
# Machine flags. These are necessary to support
# TODO: We should make a way to support miscellaneous machine
# flags and other gcc flags as well.
# Always add -march based on cpu in triple. Sometimes there is a
# discrepency (x86_64 vs. x86-64), so we provide an "arch" arg in
# that case.
+ optionalString (targetPlatform ? platform.gcc.arch || targetPlatform.parsed.cpu ? arch) ''
echo "-march=${targetPlatform.platform.gcc.arch or targetPlatform.parsed.cpu.arch}" >> $out/nix-support/cc-cflags-before
''
# -mcpu is not very useful. You should use mtune and march
# instead. Its provided here for backwards compatibility.
+ optionalString (targetPlatform ? platform.gcc.cpu) ''
echo "-mcpu=${targetPlatform.platform.gcc.cpu}" >> $out/nix-support/cc-cflags-before
''
# -mfloat-abi only matters on arm32 but we set it here
# unconditionally just in case. If the abi specifically sets hard
# vs. soft floats we use it here.
+ optionalString (targetPlatform ? platform.gcc.float-abi || targetPlatform.parsed.abi ? float) ''
echo "-mfloat-abi=${targetPlatform.platform.gcc.float-abi or targetPlatform.parsed.abi.float}" >> $out/nix-support/cc-cflags-before
''
+ optionalString (targetPlatform ? platform.gcc.fpu) ''
echo "-mfpu=${targetPlatform.platform.gcc.fpu}" >> $out/nix-support/cc-cflags-before
''
+ optionalString (targetPlatform ? platform.gcc.mode) ''
echo "-mmode=${targetPlatform.platform.gcc.mode}" >> $out/nix-support/cc-cflags-before
''
+ optionalString (targetPlatform ? platform.gcc.tune) ''
echo "-mtune=${targetPlatform.platform.gcc.tune}" >> $out/nix-support/cc-cflags-before
''
# TODO: categorize these and figure out a better place for them
+ optionalString hostPlatform.isCygwin ''
hardening_unsupported_flags+=" pic"
''
+ optionalString targetPlatform.isMinGW ''
'' + optionalString targetPlatform.isMinGW ''
hardening_unsupported_flags+=" stackprotector"
''
+ optionalString targetPlatform.isAvr ''
'' + optionalString targetPlatform.isAvr ''
hardening_unsupported_flags+=" stackprotector pic"
''
+ optionalString targetPlatform.isNetBSD ''
hardening_unsupported_flags+=" stackprotector fortify"
''
+ optionalString (targetPlatform.libc == "newlib") ''
'' + optionalString (targetPlatform.libc == "newlib") ''
hardening_unsupported_flags+=" stackprotector fortify pie pic"
'' + optionalString targetPlatform.isNetBSD ''
hardening_unsupported_flags+=" stackprotector fortify"
''
+ optionalString (libc != null && targetPlatform.isAvr) ''

View file

@ -90,26 +90,7 @@ rec {
echo "-target ${stdenv.targetPlatform.config}" >> $out/nix-support/cc-cflags
echo "-resource-dir=$(echo ${androidndk}/libexec/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/${hostInfo.double}/lib*/clang/*)" >> $out/nix-support/cc-cflags
echo "--gcc-toolchain=${androidndk}/libexec/android-sdk/ndk-bundle/toolchains/${targetInfo.toolchain}-${targetInfo.gccVer}/prebuilt/${hostInfo.double}" >> $out/nix-support/cc-cflags
''
+ lib.optionalString stdenv.targetPlatform.isAarch32 (let
p = stdenv.targetPlatform.platform.gcc or {}
// stdenv.targetPlatform.parsed.abi;
flags = lib.concatLists [
(lib.optional (p ? arch) "-march=${p.arch}")
(lib.optional (p ? cpu) "-mcpu=${p.cpu}")
(lib.optional (p ? abi) "-mabi=${p.abi}")
(lib.optional (p ? fpu) "-mfpu=${p.fpu}")
(lib.optional (p ? float-abi) "-mfloat-abi=${p.float-abi}")
(lib.optional (p ? mode) "-mmode=${p.mode}")
];
in ''
sed -E -i \
$out/bin/${stdenv.targetPlatform.config}-cc \
$out/bin/${stdenv.targetPlatform.config}-c++ \
$out/bin/${stdenv.targetPlatform.config}-clang \
$out/bin/${stdenv.targetPlatform.config}-clang++ \
-e 's|^(extraBefore=)\((.*)\)$|\1(\2 -Wl,--fix-cortex-a8 ${builtins.toString flags})|'
'');
'';
};
# Bionic lib C and other libraries.