about summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
authorAdam Joseph <adam@westernsemico.com>2022-12-07 18:56:32 -0800
committerAdam Joseph <54836058+amjoseph-nixpkgs@users.noreply.github.com>2023-10-23 01:31:21 +0000
commit0b2036cad0c49e9aeb0c9b9feac9f734016460d3 (patch)
tree82c155e74139a2a58480d6af1a7980703dd204dd /pkgs/build-support
parent0f9bb8236ab7b6357c1381439cbdaa5224c2710a (diff)
downloadnixlib-0b2036cad0c49e9aeb0c9b9feac9f734016460d3.tar
nixlib-0b2036cad0c49e9aeb0c9b9feac9f734016460d3.tar.gz
nixlib-0b2036cad0c49e9aeb0c9b9feac9f734016460d3.tar.bz2
nixlib-0b2036cad0c49e9aeb0c9b9feac9f734016460d3.tar.lz
nixlib-0b2036cad0c49e9aeb0c9b9feac9f734016460d3.tar.xz
nixlib-0b2036cad0c49e9aeb0c9b9feac9f734016460d3.tar.zst
nixlib-0b2036cad0c49e9aeb0c9b9feac9f734016460d3.zip
cc-wrapper: fix -mtune= validation, add ARM, add fallbacks
Before this commit, cc-wrapper/default.nix was using
`isGccArchSupported` to validate `-mtune=` values.  This has two
problems:

- On x86, `-mtune=` can take the same values as `-march`, plus two
  additional values `generic` and `intel` which are not valid for
  `-march`.

- On ARM, `-mtune=` does not take the same values as `-march=`;
  instead it takes the same values as `-mcpu`.

This commit fixes these two problems by adding a new
`isGccTuneSupported` function.  For `isx86` this returns `true` for
the two special values and otherwise defers to `isGccArchSupported`.

This commit also adds support for `-mtune=` on Aarch64.

Unfortunately on Aarch64, Clang does not accept as wide a variety of
`-mtune=` values as Gcc does.  In particular, Clang does not tune
for big.LITTLE mixed-model chips like the very popular RK3399, which
is targeted using `-march=cortex-a72.cortex-a53` in gcc.

To address this problem, this commit also adds a function
`findBestTuneApproximation` which can be used to map
clang-unsupported tunings like `cortex-a72.cortex-a53` to
less-precise tunings like `cortex-a53`.

The work which led to this commit arose because we now have
packages, like `crosvm`, which use *both* `clang` *and* `gcc`.
Previously I had been using `overrideAttrs` to set
`NIX_CFLAGS_COMPILE` on a package-by-package basis based on which
compiler that package used.  Since we now have packages which use
*both* compilers, this strategy no longer works.

I briefly considered splitting `NIX_CFLAGS_COMPILE` into
`NIX_CFLAGS_COMPILE_GCC` and `NIX_CFLAGS_COMPILE_CLANG`, but since
`NIX_CFLAGS_COMPILE` is sort of a hack to begin with I figured that
adding the logic to `cc-wrapper` would be preferable.
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/cc-wrapper/default.nix70
1 files changed, 65 insertions, 5 deletions
diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix
index eef67154ef94..8ac11436c5f7 100644
--- a/pkgs/build-support/cc-wrapper/default.nix
+++ b/pkgs/build-support/cc-wrapper/default.nix
@@ -110,7 +110,20 @@ let
   gccForLibs_solib = getLib gccForLibs
     + optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}";
 
-  # older compilers (for example bootstrap's GCC 5) fail with -march=too-modern-cpu
+  # The following two functions, `isGccArchSupported` and
+  # `isGccTuneSupported`, only handle those situations where a flag
+  # (`-march` or `-mtune`) is accepted by one compiler but rejected
+  # by another, and both compilers are relevant to nixpkgs.  We are
+  # not trying to maintain a complete list of all flags accepted by
+  # all versions of all compilers ever in nixpkgs.
+  #
+  # The two main cases of interest are:
+  #
+  # - One compiler is gcc and the other is clang
+  # - One compiler is pkgs.gcc and the other is bootstrap-files.gcc
+  #   -- older compilers (for example bootstrap's GCC 5) fail with
+  #   -march=too-modern-cpu
+
   isGccArchSupported = arch:
     if targetPlatform.isPower then false else # powerpc does not allow -march=
     if isGNU then
@@ -159,6 +172,51 @@ let
     else
       false;
 
+  isGccTuneSupported = tune:
+    # for x86 -mtune= takes the same values as -march, plus two more:
+    if targetPlatform.isx86 then
+      {
+        generic = true;
+        intel = true;
+      }.${tune} or (isGccArchSupported tune)
+    # on arm64, the -mtune= values are specific processors
+    else if targetPlatform.isAarch64 then
+      (if isGNU then
+        {
+          cortex-a53              = versionAtLeast ccVersion "4.8";  # gcc 8c075f
+          cortex-a72              = versionAtLeast ccVersion "5.1";  # gcc d8f70d
+          "cortex-a72.cortex-a53" = versionAtLeast ccVersion "5.1";  # gcc d8f70d
+        }.${tune} or false
+       else if isClang then
+         {
+           cortex-a53             = versionAtLeast ccVersion "3.9"; # llvm dfc5d1
+         }.${tune} or false
+       else false)
+    else if targetPlatform.isPower then
+      # powerpc does not support -march
+      true
+    else if targetPlatform.isMips then
+      # for mips -mtune= takes the same values as -march
+      isGccArchSupported tune
+    else
+      false;
+
+  # Clang does not support as many `-mtune=` values as gcc does;
+  # this function will return the best possible approximation of the
+  # provided `-mtune=` value, or `null` if none exists.
+  #
+  # Note: this function can make use of ccVersion; for example, `if
+  # versionOlder ccVersion "12" then ...`
+  findBestTuneApproximation = tune:
+    let guess = if isClang
+                then {
+                  # clang does not tune for big.LITTLE chips
+                  "cortex-a72.cortex-a53" = "cortex-a72";
+                }.${tune} or tune
+                else tune;
+    in if isGccTuneSupported guess
+       then guess
+       else null;
 
   darwinPlatformForCC = optionalString stdenv.targetPlatform.isDarwin (
     if (targetPlatform.darwinPlatform == "macos" && isGNU) then "macosx"
@@ -559,10 +617,12 @@ stdenv.mkDerivation {
     + optionalString (targetPlatform ? gcc.thumb) ''
       echo "-m${if targetPlatform.gcc.thumb then "thumb" else "arm"}" >> $out/nix-support/cc-cflags-before
     ''
-    + optionalString (targetPlatform ? gcc.tune &&
-                      isGccArchSupported targetPlatform.gcc.tune) ''
-      echo "-mtune=${targetPlatform.gcc.tune}" >> $out/nix-support/cc-cflags-before
-    ''
+    + (let tune = if targetPlatform ? gcc.tune
+                  then findBestTuneApproximation targetPlatform.gcc.tune
+                  else null;
+      in optionalString (tune != null) ''
+      echo "-mtune=${tune}" >> $out/nix-support/cc-cflags-before
+    '')
 
     # TODO: categorize these and figure out a better place for them
     + optionalString targetPlatform.isWindows ''