diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/.bazeliskrc b/examples/toolchains/cc_cross_osx_to_linux_amd64/.bazeliskrc new file mode 100644 index 000000000..773a4f4c6 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/.bazeliskrc @@ -0,0 +1 @@ +USE_BAZEL_VERSION=6.x diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/.bazelrc b/examples/toolchains/cc_cross_osx_to_linux_amd64/.bazelrc new file mode 100644 index 000000000..404847659 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/.bazelrc @@ -0,0 +1,6 @@ +build --incompatible_enable_cc_toolchain_resolution +build:nix --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host +build:nix --crosstool_top=@nixpkgs_config_cc//:toolchain +build:cross --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host +build:cross --host_crosstool_top=@nixpkgs_config_cc//:toolchain +build:cross --cpu=k8 --crosstool_top=@nixpkgs_cross_cc//:toolchain --platforms=//toolchains:linux_x86_64 \ No newline at end of file diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/BUILD b/examples/toolchains/cc_cross_osx_to_linux_amd64/BUILD new file mode 100644 index 000000000..ddce225d4 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/BUILD @@ -0,0 +1,10 @@ +load("@rules_cc//cc:defs.bzl", "cc_binary") + +cc_binary( + name = "hello", + srcs = ["hello.cc"], + deps = [ + "@boost.dev//:boost", + "@zlib.dev//:zlib", + ], +) diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/README.md b/examples/toolchains/cc_cross_osx_to_linux_amd64/README.md new file mode 100644 index 000000000..50fbaf863 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/README.md @@ -0,0 +1,13 @@ +C++ With Dependencies Toolchain Example +======================================= + +This is an example C++ project with dependencies that uses `rules_cc`. + +This example uses the Nix package manager to provide C++ dependencies, and as such only works with Nix installed. Demonstrating other methods of providing C++ dependencies is out of scope of this example. + +# Usage + +To run the example with Nix, issue the following command: +``` +nix-shell --command 'bazel run --config=cross:hello' +``` diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/WORKSPACE b/examples/toolchains/cc_cross_osx_to_linux_amd64/WORKSPACE new file mode 100644 index 000000000..bc1908006 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/WORKSPACE @@ -0,0 +1,111 @@ +# Replace with http_archive: https://github.com/tweag/rules_nixpkgs/#setup +local_repository( + name = "io_tweag_rules_nixpkgs", + path = "../../../", +) + +load("@io_tweag_rules_nixpkgs//nixpkgs:repositories.bzl", "rules_nixpkgs_dependencies") + +rules_nixpkgs_dependencies() + +load( + "@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl", + "nixpkgs_cc_configure", + "nixpkgs_local_repository", +) + +nixpkgs_local_repository( + name = "nixpkgs", + nix_file = "//:nixpkgs.nix", + nix_file_deps = ["//:nixpkgs.json"], +) + +nixpkgs_cc_configure( + name = "nixpkgs_config_cc", + nix_file = "//toolchains:cc.nix", + repository = "@nixpkgs", +) + +nixpkgs_cc_configure( + name = "nixpkgs_cross_cc", + cross_cpu = "k8", + exec_constraints = [ + "@platforms//os:osx", + "@platforms//cpu:arm64", + ], + nix_file = "//toolchains:osxcross_cc.nix", + nixopts = [ + "--arg", + "ccPkgs", + "import { crossSystem = \"x86_64-linux\";}", + "--show-trace", + ], + repository = "@nixpkgs", + target_constraints = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + "@rules_nixpkgs_core//constraints:support_nix", + ], +) + +load("@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl", "nixpkgs_package") + +# We would probably want a select or something to make this work with OSX as well, for a more +# production set up. +nixpkgs_package( + name = "boost", + attribute_path = "boost175", + nix_file_content = """import { config = {}; overlays = []; system = "x86_64-linux"; }""", + repository = "@nixpkgs", +) + +nixpkgs_package( + name = "boost.dev", + attribute_path = "boost175.dev", + build_file_content = """\ +load("@rules_cc//cc:defs.bzl", "cc_library") +filegroup( + name = "include", + srcs = glob(["include/**/*.h", "include/**/*.hpp"]), + visibility = ["//visibility:public"], +) +cc_library( + name = "boost", + srcs = ["@boost//:lib"], + hdrs = [":include"], + strip_include_prefix = "include", + visibility = ["//visibility:public"], +) +""", + nix_file_content = """import { config = {}; overlays = []; system = "x86_64-linux"; }""", + repository = "@nixpkgs", +) + +nixpkgs_package( + name = "zlib", + attribute_path = "zlib", + nix_file_content = """import { config = {}; overlays = []; system = "x86_64-linux"; }""", + repository = "@nixpkgs", +) + +nixpkgs_package( + name = "zlib.dev", + attribute_path = "zlib.dev", + build_file_content = """\ +load("@rules_cc//cc:defs.bzl", "cc_library") +filegroup( + name = "include", + srcs = glob(["include/**/*.h"]), + visibility = ["//visibility:public"], +) +cc_library( + name = "zlib", + srcs = ["@zlib//:lib"], + hdrs = [":include"], + strip_include_prefix = "include", + visibility = ["//visibility:public"], +) +""", + nix_file_content = """import { config = {}; overlays = []; system = "x86_64-linux"; }""", + repository = "@nixpkgs", +) diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/hello.cc b/examples/toolchains/cc_cross_osx_to_linux_amd64/hello.cc new file mode 100644 index 000000000..cdb8fc0da --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/hello.cc @@ -0,0 +1,8 @@ +#include +#include +#include + +int main() +{ + std::cout << "Hello world!\n"; +} diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/nixpkgs.json b/examples/toolchains/cc_cross_osx_to_linux_amd64/nixpkgs.json new file mode 100644 index 000000000..d470df94d --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/nixpkgs.json @@ -0,0 +1,7 @@ +{ + "owner": "NixOS", + "repo": "nixpkgs", + "branch": "23.05", + "rev": "3ad64d9e2d5bf80c877286102355b1625891ae9a", + "sha256": "sha256-PuZSAHeq4/9pP/uYH1FcagQ3nLm/DrDrvKi/xC9glvw=" +} diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/nixpkgs.nix b/examples/toolchains/cc_cross_osx_to_linux_amd64/nixpkgs.nix new file mode 100644 index 000000000..6db312a36 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/nixpkgs.nix @@ -0,0 +1,8 @@ +let + spec = builtins.fromJSON (builtins.readFile ./nixpkgs.json); + nixpkgs = fetchTarball { + url = "https://github.com/${spec.owner}/${spec.repo}/archive/${spec.rev}.tar.gz"; + sha256 = spec.sha256; + }; +in +import nixpkgs diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/shell.nix b/examples/toolchains/cc_cross_osx_to_linux_amd64/shell.nix new file mode 100644 index 000000000..a411bd037 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/shell.nix @@ -0,0 +1,3 @@ +{ pkgs ? import ./nixpkgs.nix { } }: + +pkgs.mkShellNoCC { nativeBuildInputs = [ pkgs.bazel_6 ]; } diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/BUILD b/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/BUILD new file mode 100644 index 000000000..46503a9c4 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/BUILD @@ -0,0 +1,9 @@ +platform( + name = "linux_x86_64", + constraint_values = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + "@rules_nixpkgs_core//constraints:support_nix", + ], + visibility = ["//visibility:public"], +) diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/cc.nix b/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/cc.nix new file mode 100644 index 000000000..ccb549395 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/cc.nix @@ -0,0 +1,72 @@ +# We need to write a fancy nix file to handle the CC compiler due to OSX: https://github.com/tweag/rules_nixpkgs/issues/368 +# What this file is basically saying is: if OSX, change the CXX compiler to use a bunch of Apple frameworks, LLVM libs, +# libc++ instead of libstdc++, and some additional compiler flags to ignore some warnings, otherwise, just use clang11 +let + pkgs = import {}; +in let + clang = pkgs.clang_11; + # The original `postLinkSignHook` from nixpkgs assumes `codesign_allocate` is + # in the PATH which is not the case when using our cc_wrapper. Set + # `CODESIGN_ALLOCATE` to an absolute path here and override the hook for + # `darwinCC` below. + postLinkSignHook = with pkgs; + writeTextFile { + name = "post-link-sign-hook"; + executable = true; + + text = '' + CODESIGN_ALLOCATE=${darwin.cctools}/bin/codesign_allocate \ + ${darwin.sigtool}/bin/codesign -f -s - "$linkerOutput" + ''; + }; + darwinCC = + # Work around https://github.com/NixOS/nixpkgs/issues/42059. + # See also https://github.com/NixOS/nixpkgs/pull/41589. + pkgs.wrapCCWith rec { + cc = clang; + bintools = pkgs.stdenv.cc.bintools.override {inherit postLinkSignHook;}; + extraBuildCommands = with pkgs.darwin.apple_sdk.frameworks; '' + echo "-Wno-unused-command-line-argument" >> $out/nix-support/cc-cflags + echo "-Wno-elaborated-enum-base" >> $out/nix-support/cc-cflags + echo "-isystem ${pkgs.llvmPackages_11.libcxx.dev}/include/c++/v1" >> $out/nix-support/cc-cflags + echo "-isystem ${pkgs.llvmPackages_11.clang-unwrapped.lib}/lib/clang/${cc.version}/include" >> $out/nix-support/cc-cflags + echo "-F${CoreFoundation}/Library/Frameworks" >> $out/nix-support/cc-cflags + echo "-F${CoreServices}/Library/Frameworks" >> $out/nix-support/cc-cflags + echo "-F${Security}/Library/Frameworks" >> $out/nix-support/cc-cflags + echo "-F${Foundation}/Library/Frameworks" >> $out/nix-support/cc-cflags + echo "-L${pkgs.llvmPackages_11.libcxx}/lib" >> $out/nix-support/cc-cflags + echo "-L${pkgs.llvmPackages_11.libcxxabi}/lib" >> $out/nix-support/cc-cflags + echo "-L${pkgs.libiconv}/lib" >> $out/nix-support/cc-cflags + echo "-L${pkgs.darwin.libobjc}/lib" >> $out/nix-support/cc-cflags + echo "-resource-dir=${pkgs.stdenv.cc}/resource-root" >> $out/nix-support/cc-cflags + ''; + }; + linuxCC = pkgs.wrapCCWith rec { + cc = clang; + bintools = pkgs.stdenv.cc.bintools; + extraPackages = [pkgs.glibc.static]; + extraBuildCommands = '' + echo "-isystem ${pkgs.llvmPackages_11.clang-unwrapped.lib}/lib/clang/${cc.version}/include" >> $out/nix-support/cc-cflags + echo "-L ${pkgs.glibc.static}/lib" >> $out/nix-support/cc-ldflags + echo "-resource-dir=${cc}/resource-root" >> $out/nix-support/cc-cflags + ''; + }; +in + pkgs.buildEnv ( + let + cc = + if pkgs.stdenv.isDarwin + then darwinCC + else linuxCC; + in { + name = "bazel-nixpkgs-cc"; + # XXX: `gcov` is missing in `/bin`. + # It exists in `stdenv.cc.cc` but that collides with `stdenv.cc`. + paths = [cc cc.bintools] ++ pkgs.lib.optional pkgs.stdenv.isDarwin pkgs.darwin.cctools; + pathsToLink = ["/bin"]; + passthru = { + inherit (cc) isClang targetPrefix; + orignalName = cc.name; + }; + } + ) diff --git a/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/osxcross_cc.nix b/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/osxcross_cc.nix new file mode 100644 index 000000000..e3111abd2 --- /dev/null +++ b/examples/toolchains/cc_cross_osx_to_linux_amd64/toolchains/osxcross_cc.nix @@ -0,0 +1,67 @@ +# This will take many hours to build. Caching this somewhere is recommended. +let + targetSystem = "x86_64-linux"; + og = import {}; + nixpkgs = import { + buildSystem = builtins.currentSystem; + hostSystem = targetSystem; + crossSystem = { + config = targetSystem; + }; + crossOverlays = [ + (self: super: { + # Apparently this is a hacky way to extend llvmPackages, but whatever + llvmPackages_11 = super.llvmPackages_11.extend (final: prev: rec { + libllvm = prev.libllvm.overrideAttrs (old: { + # We need to override LDFLAGS because it puts non-Darwin compatible flags, + # so remove the old flags, and also explicitly tell the compiler where to + # find libcxxabi. Not sure why we need to do this. + LDFLAGS = "-L ${super.llvmPackages_11.libcxxabi}/lib"; + # We need to make sure cctools is available because darwin code signing needs it + # in your $PATH. + nativeBuildInputs = (old.nativeBuildInputs or []) ++ [og.darwin.cctools]; + }); + libclang = prev.libclang.override { + inherit libllvm; + }; + libraries = super.llvmPackages_11.libraries; + }); + }) + ]; + }; + # this will use linux binaries from binary cache, so no need to build those + pkgsLinux = import { + config = {}; + overlays = []; + system = targetSystem; + }; +in let + pkgs = builtins.trace nixpkgs.stdenv.name nixpkgs.buildPackages; + linuxCC = pkgs.wrapCCWith rec { + cc = pkgs.llvmPackages_11.clang-unwrapped; + bintools = pkgs.llvmPackages_11.bintools; + extraPackages = [pkgsLinux.glibc.static pkgs.llvmPackages_11.libraries.libcxxabi pkgs.llvmPackages_11.libraries.libcxx]; + extraBuildCommands = '' + echo "-isystem ${pkgs.llvmPackages_11.clang-unwrapped.lib}/lib/clang/${cc.version}/include" >> $out/nix-support/cc-cflags + echo "-isystem ${pkgsLinux.glibc.dev}/include" >> $out/nix-support/cc-cflags + echo "-L ${pkgs.llvmPackages_11.libraries.libcxxabi}/lib" >> $out/nix-support/cc-ldflags + echo "-L ${pkgsLinux.glibc.static}/lib" >> $out/nix-support/cc-ldflags + echo "-resource-dir=${cc}/resource-root" >> $out/nix-support/cc-cflags + ''; + }; +in + pkgs.buildEnv ( + let + cc = linuxCC; + in { + name = "bazel-${cc.name}-cc"; + # XXX: `gcov` is missing in `/bin`. + # It exists in `stdenv.cc.cc` but that collides with `stdenv.cc`. + paths = [cc cc.bintools]; + pathsToLink = ["/bin"]; + passthru = { + inherit (cc) isClang targetPrefix; + orignalName = cc.name; + }; + } + ) diff --git a/toolchains/cc/cc.bzl b/toolchains/cc/cc.bzl index fe5d8ff00..b846e14f5 100644 --- a/toolchains/cc/cc.bzl +++ b/toolchains/cc/cc.bzl @@ -123,7 +123,7 @@ def _parse_cc_toolchain_info(content, filename): def _nixpkgs_cc_toolchain_config_impl(repository_ctx): host_cpu = get_cpu_value(repository_ctx) cross_cpu = repository_ctx.attr.cross_cpu or host_cpu - darwin = host_cpu == "darwin" or host_cpu == "darwin_arm64" + darwin = (host_cpu == "darwin" or host_cpu == "darwin_arm64") and cross_cpu == host_cpu cc_toolchain_info_file = repository_ctx.path(repository_ctx.attr.cc_toolchain_info) if not cc_toolchain_info_file.exists and not repository_ctx.attr.fail_not_supported: