From d7762a5a78273ffb76da6f6902245983143f63f6 Mon Sep 17 00:00:00 2001 From: Victor Fuentes Date: Sun, 22 Sep 2024 02:55:02 +0000 Subject: [PATCH] add bootstraped x86_64-linux cross compiled gcc (#8) Work in progress cross compiler for x86_64. I've managed to get a full x86_64 gcc using the binaries built from foundation, and am working on implementing their builds into tidepool. ### Bootstrapping steps 0) Start with i686 tools (gcc, binutils, musl, etc) 1) Build binutils targeting x86_64-linux 2) Build a minimal gcc cross compiler using the cross binutils. This minimal cross compiler does not have support for libc, so is pretty much only useful for building musl or glibc. 3) Use the minimal cross compiler to build x86_64-linux glibc or musl 4) Now that we have a cross compiler and x86_64-linux libc, we can build gcc for the target architecture! 5) Profit! We can now build anything x86_64 using our gcc compiler! Co-authored-by: Jake Hamilton Reviewed-on: https://git.auxolotl.org/auxolotl/labs/pulls/8 Reviewed-by: Jake Hamilton Co-authored-by: Victor Fuentes Co-committed-by: Victor Fuentes --- foundation/flake.lock | 13 +- tidepool/flake.lock | 26 +- tidepool/src/builders/basic.nix | 11 +- tidepool/src/export.nix | 31 +- tidepool/src/lib/types.nix | 47 ++- tidepool/src/packages/aux/a.nix | 2 +- tidepool/src/packages/default.nix | 44 ++- .../packages/foundation/binutils/default.nix | 212 ++++++---- .../src/packages/foundation/gcc/bootstrap.nix | 84 ++++ .../src/packages/foundation/gcc/cross.nix | 104 +++++ .../src/packages/foundation/gcc/default.nix | 363 +++++++++++------- .../src/packages/foundation/gcc/newlib.nix | 71 ++++ .../gcc/patches/libstdc++-target.patch | 33 ++ .../src/packages/foundation/glibc/default.nix | 193 ++++++---- .../foundation/linux-headers/default.nix | 14 +- 15 files changed, 903 insertions(+), 345 deletions(-) create mode 100644 tidepool/src/packages/foundation/gcc/bootstrap.nix create mode 100644 tidepool/src/packages/foundation/gcc/cross.nix create mode 100644 tidepool/src/packages/foundation/gcc/newlib.nix create mode 100644 tidepool/src/packages/foundation/gcc/patches/libstdc++-target.patch diff --git a/foundation/flake.lock b/foundation/flake.lock index 37bbbad..f58668e 100644 --- a/foundation/flake.lock +++ b/foundation/flake.lock @@ -3,17 +3,18 @@ "lib": { "locked": { "dir": "lib", - "dirtyRev": "2be3111b2c0911f40b47fe0a1fb22b5f5188cf59-dirty", - "dirtyShortRev": "2be3111-dirty", - "lastModified": 1719251485, - "narHash": "sha256-63NvfFVeTDITfNu60rmCUlaZtAeZUnvrIaOLSk9ScC8=", + "lastModified": 1723737980, + "narHash": "sha256-1WnFatW5kSuO2jjt62hvSbH84TSYyO+VmvkJ0d5e/ZY=", + "ref": "master", + "rev": "cadfaabc853d20f2bc20bad794fcbe520ea48f13", + "revCount": 82, "type": "git", - "url": "file:../?dir=lib" + "url": "file:../" }, "original": { "dir": "lib", "type": "git", - "url": "file:../?dir=lib" + "url": "file:../" } }, "root": { diff --git a/tidepool/flake.lock b/tidepool/flake.lock index 990a516..746a587 100644 --- a/tidepool/flake.lock +++ b/tidepool/flake.lock @@ -8,33 +8,35 @@ }, "locked": { "dir": "foundation", - "dirtyRev": "3f9d287065ac685ce500c2cddb35428b2927f5a2-dirty", - "dirtyShortRev": "3f9d287-dirty", - "lastModified": 1720514984, - "narHash": "sha256-AuixwSlYk34Z6+GEc7y4QotF3Hk963zC9I9hAwX5KCE=", + "lastModified": 1724190751, + "narHash": "sha256-e8sOmeXS9YWuQqjW6gvtS3PIueazkf4S1iiJ/94eXv4=", + "ref": "master", + "rev": "4b36a5a0133f5481840bdfaf693c971215a7ef1f", + "revCount": 84, "type": "git", - "url": "file:../?dir=foundation" + "url": "file:../" }, "original": { "dir": "foundation", "type": "git", - "url": "file:../?dir=foundation" + "url": "file:../" } }, "lib": { "locked": { "dir": "lib", - "dirtyRev": "3f9d287065ac685ce500c2cddb35428b2927f5a2-dirty", - "dirtyShortRev": "3f9d287-dirty", - "lastModified": 1720514984, - "narHash": "sha256-AuixwSlYk34Z6+GEc7y4QotF3Hk963zC9I9hAwX5KCE=", + "lastModified": 1724190751, + "narHash": "sha256-e8sOmeXS9YWuQqjW6gvtS3PIueazkf4S1iiJ/94eXv4=", + "ref": "master", + "rev": "4b36a5a0133f5481840bdfaf693c971215a7ef1f", + "revCount": 84, "type": "git", - "url": "file:../?dir=lib" + "url": "file:../" }, "original": { "dir": "lib", "type": "git", - "url": "file:../?dir=lib" + "url": "file:../" } }, "root": { diff --git a/tidepool/src/builders/basic.nix b/tidepool/src/builders/basic.nix index e7badef..f2e01d2 100644 --- a/tidepool/src/builders/basic.nix +++ b/tidepool/src/builders/basic.nix @@ -65,7 +65,15 @@ in PATH = let bins = lib.paths.bin ( - (lib.packages.dependencies.get dependencies.build.host) + (lib.packages.dependencies.get dependencies.build.only) + ++ (lib.packages.dependencies.get dependencies.build.build) + ++ (lib.packages.dependencies.get dependencies.build.host) + ++ (lib.packages.dependencies.get dependencies.build.target) + ++ (lib.packages.dependencies.get dependencies.host.only) + ++ (lib.packages.dependencies.get dependencies.host.host) + ++ (lib.packages.dependencies.get dependencies.host.target) + ++ (lib.packages.dependencies.get dependencies.target.only) + ++ (lib.packages.dependencies.get dependencies.target.target) ++ [ foundation.stage2-bash foundation.stage2-coreutils @@ -99,6 +107,7 @@ in } ); in + # (builtins.trace "build: ${package.name} -> build=${package.platform.build.triple} host=${package.platform.host.triple} target=${package.platform.target.triple}") built // { inherit (package) meta; diff --git a/tidepool/src/export.nix b/tidepool/src/export.nix index 8eb98c3..58d672f 100644 --- a/tidepool/src/export.nix +++ b/tidepool/src/export.nix @@ -16,27 +16,24 @@ in aux-a = config.packages.aux.a; aux-b = config.packages.aux.b; - # foundation-gcc-x86_64 = - # (config.packages.foundation.gcc.versions."13.2.0".extend (args: { - # config = { - # platform = { - # target = lib.modules.overrides.force "x86_64-linux"; - # }; - # }; - # })) - # .config; foundation-gcc = config.packages.foundation.gcc; + foundation-glibc = config.packages.foundation.glibc; foundation-binutils = config.packages.foundation.binutils; foundation-linux-headers = config.packages.foundation.linux-headers; - # foundation-linux-headers = config.packages.foundation.linux-headers.versions.latest.extend { - # platform.host = lib.modules.overrides.force "x86_64-linux"; - # }; - # example-x = config.packages.example.x; - cross-aux-a-x86_64-linux = config.packages.cross.x86_64-linux.aux.a; - cross-foundation-gcc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.gcc; + + cross-foundation-glibc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.glibc; + cross-foundation-binutils-x86_64-linux = config.packages.cross.x86_64-linux.foundation.binutils; + + cross-tool-foundation-gcc-newlib-x86_64-linux = config.packages.cross-tools.x86_64-linux.foundation.gcc-newlib; + cross-tool-foundation-gcc-x86_64-linux = config.packages.cross-tools.x86_64-linux.foundation.gcc-cross; + cross-foundation-gcc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.gcc-bootstrap; + + example-a = config.packages.foundation.gcc.versions.latest.extend { + platform = { + target = lib.modules.override 0 "x86_64-linux"; + }; + }; }; }; - - # exported.packages.i686-linux.cross-foundation-gcc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.gcc.package; }; } diff --git a/tidepool/src/lib/types.nix b/tidepool/src/lib/types.nix index d4723b1..16caad9 100644 --- a/tidepool/src/lib/types.nix +++ b/tidepool/src/lib/types.nix @@ -230,6 +230,34 @@ in default.value = [ ]; }; + # extend = lib.options.create { + # description = "Extend the package definition."; + # type = lib.types.function lib.types.raw; + # internal = true; + # writable = false; + # default.value = module: + # let + # normalized = + # if builtins.isList module then + # module + # else if builtins.isFunction module || module ? config then + # [ module ] + # else + # [{ + # config = module; + # }]; + # result = meta.extend { + # modules = + # normalized ++ [ + # { + # config.__modules__ = lib.modules.overrides.force (config.__modules__ ++ normalized); + # } + # ]; + # }; + # in + # result.config; + # }; + extend = lib.options.create { description = "Extend the package definition."; type = lib.types.function lib.types.raw; @@ -246,13 +274,14 @@ in [{ config = module; }]; - result = meta.extend { - modules = - normalized ++ [ - { - config.__modules__ = lib.modules.overrides.force (config.__modules__ ++ normalized); - } - ]; + + modules = config.__modules__ ++ normalized; + + result = lib.modules.run { + modules = [ + submodule + { config.__modules__ = modules; } + ] ++ modules; }; in result.config; @@ -261,8 +290,8 @@ in meta = { description = lib.options.create { description = "The description for the package."; - type = lib.types.nullish lib.types.string; - default.value = null; + type = lib.types.string; + default.value = ""; }; homepage = lib.options.create { diff --git a/tidepool/src/packages/aux/a.nix b/tidepool/src/packages/aux/a.nix index 3848de8..7efef9b 100644 --- a/tidepool/src/packages/aux/a.nix +++ b/tidepool/src/packages/aux/a.nix @@ -1,4 +1,4 @@ -{ lib', config }: +{ config }: let inherit (config) builders packages; in diff --git a/tidepool/src/packages/default.nix b/tidepool/src/packages/default.nix index 1807094..03a210c 100644 --- a/tidepool/src/packages/default.nix +++ b/tidepool/src/packages/default.nix @@ -4,7 +4,7 @@ let doubles = lib.systems.doubles.all; - packages = builtins.removeAttrs config.packages [ "cross" ]; + packages = builtins.removeAttrs config.packages [ "cross" "cross-tools" ]; in { includes = [ @@ -21,6 +21,14 @@ in freeform = lib.types.packages; options = { + cross-tools = lib.attrs.generate doubles ( + system: + lib.options.create { + description = "The cross-compilation tools for the ${system} target."; + type = lib.types.packages; + default.value = { }; + } + ); cross = lib.attrs.generate doubles ( system: lib.options.create { @@ -54,6 +62,36 @@ in }; config = { + packages.cross-tools = lib.attrs.generate doubles ( + system: + builtins.mapAttrs + ( + namespace: + builtins.mapAttrs ( + name: alias: + let + setTarget = + package: + package + // { + __modules__ = package.__modules__ ++ [ + { + config.platform = { + target = lib.modules.override 5 system; + }; + } + ]; + }; + + updated = alias // { + versions = builtins.mapAttrs (version: package: setTarget package) alias.versions; + }; + in + updated + ) + ) + packages + ); packages.cross = lib.attrs.generate doubles ( system: builtins.mapAttrs @@ -62,7 +100,7 @@ in builtins.mapAttrs ( name: alias: let - setHost = + setPlatform = package: package // { @@ -77,7 +115,7 @@ in }; updated = alias // { - versions = builtins.mapAttrs (version: package: setHost package) alias.versions; + versions = builtins.mapAttrs (version: package: setPlatform package) alias.versions; }; in updated diff --git a/tidepool/src/packages/foundation/binutils/default.nix b/tidepool/src/packages/foundation/binutils/default.nix index 77c4bdd..caa2879 100644 --- a/tidepool/src/packages/foundation/binutils/default.nix +++ b/tidepool/src/packages/foundation/binutils/default.nix @@ -1,8 +1,8 @@ -{ - lib, - lib', - config, - options, +{ lib +, lib' +, config +, options +, }: let inherit (config) @@ -27,101 +27,149 @@ in }; }; - config = { - meta = { - platforms = [ "i686-linux" ]; - }; + config = + let + isBuildBootstrapped = config.platform.build.double == "i686-linux"; + isHostBootstrapped = config.platform.host.double == "i686-linux"; - pname = "binutils"; - version = "2.41"; + isBootstrapped = isBuildBootstrapped && isHostBootstrapped; - builder = builders.basic; + isCross = + config.platform.build.double != config.platform.host.double + && config.platform.host.double == config.platform.target.double; + in + { + meta = { + platforms = [ + "i686-linux" + "x86_64-linux" + ]; + }; - deps = { - build = { - host = { - inherit (packages.foundation) gcc; + pname = "binutils"; + version = "2.41"; + + builder = builders.basic; + + deps = { + build = { + only = { + gcc = lib.modules.when (!isBootstrapped) ( + if isCross then + packages.foundation.gcc-cross.versions.latest.extend + { + platform = lib.modules.override 0 { + inherit (config.platform) build target; + host = config.platform.build; + }; + } + else + packages.foundation.gcc.versions.latest + ); + glibc = lib.modules.when (isCross) ( + packages.foundation.glibc.versions.latest.extend { + platform = lib.modules.override 0 { + inherit (config.platform) host target build; + }; + } + ); + binutils = lib.modules.when (isCross) ( + packages.foundation.binutils.versions.latest.extend { + platform = lib.modules.override 0 { + inherit (config.platform) target build; + host = config.platform.build; + }; + } + ); + }; }; }; - }; - env = { - PATH = lib.paths.bin [ - # foundation.stage2-gcc - foundation.stage2-binutils - foundation.stage2-gnumake - foundation.stage2-gnupatch - foundation.stage2-gnused - foundation.stage2-gnugrep - foundation.stage2-gawk - foundation.stage2-diffutils - foundation.stage2-findutils - foundation.stage2-gnutar - foundation.stage1-xz - ]; - }; + env = { + PATH = lib.paths.bin ( + lib.lists.when (isBootstrapped) [ foundation.stage2-gcc ] + ++ [ + foundation.stage2-gcc + foundation.stage2-binutils + foundation.stage2-gnumake + foundation.stage2-gnupatch + foundation.stage2-gnused + foundation.stage2-gnugrep + foundation.stage2-gawk + foundation.stage2-diffutils + foundation.stage2-findutils + foundation.stage2-gnutar + foundation.stage1-xz + ] + ); + } // (lib.attrs.when (isCross) { + LDFLAGS_FOR_TARGET = "-B${config.deps.build.only.glibc.package}/lib -L${config.deps.build.only.glibc.package}/lib -I${config.deps.build.only.glibc.package}/include"; + }); - phases = - let - patches = [ - # Make binutils output deterministic by default. - ./patches/deterministic.patch - ]; + phases = + let + patches = [ + # Make binutils output deterministic by default. + ./patches/deterministic.patch + ]; - configureFlags = [ - # "CC=musl-gcc" - "LDFLAGS=--static" - "--prefix=${builtins.placeholder "out"}" - "--build=${config.platform.build.triple}" - "--host=${config.platform.host.triple}" - "--target=${config.platform.target.triple}" + configureFlags = + lib.lists.when (!isCross) [ + "LDFLAGS=--static" + ] + ++ [ + "--prefix=${builtins.placeholder "out"}" + "--build=${config.platform.build.triple}" + "--host=${config.platform.host.triple}" + "--target=${config.platform.target.triple}" - "--with-sysroot=/" - "--enable-deterministic-archives" - # depends on bison - "--disable-gprofng" + "--with-sysroot=/" + "--enable-deterministic-archives" + # depends on bison + "--disable-gprofng" - # Turn on --enable-new-dtags by default to make the linker set - # RUNPATH instead of RPATH on binaries. This is important because - # RUNPATH can be overridden using LD_LIBRARY_PATH at runtime. - "--enable-new-dtags" + # Turn on --enable-new-dtags by default to make the linker set + # RUNPATH instead of RPATH on binaries. This is important because + # RUNPATH can be overridden using LD_LIBRARY_PATH at runtime. + "--enable-new-dtags" - # By default binutils searches $libdir for libraries. This brings in - # libbfd and libopcodes into a default visibility. Drop default lib - # path to force users to declare their use of these libraries. - "--with-lib-path=:" + # By default binutils searches $libdir for libraries. This brings in + # libbfd and libopcodes into a default visibility. Drop default lib + # path to force users to declare their use of these libraries. + "--with-lib-path=:" - "--disable-multilib" - ]; - in - { - unpack = '' - tar xf ${config.src} - cd binutils-${config.version} - ''; + "--disable-multilib" - patch = '' - ${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches} - ''; + ]; + in + { + unpack = '' + tar xf ${config.src} + cd binutils-${config.version} + ''; - configure = '' - bash ./configure ${builtins.concatStringsSep " " configureFlags} - ''; + patch = '' + ${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches} + ''; - build = '' - make -j $NIX_BUILD_CORES - ''; + configure = '' + bash ./configure ${builtins.concatStringsSep " " configureFlags} + ''; - install = '' - make -j $NIX_BUILD_CORES install-strip - ''; + build = '' + make -j $NIX_BUILD_CORES + ''; + + install = '' + make -j $NIX_BUILD_CORES install-strip + ''; + }; + + src = builtins.fetchurl { + url = "${mirrors.gnu}/binutils/binutils-${config.version}.tar.xz"; + sha256 = "rppXieI0WeWWBuZxRyPy0//DHAMXQZHvDQFb3wYAdFA="; }; - - src = builtins.fetchurl { - url = "${mirrors.gnu}/binutils/binutils-${config.version}.tar.xz"; - sha256 = "rppXieI0WeWWBuZxRyPy0//DHAMXQZHvDQFb3wYAdFA="; }; - }; }; }; }; diff --git a/tidepool/src/packages/foundation/gcc/bootstrap.nix b/tidepool/src/packages/foundation/gcc/bootstrap.nix new file mode 100644 index 0000000..399be1a --- /dev/null +++ b/tidepool/src/packages/foundation/gcc/bootstrap.nix @@ -0,0 +1,84 @@ +{ config, options }: +let + inherit (config) + lib + packages + ; +in +{ + config.packages.foundation.gcc-bootstrap = { + versions = { + "latest" = config.packages.foundation.gcc.versions.latest.extend + ( + { config }: + { + config = { + meta = { + platforms = lib.modules.override 0 [ + "i686-linux" + ]; + }; + + deps = { + build = { + build = { + gcc = lib.modules.override 0 ( + packages.foundation.gcc-cross.versions.latest.extend { + platform = lib.modules.override 0 { + build = "i686-linux"; + target = config.platform.target; + host = "i686-linux"; + }; + } + ); + binutils = lib.modules.override 0 ( + packages.foundation.binutils.versions.latest.extend { + platform = lib.modules.override 0 { + build = "i686-linux"; + target = config.platform.target; + host = config.platform.host; + }; + } + ); + glibc = lib.modules.override 0 ( + packages.foundation.glibc.versions.latest.extend { + platform = lib.modules.override 0 { + build = "i686-linux"; + target = config.platform.target; + host = config.platform.host; + }; + } + ); + }; + }; + }; + + env = { + LIBRARY_PATH = lib.modules.override 0 "${config.deps.build.build.glibc.package}/lib"; + LDFLAGS_FOR_TARGET = + lib.modules.override 0 + "-L$(pwd)/${config.platform.target.triple}/libgcc -L${config.deps.build.build.glibc.package}/lib"; + }; + + configureFlags = lib.modules.override 0 [ + "--prefix=${builtins.placeholder "out"}" + # Pretend we're native even though we're not + "--build=${config.platform.target.triple}" + "--host=${config.platform.host.triple}" + "--target=${config.platform.target.triple}" + "--with-as=${config.deps.build.build.binutils.package}/bin/as" + "--with-ld=${config.deps.build.build.binutils.package}/bin/ld" + "--enable-languages=c,c++" + "--disable-bootstrap" + "--disable-libsanitizer" + "--disable-multilib" + "--with-native-system-header-dir=${config.deps.build.build.glibc.package}/include" + "--with-gxx-include-dir=${placeholder "out"}/include/c++/${config.version}/" + "--with-build-sysroot=/" + ]; + }; + } + ); + }; + }; +} diff --git a/tidepool/src/packages/foundation/gcc/cross.nix b/tidepool/src/packages/foundation/gcc/cross.nix new file mode 100644 index 0000000..638113c --- /dev/null +++ b/tidepool/src/packages/foundation/gcc/cross.nix @@ -0,0 +1,104 @@ +{ config, options }: +let + inherit (config) + lib + foundation + packages + ; +in +{ + config.packages.foundation.gcc-cross = { + versions = { + "latest" = config.packages.foundation.gcc.versions.latest.extend + ( + { config }: + { + config = + let + programPrefix = lib.strings.when + ( + config.platform.build.triple != config.platform.target.triple + ) "${config.platform.target.triple}-"; + in + { + meta = { + platforms = lib.modules.override 0 [ + "i686-linux" + ]; + }; + + deps = { + build = { + build = { + binutils = ( + packages.foundation.binutils.versions.latest.extend { + platform = lib.modules.override 0 config.platform; + } + ); + glibc = ( + packages.foundation.glibc.versions.latest.extend { + platform = lib.modules.override 0 { + inherit (config.platform) build target; + host = config.platform.target; + }; + } + ); + linux-headers = ( + packages.foundation.linux-headers.versions.latest.extend { + platform.target = lib.modules.override 0 config.platform.target; + } + ); + }; + }; + }; + + env = { + # LIBRARY_PATH = lib.modules.override 0 "${foundation.stage1-musl}/lib"; + CC = lib.modules.override 0 "gcc -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so -idirafter ${foundation.stage1-musl}/include"; + CXX = lib.modules.override 0 "g++ -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so -idirafter ${foundation.stage1-musl}/include"; + CFLAGS_FOR_TARGET = + lib.modules.override 0 + "-Wl,-dynamic-linker -Wl,${config.deps.build.build.glibc.package}/lib/ld-linux-x86-64.so.2 -B${config.deps.build.build.glibc.package}/lib"; + LDFLAGS_FOR_TARGET = + lib.modules.override 0 + "-L$(pwd)/${config.platform.target.triple}/libgcc -L${config.deps.build.build.glibc.package}/lib"; + }; + + configureFlags = lib.modules.override 0 [ + "--prefix=${builtins.placeholder "out"}" + "--build=${config.platform.build.triple}" + "--host=${config.platform.host.triple}" + "--target=${config.platform.target.triple}" + "--with-as=${config.deps.build.build.binutils.package}/bin/${programPrefix}as" + "--with-ld=${config.deps.build.build.binutils.package}/bin/${programPrefix}ld" + "--enable-languages=c,c++" + "--disable-libsanitizer" + "--disable-lto" + "--disable-multilib" + "--with-headers=${config.deps.build.build.glibc.package}/include" + "--with-build-sysroot=/" + # "--with-sysroot=${config.deps.build.build.glibc.package}" + "--with-native-system-header-dir=${config.deps.build.build.glibc.package}/include" + ]; + + phases.configure = lib.modules.override 0 '' + # Configure + + mkdir build + cd build + echo PATH=$PATH + + # TODO(vlinkz) Hack to fix missing crti.o and crtn.o. Figure out how to properly find their paths. + mkdir gcc + ln -sv ${config.deps.build.build.glibc.package}/lib/{crti.o,crtn.o} gcc + mkdir -p x86_64-unknown-linux-gnu/libstdc++-v3/src + ln -sv ${config.deps.build.build.glibc.package}/lib/{crti.o,crtn.o} x86_64-unknown-linux-gnu/libstdc++-v3/src + + bash ../configure ${builtins.concatStringsSep " " config.configureFlags} + ''; + }; + } + ); + }; + }; +} diff --git a/tidepool/src/packages/foundation/gcc/default.nix b/tidepool/src/packages/foundation/gcc/default.nix index 44df14e..b75bcb4 100644 --- a/tidepool/src/packages/foundation/gcc/default.nix +++ b/tidepool/src/packages/foundation/gcc/default.nix @@ -11,12 +11,11 @@ let ; in { - config.packages.context.options = { - "foundation:cflags" = lib.options.create { - type = lib.types.list.of lib.types.string; - default.value = [ ]; - }; - }; + includes = [ + ./newlib.nix + ./cross.nix + ./bootstrap.nix + ]; config.packages.foundation.gcc = { versions = { @@ -82,135 +81,239 @@ in description = "Version of isl."; }; }; - }; - config = { - meta = { - platforms = [ "i686-linux" ]; + configureFlags = lib.options.create { + type = lib.types.list.of lib.types.string; + description = "Flags to pass to the configure script."; }; - pname = "gcc"; - version = "13.2.0"; - - builder = builders.basic; - - env = { - PATH = lib.paths.bin [ - foundation.stage2-gcc - foundation.stage2-binutils - foundation.stage2-gnumake - foundation.stage2-gnused - foundation.stage2-gnugrep - foundation.stage2-gawk - foundation.stage2-diffutils - foundation.stage2-findutils - foundation.stage2-gnutar - foundation.stage2-gzip - foundation.stage2-bzip2 - foundation.stage1-xz - ]; - }; - - phases = - let - host = lib.systems.withBuildInfo config.platform.host; - - mbits = if host.system.cpu.family == "x86" then if host.is64bit then "-m64" else "-m32" else ""; - in - { - unpack = '' - # Unpack - tar xf ${config.src} - tar xf ${config.gmp.src} - tar xf ${config.mpfr.src} - tar xf ${config.mpc.src} - tar xf ${config.isl.src} - cd gcc-${config.version} - - ln -s ../gmp-${config.gmp.version} gmp - ln -s ../mpfr-${config.mpfr.version} mpfr - ln -s ../mpc-${config.mpc.version} mpc - ln -s ../isl-${config.isl.version} isl - ''; - - patch = '' - # Patch - # force musl even if host triple is gnu - sed -i 's|"os/gnu-linux"|"os/generic"|' libstdc++-v3/configure.host - ''; - - configure = '' - # Configure - export CC="gcc -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so" - export CXX="g++ -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so" - export CFLAGS_FOR_TARGET="-Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so" - export LIBRARY_PATH="${foundation.stage1-musl}/lib" - - bash ./configure \ - --prefix=$out \ - --build=${config.platform.build.triple} \ - --host=${config.platform.host.triple} \ - --target=${config.platform.target.triple} \ - --with-native-system-header-dir=/include \ - --with-sysroot=${foundation.stage1-musl} \ - --enable-languages=c,c++ \ - --disable-bootstrap \ - --disable-libsanitizer \ - --disable-lto \ - --disable-multilib \ - --disable-plugin \ - CFLAGS=-static \ - CXXFLAGS=-static - ''; - - build = '' - # Build - make -j $NIX_BUILD_CORES - ''; - - install = '' - # Install - make -j $NIX_BUILD_CORES install-strip - ''; - }; - - src = builtins.fetchurl { - url = "${mirrors.gnu}/gcc/gcc-${config.version}/gcc-${config.version}.tar.xz"; - sha256 = "4nXnZEKmBnNBon8Exca4PYYTFEAEwEE1KIY9xrXHQ9o="; - }; - - gmp = { - version = "6.3.0"; - src = builtins.fetchurl { - url = "${mirrors.gnu}/gmp/gmp-${config.gmp.version}.tar.xz"; - sha256 = "o8K4AgG4nmhhb0rTC8Zq7kknw85Q4zkpyoGdXENTiJg="; - }; - }; - - mpfr = { - version = "4.2.1"; - src = builtins.fetchurl { - url = "${mirrors.gnu}/mpfr/mpfr-${config.mpfr.version}.tar.xz"; - sha256 = "J3gHNTpnJpeJlpRa8T5Sgp46vXqaW3+yeTiU4Y8fy7I="; - }; - }; - - mpc = { - version = "1.3.1"; - src = builtins.fetchurl { - url = "${mirrors.gnu}/mpc/mpc-${config.mpc.version}.tar.gz"; - sha256 = "q2QkkvXPiCt0qgy3MM1BCoHtzb7IlRg86TDnBsHHWbg="; - }; - }; - - isl = { - version = "0.24"; - src = builtins.fetchurl { - url = "https://gcc.gnu.org/pub/gcc/infrastructure/isl-${config.isl.version}.tar.bz2"; - sha256 = "/PeN2WVsEOuM+fvV9ZoLawE4YgX+GTSzsoegoYmBRcA="; - }; + exports = lib.options.create { + type = lib.types.attrs.of lib.types.string; + description = "List of exports to add to the environment."; }; }; + + config = + let + isBuildBootstrapped = config.platform.build.double == "i686-linux"; + isHostBootstrapped = config.platform.host.double == "i686-linux"; + + isBootstrapped = isBuildBootstrapped && isHostBootstrapped; + + crossTool = + (config.platform.target.triple != config.platform.host.triple) + && (config.platform.host.triple == config.platform.build.triple); + cross = + (config.platform.target.triple != config.platform.host.triple) + && (config.platform.host.triple == config.platform.target.triple); + + programPrefix = lib.strings.when + ( + config.platform.build.triple != config.platform.target.triple + ) "${config.platform.target.triple}-"; + + libc = if isBootstrapped then foundation.stage1-musl else config.deps.build.build.glibc.package; + libcLd = + if isBootstrapped then + "${foundation.stage1-musl}/lib/libc.so" + else + "${config.deps.build.build.glibc.package}/lib/ld-linux-x86-64.so.2"; + + host = lib.systems.withBuildInfo config.platform.host; + target = lib.systems.withBuildInfo config.platform.target; + in + { + meta = { + platforms = [ + "i686-linux" + ]; + }; + + pname = "gcc-${config.platform.build.double}--${config.platform.host.double}--${config.platform.target.double}"; + version = "13.2.0"; + + builder = builders.basic; + + deps = { + build = { + build = lib.modules.when (!isBootstrapped) { + gcc = packages.foundation.gcc-cross.versions.latest; + glibc = packages.foundation.glibc.versions.latest; + linux-headers = packages.foundation.linux-headers.versions.latest; + binutils = packages.foundation.binutils.versions.latest; + }; + }; + }; + + env = + { + PATH = lib.modules.when (isBuildBootstrapped) ( + lib.paths.bin ([ + foundation.stage2-gnumake + foundation.stage2-gnused + foundation.stage2-gnugrep + foundation.stage2-gnupatch + foundation.stage2-gawk + foundation.stage2-diffutils + foundation.stage2-findutils + foundation.stage2-gnutar + foundation.stage2-gzip + foundation.stage2-bzip2 + foundation.stage1-xz + ] ++ (lib.lists.when (isBootstrapped) [ + foundation.stage2-gcc + foundation.stage2-binutils + ])) + ); + CFLAGS_FOR_TARGET = "-Wl,-dynamic-linker -Wl,${libcLd}"; + } + // lib.attrs.when (isBootstrapped) { + CC = "gcc -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so"; + CXX = "g++ -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so"; + } + // lib.attrs.when (!cross && !crossTool) { + LIBRARY_PATH = "${libc}/lib"; + }; + + hooks = + let + flags = + if (isBootstrapped && !(cross || crossTool)) then + [ + "-Wl,-dynamic-linker" + "-Wl,${foundation.stage1-musl}/lib/libc.so" + ] + else + [ + "-Wl,-dynamic-linker" + "-Wl,${config.deps.build.build.glibc.package}/lib/ld-linux${lib.strings.when (target.isx86 && target.is64bit) "-x86-64"}.so.2" + "-B${config.deps.build.build.glibc.package}/lib" + # "-idirafter ${config.deps.build.build.glibc.package}/include" + ]; + in + ctx: { + "aux:gcc:env" = lib.dag.entry.between [ "unpack" ] [ "configure" ] '' + export CC='${config.package}/bin/${programPrefix}gcc ${builtins.concatStringsSep " " flags}' + export CXX='${config.package}/bin/${programPrefix}g++ ${builtins.concatStringsSep " " flags}' + export CC_FOR_TARGET=$CC + export CXX_FOR_TARGET=$CXX + export CC_FOR_BUILD=$CC + export CXX_FOR_BUILD=$CXX + alias gcc='$CC' + alias g++='$CXX' + ''; + }; + + configureFlags = + [ + "--prefix=${builtins.placeholder "out"}" + "--build=${config.platform.build.triple}" + "--host=${config.platform.host.triple}" + "--target=${config.platform.target.triple}" + "--enable-languages=c,c++" + "--disable-bootstrap" + "--disable-libsanitizer" + "--disable-multilib" + "--with-build-sysroot=/" + "--with-native-system-header-dir=${libc}/include" + ] + ++ lib.lists.when (isBootstrapped) [ + "--disable-lto" + ]; + + phases = + let + patches = [ + # Make binutils output deterministic by default. + ./patches/libstdc++-target.patch + ]; + in + { + unpack = '' + # Unpack + tar xf ${config.src} + tar xf ${config.gmp.src} + tar xf ${config.mpfr.src} + tar xf ${config.mpc.src} + tar xf ${config.isl.src} + cd gcc-${config.version} + + ln -s ../gmp-${config.gmp.version} gmp + ln -s ../mpfr-${config.mpfr.version} mpfr + ln -s ../mpc-${config.mpc.version} mpc + ln -s ../isl-${config.isl.version} isl + ''; + + patch = '' + ${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches} + ${lib.strings.when (isBootstrapped && !(crossTool || cross))'' + # force musl even if host triple is gnu + sed -i 's|"os/gnu-linux"|"os/generic"|' libstdc++-v3/configure.host + ''} + ''; + + configure = '' + # Configure + mkdir build + cd build + + bash ../configure ${builtins.concatStringsSep " " config.configureFlags} + ''; + + build = '' + # Build + make -j $NIX_BUILD_CORES + ''; + + install = '' + # Install + ${ + lib.strings.when (host.is64bit) '' + mkdir -p $out/lib + ln -s lib $out/lib64 + '' + } + make -j $NIX_BUILD_CORES install + ''; + }; + + src = builtins.fetchurl { + url = "${mirrors.gnu}/gcc/gcc-${config.version}/gcc-${config.version}.tar.xz"; + sha256 = "4nXnZEKmBnNBon8Exca4PYYTFEAEwEE1KIY9xrXHQ9o="; + }; + + gmp = { + version = "6.3.0"; + src = builtins.fetchurl { + url = "${mirrors.gnu}/gmp/gmp-${config.gmp.version}.tar.xz"; + sha256 = "o8K4AgG4nmhhb0rTC8Zq7kknw85Q4zkpyoGdXENTiJg="; + }; + }; + + mpfr = { + version = "4.2.1"; + src = builtins.fetchurl { + url = "${mirrors.gnu}/mpfr/mpfr-${config.mpfr.version}.tar.xz"; + sha256 = "J3gHNTpnJpeJlpRa8T5Sgp46vXqaW3+yeTiU4Y8fy7I="; + }; + }; + + mpc = { + version = "1.3.1"; + src = builtins.fetchurl { + url = "${mirrors.gnu}/mpc/mpc-${config.mpc.version}.tar.gz"; + sha256 = "q2QkkvXPiCt0qgy3MM1BCoHtzb7IlRg86TDnBsHHWbg="; + }; + }; + + isl = { + version = "0.24"; + src = builtins.fetchurl { + url = "https://gcc.gnu.org/pub/gcc/infrastructure/isl-${config.isl.version}.tar.bz2"; + sha256 = "/PeN2WVsEOuM+fvV9ZoLawE4YgX+GTSzsoegoYmBRcA="; + }; + }; + }; }; }; }; diff --git a/tidepool/src/packages/foundation/gcc/newlib.nix b/tidepool/src/packages/foundation/gcc/newlib.nix new file mode 100644 index 0000000..b098af6 --- /dev/null +++ b/tidepool/src/packages/foundation/gcc/newlib.nix @@ -0,0 +1,71 @@ +{ config, options }: +let + inherit (config) + lib + packages + ; +in +{ + config.packages.foundation.gcc-newlib = { + versions = { + "latest" = config.packages.foundation.gcc.versions.latest.extend ( + { config }: + { + config = + let + programPrefix = lib.strings.when + ( + config.platform.build.triple != config.platform.target.triple + ) "${config.platform.target.triple}-"; + in + { + meta = { + platforms = lib.modules.override 0 [ + "i686-linux" + ]; + }; + + deps = { + build = { + build = { + binutils = ( + packages.foundation.binutils.versions.latest.extend { + platform = lib.modules.override 0 config.platform; + } + ); + }; + }; + }; + + configureFlags = lib.modules.override 0 [ + "--prefix=${builtins.placeholder "out"}" + "--build=${config.platform.build.triple}" + "--host=${config.platform.host.triple}" + "--target=${config.platform.target.triple}" + "--with-as=${config.deps.build.build.binutils.package}/bin/${programPrefix}as" + "--with-ld=${config.deps.build.build.binutils.package}/bin/${programPrefix}ld" + "--enable-languages=c,c++" + "--disable-bootstrap" + "--disable-libsanitizer" + "--disable-lto" + "--disable-multilib" + "--disable-plugin" + "--disable-libssp" + "--disable-libvtv" + "--disable-libstdcxx" + "--disable-libquadmath" + "--disable-threads" + "--disable-decimal-float" + "--disable-shared" + "--disable-libmudflap" + "--disable-libgomp" + "--disable-libatomic" + "--without-headers" + "--with-newlib" + ]; + }; + } + ); + }; + }; +} diff --git a/tidepool/src/packages/foundation/gcc/patches/libstdc++-target.patch b/tidepool/src/packages/foundation/gcc/patches/libstdc++-target.patch new file mode 100644 index 0000000..2fa8883 --- /dev/null +++ b/tidepool/src/packages/foundation/gcc/patches/libstdc++-target.patch @@ -0,0 +1,33 @@ +# From https://github.com/NixOS/nixpkgs/blob/nixos-24.05/pkgs/development/compilers/gcc/patches/libstdc%2B%2B-target.patch +Patch to make the target libraries 'configure' scripts find the proper CPP. +I noticed that building the mingw32 cross compiler. +Looking at the build script for mingw in archlinux, I think that only nixos +needs this patch. I don't know why. +diff --git a/Makefile.in b/Makefile.in +index 93f66b6..d691917 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -266,6 +266,7 @@ BASE_TARGET_EXPORTS = \ + AR="$(AR_FOR_TARGET)"; export AR; \ + AS="$(COMPILER_AS_FOR_TARGET)"; export AS; \ + CC="$(CC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CC; \ ++ CPP="$(CC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CC; \ + CFLAGS="$(CFLAGS_FOR_TARGET)"; export CFLAGS; \ + CONFIG_SHELL="$(SHELL)"; export CONFIG_SHELL; \ + CPPFLAGS="$(CPPFLAGS_FOR_TARGET)"; export CPPFLAGS; \ +@@ -291,11 +292,13 @@ BASE_TARGET_EXPORTS = \ + RAW_CXX_TARGET_EXPORTS = \ + $(BASE_TARGET_EXPORTS) \ + CXX_FOR_TARGET="$(RAW_CXX_FOR_TARGET)"; export CXX_FOR_TARGET; \ +- CXX="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX; ++ CXX="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX; \ ++ CXXCPP="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CXX; + + NORMAL_TARGET_EXPORTS = \ + $(BASE_TARGET_EXPORTS) \ +- CXX="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX; ++ CXX="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX; \ ++ CXXCPP="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CXX; + + # Where to find GMP + HOST_GMPLIBS = @gmplibs@ \ No newline at end of file diff --git a/tidepool/src/packages/foundation/glibc/default.nix b/tidepool/src/packages/foundation/glibc/default.nix index 8e8de03..b8e11ce 100644 --- a/tidepool/src/packages/foundation/glibc/default.nix +++ b/tidepool/src/packages/foundation/glibc/default.nix @@ -3,6 +3,7 @@ lib', config, options, + packages, }: let inherit (config) @@ -10,6 +11,7 @@ let builders # These are the upstream foundational packages exported from the Aux Foundation project. + packages foundation ; in @@ -26,87 +28,124 @@ in }; }; - config = { - meta = { - platforms = [ "i686-linux" ]; - }; + config = + let + isCross = + (config.platform.build.triple != config.platform.host.triple) + && (config.platform.host.triple == config.platform.target.triple); - pname = "gcc"; - version = "2.38"; + binutils = + if isCross then + "${ + (packages.foundation.binutils.versions.latest.extend { + platform = lib.modules.override 0 { + inherit (config.platform) build target; + host = config.platform.build; + }; + }).package + }/${config.platform.target.triple}" + else + foundation.stage2-binutils; + in + { - src = builtins.fetchurl { - url = "${mirrors.gnu}/libc/glibc-${config.version}.tar.xz"; - sha256 = "+4KZiZiyspllRnvBtp0VLpwwfSzzAcnq+0VVt3DvP9I="; - }; - - builder = builders.basic; - - env = { - PATH = - let - gcc = - if - config.platform.build.triple == config.platform.host.triple - # If we're on the same system then we can use the existing GCC instance. - then - foundation.stage2-gcc - # Otherwise we are going to need a cross-compiler. - else - (meta.extend (args: { - config = { - platform = { - build = config.platform.build.triple; - host = config.platform.build.triple; - target = lib.modules.override.force config.platform.host.triple; - }; - }; - })).config.package; - in - lib.paths.bin [ - foundation.stage2-gcc - foundation.stage2-binutils - foundation.stage2-gnumake - foundation.stage2-gnused - foundation.stage2-gnugrep - foundation.stage2-gawk - foundation.stage2-diffutils - foundation.stage2-findutils - foundation.stage2-gnutar - foundation.stage2-gzip - foundation.stage2-bzip2 - foundation.stage1-xz + meta = { + platforms = [ + "i686-linux" + "x86_64-linux" ]; + }; + + pname = "glibc"; + version = "2.38"; + + src = builtins.fetchurl { + url = "${mirrors.gnu}/libc/glibc-${config.version}.tar.xz"; + sha256 = "+4KZiZiyspllRnvBtp0VLpwwfSzzAcnq+0VVt3DvP9I="; + }; + + builder = builders.basic; + + deps = { + build = { + host = { + linux-headers = ( + packages.foundation.linux-headers.versions.latest.extend { + platform.target = lib.modules.override 0 config.platform.target; + } + ); + }; + }; + }; + + env = { + PATH = + let + gcc = + if + isCross + # Otherwise we are going to need a cross-compiler. + then + (packages.foundation.gcc-newlib.versions.latest.extend { + platform = lib.modules.override 0 { + inherit (config.platform) build target; + host = config.platform.build; + }; + }).package + # If we're on the same system then we can use the existing GCC instance. + else + foundation.stage2-gcc; + in + lib.paths.bin [ + gcc + binutils + foundation.stage2-gnumake + foundation.stage2-gnused + foundation.stage2-gnugrep + foundation.stage2-gawk + foundation.stage2-diffutils + foundation.stage2-findutils + foundation.stage2-gnutar + foundation.stage2-gzip + foundation.stage2-bzip2 + foundation.stage1-python + foundation.stage1-bison + foundation.stage1-xz + ]; + }; + + phases = + + { + unpack = '' + tar xf ${config.src} + cd glibc-${config.version} + ''; + + configure = '' + mkdir build + cd build + + bash ../configure \ + --prefix=$out \ + --build=${config.platform.build.triple} \ + --host=${config.platform.host.triple} \ + --with-headers=${config.deps.build.host.linux-headers.package}/include \ + --with-binutils=${binutils}/bin + ''; + + build = '' + # Build + make -j $NIX_BUILD_CORES + ''; + + install = '' + # Install + make -j $NIX_BUILD_CORES install + ln -sv $(ls -d ${config.deps.build.host.linux-headers.package}/include/* | grep -v scsi\$) $out/include/ + ''; + }; }; - - phases = { - unpack = '' - tar xf ${config.src} - cd glibc-${config.version} - ''; - - configure = '' - mkdir build - cd build - # libstdc++.so is built against musl and fails to link - export CXX=false - bash ../configure \ - --prefix=$out \ - --build=${config.platform.build.triple} \ - --host=${config.platform.host.triple} \ - --with-headers=${foundation.stage1-linux-headers}/include - ''; - - build = '' - # Build - make -j $NIX_BUILD_CORES - ''; - - install = '' - # Install - make -j $NIX_BUILD_CORES install-strip - ''; - }; - }; }; }; }; diff --git a/tidepool/src/packages/foundation/linux-headers/default.nix b/tidepool/src/packages/foundation/linux-headers/default.nix index 2201046..a2fad63 100644 --- a/tidepool/src/packages/foundation/linux-headers/default.nix +++ b/tidepool/src/packages/foundation/linux-headers/default.nix @@ -1,8 +1,8 @@ -{ - lib, - lib', - config, - options, +{ lib +, lib' +, config +, options +, }: let inherit (config) @@ -28,7 +28,7 @@ in config = { meta = { - platforms = [ "i686-linux" ]; + platforms = [ "x86_64-linux" "i686-linux" ]; }; pname = "linux-headers"; @@ -60,7 +60,7 @@ in ''; build = '' - make -j $NIX_BUILD_CORES CC=musl-gcc HOSTCC=musl-gcc ARCH=${config.platform.host.linux.arch} headers + make -j $NIX_BUILD_CORES CC=musl-gcc HOSTCC=musl-gcc ARCH=${config.platform.target.linux.arch} headers ''; install = ''