From 6abd09a0f0d499c42cafdfe1b5f64ae17c82a9c8 Mon Sep 17 00:00:00 2001 From: Siddhartha Bagaria Date: Wed, 22 Sep 2021 22:31:41 -0700 Subject: [PATCH] Add a test for darwin to linux cross-compilation Two changes were needed to make cross-compilation actually work: 1. The target triple needed to be provided. 2. C++ standard flags needed to be revised. --- .github/workflows/tests.yml | 10 ++- platforms/BUILD.bazel | 37 +++++++++ tests/BUILD.bazel | 3 + tests/scripts/run_xcompile_tests.sh | 53 ++++++++++++ toolchain/cc_toolchain_config.bzl | 124 ++++++++++++++++------------ 5 files changed, 168 insertions(+), 59 deletions(-) create mode 100644 platforms/BUILD.bazel create mode 100755 tests/scripts/run_xcompile_tests.sh diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 01710aab..aea73a83 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,8 +17,6 @@ jobs: steps: - uses: actions/checkout@v2 - name: test - env: - BAZELISK_GITHUB_TOKEN: ${{ secrets.BAZELISK_GITHUB_TOKEN }} run: tests/scripts/${{ matrix.script }} container_test: runs-on: ubuntu-latest @@ -32,6 +30,10 @@ jobs: steps: - uses: actions/checkout@v2 - name: test - env: - BAZELISK_GITHUB_TOKEN: ${{ secrets.BAZELISK_GITHUB_TOKEN }} run: tests/scripts/${{ matrix.script }}_test.sh + xcompile_test: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: test + run: tests/scripts/run_xcompile_tests.sh diff --git a/platforms/BUILD.bazel b/platforms/BUILD.bazel new file mode 100644 index 00000000..3ca82683 --- /dev/null +++ b/platforms/BUILD.bazel @@ -0,0 +1,37 @@ +# Copyright 2021 The Bazel Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +platform( + name = "linux-x86_64", + constraint_values = [ + "@platforms//os:linux", + "@platforms//cpu:x86_64", + ], +) + +platform( + name = "linux-aarch64", + constraint_values = [ + "@platforms//os:osx", + "@platforms//cpu:aarch64", + ], +) + +platform( + name = "darwin-x86_64", + constraint_values = [ + "@platforms//os:osx", + "@platforms//cpu:x86_64", + ], +) diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index eaa2a4e8..202a899c 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -20,9 +20,12 @@ cc_library( hdrs = ["stdlib.h"], ) +# We want to emulate the behavior of cc_binary but be able to run the target as +# a test, so we use a cc_test target with linkstatic. cc_test( name = "stdlib_test", srcs = ["stdlib_test.cc"], + linkstatic = True, deps = [":stdlib"], ) diff --git a/tests/scripts/run_xcompile_tests.sh b/tests/scripts/run_xcompile_tests.sh new file mode 100755 index 00000000..b0a7cfb8 --- /dev/null +++ b/tests/scripts/run_xcompile_tests.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Copyright 2021 The Bazel Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +source "$(dirname "${BASH_SOURCE[0]}")/bazel.sh" +"${bazel}" version + +binpath="$("${bazel}" info bazel-bin)/tests/stdlib_test" + +check_with_image() { + if "${CI:-false}"; then + # macOS GitHub Action Runners do not have docker installed on them. + return + fi + local image="$1" + docker run --rm --mount "type=bind,source=${binpath},target=/stdlib_test" "${image}" /stdlib_test +} + +echo "" +echo "Testing static linked user libraries and dynamic linked system libraries" +build_args=( + --incompatible_enable_cc_toolchain_resolution + --platforms=//platforms:linux-x86_64 + --extra_toolchains=@llvm_toolchain_with_sysroot//:cc-toolchain-x86_64-linux + --symlink_prefix=/ + --color=yes + --show_progress_rate_limit=30 +) +"${bazel}" --bazelrc=/dev/null build "${build_args[@]}" //tests:stdlib_test +file "${binpath}" | tee /dev/stderr | grep -q ELF +check_with_image "frolvlad/alpine-glibc" # Need glibc image for system libraries. + +echo "" +echo "Testing static linked user and system libraries" +build_args+=( + --features=fully_static_link +) +"${bazel}" --bazelrc=/dev/null build "${build_args[@]}" //tests:stdlib_test +file "${binpath}" | tee /dev/stderr | grep -q ELF +check_with_image "alpine" diff --git a/toolchain/cc_toolchain_config.bzl b/toolchain/cc_toolchain_config.bzl index 84166aed..ddc36388 100644 --- a/toolchain/cc_toolchain_config.bzl +++ b/toolchain/cc_toolchain_config.bzl @@ -96,87 +96,101 @@ def cc_toolchain_config( is_xcompile = not (host_os == target_os and host_arch == target_arch) + # Default compiler flags: + compile_flags = [ + "--target=" + target_system_name, + # Security + "-U_FORTIFY_SOURCE", # https://github.com/google/sanitizers/issues/247 + "-fstack-protector", + "-fno-omit-frame-pointer", + # Diagnostics + "-fcolor-diagnostics", + "-Wall", + "-Wthread-safety", + "-Wself-assign", + ] + + dbg_compile_flags = ["-g", "-fstandalone-debug"] + + opt_compile_flags = [ + "-g0", + "-O2", + "-D_FORTIFY_SOURCE=1", + "-DNDEBUG", + "-ffunction-sections", + "-fdata-sections", + ] + + link_flags = [ + "--target=" + target_system_name, + "-lm", + "-no-canonical-prefixes", + ] + # Linker flags: if host_os == "darwin" and not is_xcompile: # lld is experimental for Mach-O, so we use the native ld64 linker. use_lld = False - linker_flags = [ + link_flags.extend([ "-headerpad_max_install_names", "-undefined", "dynamic_lookup", - ] + ]) else: # We prefer the lld linker. # Note that for xcompiling from darwin to linux, the native ld64 is # not an option because it is not a cross-linker, so lld is the # only option. use_lld = True - linker_flags = [ + link_flags.extend([ "-fuse-ld=lld", "-Wl,--build-id=md5", "-Wl,--hash-style=gnu", "-Wl,-z,relro,-z,now", - ] + ]) + # Flags related to C++ standard. # The linker has no way of knowing if there are C++ objects; so we # always link C++ libraries. - if host_os == "linux" and not is_xcompile: - # For single-platform linux builds, we can statically link the bundled - # libraries. - linker_flags.extend([ - "-L{}lib".format(toolchain_path_prefix), - "-l:libc++.a", - "-l:libc++abi.a", - "-l:libunwind.a", - # Compiler runtime features. - "-rtlib=compiler-rt", - # To support libunwind. - "-lpthread", - "-ldl", - ]) + if not is_xcompile: + cxx_flags = [ + "-std=c++17", + "-stdlib=libc++", + ] + if use_lld: + # For single-platform builds, we can statically link the bundled + # libraries. + link_flags.extend([ + "-L{}lib".format(toolchain_path_prefix), + "-l:libc++.a", + "-l:libc++abi.a", + "-l:libunwind.a", + # Compiler runtime features. + "-rtlib=compiler-rt", + # To support libunwind. + "-lpthread", + "-ldl", + ]) + else: + # TODO: Not sure how to achieve static linking of bundled libraries + # with ld64; maybe we don't really need it. + link_flags.extend([ + "-lc++", + "-lc++abi", + ]) else: + cxx_flags = [ + "-std=c++17", + "-stdlib=libstdc++", + ] + # For xcompile, we expect to pick up these libraries from the sysroot. - # TODO: For single-platform darwin builds, we can statically link the - # bundled libraries but I do not know the right flags to make it - # happen. - linker_flags.extend([ - "-lc++", - "-lc++abi", + link_flags.extend([ + "-l:libstdc++.a", ]) - link_flags = [ - "-lm", - "-no-canonical-prefixes", - ] + linker_flags - opt_link_flags = ["-Wl,--gc-sections"] if target_os == "linux" else [] - # Default compiler flags: - compile_flags = [ - # Security - "-U_FORTIFY_SOURCE", # https://github.com/google/sanitizers/issues/247 - "-fstack-protector", - "-fno-omit-frame-pointer", - # Diagnostics - "-fcolor-diagnostics", - "-Wall", - "-Wthread-safety", - "-Wself-assign", - ] - - dbg_compile_flags = ["-g", "-fstandalone-debug"] - - opt_compile_flags = [ - "-g0", - "-O2", - "-D_FORTIFY_SOURCE=1", - "-DNDEBUG", - "-ffunction-sections", - "-fdata-sections", - ] - - cxx_flags = ["-std=c++17", "-stdlib=libc++"] - # Coverage flags: coverage_compile_flags = ["-fprofile-instr-generate", "-fcoverage-mapping"] coverage_link_flags = ["-fprofile-instr-generate"]