Skip to content

Commit e745468

Browse files
authored
Fix rpath for binaries in external repositories (bazelbuild#16079)
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 82452c7 commit e745468

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;
@@ -798,7 +799,8 @@ public CppLinkAction build() throws InterruptedException, RuleErrorException {
798799
allowLtoIndexing,
799800
nonExpandedLinkerInputs,
800801
needWholeArchive,
801-
ruleErrorConsumer);
802+
ruleErrorConsumer,
803+
((RuleContext) actionConstructionContext).getWorkspaceName());
802804
CollectedLibrariesToLink collectedLibrariesToLink =
803805
librariesToLinkCollector.collectLibrariesToLink();
804806

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

+17-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.common.collect.Iterables;
2121
import com.google.devtools.build.lib.actions.Artifact;
2222
import com.google.devtools.build.lib.analysis.RuleErrorConsumer;
23+
import com.google.devtools.build.lib.cmdline.LabelConstants;
2324
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
2425
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
2526
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-
Strings.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 = Strings.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 = Strings.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
@@ -3811,4 +3811,62 @@ EOF
38113811
expect_log "Executing genrule .* failed: (Exit 1):"
38123812
}
38133813

3814+
function test_external_cc_test() {
3815+
if [[ "$PLATFORM" == "darwin" ]]; then
3816+
# TODO(b/37355380): This test is disabled due to RemoteWorker not supporting
3817+
# setting SDKROOT and DEVELOPER_DIR appropriately, as is required of
3818+
# action executors in order to select the appropriate Xcode toolchain.
3819+
return 0
3820+
fi
3821+
3822+
cat >> WORKSPACE <<'EOF'
3823+
local_repository(
3824+
name = "other_repo",
3825+
path = "other_repo",
3826+
)
3827+
EOF
3828+
3829+
mkdir -p other_repo
3830+
touch other_repo/WORKSPACE
3831+
3832+
mkdir -p other_repo/lib
3833+
cat > other_repo/lib/BUILD <<'EOF'
3834+
cc_library(
3835+
name = "lib",
3836+
srcs = ["lib.cpp"],
3837+
hdrs = ["lib.h"],
3838+
visibility = ["//visibility:public"],
3839+
)
3840+
EOF
3841+
cat > other_repo/lib/lib.h <<'EOF'
3842+
void print_greeting();
3843+
EOF
3844+
cat > other_repo/lib/lib.cpp <<'EOF'
3845+
#include <cstdio>
3846+
void print_greeting() {
3847+
printf("Hello, world!\n");
3848+
}
3849+
EOF
3850+
3851+
mkdir -p other_repo/test
3852+
cat > other_repo/test/BUILD <<'EOF'
3853+
cc_test(
3854+
name = "test",
3855+
srcs = ["test.cpp"],
3856+
deps = ["//lib"],
3857+
)
3858+
EOF
3859+
cat > other_repo/test/test.cpp <<'EOF'
3860+
#include "lib/lib.h"
3861+
int main() {
3862+
print_greeting();
3863+
}
3864+
EOF
3865+
3866+
bazel test \
3867+
--test_output=errors \
3868+
--remote_executor=grpc://localhost:${worker_port} \
3869+
@other_repo//test >& $TEST_log || fail "Test should pass"
3870+
}
3871+
38143872
run_suite "Remote execution and remote cache tests"

0 commit comments

Comments
 (0)