Skip to content

Commit 95a5bfd

Browse files
fmeumcopybara-github
authored andcommitted
Fix rpath for binaries in external repositories
The solib directory is located within the subdirectory of the runfiles directory corresponding to the workspace. Thus, if a binary is contained in an external repository, its $ORIGIN relative rpath has to first ascend to the runfiles directory and then descend into the workspace directory. Fixes bazelbuild#16003 Closes bazelbuild#16008. PiperOrigin-RevId: 466634083 Change-Id: I4ada28b459f23f68a2091dbaad9147cfec2fbe43
1 parent 04e8b63 commit 95a5bfd

File tree

3 files changed

+78
-6
lines changed

3 files changed

+78
-6
lines changed

src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.devtools.build.lib.actions.ActionOwner;
2727
import com.google.devtools.build.lib.actions.Artifact;
2828
import com.google.devtools.build.lib.actions.ParameterFile;
29+
import com.google.devtools.build.lib.analysis.RuleContext;
2930
import com.google.devtools.build.lib.analysis.RuleErrorConsumer;
3031
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
3132
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
@@ -801,7 +802,8 @@ public CppLinkAction build() throws InterruptedException, RuleErrorException {
801802
allowLtoIndexing,
802803
nonExpandedLinkerInputs,
803804
needWholeArchive,
804-
ruleErrorConsumer);
805+
ruleErrorConsumer,
806+
((RuleContext) actionConstructionContext).getWorkspaceName());
805807
CollectedLibrariesToLink collectedLibrariesToLink =
806808
librariesToLinkCollector.collectLibrariesToLink();
807809

src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java

+17-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.google.common.collect.Iterables;
2020
import com.google.devtools.build.lib.actions.Artifact;
2121
import com.google.devtools.build.lib.analysis.RuleErrorConsumer;
22+
import com.google.devtools.build.lib.cmdline.LabelConstants;
2223
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
2324
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
2425
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
@@ -69,7 +70,8 @@ public LibrariesToLinkCollector(
6970
boolean allowLtoIndexing,
7071
Iterable<LinkerInput> linkerInputs,
7172
boolean needWholeArchive,
72-
RuleErrorConsumer ruleErrorConsumer) {
73+
RuleErrorConsumer ruleErrorConsumer,
74+
String workspaceName) {
7375
this.isNativeDeps = isNativeDeps;
7476
this.cppConfiguration = cppConfiguration;
7577
this.ccToolchainProvider = toolchain;
@@ -106,10 +108,20 @@ public LibrariesToLinkCollector(
106108
// there's no *one* RPATH setting that fits all targets involved in the sharing.
107109
rpathRoot = ccToolchainProvider.getSolibDirectory() + "/";
108110
} else {
109-
rpathRoot =
110-
"../".repeat(outputArtifact.getRootRelativePath().segmentCount() - 1)
111-
+ ccToolchainProvider.getSolibDirectory()
112-
+ "/";
111+
// When executed from within a runfiles directory, the binary lies under a path such as
112+
// target.runfiles/some_repo/pkg/file, whereas the solib directory is located under
113+
// target.runfiles/main_repo.
114+
PathFragment runfilesPath = outputArtifact.getRunfilesPath();
115+
String runfilesExecRoot;
116+
if (runfilesPath.startsWith(LabelConstants.EXTERNAL_RUNFILES_PATH_PREFIX)) {
117+
// runfilesPath is of the form ../some_repo/pkg/file, walk back some_repo/pkg and then
118+
// descend into the main workspace.
119+
runfilesExecRoot = "../".repeat(runfilesPath.segmentCount() - 2) + workspaceName + "/";
120+
} else {
121+
// runfilesPath is of the form pkg/file, walk back pkg to reach the main workspace.
122+
runfilesExecRoot = "../".repeat(runfilesPath.segmentCount() - 1);
123+
}
124+
rpathRoot = runfilesExecRoot + ccToolchainProvider.getSolibDirectory() + "/";
113125
}
114126

115127
ltoMap = generateLtoMap();

src/test/shell/bazel/remote/remote_execution_test.sh

+58
Original file line numberDiff line numberDiff line change
@@ -2906,4 +2906,62 @@ EOF
29062906
|| fail "Remote execution generated different result"
29072907
}
29082908

2909+
function test_external_cc_test() {
2910+
if [[ "$PLATFORM" == "darwin" ]]; then
2911+
# TODO(b/37355380): This test is disabled due to RemoteWorker not supporting
2912+
# setting SDKROOT and DEVELOPER_DIR appropriately, as is required of
2913+
# action executors in order to select the appropriate Xcode toolchain.
2914+
return 0
2915+
fi
2916+
2917+
cat >> WORKSPACE <<'EOF'
2918+
local_repository(
2919+
name = "other_repo",
2920+
path = "other_repo",
2921+
)
2922+
EOF
2923+
2924+
mkdir -p other_repo
2925+
touch other_repo/WORKSPACE
2926+
2927+
mkdir -p other_repo/lib
2928+
cat > other_repo/lib/BUILD <<'EOF'
2929+
cc_library(
2930+
name = "lib",
2931+
srcs = ["lib.cpp"],
2932+
hdrs = ["lib.h"],
2933+
visibility = ["//visibility:public"],
2934+
)
2935+
EOF
2936+
cat > other_repo/lib/lib.h <<'EOF'
2937+
void print_greeting();
2938+
EOF
2939+
cat > other_repo/lib/lib.cpp <<'EOF'
2940+
#include <cstdio>
2941+
void print_greeting() {
2942+
printf("Hello, world!\n");
2943+
}
2944+
EOF
2945+
2946+
mkdir -p other_repo/test
2947+
cat > other_repo/test/BUILD <<'EOF'
2948+
cc_test(
2949+
name = "test",
2950+
srcs = ["test.cpp"],
2951+
deps = ["//lib"],
2952+
)
2953+
EOF
2954+
cat > other_repo/test/test.cpp <<'EOF'
2955+
#include "lib/lib.h"
2956+
int main() {
2957+
print_greeting();
2958+
}
2959+
EOF
2960+
2961+
bazel test \
2962+
--test_output=errors \
2963+
--remote_executor=grpc://localhost:${worker_port} \
2964+
@other_repo//test >& $TEST_log || fail "Test should pass"
2965+
}
2966+
29092967
run_suite "Remote execution and remote cache tests"

0 commit comments

Comments
 (0)