Skip to content

Commit

Permalink
Update wrapped_clang to make -add_ast_path options absolute
Browse files Browse the repository at this point in the history
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
  • Loading branch information
DavidGoldman authored and copybara-github committed Apr 23, 2019
1 parent e39e5c9 commit a8fa6e2
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 2 deletions.
1 change: 1 addition & 0 deletions .bazelci/postsubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ platforms:
- "//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.
Expand Down
1 change: 1 addition & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ platforms:
- "//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"
Expand Down
28 changes: 26 additions & 2 deletions tools/osx/crosstool/BUILD
Original file line number Diff line number Diff line change
@@ -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",
],
)
39 changes: 39 additions & 0 deletions tools/osx/crosstool/wrapped_clang.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ 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) {
Expand Down Expand Up @@ -151,6 +153,21 @@ std::string GetMandatoryEnvVar(const std::string &var_name) {
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[]) {
Expand Down Expand Up @@ -203,9 +220,31 @@ int main(int argc, char *argv[]) {
}
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())) {
Expand Down
77 changes: 77 additions & 0 deletions tools/osx/crosstool/wrapped_clang_test.sh
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit a8fa6e2

Please sign in to comment.