From f99b06b46da0a07c8a2621a1ecb83895da9be280 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 14 Mar 2023 04:29:32 -0700 Subject: [PATCH] Automated rollback of commit d56dc18e1978102e35fbcf92c5d63f9f9eef37cd. *** Reason for rollback *** Breaks builds internally. *** Original change description *** Move Apple toolchain setup to apple_support This moves the CC toolchain for building Apple platforms besides macOS to the apple_support repo https://github.com/bazelbuild/apple_support/pull/113 The default unix toolchain is now used if someone wants to build for macOS without the apple_support toolchain, but it doesn't handle as many platform specific features as the previous toolchain. Fixes https://github.com/bazelbuild/bazel/issues/1... *** PiperOrigin-RevId: 516486823 Change-Id: If9b2542699cf8704e0a511e684d8519468ddd937 --- .bazelci/postsubmit.yml | 2 + .bazelci/presubmit.yml | 2 + src/create_embedded_tools.py | 2 + .../builtins_bzl/common/objc/objc_library.bzl | 10 - .../lib/packages/util/MockObjcSupport.java | 8 + .../util/mock/osx_cc_toolchain_config.bzl | 12 - src/test/py/bazel/bzlmod/bzlmod_query_test.py | 2 +- src/test/shell/bazel/apple/BUILD | 1 + .../shell/bazel/apple/bazel_apple_test.sh | 344 ++ src/test/shell/bazel/apple/bazel_objc_test.sh | 160 +- src/test/shell/bazel/cc_integration_test.sh | 2 +- src/test/shell/integration/aquery_test.sh | 4 +- tools/BUILD | 2 + tools/cpp/cc_configure.bzl | 56 +- tools/cpp/osx_cc_configure.bzl | 255 ++ tools/cpp/unix_cc_configure.bzl | 5 +- tools/cpp/unix_cc_toolchain_config.bzl | 79 +- tools/objc/libtool_check_unique.cc | 109 + tools/osx/BUILD | 4 +- tools/osx/crosstool/BUILD | 39 + tools/osx/crosstool/BUILD.toolchains | 103 + tools/osx/crosstool/BUILD.tpl | 124 + tools/osx/crosstool/cc_toolchain_config.bzl | 2755 +++++++++++++++++ tools/osx/crosstool/osx_archs.bzl | 38 + tools/osx/crosstool/wrapped_clang.cc | 429 +++ tools/osx/crosstool/wrapped_clang_test.sh | 99 + 26 files changed, 4536 insertions(+), 110 deletions(-) create mode 100644 tools/cpp/osx_cc_configure.bzl create mode 100644 tools/objc/libtool_check_unique.cc create mode 100644 tools/osx/crosstool/BUILD create mode 100644 tools/osx/crosstool/BUILD.toolchains create mode 100644 tools/osx/crosstool/BUILD.tpl create mode 100644 tools/osx/crosstool/cc_toolchain_config.bzl create mode 100644 tools/osx/crosstool/osx_archs.bzl create mode 100644 tools/osx/crosstool/wrapped_clang.cc create mode 100755 tools/osx/crosstool/wrapped_clang_test.sh diff --git a/.bazelci/postsubmit.yml b/.bazelci/postsubmit.yml index fe12452b07d62c..2a4c2a1d922e2e 100644 --- a/.bazelci/postsubmit.yml +++ b/.bazelci/postsubmit.yml @@ -202,6 +202,7 @@ tasks: - "//third_party/ijar/..." - "//tools/android/..." - "//tools/aquery_differ/..." + - "//tools/osx/crosstool/..." - "//tools/python/..." # C++ coverage is not supported on macOS yet. - "-//src/test/shell/bazel:bazel_cc_code_coverage_test" @@ -265,6 +266,7 @@ tasks: - "//third_party/ijar/..." - "//tools/android/..." - "//tools/aquery_differ/..." + - "//tools/osx/crosstool/..." - "//tools/python/..." # C++ coverage is not supported on macOS yet. - "-//src/test/shell/bazel:bazel_cc_code_coverage_test" diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index d59ee24a28a988..e1daa3ee923312 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -192,6 +192,7 @@ tasks: - "//third_party/ijar/..." - "//tools/android/..." - "//tools/aquery_differ/..." + - "//tools/osx/crosstool/..." - "//tools/python/..." # Re-enable once fixed: https://github.com/bazelbuild/bazel/issues/8162 - "-//src/java_tools/buildjar/..." @@ -255,6 +256,7 @@ tasks: - "//third_party/ijar/..." - "//tools/android/..." - "//tools/aquery_differ/..." + - "//tools/osx/crosstool/..." - "//tools/python/..." # Re-enable once fixed: https://github.com/bazelbuild/bazel/issues/8162 - "-//src/java_tools/buildjar/..." diff --git a/src/create_embedded_tools.py b/src/create_embedded_tools.py index 2022e202d84d09..b4bb92b90436fd 100644 --- a/src/create_embedded_tools.py +++ b/src/create_embedded_tools.py @@ -42,6 +42,8 @@ ('*def_parser.exe', lambda x: 'tools/def_parser/def_parser.exe'), ('*zipper.exe', lambda x: 'tools/zip/zipper/zipper.exe'), ('*zipper', lambda x: 'tools/zip/zipper/zipper'), + ('*xcode*make_hashed_objlist.py', + lambda x: 'tools/objc/make_hashed_objlist.py'), ('*xcode*xcode-locator', lambda x: 'tools/objc/xcode-locator'), ('*src/tools/xcode/*', lambda x: 'tools/objc/' + os.path.basename(x)), # --experimental_sibling_repository_layout=false diff --git a/src/main/starlark/builtins_bzl/common/objc/objc_library.bzl b/src/main/starlark/builtins_bzl/common/objc/objc_library.bzl index 5ce538b0ee6bc8..b9764707f7bb9b 100644 --- a/src/main/starlark/builtins_bzl/common/objc/objc_library.bzl +++ b/src/main/starlark/builtins_bzl/common/objc/objc_library.bzl @@ -19,7 +19,6 @@ load("@_builtins//:common/objc/attrs.bzl", "common_attrs") load("@_builtins//:common/objc/objc_common.bzl", "extensions") load("@_builtins//:common/objc/transitions.bzl", "apple_crosstool_transition") load("@_builtins//:common/cc/cc_helper.bzl", "cc_helper") -load(":common/cc/cc_common.bzl", "cc_common") load(":common/cc/cc_info.bzl", "CcInfo") objc_internal = _builtins.internal.objc_internal @@ -56,15 +55,6 @@ def _objc_library_impl(ctx): _validate_attributes(srcs = ctx.attr.srcs, non_arc_srcs = ctx.attr.non_arc_srcs, label = ctx.label) cc_toolchain = cc_helper.find_cpp_toolchain(ctx) - feature_configuration = cc_common.configure_features( - ctx = ctx, - cc_toolchain = cc_toolchain, - requested_features = ctx.features, - unsupported_features = ctx.disabled_features, - ) - - if not cc_common.action_is_enabled(feature_configuration = feature_configuration, action_name = "objc-compile"): - fail("Compiling objc_library targets requires the Apple CC toolchain which can be found here: https://github.com/bazelbuild/apple_support") common_variables = compilation_support.build_common_variables( ctx = ctx, diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockObjcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockObjcSupport.java index 736cfa3e3a6e32..7716e143ca09f2 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/util/MockObjcSupport.java +++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockObjcSupport.java @@ -39,6 +39,8 @@ public final class MockObjcSupport { "tvos_x86_64", "tvos_arm64"); + private static final ImmutableList DEFAULT_OSX_CROSSTOOL_DEPS_DIRS = + ImmutableList.of("third_party/bazel/tools/osx/crosstool"); public static final String DEFAULT_OSX_CROSSTOOL_DIR = "tools/osx/crosstool"; private static final String MOCK_OSX_TOOLCHAIN_CONFIG_PATH = "com/google/devtools/build/lib/packages/util/mock/osx_cc_toolchain_config.bzl"; @@ -233,6 +235,9 @@ public static void setup(MockToolsConfig config) throws IOException { public static void setupCcToolchainConfig( MockToolsConfig config, CcToolchainConfig.Builder ccToolchainConfig) throws IOException { if (config.isRealFileSystem()) { + for (String depDir : DEFAULT_OSX_CROSSTOOL_DEPS_DIRS) { + config.linkTools(depDir); + } config.linkTools(DEFAULT_OSX_CROSSTOOL_DIR); } else { CcToolchainConfig toolchainConfig = ccToolchainConfig.build(); @@ -256,6 +261,9 @@ public static void setupCcToolchainConfig( public static void setupCcToolchainConfig(MockToolsConfig config) throws IOException { if (config.isRealFileSystem()) { + for (String depDir : DEFAULT_OSX_CROSSTOOL_DEPS_DIRS) { + config.linkTools(depDir); + } config.linkTools(DEFAULT_OSX_CROSSTOOL_DIR); } else { new Crosstool( diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/mock/osx_cc_toolchain_config.bzl b/src/test/java/com/google/devtools/build/lib/packages/util/mock/osx_cc_toolchain_config.bzl index e6790e5e74ccce..aeea9d6c748088 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/util/mock/osx_cc_toolchain_config.bzl +++ b/src/test/java/com/google/devtools/build/lib/packages/util/mock/osx_cc_toolchain_config.bzl @@ -1223,7 +1223,6 @@ def _impl(ctx): if (ctx.attr.cpu == "x64_windows"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1256,7 +1255,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "ios_arm64"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1289,7 +1287,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "tvos_arm64"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1322,7 +1319,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "ios_armv7"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1355,7 +1351,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "watchos_armv7k"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1388,7 +1383,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "watchos_arm64_32"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1421,7 +1415,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "ios_i386"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1455,7 +1448,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "watchos_i386"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1489,7 +1481,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "watchos_x86_64"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1523,7 +1514,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "ios_x86_64"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1557,7 +1547,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "tvos_x86_64"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( @@ -1591,7 +1580,6 @@ def _impl(ctx): ) elif (ctx.attr.cpu == "darwin_x86_64"): objc_compile_action = action_config( - enabled = True, action_name = ACTION_NAMES.objc_compile, flag_sets = [ flag_set( diff --git a/src/test/py/bazel/bzlmod/bzlmod_query_test.py b/src/test/py/bazel/bzlmod/bzlmod_query_test.py index ce4ebb28f15261..3b3e351a773d83 100644 --- a/src/test/py/bazel/bzlmod/bzlmod_query_test.py +++ b/src/test/py/bazel/bzlmod/bzlmod_query_test.py @@ -92,7 +92,7 @@ def testAqueryModuleRepoTargetsBelow(self): allow_failure=False) # This label is stringified into a "purpose" in some action before it # reaches aquery code, so can't decanonicalize it. - self.assertIn('cc_library-compile for @aaa~1.0//:lib_aaa', stdout) + self.assertEqual(stdout[0], 'cc_library-compile for @aaa~1.0//:lib_aaa') self.assertIn('Target: @my_repo//:lib_aaa', stdout) def testAqueryModuleRepoTransitiveDeps(self): diff --git a/src/test/shell/bazel/apple/BUILD b/src/test/shell/bazel/apple/BUILD index 4de1281ae1ea0f..c7698fbfb8f833 100644 --- a/src/test/shell/bazel/apple/BUILD +++ b/src/test/shell/bazel/apple/BUILD @@ -38,6 +38,7 @@ sh_test( "//:workspace-file", "//src/test/shell/bazel:test-deps", ], + shard_count = 3, tags = ["no_windows"], ) diff --git a/src/test/shell/bazel/apple/bazel_apple_test.sh b/src/test/shell/bazel/apple/bazel_apple_test.sh index 94cfebf58c2cb9..fe051f6dd7fa82 100755 --- a/src/test/shell/bazel/apple/bazel_apple_test.sh +++ b/src/test/shell/bazel/apple/bazel_apple_test.sh @@ -40,6 +40,101 @@ function set_up() { create_new_workspace } +function test_fat_binary_no_srcs() { + rm -rf package + mkdir -p package + make_starlark_apple_binary_rule_in package + + cat > package/BUILD < \$(@)", + tags = ["requires-darwin"], +) +EOF + touch package/a.m + cat > package/b.m < package/BUILD < \$(@)", + tags = ["requires-darwin"], +) +EOF + touch package/a.m + cat > package/b.m < package/BUILD < \$(@)", + tags = ["requires-darwin"], +) +EOF + touch package/a.m + touch package/b.m + cat > package/main.m < package/cc_lib.cc << EOF +#include + +std::string GetString() { return "h3ll0"; } +EOF + + bazel build --verbose_failures //package:lipo_out \ + --noincompatible_enable_cc_toolchain_resolution \ + --ios_multi_cpus=i386,x86_64 \ + --xcode_version=$XCODE_VERSION \ + || fail "should build starlark_apple_binary and obtain info via lipo" + + cat bazel-genfiles/package/lipo_out | grep "i386 x86_64" \ + || fail "expected output binary to be for x86_64 architecture" +} + +function test_apple_binary_crosstool_watchos() { + rm -rf package + mkdir -p package + make_starlark_apple_binary_rule_in package + + cat > package/BUILD < \$(@)", + tags = ["requires-darwin"], +) + +starlark_apple_binary( + name = "main_binary", + deps = [":main_lib"], + platform_type = "watchos", +) +objc_library( + name = "main_lib", + srcs = ["main.m"], + deps = [":lib_a"], +) +cc_library( + name = "cc_lib", + srcs = ["cc_lib.cc"], +) +# By depending on a library which requires it is built for watchos, this test +# verifies that dependencies of starlark_apple_binary are compiled for the +# specified platform_type. +objc_library( + name = "lib_a", + srcs = ["a.m"], + deps = [":cc_lib"], +) +EOF + cat > package/main.m < + +// Note that WKExtensionDelegate is only available in Watch SDK. +@interface TestInterfaceMain : NSObject +@end + +int main() { + return 0; +} +EOF + cat > package/a.m < + +// Note that WKExtensionDelegate is only available in Watch SDK. +@interface TestInterfaceA : NSObject +@end + +int aFunction() { + return 0; +} +EOF + cat > package/cc_lib.cc << EOF +#include + +std::string GetString() { return "h3ll0"; } +EOF + + bazel build --verbose_failures //package:lipo_out \ + --noincompatible_enable_cc_toolchain_resolution \ + --watchos_cpus=armv7k \ + --xcode_version=$XCODE_VERSION \ + || fail "should build watch binary" + + cat bazel-genfiles/package/lipo_out | grep "armv7k" \ + || fail "expected output binary to be for armv7k architecture" + + bazel build --verbose_failures //package:lipo_out \ + --noincompatible_enable_cc_toolchain_resolution \ + --watchos_cpus=i386 \ + --xcode_version=$XCODE_VERSION \ + || fail "should build watch binary" + + cat bazel-genfiles/package/lipo_out | grep "i386" \ + || fail "expected output binary to be for i386 architecture" +} + function test_xcode_config_select() { mkdir -p a cat > a/BUILD <<'EOF' @@ -203,4 +449,102 @@ EOF assert_contains "IOS UNKNOWN" bazel-genfiles/a/ioso } +function test_apple_binary_dsym_builds() { + rm -rf package + mkdir -p package + make_starlark_apple_binary_rule_in package + + cat > package/BUILD < package/main.m < package/BUILD < "package/the main.m" < package/BUILD < "package/dummy.m" <&2; exit 1; } +function make_lib() { + rm -rf ios + mkdir -p ios + + cat >ios/main.m < + +int main(int argc, char *argv[]) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +} +EOF + + cat >ios/BUILD <$TEST_log 2>&1 || fail "should pass" + ls bazel-out/*/bin/ios/liblib.a \ + || fail "should generate lib.a" +} + +function test_invalid_ios_sdk_version() { + setup_objc_test_support + make_lib + + ! bazel build --verbose_failures --apple_platform_type=ios \ + --ios_sdk_version=2.34 \ + //ios:lib >$TEST_log 2>&1 || fail "should fail" + expect_log "SDK \"iphonesimulator2.34\" cannot be located." +} + function test_xcodelocator_embedded_tool() { rm -rf ios mkdir -p ios @@ -45,4 +88,119 @@ EOF || fail "should be able to resolve xcode-locator" } -run_suite "objc test suite" +# Verifies contents of .a files do not contain timestamps -- if they did, the +# results would not be hermetic. +function test_archive_timestamps() { + setup_objc_test_support + + mkdir -p objclib + cat > objclib/BUILD < objclib/mysrc.m <"$TEST_log" 2>&1 \ + || fail "Should build objc_library" + + # Based on timezones, ar -tv may show the timestamp of the contents as either + # Dec 31 1969 or Jan 1 1970 -- either is fine. + # We would use 'date' here, but the format is slightly different (Jan 1 vs. + # Jan 01). + ar -tv bazel-out/*/bin/objclib/libobjclib.a \ + | grep "mysrc" | grep "Dec 31" | grep "1969" \ + || ar -tv bazel-out/*/bin/objclib/libobjclib.a \ + | grep "mysrc" | grep "Jan 1" | grep "1970" || \ + fail "Timestamp of contents of archive file should be zero" +} + +function test_strip_symbols() { + setup_objc_test_support + + rm -rf ios + mkdir -p ios + make_starlark_apple_binary_rule_in ios + + cat >ios/main.m < +/* function declaration */ +int addOne(int num); +int addOne(int num) { + return num + 1; +} + int main(int argc, char *argv[]) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +} +EOF + + cat >ios/BUILD <$TEST_log 2>&1 || fail "should pass" + ls bazel-out/*/bin/ios/app_lipobin \ + || fail "should generate lipobin (stripped binary)" + ! nm bazel-out/*/bin/ios/app_lipobin | grep addOne \ + || fail "should fail to find symbol addOne" +} + +function test_cc_test_depending_on_objc() { + setup_objc_test_support + + rm -rf foo + mkdir -p foo + + cat >foo/a.cc < +int main(int argc, char** argv) { + std::cout << "Hello! I'm a test!\n"; + return 0; +} +EOF + + cat >foo/BUILD <$TEST_log 2>&1 || fail "should pass" +} + +run_suite "objc/ios test suite" diff --git a/src/test/shell/bazel/cc_integration_test.sh b/src/test/shell/bazel/cc_integration_test.sh index adab1c967726d4..9bcb7bed650dc8 100755 --- a/src/test/shell/bazel/cc_integration_test.sh +++ b/src/test/shell/bazel/cc_integration_test.sh @@ -728,7 +728,7 @@ EOF --output_groups=out cat "bazel-bin/${package}/aspect_out" | \ - grep "\(gcc\|clang\|clanc-cl.exe\|cl.exe\|cc_wrapper.sh\)" \ + grep "\(gcc\|clang\|clanc-cl.exe\|cl.exe\)" \ || fail "args didn't contain the tool path" cat "bazel-bin/${package}/aspect_out" | grep "a.*o .*b.*o .*c.*o" \ diff --git a/src/test/shell/integration/aquery_test.sh b/src/test/shell/integration/aquery_test.sh index fd6874bdc1de05..3b15117087e3f6 100755 --- a/src/test/shell/integration/aquery_test.sh +++ b/src/test/shell/integration/aquery_test.sh @@ -1700,7 +1700,9 @@ EOF "mnemonic(CppCompile,//$pkg:main)" >output 2> "$TEST_log" || fail "Expected success" cat output >> "$TEST_log" - if "$is_windows"; then + if "$is_macos"; then + assert_contains ' key: "XCODE_VERSION_OVERRIDE"' output + elif "$is_windows"; then assert_contains ' key: "INCLUDE"' output else assert_contains ' key: "PWD"' output diff --git a/tools/BUILD b/tools/BUILD index 4102c0ae8d6e78..b86e19b880856a 100644 --- a/tools/BUILD +++ b/tools/BUILD @@ -23,6 +23,7 @@ filegroup( "//tools/j2objc:srcs", "//tools/objc:srcs", "//tools/osx:srcs", + "//tools/osx/crosstool:srcs", "//tools/proto:srcs", "//tools/windows:srcs", "//tools/test:srcs", @@ -64,6 +65,7 @@ filegroup( "//tools/runfiles:embedded_tools", "//tools/test:embedded_tools", "//tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator:embedded_tools", + "//tools/osx/crosstool:srcs", "//tools/osx:srcs", "//tools/sh:embedded_tools", "//tools/allowlists:srcs", diff --git a/tools/cpp/cc_configure.bzl b/tools/cpp/cc_configure.bzl index 56399fb4e3c000..006a51e2f91e4e 100644 --- a/tools/cpp/cc_configure.bzl +++ b/tools/cpp/cc_configure.bzl @@ -14,12 +14,21 @@ """Rules for configuring the C++ toolchain (experimental).""" load("@bazel_tools//tools/cpp:windows_cc_configure.bzl", "configure_windows_toolchain") +load("@bazel_tools//tools/cpp:osx_cc_configure.bzl", "configure_osx_toolchain") load("@bazel_tools//tools/cpp:unix_cc_configure.bzl", "configure_unix_toolchain") load( "@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value", "resolve_labels", ) +load("@bazel_tools//tools/osx:xcode_configure.bzl", "run_xcode_locator") + +def _generate_cpp_only_build_file(repository_ctx, cpu_value, paths): + repository_ctx.template( + "BUILD", + paths["@bazel_tools//tools/cpp:BUILD.toolchains.tpl"], + {"%{name}": cpu_value}, + ) def cc_autoconf_toolchains_impl(repository_ctx): """Generate BUILD file with 'toolchain' targets for the local host C++ toolchain. @@ -27,25 +36,47 @@ def cc_autoconf_toolchains_impl(repository_ctx): Args: repository_ctx: repository context """ + paths = resolve_labels(repository_ctx, [ + "@bazel_tools//tools/cpp:BUILD.toolchains.tpl", + "@bazel_tools//tools/osx/crosstool:BUILD.toolchains", + "@bazel_tools//tools/osx:xcode_locator.m", + ]) env = repository_ctx.os.environ + cpu_value = get_cpu_value(repository_ctx) # Should we try to find C++ toolchain at all? If not, we don't have to generate toolchains for C++ at all. should_detect_cpp_toolchain = "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN" not in env or env["BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN"] != "1" - if should_detect_cpp_toolchain: - paths = resolve_labels(repository_ctx, [ - "@bazel_tools//tools/cpp:BUILD.toolchains.tpl", - ]) - repository_ctx.template( - "BUILD", - paths["@bazel_tools//tools/cpp:BUILD.toolchains.tpl"], - {"%{name}": get_cpu_value(repository_ctx)}, - ) - else: + # Should we unconditionally *not* use xcode? If so, we don't have to run Xcode locator ever. + should_use_cpp_only_toolchain = "BAZEL_USE_CPP_ONLY_TOOLCHAIN" in env and env["BAZEL_USE_CPP_ONLY_TOOLCHAIN"] == "1" + + # Should we unconditionally use xcode? If so, we don't have to run Xcode locator now. + should_use_xcode = "BAZEL_USE_XCODE_TOOLCHAIN" in env and env["BAZEL_USE_XCODE_TOOLCHAIN"] == "1" + + if not should_detect_cpp_toolchain: repository_ctx.file("BUILD", "# C++ toolchain autoconfiguration was disabled by BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN env variable.") + elif cpu_value.startswith("darwin") and not should_use_cpp_only_toolchain: + xcode_toolchains = [] + + # Only detect xcode if the user didn't tell us it will be there. + if not should_use_xcode: + # TODO(#6926): Unify C++ and ObjC toolchains so we don't have to run xcode locator to generate toolchain targets. + # And also so we don't have to keep this code in sync with //tools/cpp:osx_cc_configure.bzl. + (xcode_toolchains, _xcodeloc_err) = run_xcode_locator( + repository_ctx, + paths["@bazel_tools//tools/osx:xcode_locator.m"], + ) + + if should_use_xcode or xcode_toolchains: + repository_ctx.symlink(paths["@bazel_tools//tools/osx/crosstool:BUILD.toolchains"], "BUILD") + else: + _generate_cpp_only_build_file(repository_ctx, cpu_value, paths) + else: + _generate_cpp_only_build_file(repository_ctx, cpu_value, paths) cc_autoconf_toolchains = repository_rule( environ = [ + "BAZEL_USE_CPP_ONLY_TOOLCHAIN", "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN", ], implementation = cc_autoconf_toolchains_impl, @@ -87,6 +118,9 @@ def cc_autoconf_impl(repository_ctx, overriden_tools = dict()): # TODO(ibiryukov): overriden_tools are only supported in configure_unix_toolchain. # We might want to add that to Windows too(at least for msys toolchain). configure_windows_toolchain(repository_ctx) + elif (cpu_value.startswith("darwin") and + ("BAZEL_USE_CPP_ONLY_TOOLCHAIN" not in env or env["BAZEL_USE_CPP_ONLY_TOOLCHAIN"] != "1")): + configure_osx_toolchain(repository_ctx, cpu_value, overriden_tools) else: configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools) @@ -123,6 +157,8 @@ cc_autoconf = repository_rule( "BAZEL_TARGET_CPU", "BAZEL_TARGET_LIBC", "BAZEL_TARGET_SYSTEM", + "BAZEL_USE_CPP_ONLY_TOOLCHAIN", + "BAZEL_USE_XCODE_TOOLCHAIN", "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN", "BAZEL_USE_LLVM_NATIVE_COVERAGE", "BAZEL_LLVM", diff --git a/tools/cpp/osx_cc_configure.bzl b/tools/cpp/osx_cc_configure.bzl new file mode 100644 index 00000000000000..cbfc6afe27429e --- /dev/null +++ b/tools/cpp/osx_cc_configure.bzl @@ -0,0 +1,255 @@ +# pylint: disable=g-bad-file-header +# Copyright 2016 The Bazel Authors. All rights reserved. +# +# 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. +"""Configuring the C++ toolchain on macOS.""" + +load( + "@bazel_tools//tools/osx:xcode_configure.bzl", + "OSX_EXECUTE_TIMEOUT", + "run_xcode_locator", +) +load( + "@bazel_tools//tools/cpp:lib_cc_configure.bzl", + "escape_string", + "resolve_labels", +) +load( + "@bazel_tools//tools/cpp:unix_cc_configure.bzl", + "configure_unix_toolchain", + "get_env", +) + +def _get_escaped_xcode_cxx_inc_directories(repository_ctx, cc, xcode_toolchains): + """Compute the list of default C++ include paths on Xcode-enabled darwin. + + Args: + repository_ctx: The repository context. + cc: The default C++ compiler on the local system. + xcode_toolchains: A list containing the xcode toolchains available + Returns: + include_paths: A list of builtin include paths. + """ + + # Assume that everything is managed by Xcode / toolchain installations + include_dirs = [ + "/Applications/", + "/Library/", + ] + + user = repository_ctx.os.environ.get("USER") + if user: + include_dirs.append("/Users/{}/Library/".format(user)) + + # Include extra Xcode paths in case they're installed on other volumes + for toolchain in xcode_toolchains: + include_dirs.append(escape_string(toolchain.developer_dir)) + + return include_dirs + +# TODO: Remove once Xcode 12 is the minimum supported version +def _compile_cc_file_single_arch(repository_ctx, src_name, out_name, timeout): + env = repository_ctx.os.environ + xcrun_result = repository_ctx.execute([ + "env", + "-i", + "DEVELOPER_DIR={}".format(env.get("DEVELOPER_DIR", default = "")), + "xcrun", + "--sdk", + "macosx", + "clang", + "-mmacosx-version-min=10.13", + "-std=c++11", + "-lc++", + "-O3", + "-o", + out_name, + src_name, + ], timeout) + if (xcrun_result.return_code != 0): + error_msg = ( + "return code {code}, stderr: {err}, stdout: {out}" + ).format( + code = xcrun_result.return_code, + err = xcrun_result.stderr, + out = xcrun_result.stdout, + ) + fail(out_name + " failed to generate. Please file an issue at " + + "https://github.com/bazelbuild/bazel/issues with the following:\n" + + error_msg) + +def _compile_cc_file(repository_ctx, src_name, out_name, timeout): + env = repository_ctx.os.environ + xcrun_result = repository_ctx.execute([ + "env", + "-i", + "DEVELOPER_DIR={}".format(env.get("DEVELOPER_DIR", default = "")), + "xcrun", + "--sdk", + "macosx", + "clang", + "-mmacosx-version-min=10.13", + "-std=c++11", + "-lc++", + "-arch", + "arm64", + "-arch", + "x86_64", + "-Wl,-no_adhoc_codesign", + "-Wl,-no_uuid", + "-O3", + "-o", + out_name, + src_name, + ], timeout) + + if xcrun_result.return_code == 0: + xcrun_result = repository_ctx.execute([ + "env", + "-i", + "codesign", + "--identifier", # Required to be reproducible across archs + out_name, + "--force", + "--sign", + "-", + out_name, + ], timeout) + if xcrun_result.return_code != 0: + error_msg = ( + "codesign return code {code}, stderr: {err}, stdout: {out}" + ).format( + code = xcrun_result.return_code, + err = xcrun_result.stderr, + out = xcrun_result.stdout, + ) + fail(out_name + " failed to generate. Please file an issue at " + + "https://github.com/bazelbuild/bazel/issues with the following:\n" + + error_msg) + else: + _compile_cc_file_single_arch(repository_ctx, src_name, out_name, timeout) + +def configure_osx_toolchain(repository_ctx, cpu_value, overriden_tools): + """Configure C++ toolchain on macOS. + + Args: + repository_ctx: The repository context. + overriden_tools: dictionary of overridden tools. + """ + paths = resolve_labels(repository_ctx, [ + "@bazel_tools//tools/cpp:armeabi_cc_toolchain_config.bzl", + "@bazel_tools//tools/cpp:osx_cc_wrapper.sh.tpl", + "@bazel_tools//tools/objc:libtool.sh", + "@bazel_tools//tools/objc:libtool_check_unique.cc", + "@bazel_tools//tools/objc:make_hashed_objlist.py", + "@bazel_tools//tools/objc:xcrunwrapper.sh", + "@bazel_tools//tools/osx/crosstool:BUILD.tpl", + "@bazel_tools//tools/osx/crosstool:cc_toolchain_config.bzl", + "@bazel_tools//tools/osx/crosstool:wrapped_clang.cc", + "@bazel_tools//tools/osx:xcode_locator.m", + ]) + + env = repository_ctx.os.environ + should_use_xcode = "BAZEL_USE_XCODE_TOOLCHAIN" in env and env["BAZEL_USE_XCODE_TOOLCHAIN"] == "1" + if "BAZEL_OSX_EXECUTE_TIMEOUT" in env: + timeout = int(env["BAZEL_OSX_EXECUTE_TIMEOUT"]) + else: + timeout = OSX_EXECUTE_TIMEOUT + xcode_toolchains = [] + + # Make the following logic in sync with //tools/cpp:cc_configure.bzl#cc_autoconf_toolchains_impl + (xcode_toolchains, xcodeloc_err) = run_xcode_locator( + repository_ctx, + paths["@bazel_tools//tools/osx:xcode_locator.m"], + ) + if should_use_xcode and not xcode_toolchains: + fail("BAZEL_USE_XCODE_TOOLCHAIN is set to 1 but Bazel couldn't find Xcode installed on the " + + "system. Verify that 'xcode-select -p' is correct.") + if xcode_toolchains: + # For Xcode toolchains, there's no reason to use anything other than + # wrapped_clang, so that we still get the Bazel Xcode placeholder + # substitution and other behavior for actions that invoke this + # cc_wrapper.sh script. The wrapped_clang binary is already hardcoded + # into the Objective-C crosstool actions, anyway, so this ensures that + # the C++ actions behave consistently. + cc = repository_ctx.path("wrapped_clang") + + cc_path = '"$(/usr/bin/dirname "$0")"/wrapped_clang' + repository_ctx.template( + "cc_wrapper.sh", + paths["@bazel_tools//tools/cpp:osx_cc_wrapper.sh.tpl"], + { + "%{cc}": escape_string(cc_path), + "%{env}": escape_string(get_env(repository_ctx)), + }, + ) + repository_ctx.symlink( + paths["@bazel_tools//tools/cpp:armeabi_cc_toolchain_config.bzl"], + "armeabi_cc_toolchain_config.bzl", + ) + repository_ctx.symlink( + paths["@bazel_tools//tools/objc:xcrunwrapper.sh"], + "xcrunwrapper.sh", + ) + repository_ctx.symlink( + paths["@bazel_tools//tools/objc:libtool.sh"], + "libtool", + ) + repository_ctx.symlink( + paths["@bazel_tools//tools/objc:make_hashed_objlist.py"], + "make_hashed_objlist.py", + ) + repository_ctx.symlink( + paths["@bazel_tools//tools/osx/crosstool:cc_toolchain_config.bzl"], + "cc_toolchain_config.bzl", + ) + libtool_check_unique_src_path = str(repository_ctx.path( + paths["@bazel_tools//tools/objc:libtool_check_unique.cc"], + )) + _compile_cc_file( + repository_ctx, + libtool_check_unique_src_path, + "libtool_check_unique", + timeout, + ) + wrapped_clang_src_path = str(repository_ctx.path( + paths["@bazel_tools//tools/osx/crosstool:wrapped_clang.cc"], + )) + _compile_cc_file(repository_ctx, wrapped_clang_src_path, "wrapped_clang", timeout) + repository_ctx.symlink("wrapped_clang", "wrapped_clang_pp") + + tool_paths = {} + gcov_path = repository_ctx.os.environ.get("GCOV") + if gcov_path != None: + if not gcov_path.startswith("/"): + gcov_path = repository_ctx.which(gcov_path) + tool_paths["gcov"] = gcov_path + + escaped_include_paths = _get_escaped_xcode_cxx_inc_directories(repository_ctx, cc, xcode_toolchains) + escaped_cxx_include_directories = [] + for path in escaped_include_paths: + escaped_cxx_include_directories.append((" \"%s\"," % path)) + if xcodeloc_err: + escaped_cxx_include_directories.append(" # Error: " + xcodeloc_err) + repository_ctx.template( + "BUILD", + paths["@bazel_tools//tools/osx/crosstool:BUILD.tpl"], + { + "%{cxx_builtin_include_directories}": "\n".join(escaped_cxx_include_directories), + "%{tool_paths_overrides}": ",\n ".join( + ['"%s": "%s"' % (k, v) for k, v in tool_paths.items()], + ), + }, + ) + else: + configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools = overriden_tools) diff --git a/tools/cpp/unix_cc_configure.bzl b/tools/cpp/unix_cc_configure.bzl index a489ff39493dfd..63534597be7344 100644 --- a/tools/cpp/unix_cc_configure.bzl +++ b/tools/cpp/unix_cc_configure.bzl @@ -488,10 +488,7 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools): cc, "-xc++", cxx_opts + no_canonical_prefixes_opt + ["-stdlib=libc++"], - ) + - # Always included in case the user has Xcode + the CLT installed, both - # paths can be used interchangeably - ["/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"], + ), ) if is_clang: diff --git a/tools/cpp/unix_cc_toolchain_config.bzl b/tools/cpp/unix_cc_toolchain_config.bzl index cd4cebfe9cafd9..7c69af8e7f5155 100644 --- a/tools/cpp/unix_cc_toolchain_config.bzl +++ b/tools/cpp/unix_cc_toolchain_config.bzl @@ -18,8 +18,6 @@ load( "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", "action_config", "artifact_name_pattern", - "env_entry", - "env_set", "feature", "feature_set", "flag_group", @@ -31,11 +29,6 @@ load( ) load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") -def _target_os_version(ctx): - platform_type = ctx.fragments.apple.single_arch_platform.platform_type - xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig] - return xcode_config.minimum_os_for_platform_type(platform_type) - def layering_check_features(compiler): if compiler != "clang": return [] @@ -306,18 +299,6 @@ def _impl(ctx): with_features = [with_feature_set(features = ["opt"])], ), ], - env_sets = [ - env_set( - actions = all_link_actions + lto_index_actions + [ACTION_NAMES.cpp_link_static_library], - env_entries = ([ - env_entry( - # Required for hermetic links on macOS - key = "ZERO_AR_DATE", - value = "1", - ), - ]), - ), - ], ) dbg_feature = feature(name = "dbg") @@ -988,23 +969,15 @@ def _impl(ctx): ], ) - is_linux = ctx.attr.target_libc != "macosx" - libtool_feature = feature( - name = "libtool", - enabled = not is_linux, - ) - archiver_flags_feature = feature( name = "archiver_flags", flag_sets = [ flag_set( actions = [ACTION_NAMES.cpp_link_static_library], flag_groups = [ + flag_group(flags = ["rcsD"]), flag_group( - flags = [ - "rcsD" if is_linux else "rcs", - "%{output_execpath}", - ], + flags = ["%{output_execpath}"], expand_if_available = "output_execpath", ), ], @@ -1017,12 +990,9 @@ def _impl(ctx): flag_set( actions = [ACTION_NAMES.cpp_link_static_library], flag_groups = [ + flag_group(flags = ["-static", "-s"]), flag_group( - flags = [ - "-static", - "-o", - "%{output_execpath}", - ], + flags = ["-o", "%{output_execpath}"], expand_if_available = "output_execpath", ), ], @@ -1319,34 +1289,10 @@ def _impl(ctx): ], ) - # If you have Xcode + the CLT installed the version defaults can be - # too old for some standard C apis such as thread locals - macos_minimum_os_feature = feature( - name = "macos_minimum_os", - enabled = True, - flag_sets = [ - flag_set( - actions = all_compile_actions + all_link_actions, - flag_groups = [flag_group(flags = ["-mmacos-version-min={}".format(_target_os_version(ctx))])], - ), - ], - ) - - # Kept for backwards compatibility with the crosstool that moved. Without - # linking the objc runtime binaries don't link CoreFoundation for free, - # which breaks abseil. - macos_default_link_flags_feature = feature( - name = "macos_default_link_flags", - enabled = True, - flag_sets = [ - flag_set( - actions = all_link_actions, - flag_groups = [flag_group(flags = [ - "-no-canonical-prefixes", - "-fobjc-link-runtime", - ])], - ), - ], + is_linux = ctx.attr.target_libc != "macosx" + libtool_feature = feature( + name = "libtool", + enabled = not is_linux, ) # TODO(#8303): Mac crosstool should also declare every feature. @@ -1419,10 +1365,9 @@ def _impl(ctx): ), ] features = [ - macos_minimum_os_feature, - macos_default_link_flags_feature, libtool_feature, archiver_flags_feature, + supports_pic_feature, asan_feature, tsan_feature, ubsan_feature, @@ -1438,6 +1383,7 @@ def _impl(ctx): user_link_flags_feature, default_link_libs_feature, fdo_optimize_feature, + supports_dynamic_linker_feature, dbg_feature, opt_feature, user_compile_flags_feature, @@ -1492,11 +1438,6 @@ cc_toolchain_config = rule( "coverage_link_flags": attr.string_list(), "supports_start_end_lib": attr.bool(), "builtin_sysroot": attr.string(), - "_xcode_config": attr.label(default = configuration_field( - fragment = "apple", - name = "xcode_config_label", - )), }, - fragments = ["apple"], provides = [CcToolchainConfigInfo], ) diff --git a/tools/objc/libtool_check_unique.cc b/tools/objc/libtool_check_unique.cc new file mode 100644 index 00000000000000..7ba32deb61b4be --- /dev/null +++ b/tools/objc/libtool_check_unique.cc @@ -0,0 +1,109 @@ +// Copyright 2020 The Bazel Authors. All rights reserved. +// +// 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. + +#include +#include +#include +#include // NOLINT +#include + +using std::ifstream; +using std::regex; +using std::string; +using std::unordered_set; +using std::vector; + +const regex libRegex = regex(".*\\.a$"); +const regex noArgFlags = + regex("-static|-s|-a|-c|-L|-T|-D|-v|-no_warning_for_no_symbols"); +const regex singleArgFlags = regex("-arch_only|-syslibroot|-o"); + +string getBasename(const string &path) { + // Assumes we're on an OS with "/" as the path separator + auto idx = path.find_last_of("/"); + if (idx == string::npos) { + return path; + } + return path.substr(idx + 1); +} + +vector readFile(const string path) { + vector lines; + ifstream file(path); + string line; + while (std::getline(file, line)) { + if (!line.empty()) { + lines.push_back(line); + } + } + + return lines; +} + +unordered_set parseArgs(vector args) { + unordered_set basenames; + for (auto it = args.begin(); it != args.end(); ++it) { + const string arg = *it; + if (arg == "-filelist") { + ++it; + ifstream list(*it); + for (string line; getline(list, line);) { + const string basename = getBasename(line); + const auto pair = basenames.insert(basename); + if (!pair.second) { + exit(EXIT_FAILURE); + } + } + list.close(); + } else if (arg[0] == '@') { + string paramsFilePath(arg.substr(1)); + auto newBasenames = parseArgs(readFile(paramsFilePath)); + for (auto newBasename : newBasenames) { + const auto pair = basenames.insert(newBasename); + if (!pair.second) { + exit(EXIT_FAILURE); + } + } + } else if (regex_match(arg, noArgFlags)) { + } else if (regex_match(arg, singleArgFlags)) { + ++it; + } else if (arg[0] == '-') { + exit(EXIT_FAILURE); + // Unrecognized flag, let the wrapper deal with it, any flags added to + // libtool.sh should also be added here. + } else if (regex_match(arg, libRegex)) { + // Archive inputs can remain untouched, as they come from other targets. + } else { + const string basename = getBasename(arg); + const auto pair = basenames.insert(basename); + if (!pair.second) { + exit(EXIT_FAILURE); + } + } + } + + return basenames; +} + +// Returns 0 if there are no duplicate basenames in the object files (via +// -filelist, params files, and shell args), 1 otherwise +int main(int argc, const char *argv[]) { + vector args; + // Set i to 1 to skip executable path + for (int i = 1; argv[i] != nullptr; i++) { + args.push_back(argv[i]); + } + parseArgs(args); + return EXIT_SUCCESS; +} diff --git a/tools/osx/BUILD b/tools/osx/BUILD index 627a0d8ece181a..79344650445338 100644 --- a/tools/osx/BUILD +++ b/tools/osx/BUILD @@ -16,7 +16,9 @@ filegroup( filegroup( name = "bzl_srcs", - srcs = glob(["*.bzl"]), + srcs = glob(["*.bzl"]) + [ + "//tools/osx/crosstool:bzl_srcs", + ], visibility = ["//tools:__pkg__"], ) diff --git a/tools/osx/crosstool/BUILD b/tools/osx/crosstool/BUILD new file mode 100644 index 00000000000000..d3d8d068daec24 --- /dev/null +++ b/tools/osx/crosstool/BUILD @@ -0,0 +1,39 @@ +package(default_visibility = ["//visibility:public"]) + +# Files which shouldn't be publicly visible and dependencies of all objc_* or ios_* rules should be excluded. +exports_files(glob( + ["**"], + exclude = ["wrapped_clang_test.sh"], +)) + +filegroup( + name = "srcs", + srcs = glob(["**"]), +) + +filegroup( + name = "bzl_srcs", + srcs = glob(["*.bzl"]), + visibility = ["//tools/osx:__pkg__"], +) + +cc_binary( + name = "wrapped_clang", + testonly = True, + srcs = [ + "wrapped_clang.cc", + ], +) + +sh_test( + name = "wrapped_clang_test", + size = "small", + srcs = [ + "wrapped_clang_test.sh", + ], + data = [ + ":wrapped_clang", + "//src/test/shell:bashunit", + "@bazel_tools//tools/bash/runfiles", + ], +) diff --git a/tools/osx/crosstool/BUILD.toolchains b/tools/osx/crosstool/BUILD.toolchains new file mode 100644 index 00000000000000..866c6f5ee73314 --- /dev/null +++ b/tools/osx/crosstool/BUILD.toolchains @@ -0,0 +1,103 @@ +load("@bazel_tools//tools/osx/crosstool:osx_archs.bzl", "OSX_TOOLS_ARCHS") + +package(default_visibility = ["//visibility:public"]) + +exports_files(["osx_archs.bzl"]) + +# Target constraints for each arch. +# TODO(apple-rules): Rename osx constraint to macOS. +OSX_TOOLS_CONSTRAINTS = { + "armeabi-v7a": [ + "@platforms//cpu:armv7", + "@platforms//os:android", + ], + "darwin_arm64": [ + "@platforms//os:osx", + "@platforms//cpu:arm64", + ], + "darwin_arm64e": [ + "@platforms//os:osx", + "@platforms//cpu:arm64", + ], + "darwin_x86_64": [ + "@platforms//os:osx", + "@platforms//cpu:x86_64", + ], + "ios_arm64": [ + "@platforms//os:ios", + "@platforms//cpu:arm64", + ], + "ios_arm64e": [ + "@platforms//os:ios", + "@platforms//cpu:arm64", + ], + "ios_armv7": [ + "@platforms//os:ios", + "@platforms//cpu:armv7", + ], + "ios_i386": [ + "@platforms//os:ios", + "@platforms//cpu:i386", + ], + "ios_x86_64": [ + "@platforms//os:ios", + "@platforms//cpu:x86_64", + ], + "ios_sim_arm64": [ + "@platforms//os:ios", + "@platforms//cpu:arm64", + ], + "tvos_arm64": [ + "@platforms//os:tvos", + "@platforms//cpu:arm64", + ], + "tvos_x86_64": [ + "@platforms//os:tvos", + "@platforms//cpu:x86_64", + ], + "tvos_sim_arm64": [ + "@platforms//os:tvos", + "@platforms//cpu:arm64", + ], + "watchos_arm64": [ + "@platforms//os:watchos", + "@platforms//cpu:arm64", + ], + "watchos_arm64_32": [ + "@platforms//os:watchos", + "@platforms//cpu:arm64_32", + ], + "watchos_armv7k": [ + "@platforms//os:watchos", + "@platforms//cpu:armv7k", + ], + "watchos_i386": [ + "@platforms//os:watchos", + "@platforms//cpu:i386", + ], + "watchos_x86_64": [ + "@platforms//os:watchos", + "@platforms//cpu:x86_64", + ], +} + +OSX_DEVELOPER_PLATFORM_CPUS = [ + "arm64", + "x86_64", +] + +[ + toolchain( + name = "cc-toolchain-" + arch + "-" + cpu, + exec_compatible_with = [ + # These only execute on macOS. + "@platforms//os:osx", + "@platforms//cpu:" + cpu, + ], + target_compatible_with = OSX_TOOLS_CONSTRAINTS[arch], + toolchain = "@local_config_cc//:cc-compiler-" + arch, + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", + ) + for arch in OSX_TOOLS_ARCHS + ["armeabi-v7a"] + for cpu in OSX_DEVELOPER_PLATFORM_CPUS +] diff --git a/tools/osx/crosstool/BUILD.tpl b/tools/osx/crosstool/BUILD.tpl new file mode 100644 index 00000000000000..593d269628fd44 --- /dev/null +++ b/tools/osx/crosstool/BUILD.tpl @@ -0,0 +1,124 @@ +package(default_visibility = ["//visibility:public"]) + +load("@bazel_tools//tools/osx/crosstool:osx_archs.bzl", "OSX_TOOLS_ARCHS") +load("@rules_cc//cc:defs.bzl", "cc_toolchain_suite", "cc_library") +load(":armeabi_cc_toolchain_config.bzl", "armeabi_cc_toolchain_config") +load(":cc_toolchain_config.bzl", "cc_toolchain_config") + +# Reexporting osx_arch.bzl for backwards compatibility +# Originally this file was present in @local_config_cc, but with the split in +# https://github.com/bazelbuild/bazel/pull/8459 we had to move the file to +# @local_config_cc_toolchains. This alias is there to keep the code backwards +# compatible (and serves no other purpose). +alias(name = "osx_archs.bzl", actual = "@bazel_tools//tools/osx/crosstool:osx_archs.bzl") + +CC_TOOLCHAINS = [( + cpu + "|clang", + ":cc-compiler-" + cpu, +) for cpu in OSX_TOOLS_ARCHS] + [( + cpu, + ":cc-compiler-" + cpu, +) for cpu in OSX_TOOLS_ARCHS] + [ + ("k8|clang", ":cc-compiler-darwin_x86_64"), + ("darwin|clang", ":cc-compiler-darwin_x86_64"), + ("k8", ":cc-compiler-darwin_x86_64"), + ("darwin", ":cc-compiler-darwin_x86_64"), + ("armeabi-v7a|compiler", ":cc-compiler-armeabi-v7a"), + ("armeabi-v7a", ":cc-compiler-armeabi-v7a"), +] + +cc_library( + name = "link_extra_lib", +) + +cc_library( + name = "malloc", +) + +filegroup( + name = "empty", + srcs = [], +) + +filegroup( + name = "cc_wrapper", + srcs = ["cc_wrapper.sh"], +) + +cc_toolchain_suite( + name = "toolchain", + toolchains = dict(CC_TOOLCHAINS), +) + +[ + filegroup( + name = "osx_tools_" + arch, + srcs = [ + ":cc_wrapper", + ":libtool", + ":libtool_check_unique", + ":make_hashed_objlist.py", + ":wrapped_clang", + ":wrapped_clang_pp", + ":xcrunwrapper.sh", + ], + ) + for arch in OSX_TOOLS_ARCHS +] + +[ + apple_cc_toolchain( + name = "cc-compiler-" + arch, + all_files = ":osx_tools_" + arch, + ar_files = ":osx_tools_" + arch, + as_files = ":osx_tools_" + arch, + compiler_files = ":osx_tools_" + arch, + dwp_files = ":empty", + linker_files = ":osx_tools_" + arch, + objcopy_files = ":empty", + strip_files = ":osx_tools_" + arch, + supports_param_files = 1, + toolchain_config = arch, + toolchain_identifier = arch, + ) + for arch in OSX_TOOLS_ARCHS +] + +# When xcode_locator fails and causes cc_autoconf_toolchains to fall back +# to the non-Xcode C++ toolchain, it uses the legacy cpu value to refer to +# the toolchain, which is "darwin" for x86_64 macOS. +alias( + name = "cc-compiler-darwin", + actual = ":cc-compiler-darwin_x86_64", +) + +[ + cc_toolchain_config( + name = arch, + compiler = "clang", + cpu = arch, + cxx_builtin_include_directories = [ +%{cxx_builtin_include_directories} + ], + tool_paths_overrides = {%{tool_paths_overrides}}, + ) + for arch in OSX_TOOLS_ARCHS +] + +# Android tooling requires a default toolchain for the armeabi-v7a cpu. +cc_toolchain( + name = "cc-compiler-armeabi-v7a", + toolchain_identifier = "stub_armeabi-v7a", + toolchain_config = ":stub_armeabi-v7a", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 1, +) + +armeabi_cc_toolchain_config(name = "stub_armeabi-v7a") diff --git a/tools/osx/crosstool/cc_toolchain_config.bzl b/tools/osx/crosstool/cc_toolchain_config.bzl new file mode 100644 index 00000000000000..4529fa957a27f7 --- /dev/null +++ b/tools/osx/crosstool/cc_toolchain_config.bzl @@ -0,0 +1,2755 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# 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. +"""A C++ toolchain configuration rule for macOS.""" + +load( + "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", + "action_config", + "artifact_name_pattern", + "env_entry", + "env_set", + "feature", + "feature_set", + "flag_group", + "flag_set", + "make_variable", + "tool", + "tool_path", + "variable_with_value", + "with_feature_set", +) +load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") + +# The Xcode version from which that has support for deterministic mode +_SUPPORTS_DETERMINISTIC_MODE = "10.2" + +def _compare_versions(dv1, v2): + """Return value is <0, 0, >0 depending on DottedVersion dv1 comparison to string v2.""" + return dv1.compare_to(apple_common.dotted_version(v2)) + +def _can_use_deterministic_libtool(ctx): + """Returns `True` if the current version of `libtool` has support for + deterministic mode, and `False` otherwise.""" + xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig] + xcode_version = xcode_config.xcode_version() + if _compare_versions(xcode_version, _SUPPORTS_DETERMINISTIC_MODE) >= 0: + return True + else: + return False + +def _deterministic_libtool_flags(ctx): + """Returns additional `libtool` flags to enable deterministic mode, if they + are available.""" + if _can_use_deterministic_libtool(ctx): + return ["-D"] + return [] + +def _target_os_version(ctx): + platform_type = ctx.fragments.apple.single_arch_platform.platform_type + xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig] + return xcode_config.minimum_os_for_platform_type(platform_type) + +def _impl(ctx): + target_os_version = _target_os_version(ctx) + + if (ctx.attr.cpu == "ios_arm64"): + target_system_name = "arm64-apple-ios{}".format(target_os_version) + elif (ctx.attr.cpu == "tvos_arm64"): + target_system_name = "arm64-apple-tvos{}".format(target_os_version) + elif (ctx.attr.cpu == "watchos_arm64_32"): + target_system_name = "arm64_32-apple-watchos{}".format(target_os_version) + elif (ctx.attr.cpu == "ios_arm64e"): + target_system_name = "arm64e-apple-ios{}".format(target_os_version) + elif (ctx.attr.cpu == "ios_armv7"): + target_system_name = "armv7-apple-ios{}".format(target_os_version) + elif (ctx.attr.cpu == "watchos_armv7k"): + target_system_name = "armv7k-apple-watchos{}".format(target_os_version) + elif (ctx.attr.cpu == "ios_i386"): + target_system_name = "i386-apple-ios{}-simulator".format(target_os_version) + elif (ctx.attr.cpu == "watchos_i386"): + target_system_name = "i386-apple-watchos{}-simulator".format(target_os_version) + elif (ctx.attr.cpu == "ios_x86_64"): + target_system_name = "x86_64-apple-ios{}-simulator".format(target_os_version) + elif (ctx.attr.cpu == "ios_sim_arm64"): + target_system_name = "arm64-apple-ios{}-simulator".format(target_os_version) + elif (ctx.attr.cpu == "tvos_sim_arm64"): + target_system_name = "arm64-apple-tvos{}-simulator".format(target_os_version) + elif (ctx.attr.cpu == "watchos_arm64"): + target_system_name = "arm64-apple-watchos{}-simulator".format(target_os_version) + elif (ctx.attr.cpu == "darwin_x86_64"): + target_system_name = "x86_64-apple-macosx{}".format(target_os_version) + elif (ctx.attr.cpu == "darwin_arm64"): + target_system_name = "arm64-apple-macosx{}".format(target_os_version) + elif (ctx.attr.cpu == "darwin_arm64e"): + target_system_name = "arm64e-apple-macosx{}".format(target_os_version) + elif (ctx.attr.cpu == "tvos_x86_64"): + target_system_name = "x86_64-apple-tvos{}-simulator".format(target_os_version) + elif (ctx.attr.cpu == "watchos_x86_64"): + target_system_name = "x86_64-apple-watchos{}-simulator".format(target_os_version) + else: + fail("Unreachable") + + if ctx.attr.cpu.startswith("darwin_"): + target_libc = "macosx" + else: + target_libc = ctx.attr.cpu.split("_")[0] + + if ctx.attr.cpu == "darwin_x86_64": + abi_libc_version = "darwin_x86_64" + abi_version = "darwin_x86_64" + else: + abi_libc_version = "local" + abi_version = "local" + + host_system_name = "x86_64-apple-macosx" + arch = ctx.attr.cpu.split("_", 1)[-1] + if ctx.attr.cpu in ["ios_sim_arm64", "tvos_sim_arm64", "watchos_arm64"]: + arch = "arm64" + + all_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.clif_match, + ACTION_NAMES.lto_backend, + ] + + all_cpp_compile_actions = [ + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.clif_match, + ] + + preprocessor_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.clif_match, + ] + + codegen_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ] + + all_link_actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ] + + strip_action = action_config( + action_name = ACTION_NAMES.strip, + flag_sets = [ + flag_set( + flag_groups = [ + flag_group(flags = ["-S", "-o", "%{output_file}"]), + flag_group( + flags = ["%{stripopts}"], + iterate_over = "stripopts", + ), + flag_group(flags = ["%{input_file}"]), + ], + ), + ], + tools = [tool(path = "/usr/bin/strip")], + ) + + xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig] + xcode_execution_requirements = xcode_config.execution_info().keys() + + cpp_header_parsing_action = action_config( + action_name = ACTION_NAMES.cpp_header_parsing, + implies = [ + "preprocessor_defines", + "include_system_dirs", + "objc_arc", + "no_objc_arc", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "compiler_input_flags", + "compiler_output_flags", + "unfiltered_cxx_flags", + ], + tools = [ + tool( + path = "wrapped_clang", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + objc_compile_action = action_config( + action_name = ACTION_NAMES.objc_compile, + flag_sets = [ + flag_set( + flag_groups = [flag_group(flags = ["-target", target_system_name])], + ), + ], + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "objc_actions", + "apply_default_compiler_flags", + "apply_default_warnings", + "framework_paths", + "preprocessor_defines", + "include_system_dirs", + "objc_arc", + "no_objc_arc", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "apply_simulator_compiler_flags", + ], + tools = [ + tool( + path = "wrapped_clang", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + cpp_link_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_dynamic_library, + implies = [ + "contains_objc_source", + "has_configured_linker_path", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "runtime_root_flags", + "input_param_flags", + "strip_debug_symbols", + "linker_param_file", + "apple_env", + "sysroot", + "cpp_linker_flags", + ], + tools = [ + tool( + path = "cc_wrapper.sh", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + cpp_link_static_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_static_library, + implies = [ + "runtime_root_flags", + "archiver_flags", + "input_param_flags", + "linker_param_file", + "apple_env", + ], + tools = [ + tool( + path = "libtool", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + c_compile_action = action_config( + action_name = ACTION_NAMES.c_compile, + implies = [ + "preprocessor_defines", + "include_system_dirs", + "objc_arc", + "no_objc_arc", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "compiler_input_flags", + "compiler_output_flags", + "unfiltered_cxx_flags", + ], + tools = [ + tool( + path = "wrapped_clang", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + cpp_compile_action = action_config( + action_name = ACTION_NAMES.cpp_compile, + implies = [ + "preprocessor_defines", + "include_system_dirs", + "objc_arc", + "no_objc_arc", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "compiler_input_flags", + "compiler_output_flags", + "unfiltered_cxx_flags", + ], + tools = [ + tool( + path = "wrapped_clang_pp", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + objcpp_compile_action = action_config( + action_name = ACTION_NAMES.objcpp_compile, + flag_sets = [ + flag_set( + flag_groups = [ + flag_group( + flags = [ + "-target", + target_system_name, + "-stdlib=libc++", + "-std=gnu++11", + ], + ), + ], + ), + ], + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "apply_default_compiler_flags", + "apply_default_warnings", + "framework_paths", + "preprocessor_defines", + "include_system_dirs", + "objc_arc", + "no_objc_arc", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "apply_simulator_compiler_flags", + ], + tools = [ + tool( + path = "wrapped_clang_pp", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + assemble_action = action_config( + action_name = ACTION_NAMES.assemble, + implies = [ + "objc_arc", + "no_objc_arc", + "include_system_dirs", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "compiler_input_flags", + "compiler_output_flags", + "unfiltered_cxx_flags", + ], + tools = [ + tool( + path = "wrapped_clang", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + preprocess_assemble_action = action_config( + action_name = ACTION_NAMES.preprocess_assemble, + implies = [ + "preprocessor_defines", + "include_system_dirs", + "objc_arc", + "no_objc_arc", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "compiler_input_flags", + "compiler_output_flags", + "unfiltered_cxx_flags", + ], + tools = [ + tool( + path = "wrapped_clang", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + objc_executable_action = action_config( + action_name = "objc-executable", + flag_sets = [ + flag_set( + flag_groups = [ + flag_group( + flags = [ + "-Xlinker", + "-objc_abi_version", + "-Xlinker", + "2", + "-fobjc-link-runtime", + "-ObjC", + ], + ), + ], + with_features = [with_feature_set(not_features = ["kernel_extension"])], + ), + flag_set( + flag_groups = [ + flag_group(flags = ["-target", target_system_name]), + flag_group( + flags = ["-l%{library_names}"], + iterate_over = "library_names", + ), + flag_group(flags = ["-filelist", "%{filelist}"]), + flag_group(flags = ["-o", "%{linked_binary}"]), + flag_group( + flags = ["-force_load", "%{force_load_exec_paths}"], + iterate_over = "force_load_exec_paths", + ), + flag_group( + flags = ["%{dep_linkopts}"], + iterate_over = "dep_linkopts", + ), + flag_group( + flags = ["-Wl,%{attr_linkopts}"], + iterate_over = "attr_linkopts", + ), + ], + ), + ], + implies = [ + "include_system_dirs", + "framework_paths", + "strip_debug_symbols", + "apple_env", + "apply_implicit_frameworks", + ], + tools = [ + tool( + path = "wrapped_clang", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + cpp_link_executable_action = action_config( + action_name = ACTION_NAMES.cpp_link_executable, + implies = [ + "contains_objc_source", + "linkstamps", + "output_execpath_flags", + "runtime_root_flags", + "input_param_flags", + "force_pic_flags", + "strip_debug_symbols", + "linker_param_file", + "apple_env", + "sysroot", + "cpp_linker_flags", + ], + tools = [ + tool( + path = "cc_wrapper.sh", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + linkstamp_compile_action = action_config( + action_name = ACTION_NAMES.linkstamp_compile, + implies = [ + "preprocessor_defines", + "include_system_dirs", + "objc_arc", + "no_objc_arc", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "compiler_input_flags", + "compiler_output_flags", + ], + tools = [ + tool( + path = "wrapped_clang", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + cpp_module_compile_action = action_config( + action_name = ACTION_NAMES.cpp_module_compile, + implies = [ + "preprocessor_defines", + "include_system_dirs", + "objc_arc", + "no_objc_arc", + "apple_env", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + "compiler_input_flags", + "compiler_output_flags", + "unfiltered_cxx_flags", + ], + tools = [ + tool( + path = "wrapped_clang", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + cpp_link_nodeps_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library, + implies = [ + "contains_objc_source", + "has_configured_linker_path", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "runtime_root_flags", + "input_param_flags", + "strip_debug_symbols", + "linker_param_file", + "apple_env", + "sysroot", + "cpp_linker_flags", + ], + tools = [ + tool( + path = "cc_wrapper.sh", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + objc_fully_link_action = action_config( + action_name = "objc-fully-link", + flag_sets = [ + flag_set( + flag_groups = [ + flag_group( + flags = _deterministic_libtool_flags(ctx) + [ + "-no_warning_for_no_symbols", + "-static", + "-arch_only", + arch, + "-syslibroot", + "%{sdk_dir}", + "-o", + "%{fully_linked_archive_path}", + ], + ), + flag_group( + flags = ["%{objc_library_exec_paths}"], + iterate_over = "objc_library_exec_paths", + ), + flag_group( + flags = ["%{cc_library_exec_paths}"], + iterate_over = "cc_library_exec_paths", + ), + flag_group( + flags = ["%{imported_library_exec_paths}"], + iterate_over = "imported_library_exec_paths", + ), + ], + ), + ], + implies = ["apple_env"], + tools = [ + tool( + path = "libtool", + execution_requirements = xcode_execution_requirements, + ), + ], + ) + + objcopy_embed_data_action = action_config( + action_name = "objcopy_embed_data", + enabled = True, + tools = [tool(path = "/usr/bin/objcopy")], + ) + + action_configs = [ + strip_action, + c_compile_action, + cpp_compile_action, + linkstamp_compile_action, + cpp_module_compile_action, + cpp_header_parsing_action, + objc_compile_action, + objcpp_compile_action, + assemble_action, + preprocess_assemble_action, + objc_executable_action, + cpp_link_executable_action, + cpp_link_dynamic_library_action, + cpp_link_nodeps_dynamic_library_action, + cpp_link_static_library_action, + objc_fully_link_action, + objcopy_embed_data_action, + ] + + if (ctx.attr.cpu == "ios_arm64" or + ctx.attr.cpu == "ios_arm64e" or + ctx.attr.cpu == "ios_armv7" or + ctx.attr.cpu == "ios_i386" or + ctx.attr.cpu == "ios_x86_64" or + ctx.attr.cpu == "ios_sim_arm64" or + ctx.attr.cpu == "watchos_arm64_32" or + ctx.attr.cpu == "watchos_armv7k" or + ctx.attr.cpu == "watchos_i386" or + ctx.attr.cpu == "watchos_x86_64" or + ctx.attr.cpu == "watchos_arm64"): + apply_default_compiler_flags_feature = feature( + name = "apply_default_compiler_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.objc_compile, ACTION_NAMES.objcpp_compile], + flag_groups = [flag_group(flags = ["-DOS_IOS", "-fno-autolink"])], + ), + ], + ) + elif (ctx.attr.cpu == "darwin_x86_64" or + ctx.attr.cpu == "darwin_arm64" or + ctx.attr.cpu == "darwin_arm64e"): + apply_default_compiler_flags_feature = feature( + name = "apply_default_compiler_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.objc_compile, ACTION_NAMES.objcpp_compile], + flag_groups = [flag_group(flags = ["-DOS_MACOSX", "-fno-autolink"])], + ), + ], + ) + elif (ctx.attr.cpu == "tvos_arm64" or + ctx.attr.cpu == "tvos_x86_64" or + ctx.attr.cpu == "tvos_sim_arm64"): + apply_default_compiler_flags_feature = feature( + name = "apply_default_compiler_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.objc_compile, ACTION_NAMES.objcpp_compile], + flag_groups = [flag_group(flags = ["-DOS_TVOS", "-fno-autolink"])], + ), + ], + ) + else: + apply_default_compiler_flags_feature = None + + dynamic_linking_mode_feature = feature(name = "dynamic_linking_mode") + + compile_all_modules_feature = feature(name = "compile_all_modules") + + runtime_root_flags_feature = feature( + name = "runtime_root_flags", + flag_sets = [ + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = [ + "-Xlinker", + "-rpath", + "-Xlinker", + "@loader_path/%{runtime_library_search_directories}", + ], + iterate_over = "runtime_library_search_directories", + expand_if_available = "runtime_library_search_directories", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["%{runtime_root_flags}"], + iterate_over = "runtime_root_flags", + expand_if_available = "runtime_root_flags", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["%{runtime_root_entries}"], + iterate_over = "runtime_root_entries", + expand_if_available = "runtime_root_entries", + ), + ], + ), + ], + ) + + objc_arc_feature = feature( + name = "objc_arc", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-fobjc-arc"], + expand_if_available = "objc_arc", + ), + ], + ), + ], + ) + + unfiltered_cxx_flags_feature = feature( + name = "unfiltered_cxx_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ], + flag_groups = [ + flag_group(flags = ["-no-canonical-prefixes", "-pthread"]), + ], + ), + ], + ) + + compiler_input_flags_feature = feature( + name = "compiler_input_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-c", "%{source_file}"], + expand_if_available = "source_file", + ), + ], + ), + ], + ) + + strip_debug_symbols_feature = feature( + name = "strip_debug_symbols", + flag_sets = [ + flag_set( + actions = all_link_actions + ["objc-executable"], + flag_groups = [ + flag_group( + flags = ["-Wl,-S"], + expand_if_available = "strip_debug_symbols", + ), + ], + ), + ], + ) + + shared_flag_feature = feature( + name = "shared_flag", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["-shared"])], + ), + ], + ) + + if (ctx.attr.cpu == "ios_i386" or + ctx.attr.cpu == "ios_x86_64" or + ctx.attr.cpu == "ios_sim_arm64" or + ctx.attr.cpu == "tvos_x86_64" or + ctx.attr.cpu == "tvos_sim_arm64" or + ctx.attr.cpu == "watchos_i386" or + ctx.attr.cpu == "watchos_x86_64" or + ctx.attr.cpu == "watchos_arm64"): + apply_simulator_compiler_flags_feature = feature( + name = "apply_simulator_compiler_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.objc_compile, ACTION_NAMES.objcpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-fexceptions", + "-fasm-blocks", + "-fobjc-abi-version=2", + "-fobjc-legacy-dispatch", + ], + ), + ], + ), + ], + ) + else: + apply_simulator_compiler_flags_feature = feature(name = "apply_simulator_compiler_flags") + + supports_pic_feature = feature(name = "supports_pic", enabled = True) + + fastbuild_feature = feature(name = "fastbuild") + + no_legacy_features_feature = feature(name = "no_legacy_features") + + user_link_flags_feature = feature( + name = "user_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions + ["objc-executable"], + flag_groups = [ + flag_group( + flags = ["%{user_link_flags}"], + iterate_over = "user_link_flags", + expand_if_available = "user_link_flags", + ), + ], + ), + ], + ) + + if (ctx.attr.cpu == "ios_arm64" or + ctx.attr.cpu == "ios_arm64e" or + ctx.attr.cpu == "ios_armv7" or + ctx.attr.cpu == "ios_i386" or + ctx.attr.cpu == "ios_x86_64" or + ctx.attr.cpu == "ios_sim_arm64" or + ctx.attr.cpu == "tvos_arm64" or + ctx.attr.cpu == "tvos_x86_64" or + ctx.attr.cpu == "tvos_sim_arm64" or + ctx.attr.cpu == "watchos_arm64_32" or + ctx.attr.cpu == "watchos_armv7k" or + ctx.attr.cpu == "watchos_i386" or + ctx.attr.cpu == "watchos_x86_64" or + ctx.attr.cpu == "watchos_arm64"): + contains_objc_source_feature = feature( + name = "contains_objc_source", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-fobjc-link-runtime"])], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-framework", "UIKit"])], + ), + ], + ) + elif (ctx.attr.cpu == "darwin_x86_64" or + ctx.attr.cpu == "darwin_arm64" or + ctx.attr.cpu == "darwin_arm64e"): + contains_objc_source_feature = feature( + name = "contains_objc_source", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-fobjc-link-runtime"])], + ), + ], + ) + else: + contains_objc_source_feature = None + + includes_feature = feature( + name = "includes", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ACTION_NAMES.clif_match, + ], + flag_groups = [ + flag_group( + flags = ["-include", "%{includes}"], + iterate_over = "includes", + expand_if_available = "includes", + ), + ], + ), + ], + ) + + gcc_coverage_map_format_feature = feature( + name = "gcc_coverage_map_format", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-fprofile-arcs", "-ftest-coverage", "-g"], + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["--coverage"])], + ), + ], + requires = [feature_set(features = ["coverage"])], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions + ["objc-executable"], + flag_groups = [ + flag_group( + flags = [ + "-no-canonical-prefixes", + "-target", + target_system_name, + ], + ), + ], + ), + ], + ) + + no_deduplicate_feature = feature( + name = "no_deduplicate", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions + ["objc-executable"], + flag_groups = [ + flag_group( + flags = [ + "-Xlinker", + "-no_deduplicate", + ], + ), + ], + with_features = [ + with_feature_set(not_features = ["opt"]), + ], + ), + ], + ) + + output_execpath_flags_feature = feature( + name = "output_execpath_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["-o", "%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + pic_feature = feature( + name = "pic", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.preprocess_assemble, + ], + flag_groups = [ + flag_group(flags = ["-fPIC"], expand_if_available = "pic"), + ], + ), + ], + ) + + framework_paths_feature = feature( + name = "framework_paths", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-F%{framework_include_paths}"], + iterate_over = "framework_include_paths", + ), + ], + ), + flag_set( + actions = ["objc-executable"], + flag_groups = [ + flag_group( + flags = ["-F%{framework_paths}"], + iterate_over = "framework_paths", + ), + flag_group( + flags = ["-framework", "%{framework_names}"], + iterate_over = "framework_names", + ), + flag_group( + flags = ["-weak_framework", "%{weak_framework_names}"], + iterate_over = "weak_framework_names", + ), + ], + ), + ], + ) + + compiler_output_flags_feature = feature( + name = "compiler_output_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-S"], + expand_if_available = "output_assembly_file", + ), + flag_group( + flags = ["-E"], + expand_if_available = "output_preprocess_file", + ), + flag_group( + flags = ["-o", "%{output_file}"], + expand_if_available = "output_file", + ), + ], + ), + ], + ) + + opt_feature = feature(name = "opt") + + pch_feature = feature( + name = "pch", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ], + flag_groups = [ + flag_group( + flags = [ + "-include", + "%{pch_file}", + ], + expand_if_available = "pch_file", + ), + ], + ), + ], + ) + + coverage_feature = feature(name = "coverage") + + include_system_dirs_feature = feature( + name = "include_system_dirs", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + "objc-executable", + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ], + flag_groups = [ + flag_group( + flags = [ + "-isysroot", + "%{sdk_dir}", + "-F%{sdk_framework_dir}", + "-F%{platform_developer_framework_dir}", + ], + ), + ], + ), + ], + ) + + input_param_flags_feature = feature( + name = "input_param_flags", + flag_sets = [ + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["-L%{library_search_directories}"], + iterate_over = "library_search_directories", + expand_if_available = "library_search_directories", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["%{libopts}"], + iterate_over = "libopts", + expand_if_available = "libopts", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["-Wl,-force_load,%{whole_archive_linker_params}"], + iterate_over = "whole_archive_linker_params", + expand_if_available = "whole_archive_linker_params", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["%{linker_input_params}"], + iterate_over = "linker_input_params", + expand_if_available = "linker_input_params", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link", + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link.object_files", + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.object_files}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,%{libraries_to_link.object_files}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "interface_library", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "static_library", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["-l%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,-l%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "dynamic_library", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["-l:%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,-l:%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "versioned_dynamic_library", + ), + ), + ], + expand_if_available = "libraries_to_link", + ), + ], + ), + ], + ) + + per_object_debug_info_feature = feature( + name = "per_object_debug_info", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ], + flag_groups = [ + flag_group( + flags = ["-gsplit-dwarf", "-g"], + expand_if_available = "per_object_debug_info_file", + ), + ], + ), + ], + ) + + lipo_feature = feature( + name = "lipo", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-fripa"])], + ), + ], + requires = [ + feature_set(features = ["autofdo"]), + feature_set(features = ["fdo_optimize"]), + feature_set(features = ["fdo_instrument"]), + ], + ) + + apple_env_feature = feature( + name = "apple_env", + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + "objc-fully-link", + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + "objc-executable", + ACTION_NAMES.linkstamp_compile, + ], + env_entries = [ + env_entry( + key = "XCODE_VERSION_OVERRIDE", + value = "%{xcode_version_override_value}", + ), + env_entry( + key = "APPLE_SDK_VERSION_OVERRIDE", + value = "%{apple_sdk_version_override_value}", + ), + env_entry( + key = "APPLE_SDK_PLATFORM", + value = "%{apple_sdk_platform_value}", + ), + env_entry( + key = "ZERO_AR_DATE", + value = "1", + ), + ] + [env_entry(key = key, value = value) for key, value in ctx.attr.extra_env.items()], + ), + ], + ) + + if (ctx.attr.cpu == "ios_arm64" or + ctx.attr.cpu == "ios_arm64e" or + ctx.attr.cpu == "ios_armv7" or + ctx.attr.cpu == "ios_i386" or + ctx.attr.cpu == "ios_x86_64" or + ctx.attr.cpu == "ios_sim_arm64" or + ctx.attr.cpu == "tvos_arm64" or + ctx.attr.cpu == "tvos_x86_64" or + ctx.attr.cpu == "tvos_sim_arm64" or + ctx.attr.cpu == "watchos_arm64_32" or + ctx.attr.cpu == "watchos_armv7k" or + ctx.attr.cpu == "watchos_i386" or + ctx.attr.cpu == "watchos_x86_64" or + ctx.attr.cpu == "watchos_arm64"): + apply_implicit_frameworks_feature = feature( + name = "apply_implicit_frameworks", + flag_sets = [ + flag_set( + actions = ["objc-executable"], + flag_groups = [ + flag_group( + flags = ["-framework", "Foundation", "-framework", "UIKit"], + ), + ], + ), + ], + ) + elif (ctx.attr.cpu == "darwin_x86_64" or + ctx.attr.cpu == "darwin_arm64" or + ctx.attr.cpu == "darwin_arm64e"): + apply_implicit_frameworks_feature = feature( + name = "apply_implicit_frameworks", + flag_sets = [ + flag_set( + actions = ["objc-executable"], + flag_groups = [flag_group(flags = ["-framework", "Foundation"])], + with_features = [with_feature_set(not_features = ["kernel_extension"])], + ), + ], + ) + else: + apply_implicit_frameworks_feature = None + + dbg_feature = feature(name = "dbg") + + has_configured_linker_path_feature = feature(name = "has_configured_linker_path") + + random_seed_feature = feature( + name = "random_seed", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["-frandom-seed=%{output_file}"], + expand_if_available = "output_file", + ), + ], + ), + ], + ) + + llvm_coverage_map_format_feature = feature( + name = "llvm_coverage_map_format", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-fprofile-instr-generate", "-fcoverage-mapping", "-g"], + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + "objc-executable", + ], + flag_groups = [flag_group(flags = ["-fprofile-instr-generate"])], + ), + ], + requires = [feature_set(features = ["coverage"])], + ) + + force_pic_flags_feature = feature( + name = "force_pic_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_link_executable], + flag_groups = [ + flag_group( + flags = ["-Wl,-pie"], + expand_if_available = "force_pic", + ), + ], + ), + ], + ) + + sysroot_feature = feature( + name = "sysroot", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.clif_match, + ], + flag_groups = [ + flag_group( + flags = ["--sysroot=%{sysroot}"], + expand_if_available = "sysroot", + ), + ], + ), + ], + ) + + autofdo_feature = feature( + name = "autofdo", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-fauto-profile=%{fdo_profile_path}", + "-fprofile-correction", + ], + expand_if_available = "fdo_profile_path", + ), + ], + ), + ], + provides = ["profile"], + ) + + link_libcpp_feature = feature( + name = "link_libc++", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions + ["objc-executable"], + flag_groups = [flag_group(flags = ["-lc++"])], + with_features = [with_feature_set(not_features = ["kernel_extension"])], + ), + ], + ) + + objc_actions_feature = feature( + name = "objc_actions", + implies = [ + "objc-compile", + "objc-fully-link", + "objc-executable", + "assemble", + "preprocess-assemble", + "c-compile", + "c++-compile", + "c++-link-static-library", + "c++-link-dynamic-library", + "c++-link-nodeps-dynamic-library", + "c++-link-executable", + ], + ) + + module_maps_feature = feature(name = "module_maps", enabled = True) + + unfiltered_compile_flags_feature = feature( + name = "unfiltered_compile_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.linkstamp_compile, + ], + flag_groups = [ + flag_group( + flags = [ + "-no-canonical-prefixes", + "-Wno-builtin-macro-redefined", + "-D__DATE__=\"redacted\"", + "-D__TIMESTAMP__=\"redacted\"", + "-D__TIME__=\"redacted\"", + "-target", + target_system_name, + ], + ), + ], + ), + ], + ) + + linker_param_file_feature = feature( + name = "linker_param_file", + flag_sets = [ + flag_set( + actions = all_link_actions + [ + ACTION_NAMES.cpp_link_static_library, + ACTION_NAMES.objc_fully_link, + ACTION_NAMES.objc_executable, + ], + flag_groups = [ + flag_group( + flags = ["@%{linker_param_file}"], + expand_if_available = "linker_param_file", + ), + ], + ), + ], + ) + + relative_ast_path_feature = feature( + name = "relative_ast_path", + env_sets = [ + env_set( + actions = all_link_actions + [ + ACTION_NAMES.objc_executable, + ], + env_entries = [ + env_entry( + key = "RELATIVE_AST_PATH", + value = "true", + ), + ], + ), + ], + ) + + archiver_flags_feature = feature( + name = "archiver_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = _deterministic_libtool_flags(ctx) + [ + "-no_warning_for_no_symbols", + "-static", + "-o", + "%{output_execpath}", + ], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + fdo_optimize_feature = feature( + name = "fdo_optimize", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-fprofile-use=%{fdo_profile_path}", + "-Wno-profile-instr-unprofiled", + "-Wno-profile-instr-out-of-date", + "-fprofile-correction", + ], + expand_if_available = "fdo_profile_path", + ), + ], + ), + ], + provides = ["profile"], + ) + + no_objc_arc_feature = feature( + name = "no_objc_arc", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-fno-objc-arc"], + expand_if_available = "no_objc_arc", + ), + ], + ), + ], + ) + + cpp_linker_flags_feature = feature( + name = "cpp_linker_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["-lc++", "-target", target_system_name], + ), + ], + ), + ], + ) + + exclude_private_headers_in_module_maps_feature = feature(name = "exclude_private_headers_in_module_maps") + + debug_prefix_map_pwd_is_dot_feature = feature( + name = "debug_prefix_map_pwd_is_dot", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [flag_group(flags = ["DEBUG_PREFIX_MAP_PWD=."])], + ), + ], + ) + + remap_xcode_path_feature = feature( + name = "remap_xcode_path", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [flag_group(flags = [ + "-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=DEVELOPER_DIR", + ])], + ), + ], + ) + + linkstamps_feature = feature( + name = "linkstamps", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{linkstamp_paths}"], + iterate_over = "linkstamp_paths", + expand_if_available = "linkstamp_paths", + ), + ], + ), + ], + ) + + include_paths_feature = feature( + name = "include_paths", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.clif_match, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-iquote", "%{quote_include_paths}"], + iterate_over = "quote_include_paths", + ), + flag_group( + flags = ["-I%{include_paths}"], + iterate_over = "include_paths", + ), + flag_group( + flags = ["-isystem", "%{system_include_paths}"], + iterate_over = "system_include_paths", + ), + ], + ), + ], + ) + + only_doth_headers_in_module_maps_feature = feature(name = "only_doth_headers_in_module_maps") + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = [ + "-D_FORTIFY_SOURCE=1", + ], + ), + ], + with_features = [with_feature_set(not_features = ["asan"])], + ), + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = [ + "-fstack-protector", + "-fcolor-diagnostics", + "-Wall", + "-Wthread-safety", + "-Wself-assign", + "-fno-omit-frame-pointer", + ], + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [flag_group(flags = ["-O0", "-DDEBUG"])], + with_features = [with_feature_set(features = ["fastbuild"])], + ), + flag_set( + actions = all_compile_actions, + flag_groups = [ + flag_group( + flags = [ + "-g0", + "-O2", + "-DNDEBUG", + "-DNS_BLOCK_ASSERTIONS=1", + ], + ), + ], + with_features = [with_feature_set(features = ["opt"])], + ), + flag_set( + actions = all_compile_actions, + flag_groups = [flag_group(flags = ["-g"])], + with_features = [with_feature_set(features = ["dbg"])], + ), + flag_set( + actions = [ + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = [flag_group(flags = ["-std=c++11"])], + ), + ], + ) + + objcopy_embed_flags_feature = feature( + name = "objcopy_embed_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = ["objcopy_embed_data"], + flag_groups = [flag_group(flags = ["-I", "binary"])], + ), + ], + ) + + dead_strip_feature = feature( + name = "dead_strip", + flag_sets = [ + flag_set( + actions = all_link_actions + ["objc-executable"], + flag_groups = [ + flag_group( + flags = ["-dead_strip"], + ), + ], + ), + ], + requires = [feature_set(features = ["opt"])], + ) + + oso_prefix_feature = feature( + name = "oso_prefix_is_pwd", + flag_sets = [ + flag_set( + actions = all_link_actions + ["objc-executable"], + flag_groups = [flag_group(flags = ["OSO_PREFIX_MAP_PWD"])], + ), + ], + ) + + generate_dsym_file_feature = feature( + name = "generate_dsym_file", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + "objc-executable", + ], + flag_groups = [flag_group(flags = ["-g"])], + ), + flag_set( + actions = ["objc-executable"], + flag_groups = [ + flag_group( + flags = [ + "DSYM_HINT_LINKED_BINARY=%{linked_binary}", + "DSYM_HINT_DSYM_PATH=%{dsym_path}", + ], + ), + ], + ), + ], + ) + + # Kernel extensions for Apple Silicon are arm64e. + if (ctx.attr.cpu == "darwin_x86_64" or + ctx.attr.cpu == "darwin_arm64e"): + kernel_extension_feature = feature( + name = "kernel_extension", + flag_sets = [ + flag_set( + actions = ["objc-executable"], + flag_groups = [ + flag_group( + flags = [ + "-nostdlib", + "-lkmod", + "-lkmodc++", + "-lcc_kext", + "-Xlinker", + "-kext", + ], + ), + ], + ), + ], + ) + else: + kernel_extension_feature = feature(name = "kernel_extension") + + apply_default_warnings_feature = feature( + name = "apply_default_warnings", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.objc_compile, ACTION_NAMES.objcpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-Wshorten-64-to-32", + "-Wbool-conversion", + "-Wconstant-conversion", + "-Wduplicate-method-match", + "-Wempty-body", + "-Wenum-conversion", + "-Wint-conversion", + "-Wunreachable-code", + "-Wmismatched-return-types", + "-Wundeclared-selector", + "-Wuninitialized", + "-Wunused-function", + "-Wunused-variable", + ], + ), + ], + ), + ], + ) + + dependency_file_feature = feature( + name = "dependency_file", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ACTION_NAMES.cpp_header_parsing, + ], + flag_groups = [ + flag_group( + flags = ["-MD", "-MF", "%{dependency_file}"], + expand_if_available = "dependency_file", + ), + ], + ), + ], + ) + + serialized_diagnostics_file_feature = feature( + name = "serialized_diagnostics_file", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ACTION_NAMES.cpp_header_parsing, + ], + flag_groups = [ + flag_group( + flags = ["--serialize-diagnostics", "%{serialized_diagnostics_file}"], + expand_if_available = "serialized_diagnostics_file", + ), + ], + ), + ], + ) + + preprocessor_defines_feature = feature( + name = "preprocessor_defines", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["-D%{preprocessor_defines}"], + iterate_over = "preprocessor_defines", + ), + ], + ), + ], + ) + + fdo_instrument_feature = feature( + name = "fdo_instrument", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [ + flag_group( + flags = [ + "-fprofile-generate=%{fdo_instrument_path}", + "-fno-data-sections", + ], + expand_if_available = "fdo_instrument_path", + ), + ], + ), + ], + provides = ["profile"], + ) + + if (ctx.attr.cpu == "darwin_x86_64" or + ctx.attr.cpu == "darwin_arm64" or + ctx.attr.cpu == "darwin_arm64e"): + link_cocoa_feature = feature( + name = "link_cocoa", + flag_sets = [ + flag_set( + actions = ["objc-executable"], + flag_groups = [flag_group(flags = ["-framework", "Cocoa"])], + ), + ], + ) + else: + link_cocoa_feature = feature(name = "link_cocoa") + + user_compile_flags_feature = feature( + name = "user_compile_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ) + + headerpad_feature = feature( + name = "headerpad", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions + [ + ACTION_NAMES.objc_executable, + ], + flag_groups = [flag_group(flags = ["-headerpad_max_install_names"])], + with_features = [with_feature_set(not_features = [ + "bitcode_embedded", + "bitcode_embedded_markers", + ])], + ), + ], + ) + + if (ctx.attr.cpu == "ios_arm64" or + ctx.attr.cpu == "ios_arm64e" or + ctx.attr.cpu == "ios_armv7" or + ctx.attr.cpu == "tvos_arm64" or + ctx.attr.cpu == "watchos_arm64_32" or + ctx.attr.cpu == "watchos_armv7k" or + ctx.attr.cpu == "darwin_x86_64" or + ctx.attr.cpu == "darwin_arm64" or + ctx.attr.cpu == "darwin_arm64e"): + bitcode_embedded_feature = feature( + name = "bitcode_embedded", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [flag_group(flags = ["-fembed-bitcode"])], + ), + flag_set( + actions = all_link_actions + [ + ACTION_NAMES.objc_executable, + ], + flag_groups = [ + flag_group( + flags = [ + "-fembed-bitcode", + "-Xlinker", + "-bitcode_verify", + "-Xlinker", + "-bitcode_hide_symbols", + "-Xlinker", + "-bitcode_symbol_map", + "-Xlinker", + "%{bitcode_symbol_map_path}", + ], + expand_if_available = "bitcode_symbol_map_path", + ), + ], + ), + ], + ) + bitcode_embedded_markers_feature = feature( + name = "bitcode_embedded_markers", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [flag_group(flags = ["-fembed-bitcode-marker"])], + ), + flag_set( + actions = all_link_actions + [ + ACTION_NAMES.objc_executable, + ], + flag_groups = [flag_group(flags = ["-fembed-bitcode-marker"])], + ), + ], + ) + else: + bitcode_embedded_markers_feature = feature(name = "bitcode_embedded_markers") + bitcode_embedded_feature = feature(name = "bitcode_embedded") + + generate_linkmap_feature = feature( + name = "generate_linkmap", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.objc_executable, + ], + flag_groups = [ + flag_group( + flags = [ + "-Xlinker", + "-map", + "-Xlinker", + "%{linkmap_exec_path}", + ], + ), + ], + ), + ], + ) + + set_install_name = feature( + name = "set_install_name", + enabled = ctx.fragments.cpp.do_not_use_macos_set_install_name, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = [ + "-Wl,-install_name,@rpath/%{runtime_solib_name}", + ], + expand_if_available = "runtime_solib_name", + ), + ], + ), + ], + ) + + asan_feature = feature( + name = "asan", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group(flags = ["-fsanitize=address"]), + ], + with_features = [ + with_feature_set(features = ["asan"]), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.objc_executable, + ], + flag_groups = [ + flag_group(flags = ["-fsanitize=address"]), + ], + with_features = [ + with_feature_set(features = ["asan"]), + ], + ), + ], + ) + + tsan_feature = feature( + name = "tsan", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group(flags = ["-fsanitize=thread"]), + ], + with_features = [ + with_feature_set(features = ["tsan"]), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.objc_executable, + ], + flag_groups = [ + flag_group(flags = ["-fsanitize=thread"]), + ], + with_features = [ + with_feature_set(features = ["tsan"]), + ], + ), + ], + ) + + ubsan_feature = feature( + name = "ubsan", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group(flags = ["-fsanitize=undefined"]), + ], + with_features = [ + with_feature_set(features = ["ubsan"]), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.objc_executable, + ], + flag_groups = [ + flag_group(flags = ["-fsanitize=undefined"]), + ], + with_features = [ + with_feature_set(features = ["ubsan"]), + ], + ), + ], + ) + + default_sanitizer_flags_feature = feature( + name = "default_sanitizer_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.objc_compile, + ACTION_NAMES.objcpp_compile, + ], + flag_groups = [ + flag_group( + flags = [ + "-gline-tables-only", + "-fno-omit-frame-pointer", + "-fno-sanitize-recover=all", + ], + ), + ], + with_features = [ + with_feature_set(features = ["asan"]), + with_feature_set(features = ["tsan"]), + with_feature_set(features = ["ubsan"]), + ], + ), + ], + ) + + archive_param_file_feature = feature(name = "archive_param_file") + + if (ctx.attr.cpu == "ios_arm64" or + ctx.attr.cpu == "ios_arm64e" or + ctx.attr.cpu == "ios_armv7" or + ctx.attr.cpu == "ios_i386" or + ctx.attr.cpu == "ios_x86_64" or + ctx.attr.cpu == "ios_sim_arm64" or + ctx.attr.cpu == "tvos_arm64" or + ctx.attr.cpu == "tvos_x86_64" or + ctx.attr.cpu == "tvos_sim_arm64" or + ctx.attr.cpu == "watchos_arm64_32" or + ctx.attr.cpu == "watchos_armv7k" or + ctx.attr.cpu == "watchos_i386" or + ctx.attr.cpu == "watchos_x86_64" or + ctx.attr.cpu == "watchos_arm64"): + features = [ + fastbuild_feature, + no_legacy_features_feature, + opt_feature, + dbg_feature, + link_libcpp_feature, + compile_all_modules_feature, + exclude_private_headers_in_module_maps_feature, + has_configured_linker_path_feature, + only_doth_headers_in_module_maps_feature, + default_compile_flags_feature, + debug_prefix_map_pwd_is_dot_feature, + remap_xcode_path_feature, + generate_dsym_file_feature, + generate_linkmap_feature, + oso_prefix_feature, + contains_objc_source_feature, + objc_actions_feature, + strip_debug_symbols_feature, + shared_flag_feature, + kernel_extension_feature, + linkstamps_feature, + output_execpath_flags_feature, + archiver_flags_feature, + runtime_root_flags_feature, + input_param_flags_feature, + force_pic_flags_feature, + pch_feature, + module_maps_feature, + apply_default_warnings_feature, + includes_feature, + include_paths_feature, + sysroot_feature, + dependency_file_feature, + serialized_diagnostics_file_feature, + pic_feature, + per_object_debug_info_feature, + preprocessor_defines_feature, + framework_paths_feature, + random_seed_feature, + fdo_instrument_feature, + fdo_optimize_feature, + autofdo_feature, + lipo_feature, + coverage_feature, + llvm_coverage_map_format_feature, + gcc_coverage_map_format_feature, + apply_default_compiler_flags_feature, + include_system_dirs_feature, + headerpad_feature, + bitcode_embedded_feature, + bitcode_embedded_markers_feature, + objc_arc_feature, + no_objc_arc_feature, + apple_env_feature, + relative_ast_path_feature, + user_link_flags_feature, + default_link_flags_feature, + no_deduplicate_feature, + dead_strip_feature, + cpp_linker_flags_feature, + apply_implicit_frameworks_feature, + link_cocoa_feature, + apply_simulator_compiler_flags_feature, + unfiltered_cxx_flags_feature, + user_compile_flags_feature, + unfiltered_compile_flags_feature, + linker_param_file_feature, + compiler_input_flags_feature, + compiler_output_flags_feature, + objcopy_embed_flags_feature, + set_install_name, + asan_feature, + tsan_feature, + ubsan_feature, + default_sanitizer_flags_feature, + archive_param_file_feature, + ] + elif (ctx.attr.cpu == "darwin_x86_64" or + ctx.attr.cpu == "darwin_arm64" or + ctx.attr.cpu == "darwin_arm64e"): + features = [ + fastbuild_feature, + no_legacy_features_feature, + opt_feature, + dbg_feature, + link_libcpp_feature, + compile_all_modules_feature, + exclude_private_headers_in_module_maps_feature, + has_configured_linker_path_feature, + only_doth_headers_in_module_maps_feature, + default_compile_flags_feature, + debug_prefix_map_pwd_is_dot_feature, + remap_xcode_path_feature, + generate_dsym_file_feature, + generate_linkmap_feature, + oso_prefix_feature, + contains_objc_source_feature, + objc_actions_feature, + strip_debug_symbols_feature, + shared_flag_feature, + kernel_extension_feature, + linkstamps_feature, + output_execpath_flags_feature, + archiver_flags_feature, + runtime_root_flags_feature, + input_param_flags_feature, + force_pic_flags_feature, + pch_feature, + module_maps_feature, + apply_default_warnings_feature, + includes_feature, + include_paths_feature, + sysroot_feature, + dependency_file_feature, + serialized_diagnostics_file_feature, + pic_feature, + per_object_debug_info_feature, + preprocessor_defines_feature, + framework_paths_feature, + random_seed_feature, + fdo_instrument_feature, + fdo_optimize_feature, + autofdo_feature, + lipo_feature, + coverage_feature, + llvm_coverage_map_format_feature, + gcc_coverage_map_format_feature, + apply_default_compiler_flags_feature, + include_system_dirs_feature, + headerpad_feature, + bitcode_embedded_feature, + bitcode_embedded_markers_feature, + objc_arc_feature, + no_objc_arc_feature, + apple_env_feature, + relative_ast_path_feature, + user_link_flags_feature, + default_link_flags_feature, + no_deduplicate_feature, + dead_strip_feature, + cpp_linker_flags_feature, + apply_implicit_frameworks_feature, + link_cocoa_feature, + apply_simulator_compiler_flags_feature, + unfiltered_cxx_flags_feature, + user_compile_flags_feature, + unfiltered_compile_flags_feature, + linker_param_file_feature, + compiler_input_flags_feature, + compiler_output_flags_feature, + objcopy_embed_flags_feature, + dynamic_linking_mode_feature, + set_install_name, + asan_feature, + tsan_feature, + ubsan_feature, + default_sanitizer_flags_feature, + archive_param_file_feature, + ] + else: + fail("Unreachable") + + # macOS artifact name patterns differ from the defaults only for dynamic + # libraries. + artifact_name_patterns = [ + artifact_name_pattern( + category_name = "dynamic_library", + prefix = "lib", + extension = ".dylib", + ), + ] + + make_variables = [ + make_variable( + name = "STACK_FRAME_UNLIMITED", + value = "-Wframe-larger-than=100000000 -Wno-vla", + ), + ] + + tool_paths = { + "ar": "libtool", + "cpp": "/usr/bin/cpp", + "dwp": "/usr/bin/dwp", + "gcc": "cc_wrapper.sh", + "gcov": "/usr/bin/gcov", + "ld": "/usr/bin/ld", + "nm": "/usr/bin/nm", + "objcopy": "/usr/bin/objcopy", + "objdump": "/usr/bin/objdump", + "strip": "/usr/bin/strip", + } + + tool_paths.update(ctx.attr.tool_paths_overrides) + + out = ctx.actions.declare_file(ctx.label.name) + ctx.actions.write(out, "Fake executable") + return [ + cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = ctx.attr.cxx_builtin_include_directories, + toolchain_identifier = ctx.attr.cpu, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = ctx.attr.cpu, + target_libc = target_libc, + compiler = ctx.attr.compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = [tool_path(name = name, path = path) for (name, path) in tool_paths.items()], + make_variables = make_variables, + builtin_sysroot = None, + cc_target_os = "apple", + ), + DefaultInfo( + executable = out, + ), + ] + +cc_toolchain_config = rule( + implementation = _impl, + attrs = { + "cpu": attr.string(mandatory = True), + "compiler": attr.string(), + "cxx_builtin_include_directories": attr.string_list(), + "tool_paths_overrides": attr.string_dict(), + "extra_env": attr.string_dict(), + "_xcode_config": attr.label(default = configuration_field( + fragment = "apple", + name = "xcode_config_label", + )), + }, + provides = [CcToolchainConfigInfo], + executable = True, + fragments = ["apple", "cpp"], +) diff --git a/tools/osx/crosstool/osx_archs.bzl b/tools/osx/crosstool/osx_archs.bzl new file mode 100644 index 00000000000000..aeb82ac6953cb7 --- /dev/null +++ b/tools/osx/crosstool/osx_archs.bzl @@ -0,0 +1,38 @@ +"""Information regarding crosstool-supported architectures.""" +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# 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. + +# List of architectures supported by osx crosstool. +OSX_TOOLS_NON_DEVICE_ARCHS = [ + "darwin_x86_64", + "darwin_arm64", + "darwin_arm64e", + "ios_i386", + "ios_x86_64", + "ios_sim_arm64", + "watchos_arm64", + "watchos_i386", + "watchos_x86_64", + "tvos_x86_64", + "tvos_sim_arm64", +] + +OSX_TOOLS_ARCHS = [ + "ios_armv7", + "ios_arm64", + "ios_arm64e", + "watchos_armv7k", + "watchos_arm64_32", + "tvos_arm64", +] + OSX_TOOLS_NON_DEVICE_ARCHS diff --git a/tools/osx/crosstool/wrapped_clang.cc b/tools/osx/crosstool/wrapped_clang.cc new file mode 100644 index 00000000000000..044c0c8f51f916 --- /dev/null +++ b/tools/osx/crosstool/wrapped_clang.cc @@ -0,0 +1,429 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// 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. +// +// wrapped_clang.cc: Pass args to 'xcrun clang' and zip dsym files. +// +// wrapped_clang passes its args to clang, but also supports a separate set of +// invocations to generate dSYM files. If "DSYM_HINT" flags are passed in, they +// are used to construct that separate set of invocations (instead of being +// passed to clang). +// The following "DSYM_HINT" flags control dsym generation. If any one if these +// are passed in, then they all must be passed in. +// "DSYM_HINT_LINKED_BINARY": Workspace-relative path to binary output of the +// link action generating the dsym file. +// "DSYM_HINT_DSYM_PATH": Workspace-relative path to dSYM dwarf file. + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char **environ; + +namespace { + +constexpr char kAddASTPathPrefix[] = "-Wl,-add_ast_path,"; + +// Returns the base name of the given filepath. For example, given +// /foo/bar/baz.txt, returns 'baz.txt'. +const char *Basename(const char *filepath) { + const char *base = strrchr(filepath, '/'); + return base ? (base + 1) : filepath; +} + +// Unescape and unquote an argument read from a line of a response file. +static std::string Unescape(const std::string &arg) { + std::string result; + auto length = arg.size(); + for (size_t i = 0; i < length; ++i) { + auto ch = arg[i]; + + // If it's a backslash, consume it and append the character that follows. + if (ch == '\\' && i + 1 < length) { + ++i; + result.push_back(arg[i]); + continue; + } + + // If it's a quote, process everything up to the matching quote, unescaping + // backslashed characters as needed. + if (ch == '"' || ch == '\'') { + auto quote = ch; + ++i; + while (i != length && arg[i] != quote) { + if (arg[i] == '\\' && i + 1 < length) { + ++i; + } + result.push_back(arg[i]); + ++i; + } + if (i == length) { + break; + } + continue; + } + + // It's a regular character. + result.push_back(ch); + } + + return result; +} + +// Converts an array of string arguments to char *arguments. +// The first arg is reduced to its basename as per execve conventions. +// Note that the lifetime of the char* arguments in the returned array +// are controlled by the lifetime of the strings in args. +std::vector ConvertToCArgs(const std::vector &args) { + std::vector c_args; + c_args.push_back(Basename(args[0].c_str())); + for (int i = 1; i < args.size(); i++) { + c_args.push_back(args[i].c_str()); + } + c_args.push_back(nullptr); + return c_args; +} + +// Spawns a subprocess for given arguments args. The first argument is used +// for the executable path. +bool RunSubProcess(const std::vector &args) { + std::vector exec_argv = ConvertToCArgs(args); + pid_t pid; + int status = posix_spawn(&pid, args[0].c_str(), nullptr, nullptr, + const_cast(exec_argv.data()), environ); + if (status == 0) { + int wait_status; + do { + wait_status = waitpid(pid, &status, 0); + } while ((wait_status == -1) && (errno == EINTR)); + if (wait_status < 0) { + std::cerr << "Error waiting on child process '" << args[0] << "'. " + << strerror(errno) << "\n"; + return false; + } + if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { + std::cerr << "Error in child process '" << args[0] << "'. " + << WEXITSTATUS(status) << "\n"; + return false; + } else if (WIFSIGNALED(status)) { + std::cerr << "Error in child process '" << args[0] << "'. " + << WTERMSIG(status) << "\n"; + return false; + } + } else { + std::cerr << "Error forking process '" << args[0] << "'. " + << strerror(status) << "\n"; + return false; + } + + return true; +} + +// Finds and replaces all instances of oldsub with newsub, in-place on str. +void FindAndReplace(const std::string &oldsub, const std::string &newsub, + std::string *str) { + int start = 0; + while ((start = str->find(oldsub, start)) != std::string::npos) { + str->replace(start, oldsub.length(), newsub); + start += newsub.length(); + } +} + +// If arg is of the classic flag form "foo=bar", and flagname is 'foo', sets +// str to point to a new std::string 'bar' and returns true. +// Otherwise, returns false. +bool SetArgIfFlagPresent(const std::string &arg, const std::string &flagname, + std::string *str) { + std::string prefix_string = flagname + "="; + if (arg.compare(0, prefix_string.length(), prefix_string) == 0) { + *str = arg.substr(prefix_string.length()); + return true; + } + return false; +} + +// Returns the DEVELOPER_DIR environment variable in the current process +// environment. Aborts if this variable is unset. +std::string GetMandatoryEnvVar(const std::string &var_name) { + char *env_value = getenv(var_name.c_str()); + if (env_value == nullptr) { + std::cerr << "Error: " << var_name << " not set.\n"; + exit(EXIT_FAILURE); + } + return env_value; +} + +// Returns true if `str` starts with the specified `prefix`. +bool StartsWith(const std::string &str, const std::string &prefix) { + return str.compare(0, prefix.size(), prefix) == 0; +} + +// If *`str` begins `prefix`, strip it out and return true. +// Otherwise leave *`str` unchanged and return false. +bool StripPrefixStringIfPresent(std::string *str, const std::string &prefix) { + if (StartsWith(*str, prefix)) { + *str = str->substr(prefix.size()); + return true; + } + return false; +} + +// An RAII temporary file. +class TempFile { + public: + // Create a new temporary file using the given path template string (the same + // form used by `mkstemp`). The file will automatically be deleted when the + // object goes out of scope. + static std::unique_ptr Create(const std::string &path_template) { + const char *tmpDir = getenv("TMPDIR"); + if (!tmpDir) { + tmpDir = "/tmp"; + } + size_t size = strlen(tmpDir) + path_template.size() + 2; + std::unique_ptr path(new char[size]); + snprintf(path.get(), size, "%s/%s", tmpDir, path_template.c_str()); + + if (mkstemp(path.get()) == -1) { + std::cerr << "Failed to create temporary file '" << path.get() + << "': " << strerror(errno) << "\n"; + return nullptr; + } + return std::unique_ptr(new TempFile(path.get())); + } + + // Explicitly make TempFile non-copyable and movable. + TempFile(const TempFile &) = delete; + TempFile &operator=(const TempFile &) = delete; + TempFile(TempFile &&) = default; + TempFile &operator=(TempFile &&) = default; + + ~TempFile() { remove(path_.c_str()); } + + // Gets the path to the temporary file. + std::string GetPath() const { return path_; } + + private: + explicit TempFile(const std::string &path) : path_(path) {} + + std::string path_; +}; + +static std::unique_ptr WriteResponseFile( + const std::vector &args) { + auto response_file = TempFile::Create("wrapped_clang_params.XXXXXX"); + std::ofstream response_file_stream(response_file->GetPath()); + + for (const auto &arg : args) { + // When Clang/Swift write out a response file to communicate from driver to + // frontend, they just quote every argument to be safe; we duplicate that + // instead of trying to be "smarter" and only quoting when necessary. + response_file_stream << '"'; + for (auto ch : arg) { + if (ch == '"' || ch == '\\') { + response_file_stream << '\\'; + } + response_file_stream << ch; + } + response_file_stream << "\"\n"; + } + + response_file_stream.close(); + return response_file; +} + +void ProcessArgument(const std::string arg, const std::string developer_dir, + const std::string sdk_root, const std::string cwd, + bool relative_ast_path, std::string &linked_binary, + std::string &dsym_path, + std::function consumer); + +bool ProcessResponseFile(const std::string arg, const std::string developer_dir, + const std::string sdk_root, const std::string cwd, + bool relative_ast_path, std::string &linked_binary, + std::string &dsym_path, + std::function consumer) { + auto path = arg.substr(1); + std::ifstream original_file(path); + // Ignore non-file args such as '@loader_path/...' + if (!original_file.good()) { + return false; + } + + std::string arg_from_file; + while (std::getline(original_file, arg_from_file)) { + // Arguments in response files might be quoted/escaped, so we need to + // unescape them ourselves. + ProcessArgument(Unescape(arg_from_file), developer_dir, sdk_root, cwd, + relative_ast_path, linked_binary, dsym_path, consumer); + } + + return true; +} + +std::string GetCurrentDirectory() { + // Passing null,0 causes getcwd to allocate the buffer of the correct size. + char *buffer = getcwd(nullptr, 0); + std::string cwd(buffer); + free(buffer); + return cwd; +} + +void ProcessArgument(const std::string arg, const std::string developer_dir, + const std::string sdk_root, const std::string cwd, + bool relative_ast_path, std::string &linked_binary, + std::string &dsym_path, + std::function consumer) { + auto new_arg = arg; + if (arg[0] == '@') { + if (ProcessResponseFile(arg, developer_dir, sdk_root, cwd, + relative_ast_path, linked_binary, dsym_path, + consumer)) { + return; + } + } + + if (SetArgIfFlagPresent(arg, "DSYM_HINT_LINKED_BINARY", &linked_binary)) { + return; + } + if (SetArgIfFlagPresent(arg, "DSYM_HINT_DSYM_PATH", &dsym_path)) { + return; + } + + std::string dest_dir, bitcode_symbol_map; + if (SetArgIfFlagPresent(arg, "DEBUG_PREFIX_MAP_PWD", &dest_dir)) { + new_arg = "-fdebug-prefix-map=" + cwd + "=" + dest_dir; + } + if (arg.compare("OSO_PREFIX_MAP_PWD") == 0) { + new_arg = "-Wl,-oso_prefix," + cwd + "/"; + } + + FindAndReplace("__BAZEL_XCODE_DEVELOPER_DIR__", developer_dir, &new_arg); + FindAndReplace("__BAZEL_XCODE_SDKROOT__", sdk_root, &new_arg); + + // Make the `add_ast_path` options used to embed Swift module references + // absolute to enable Swift debugging without dSYMs: see + // https://forums.swift.org/t/improving-swift-lldb-support-for-path-remappings/22694 + if (!relative_ast_path && + StripPrefixStringIfPresent(&new_arg, kAddASTPathPrefix)) { + // Only modify relative paths. + if (!StartsWith(arg, "/")) { + new_arg = std::string(kAddASTPathPrefix) + cwd + "/" + new_arg; + } else { + new_arg = std::string(kAddASTPathPrefix) + new_arg; + } + } + + consumer(new_arg); +} + +} // namespace + +int main(int argc, char *argv[]) { + std::string tool_name; + + std::string binary_name = Basename(argv[0]); + if (binary_name == "wrapped_clang_pp") { + tool_name = "clang++"; + } else if (binary_name == "wrapped_clang") { + tool_name = "clang"; + } else { + std::cerr << "Binary must either be named 'wrapped_clang' or " + "'wrapped_clang_pp', not " + << binary_name << "\n"; + return 1; + } + + std::string developer_dir = GetMandatoryEnvVar("DEVELOPER_DIR"); + std::string sdk_root = GetMandatoryEnvVar("SDKROOT"); + std::string linked_binary, dsym_path; + + const std::string cwd = GetCurrentDirectory(); + std::vector invocation_args = {"/usr/bin/xcrun", tool_name}; + std::vector processed_args = {}; + + bool relative_ast_path = getenv("RELATIVE_AST_PATH") != nullptr; + auto consumer = [&](const std::string &arg) { + processed_args.push_back(arg); + }; + for (int i = 1; i < argc; i++) { + std::string arg(argv[i]); + + ProcessArgument(arg, developer_dir, sdk_root, cwd, relative_ast_path, + linked_binary, dsym_path, consumer); + } + + // Special mode that only prints the command. Used for testing. + if (getenv("__WRAPPED_CLANG_LOG_ONLY")) { + for (const std::string &arg : invocation_args) std::cout << arg << ' '; + for (const std::string &arg : processed_args) std::cout << arg << ' '; + std::cout << "\n"; + return 0; + } + + auto response_file = WriteResponseFile(processed_args); + invocation_args.push_back("@" + response_file->GetPath()); + + // Check to see if we should postprocess with dsymutil. + bool postprocess = false; + if ((!linked_binary.empty()) || (!dsym_path.empty())) { + if ((linked_binary.empty()) || (dsym_path.empty())) { + const char *missing_dsym_flag; + if (linked_binary.empty()) { + missing_dsym_flag = "DSYM_HINT_LINKED_BINARY"; + } else { + missing_dsym_flag = "DSYM_HINT_DSYM_PATH"; + } + std::cerr << "Error in clang wrapper: If any dsym " + "hint is defined, then " + << missing_dsym_flag << " must be defined\n"; + return 1; + } else { + postprocess = true; + } + } + + if (!RunSubProcess(invocation_args)) { + return 1; + } + + if (!postprocess) { + return 0; + } + + std::vector dsymutil_args = {"/usr/bin/xcrun", + "dsymutil", + linked_binary, + "-o", + dsym_path, + "--flat", + "--no-swiftmodule-timestamp"}; + if (!RunSubProcess(dsymutil_args)) { + return 1; + } + + return 0; +} diff --git a/tools/osx/crosstool/wrapped_clang_test.sh b/tools/osx/crosstool/wrapped_clang_test.sh new file mode 100755 index 00000000000000..484b2dc2d41e26 --- /dev/null +++ b/tools/osx/crosstool/wrapped_clang_test.sh @@ -0,0 +1,99 @@ +#!/bin/bash +# -*- coding: utf-8 -*- + +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# 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. + +# Unit tests for wrapped_clang. + +# --- begin runfiles.bash initialization --- +# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). +set -euo pipefail +if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then + if [[ -f "$0.runfiles_manifest" ]]; then + export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" + elif [[ -f "$0.runfiles/MANIFEST" ]]; then + export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" + elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then + export RUNFILES_DIR="$0.runfiles" + fi +fi +if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then + source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" +elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then + source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ + "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" +else + echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" + exit 1 +fi +# --- end runfiles.bash initialization --- + + +# Load test environment +source "$(rlocation "io_bazel/src/test/shell/unittest.bash")" \ + || { echo "unittest.bash not found!" >&2; exit 1; } +WRAPPED_CLANG=$(rlocation "io_bazel/tools/osx/crosstool/wrapped_clang") + + +# This env var tells wrapped_clang to log its command instead of running. +export __WRAPPED_CLANG_LOG_ONLY=1 + + +# Test that add_ast_path is remapped properly. +function test_add_ast_path_remapping() { + env DEVELOPER_DIR=dummy SDKROOT=a \ + "${WRAPPED_CLANG}" "-Wl,-add_ast_path,foo" >$TEST_log || fail "wrapped_clang failed"; + expect_log "-Wl,-add_ast_path,${PWD}/foo" "Expected add_ast_path to be remapped." +} + +function test_disable_add_ast_path_remapping() { + env RELATIVE_AST_PATH=isset DEVELOPER_DIR=dummy SDKROOT=a \ + "${WRAPPED_CLANG}" "-Wl,-add_ast_path,relative/foo" >$TEST_log || fail "wrapped_clang failed"; + expect_log "-Wl,-add_ast_path,relative/foo" "Expected add_ast_path to not be remapped." +} + +# Test that __BAZEL_XCODE_DEVELOPER_DIR__ is remapped properly. +function test_developer_dir_remapping() { + env DEVELOPER_DIR=mydir SDKROOT=a \ + "${WRAPPED_CLANG}" "developer_dir=__BAZEL_XCODE_DEVELOPER_DIR__" \ + >$TEST_log || fail "wrapped_clang failed"; + expect_log "developer_dir=mydir" "Expected developer dir to be remapped." +} + +# Test that __BAZEL_XCODE_SDKROOT__ is remapped properly. +function test_sdkroot_remapping() { + env DEVELOPER_DIR=dummy SDKROOT=mysdkroot \ + "${WRAPPED_CLANG}" "sdkroot=__BAZEL_XCODE_SDKROOT__" \ + >$TEST_log || fail "wrapped_clang failed"; + expect_log "sdkroot=mysdkroot" "Expected sdkroot to be remapped." +} + +function test_params_expansion() { + params=$(mktemp) + { + echo "first" + echo "-rpath" + echo "@loader_path" + echo "sdkroot=__BAZEL_XCODE_SDKROOT__" + echo "developer_dir=__BAZEL_XCODE_DEVELOPER_DIR__" + } > "$params" + + env DEVELOPER_DIR=dummy SDKROOT=mysdkroot \ + "${WRAPPED_CLANG}" "@$params" \ + >"$TEST_log" || fail "wrapped_clang failed"; + expect_log "/usr/bin/xcrun clang first -rpath @loader_path sdkroot=mysdkroot developer_dir=dummy" +} + +run_suite "Wrapped clang tests"