Update wrapped_clang to make -add_ast_path options absolute
This should allow us to debug Swift binaries without using dSYMs.
See
https://forums.swift.org/t/improving-swift-lldb-support-for-path-remappings/22694
PiperOrigin-RevId: 244896679
diff --git a/.bazelci/postsubmit.yml b/.bazelci/postsubmit.yml
index c3ce4a7..5f4963a 100644
--- a/.bazelci/postsubmit.yml
+++ b/.bazelci/postsubmit.yml
@@ -183,6 +183,7 @@
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/aquery_differ/..."
+ - "//tools/osx/crosstool/..."
- "//tools/python/..."
- "-//src/test/shell/integration:minimal_jdk_test"
# C++ coverage is not supported on macOS yet.
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index d1759dd..eefe4a8 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -203,6 +203,7 @@
- "//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/tools/osx/crosstool/BUILD b/tools/osx/crosstool/BUILD
index bc74651..1695e6d 100644
--- a/tools/osx/crosstool/BUILD
+++ b/tools/osx/crosstool/BUILD
@@ -1,9 +1,33 @@
package(default_visibility = ["//visibility:public"])
-# Files which shouldn't be publicly visible and dependencies of all objc_* or ios_* rules shouldn't be in this package.
-exports_files(glob(["**"]))
+# 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(["**"]),
)
+
+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/wrapped_clang.cc b/tools/osx/crosstool/wrapped_clang.cc
index a087881..2115b8d 100644
--- a/tools/osx/crosstool/wrapped_clang.cc
+++ b/tools/osx/crosstool/wrapped_clang.cc
@@ -57,6 +57,8 @@
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) {
@@ -151,6 +153,21 @@
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;
+}
+
} // namespace
int main(int argc, char *argv[]) {
@@ -203,9 +220,31 @@
}
FindAndReplace("__BAZEL_XCODE_DEVELOPER_DIR__", developer_dir, &arg);
FindAndReplace("__BAZEL_XCODE_SDKROOT__", sdk_root, &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 (StripPrefixStringIfPresent(&arg, kAddASTPathPrefix)) {
+ // Only modify relative paths.
+ if (!StartsWith(arg, "/")) {
+ arg = std::string(kAddASTPathPrefix) +
+ std::string(cwd.get()) + "/" + arg;
+ } else {
+ arg = std::string(kAddASTPathPrefix) + arg;
+ }
+ }
+
processed_args.push_back(arg);
}
+ // Special mode that only prints the command. Used for testing.
+ if (getenv("__WRAPPED_CLANG_LOG_ONLY")) {
+ for (const std::string &arg : processed_args)
+ std::cout << arg << ' ';
+ std::cout << "\n";
+ return 0;
+ }
+
// Check to see if we should postprocess with dsymutil.
bool postprocess = false;
if ((!linked_binary.empty()) || (!dsym_path.empty())) {
diff --git a/tools/osx/crosstool/wrapped_clang_test.sh b/tools/osx/crosstool/wrapped_clang_test.sh
new file mode 100755
index 0000000..1b77d6b
--- /dev/null
+++ b/tools/osx/crosstool/wrapped_clang_test.sh
@@ -0,0 +1,77 @@
+#!/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."
+}
+
+# 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."
+}
+
+run_suite "Wrapped clang tests"