Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ test_suite(
"//clwb:headless_tests",
"//clwb:integration_tests",
"//clwb:unit_tests",
"//cpp:unit_tests",
"//cpp:unit_tests_suite",
"//dart:unit_tests",
"//python:unit_tests",
"//skylark:integration_tests",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.intellij.ideinfo.IntellijIdeInfo;
import com.google.idea.blaze.base.model.primitives.ExecutionRootPath;
import javax.annotation.Nullable;
Expand All @@ -35,6 +36,10 @@ public abstract class CToolchainIdeInfo implements ProtoWrapper<IntellijIdeInfo.

public abstract ExecutionRootPath cppCompiler();

public abstract ImmutableMap<String, String> cEnvironment();

public abstract ImmutableMap<String, String> cppEnvironment();

public abstract String targetName();

public abstract String compilerName();
Expand All @@ -51,6 +56,8 @@ static CToolchainIdeInfo fromProto(IntellijIdeInfo.CToolchainIdeInfo proto) {
.setTargetName(proto.getTargetName())
.setCompilerName(proto.getCompilerName())
.setSysroot(ExecutionRootPath.fromNullableProto(proto.getSysroot()))
.setCEnvironment(ImmutableMap.copyOf(proto.getCEnvironmentMap()))
.setCppEnvironment(ImmutableMap.copyOf(proto.getCppEnvironmentMap()))
.build();
}

Expand All @@ -63,7 +70,9 @@ public IntellijIdeInfo.CToolchainIdeInfo toProto() {
.setCCompiler(cCompiler().toProto())
.setCppCompiler(cppCompiler().toProto())
.setTargetName(targetName())
.setCompilerName(compilerName());
.setCompilerName(compilerName())
.putAllCEnvironment(cEnvironment())
.putAllCppEnvironment(cppEnvironment());

final var sysroot = sysroot();
if (sysroot != null) {
Expand All @@ -74,7 +83,9 @@ public IntellijIdeInfo.CToolchainIdeInfo toProto() {
}

public static Builder builder() {
return new AutoValue_CToolchainIdeInfo.Builder();
return new AutoValue_CToolchainIdeInfo.Builder()
.setCEnvironment(ImmutableMap.of())
.setCppEnvironment(ImmutableMap.of());
}

/**
Expand All @@ -99,6 +110,10 @@ public abstract static class Builder {

public abstract Builder setSysroot(@Nullable ExecutionRootPath value);

public abstract Builder setCEnvironment(ImmutableMap<String, String> value);

public abstract Builder setCppEnvironment(ImmutableMap<String, String> value);

public abstract CToolchainIdeInfo build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.idea.blaze.base.ideinfo.ProtoWrapper;
import com.intellij.openapi.util.io.FileUtil;
import java.io.File;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import javax.annotation.Nullable;

Expand All @@ -33,12 +34,34 @@ public abstract class ExecutionRootPath implements ProtoWrapper<String> {
private static final Path BAZEL_OUT = Path.of("bazel-out");
private static final Path BIN = Path.of("bin");

/**
* Marker Bazel emits for paths relative to the execution root.
*/
public static final Path PROC_SELF_CWD = Path.of("/proc", "self", "cwd");

public abstract Path path();

public static ExecutionRootPath create(Path path) {
// strip the /proc/self/cwd marker so it becomes an execution-root-relative path
if (isProcSelfCwd(path)) {
path = PROC_SELF_CWD.relativize(path);
}

return new AutoValue_ExecutionRootPath(path);
}

public static boolean isProcSelfCwd(Path path) {
return path.startsWith(PROC_SELF_CWD);
}

public static boolean isProcSelfCwd(String value) {
try {
return isProcSelfCwd(Path.of(value));
} catch (InvalidPathException e) {
return false;
}
}

public static ExecutionRootPath create(String path) {
return create(Path.of(path));
}
Expand All @@ -47,6 +70,29 @@ public static ExecutionRootPath create(File file) {
return create(file.toPath());
}

/**
* Returns null for genuine absolute paths which must be used as-is, and for
* invalid paths. Correctly resolves /proc/self/cwd references.
*/
public static @Nullable ExecutionRootPath tryCreate(@Nullable String location) {
if (location == null) {
return null;
}

Path path;
try {
path = Path.of(location);
} catch (InvalidPathException e) {
return null;
}

if (isProcSelfCwd(path) || !path.isAbsolute()) {
return create(path);
} else {
return null;
}
}

@Deprecated
public File getAbsoluteOrRelativeFile() {
return path().toFile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,53 @@ public void testCreateRelativePathWithOneAbsolutePathAndOneRelativePathReturnsNu

@Test
public void testCreateRelativePathWithOneAbsolutePathAndOneRelativePathReturnsNull2() {
ExecutionRootPath relativePathFragment =
ExecutionRootPath.createAncestorRelativePath(
createMockDirectory("code/lib/fastmath"), createMockDirectory("/code/lib/slowmath"));
final var relativePathFragment = ExecutionRootPath.createAncestorRelativePath(
createMockDirectory("code/lib/fastmath"),
createMockDirectory("/code/lib/slowmath")
);

assertThat(relativePathFragment).isNull();
}

@Test
public void testCreateStripsProcSelfCwdPrefixToRelativePath() {
final var path = ExecutionRootPath.create("/proc/self/cwd/foo/bar");
assertThat(path.isAbsolute()).isFalse();
assertThat(path).isEqualTo(ExecutionRootPath.create("foo/bar"));
}

@Test
public void testCreateStripsBareProcSelfCwdMarkerToExecutionRoot() {
final var path = ExecutionRootPath.create("/proc/self/cwd");
assertThat(path.isAbsolute()).isFalse();
assertThat(path).isEqualTo(ExecutionRootPath.create(""));
}

@Test
public void testCreateLeavesOtherAbsolutePathsUnchanged() {
final var path = ExecutionRootPath.create("/usr/include");
assertThat(path.isAbsolute()).isTrue();
}

@Test
public void testTryCreateReturnsNullForGenuineAbsolutePath() {
assertThat(ExecutionRootPath.tryCreate("/usr/include")).isNull();
}

@Test
public void testTryCreateAcceptsRelativeAndProcSelfCwdPaths() {
assertThat(ExecutionRootPath.tryCreate("foo/bar")).isEqualTo(ExecutionRootPath.create("foo/bar"));
assertThat(ExecutionRootPath.tryCreate("/proc/self/cwd/foo")).isEqualTo(ExecutionRootPath.create("foo"));
}

@Test
public void testIsProcSelfCwd() {
assertThat(ExecutionRootPath.isProcSelfCwd("/proc/self/cwd/foo")).isTrue();
assertThat(ExecutionRootPath.isProcSelfCwd("/proc/self/cwd")).isTrue();
assertThat(ExecutionRootPath.isProcSelfCwd("/usr/include")).isFalse();
assertThat(ExecutionRootPath.isProcSelfCwd("not-a-path-value")).isFalse();
}

private static File createMockDirectory(String path) {
File org = new File(path);
File spy = Mockito.spy(org);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,27 @@ public void testVirtualIncludesWithIncludePrefix() {
}


@Test
public void testProcSelfCwdResolvesLikeExecRootRelativePath() {
final var execRootPath = ExecutionRootPath.create("/proc/self/cwd/bazel-out/crosstool/genfiles/res/normal");
assertThat(pathResolver.resolveToIncludeDirectories(execRootPath))
.containsExactly(new File(EXECUTION_ROOT, "bazel-out/crosstool/genfiles/res/normal"));

final var outputBasePath = ExecutionRootPath.create("/proc/self/cwd/external/guava/src");
assertThat(pathResolver.resolveToIncludeDirectories(outputBasePath))
.containsExactly(new File(OUTPUT_BASE, "external/guava/src"));

final var workspacePath = ExecutionRootPath.create("/proc/self/cwd/tools/fast");
assertThat(pathResolver.resolveToIncludeDirectories(workspacePath))
.containsExactly(WORKSPACE_ROOT.fileForPath(new WorkspacePath("tools/fast")));
}

@Test
public void testProcSelfCwdResolveExecutionRootPath() {
assertThat(pathResolver.resolveExecutionRootPath(ExecutionRootPath.create("/proc/self/cwd/bazel-out/genfiles/foo")))
.isEqualTo(new File(EXECUTION_ROOT, "bazel-out/genfiles/foo"));
}

@Test
public void testExternalWorkspaceSymlinkToProject() throws IOException {
Path expectedPath = Path.of(WORKSPACE_ROOT.toString(), "guava", "src");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,48 @@
*/
package com.google.idea.blaze.clwb.environment

import com.google.common.collect.ImmutableMap
import com.google.idea.blaze.cpp.BlazeCompilerSettings
import com.google.idea.blaze.cpp.CppEnvironmentProvider
import com.intellij.execution.ExecutionException
import com.intellij.execution.configurations.GeneralCommandLine
import com.jetbrains.cidr.cpp.toolchains.CPPEnvironment
import com.jetbrains.cidr.cpp.toolchains.CPPToolchains
import com.jetbrains.cidr.lang.toolchains.CidrToolEnvironment

/**
* Forwards environment variables from [BlazeCompilerSettings.environment] to compiler invocations.
*
* Previously, these environment variables (e.g. `DEVELOPER_DIR`, `SDKROOT` on macOS)
* were embedded as `export` statements in the compiler wrapper script. Now that the wrapper
* script has been removed, this provider ensures they are still passed to the compiler.
*
* This provider is registered with `order="last"` so that more specific providers
* (MSVC, Clang-CL) take precedence when applicable.
* Fallback environment provider. Forwards the environment variables set on the
* Bazel compiler settings.
*/
class BazelEnvironmentProvider : CppEnvironmentProvider {

override fun create(settings: BlazeCompilerSettings): CidrToolEnvironment? {
val env = settings.environment()
if (env.isEmpty()) return null
companion object {

return ToolEnvironment(env)
}
/**
* Creates a CPPEnvironment that forwards the environment variables set on
* the Bazel compiler settings.
*/
@JvmStatic
fun create(settings: BlazeCompilerSettings, toolchain: CPPToolchains.Toolchain): CPPEnvironment {
return object : CPPEnvironment(toolchain) {
@Throws(ExecutionException::class)
override fun prepare(cl: GeneralCommandLine, prepareFor: PrepareFor) {
super.prepare(cl, prepareFor)
cl.environment.putAll(settings.environment())
}
}
}

private class ToolEnvironment(private val environment: ImmutableMap<String, String>) : CidrToolEnvironment() {
}

/**
* Creates a CidrToolEnvironment that forwards the environment variables set
* on the Bazel compiler settings.
*/
override fun create(settings: BlazeCompilerSettings): CidrToolEnvironment = object : CidrToolEnvironment() {
@Throws(ExecutionException::class)
override fun prepare(cl: GeneralCommandLine, prepareFor: PrepareFor) {
cl.environment.putAll(environment)
super.prepare(cl, prepareFor)
cl.environment.putAll(settings.environment())
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@
import com.google.idea.blaze.cpp.CppEnvironmentProvider;
import com.google.idea.sdkcompat.clion.OSTypeCompat;
import com.intellij.openapi.diagnostic.Logger;
import com.jetbrains.cidr.cpp.toolchains.CPPEnvironment;
import com.jetbrains.cidr.cpp.toolchains.CPPToolSet.Kind;
import com.jetbrains.cidr.cpp.toolchains.CPPToolchains;
import com.jetbrains.cidr.lang.CLanguageKind;
import com.jetbrains.cidr.lang.toolchains.CidrToolEnvironment;
import com.jetbrains.cidr.lang.workspace.compiler.ClangClCompilerKind;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -50,6 +48,6 @@ class ClangClEnvironmentProvider implements CppEnvironmentProvider {
toolchain.setToolSetKind(Kind.MSVC);
toolchain.setToolSetPath(toolSetPath);

return new CPPEnvironment(toolchain);
return BazelEnvironmentProvider.create(settings, toolchain);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.google.idea.sdkcompat.clion.OSTypeCompat;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.jetbrains.cidr.cpp.toolchains.CPPEnvironment;
import com.jetbrains.cidr.cpp.toolchains.CPPToolSet.Kind;
import com.jetbrains.cidr.cpp.toolchains.CPPToolchains;
import com.jetbrains.cidr.cpp.toolchains.MSVC;
Expand Down Expand Up @@ -68,7 +67,7 @@ class MSVCEnvironmentProvider implements CppEnvironmentProvider {
toolchain.setToolSetKind(Kind.MSVC);
toolchain.setToolSetPath(toolSetPath);

final var environment = new CPPEnvironment(toolchain);
final var environment = BazelEnvironmentProvider.create(settings, toolchain);
((MSVC) environment.getToolSet()).setToolsVersion(version);

return environment;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
import com.google.idea.blaze.base.issueparser.ToolWindowTaskIssueOutputFilter;
import com.google.idea.blaze.base.logging.EventLoggingService;
import com.google.idea.blaze.base.model.primitives.ExecutionRootPath;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.model.primitives.TargetExpression;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
Expand Down Expand Up @@ -302,7 +303,8 @@ public CidrDebugProcess createDebugProcess(CommandLineState state, XDebugSession
runner.executable.toString(),
"target:",
ImmutableList.of(
new CidrRemotePathMapping("/proc/self/cwd", workspaceRootDirectory.getParent())));
new CidrRemotePathMapping(
ExecutionRootPath.PROC_SELF_CWD.toString(), workspaceRootDirectory.getParent())));

BlazeCLionGDBDriverConfiguration debuggerDriverConfiguration =
new BlazeCLionGDBDriverConfiguration(project);
Expand Down Expand Up @@ -337,7 +339,7 @@ private ImmutableList<String> getGdbStartupCommands(File workspaceRootDirectory)
// Forge creates debug symbol paths rooted at /proc/self/cwd .
// We need to tell gdb to translate this path prefix to the user's workspace
// root so the IDE can find the files.
String from = "/proc/self/cwd";
String from = ExecutionRootPath.PROC_SELF_CWD.toString();
String to = workspaceRootDirectory.getPath();
String subPathCommand = String.format("set substitute-path %s %s", from, to);

Expand Down
11 changes: 9 additions & 2 deletions cpp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ load("@rules_java//java:defs.bzl", "java_library")
load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library")
load(
"//:build-visibility.bzl",
"DEFAULT_TEST_VISIBILITY",
"PLUGIN_PACKAGES_VISIBILITY",
)
load(
Expand Down Expand Up @@ -86,7 +85,6 @@ intellij_unit_test_suite(
class_rules = ["com.google.idea.blaze.cpp.ClionUnitTestSystemPropertiesRule"],
tags = ["noci:studio-win"],
test_package_root = "com.google.idea.blaze.cpp",
visibility = DEFAULT_TEST_VISIBILITY,
# Needed to work around one-version issue
runtime_deps = ["//intellij_platform_sdk:test_libs"],
deps = [
Expand All @@ -104,3 +102,12 @@ intellij_unit_test_suite(
"@maven//:org_mockito_mockito_core",
],
)

test_suite(
name = "unit_tests_suite",
tests = [
":unit_tests",
"//cpp/tests/unittests/com/google/idea/blaze/cpp/environment:ProcSelfCwdEnvironmentProcessorTest",
],
visibility = ["//visibility:public"],
)
Loading
Loading