Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic qsync support in CLion for linux #7094

Merged
merged 6 commits into from
Dec 16, 2024
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
8 changes: 6 additions & 2 deletions aspect/build_dependencies.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def _package_dependencies_impl(target, ctx):
qsync_aars = dep_info.aars.to_list() if dep_info.aars else [],
qsync_gensrcs = dep_info.gensrcs.to_list() if dep_info.gensrcs else [],
cc_headers = dep_info.cc_headers.to_list() if dep_info.cc_headers else [],
cc_info_file = cc_info_file + [dep_info.cc_toolchain_info.file] if dep_info.cc_toolchain_info else [],
cc_info_file = cc_info_file + ([dep_info.cc_toolchain_info.file] if dep_info.cc_toolchain_info else []),
)]

def _write_java_target_info(target, ctx, custom_prefix = ""):
Expand Down Expand Up @@ -213,12 +213,16 @@ def merge_dependencies_info(target, ctx, java_dep_info, cc_dep_info, cc_toolchai

if cc_dep_info and cc_toolchain_dep_info:
test_mode_cc_src_deps = depset(transitive = [cc_dep_info.test_mode_cc_src_deps, cc_toolchain_dep_info.test_mode_cc_src_deps])
cc_toolchain_info = cc_toolchain_dep_info.cc_toolchain_info
elif cc_dep_info:
test_mode_cc_src_deps = cc_dep_info.test_mode_cc_src_deps
cc_toolchain_info = cc_dep_info.cc_toolchain_info
elif cc_toolchain_dep_info:
test_mode_cc_src_deps = cc_toolchain_dep_info.test_mode_cc_src_deps
cc_toolchain_info = cc_toolchain_dep_info.cc_toolchain_info
else:
test_mode_cc_src_deps = None
cc_toolchain_info = None

merged = create_dependencies_info(
label = target.label,
Expand All @@ -229,7 +233,7 @@ def merge_dependencies_info(target, ctx, java_dep_info, cc_dep_info, cc_toolchai
expand_sources = java_dep_info.expand_sources if java_dep_info else None,
cc_compilation_info = cc_dep_info.cc_compilation_info if cc_dep_info else None,
cc_headers = cc_dep_info.cc_headers if cc_dep_info else None,
cc_toolchain_info = cc_toolchain_dep_info.cc_toolchain_info if cc_toolchain_dep_info else None,
cc_toolchain_info = cc_toolchain_info,
test_mode_own_files = java_dep_info.test_mode_own_files if java_dep_info else None,
test_mode_cc_src_deps = test_mode_cc_src_deps,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,78 +161,76 @@ public OutputInfo build(
Optional<BuildDepsStats.Builder> buildDepsStatsBuilder =
BuildDepsStatsScope.fromContext(context);
buildDepsStatsBuilder.ifPresent(stats -> stats.setBlazeBinaryType(invoker.getType()));
try (BuildResultHelper buildResultHelper = invoker.createBuildResultHelper()) {
String includes =
projectDefinition.projectIncludes().stream()
.map(path -> "//" + path)
.collect(joining(","));
String excludes =
projectDefinition.projectExcludes().stream()
.map(path -> "//" + path)
.collect(joining(","));
String aspectLocation = prepareAspect(context);
Set<String> ruleKindsToBuild =
Sets.difference(BlazeQueryParser.ALWAYS_BUILD_RULE_KINDS, handledRuleKinds);
String alwaysBuildParam = Joiner.on(",").join(ruleKindsToBuild);

ImmutableSet<OutputGroup> outputGroups =
languages.stream()
.map(OUTPUT_GROUPS_BY_LANGUAGE::get)
.flatMap(Collection::stream)
.collect(ImmutableSet.toImmutableSet());

ProjectViewSet projectViewSet = ProjectViewManager.getInstance(project).getProjectViewSet();
// TODO This is not SYNC_CONTEXT, but also not OTHER_CONTEXT, we need to decide what kind
// of flags need to be passed here.
List<String> additionalBlazeFlags =
BlazeFlags.blazeFlags(
project,
projectViewSet,
BlazeCommandName.BUILD,
context,
BlazeInvocationContext.OTHER_CONTEXT);

BlazeCommand.Builder builder =
BlazeCommand.builder(invoker, BlazeCommandName.BUILD, project)
.addBlazeFlags(buildTargets.stream().map(Label::toString).collect(toImmutableList()))
.addBlazeFlags(buildResultHelper.getBuildFlags())
.addBlazeFlags(additionalBlazeFlags)
.addBlazeFlags(
String.format(
"--aspects=%1$s%%collect_dependencies,%1$s%%package_dependencies",
aspectLocation))
.addBlazeFlags(String.format("--aspects_parameters=include=%s", includes))
.addBlazeFlags(String.format("--aspects_parameters=exclude=%s", excludes))
.addBlazeFlags(
String.format("--aspects_parameters=always_build_rules=%s", alwaysBuildParam))
.addBlazeFlags("--aspects_parameters=generate_aidl_classes=True")
.addBlazeFlags(
String.format(
"--aspects_parameters=use_generated_srcjars=%s",
buildGeneratedSrcJars.getValue() ? "True" : "False"))
.addBlazeFlags("--noexperimental_run_validations")
.addBlazeFlags("--keep_going");
outputGroups.stream()
.map(g -> "--output_groups=" + g.outputGroupName())
.forEach(builder::addBlazeFlags);
buildDepsStatsBuilder.ifPresent(
stats -> stats.setBuildFlags(builder.build().toArgumentList()));
Instant buildTime = Instant.now();
BlazeBuildOutputs outputs = BazelExecService.instance(project).build(context, builder);
buildDepsStatsBuilder.ifPresent(
stats -> {
stats.setBuildIds(outputs.getBuildIds());
stats.setBepByteConsumed(outputs.bepBytesConsumed);
});

BazelExitCodeException.throwIfFailed(
builder,
outputs.buildResult,
ThrowOption.ALLOW_PARTIAL_SUCCESS,
ThrowOption.ALLOW_BUILD_FAILURE);

return createOutputInfo(outputs, outputGroups, buildTime, context);
}

String includes =
projectDefinition.projectIncludes().stream()
.map(path -> "//" + path)
.collect(joining(","));
String excludes =
projectDefinition.projectExcludes().stream()
.map(path -> "//" + path)
.collect(joining(","));
String aspectLocation = prepareAspect(context);
Set<String> ruleKindsToBuild =
Sets.difference(BlazeQueryParser.ALWAYS_BUILD_RULE_KINDS, handledRuleKinds);
String alwaysBuildParam = Joiner.on(",").join(ruleKindsToBuild);

ImmutableSet<OutputGroup> outputGroups =
languages.stream()
.map(OUTPUT_GROUPS_BY_LANGUAGE::get)
.flatMap(Collection::stream)
.collect(ImmutableSet.toImmutableSet());

ProjectViewSet projectViewSet = ProjectViewManager.getInstance(project).getProjectViewSet();
// TODO This is not SYNC_CONTEXT, but also not OTHER_CONTEXT, we need to decide what kind
// of flags need to be passed here.
List<String> additionalBlazeFlags =
BlazeFlags.blazeFlags(
project,
projectViewSet,
BlazeCommandName.BUILD,
context,
BlazeInvocationContext.OTHER_CONTEXT);

BlazeCommand.Builder builder =
BlazeCommand.builder(invoker, BlazeCommandName.BUILD, project)
.addBlazeFlags(buildTargets.stream().map(Label::toString).collect(toImmutableList()))
.addBlazeFlags(additionalBlazeFlags)
.addBlazeFlags(
String.format(
"--aspects=%1$s%%collect_dependencies,%1$s%%package_dependencies",
aspectLocation))
.addBlazeFlags(String.format("--aspects_parameters=include=%s", includes))
.addBlazeFlags(String.format("--aspects_parameters=exclude=%s", excludes))
.addBlazeFlags(
String.format("--aspects_parameters=always_build_rules=%s", alwaysBuildParam))
.addBlazeFlags("--aspects_parameters=generate_aidl_classes=True")
.addBlazeFlags(
String.format(
"--aspects_parameters=use_generated_srcjars=%s",
buildGeneratedSrcJars.getValue() ? "True" : "False"))
.addBlazeFlags("--noexperimental_run_validations")
.addBlazeFlags("--keep_going");
outputGroups.stream()
.map(g -> "--output_groups=" + g.outputGroupName())
.forEach(builder::addBlazeFlags);
buildDepsStatsBuilder.ifPresent(
stats -> stats.setBuildFlags(builder.build().toArgumentList()));
Instant buildTime = Instant.now();
BlazeBuildOutputs outputs = BazelExecService.instance(project).build(context, builder);
buildDepsStatsBuilder.ifPresent(
stats -> {
stats.setBuildIds(outputs.getBuildIds());
stats.setBepByteConsumed(outputs.bepBytesConsumed);
});

BazelExitCodeException.throwIfFailed(
builder,
outputs.buildResult,
ThrowOption.ALLOW_PARTIAL_SUCCESS,
ThrowOption.ALLOW_BUILD_FAILURE);

return createOutputInfo(outputs, outputGroups, buildTime, context);
}

/**
Expand Down
7 changes: 7 additions & 0 deletions clwb/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,19 @@ clwb_integration_test(
srcs = ["tests/integrationtests/com/google/idea/blaze/clwb/ExternalIncludesTest.java"],
)

clwb_integration_test(
name = "query_sync_integration_test",
project = "simple",
srcs = ["tests/integrationtests/com/google/idea/blaze/clwb/QuerySyncTest.java"],
)

test_suite(
name = "integration_tests",
tests = [
":llvm_toolchain_integration_test",
":simple_integration_test",
":virtual_includes_integration_test",
":external_includes_integration_test",
":query_sync_integration_test",
],
)
3 changes: 3 additions & 0 deletions clwb/test_defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ def clwb_integration_test(name, project, srcs, deps = []):
# suppressed plugin sets for classic, radler is currently disabled for tests
"-Didea.suppressed.plugins.set.classic=org.jetbrains.plugins.clion.radler,intellij.rider.cpp.debugger,intellij.rider.plugins.clion.radler.cwm",
"-Didea.suppressed.plugins.set.selector=classic",
# define the path to the query sync aspects
"-Dblaze.idea.build_dependencies.bzl.file=aspect/build_dependencies.bzl",
"-Dblaze.idea.build_dependencies_deps.bzl.file=aspect/build_dependencies_deps.bzl",
],
deps = deps + [
":clwb_lib",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.google.idea.blaze.clwb;

import static com.google.common.truth.Truth.assertThat;
import static com.google.idea.blaze.clwb.base.Assertions.assertContainsHeader;

import com.google.idea.blaze.clwb.base.BazelVersionRule;
import com.google.idea.blaze.clwb.base.ClwbIntegrationTestCase;
import com.google.idea.blaze.clwb.base.OSRule;
import com.intellij.util.system.OS;
import java.util.concurrent.ExecutionException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class QuerySyncTest extends ClwbIntegrationTestCase {

// currently query sync only works on linux, TODO: fix mac and windows
@Rule
public final OSRule osRule = new OSRule(OS.Linux);

// query sync requires bazel 6+
@Rule
public final BazelVersionRule bazelRule = new BazelVersionRule(6, 0);

@Test
public void testClwb() throws Exception {
final var success = runQuerySync();
assertThat(success).isTrue();

checkAnalysis();
checkCompiler();
}

private void checkAnalysis() throws ExecutionException {
final var success = enableAnalysisFor(findProjectFile("main/hello-world.cc"));
assertThat(success).isTrue();
}

private void checkCompiler() {
final var compilerSettings = findFileCompilerSettings("main/hello-world.cc");

// TODO: query sync always uses clang : https://github.com/bazelbuild/intellij/issues/7177
// if (SystemInfo.isMac) {
// assertThat(compilerSettings.getCompilerKind()).isEqualTo(ClangCompilerKind.INSTANCE);
// } else if (SystemInfo.isLinux) {
// assertThat(compilerSettings.getCompilerKind()).isEqualTo(GCCCompilerKind.INSTANCE);
// } else if (SystemInfo.isWindows) {
// assertThat(compilerSettings.getCompilerKind()).isEqualTo(MSVCCompilerKind.INSTANCE);
// }

assertContainsHeader("iostream", compilerSettings);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
import static com.google.common.truth.Truth.assertThat;

import com.google.idea.blaze.base.async.process.ExternalTask;
import com.google.idea.blaze.base.logging.utils.querysync.QuerySyncActionStatsScope;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.project.AutoImportProjectOpenProcessor;
import com.google.idea.blaze.base.project.ExtendableBazelProjectCreator;
import com.google.idea.blaze.base.projectview.ProjectView;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.section.sections.TextBlock;
import com.google.idea.blaze.base.projectview.section.sections.TextBlockSection;
import com.google.idea.blaze.base.qsync.QuerySyncManager;
import com.google.idea.blaze.base.qsync.QuerySyncManager.TaskOrigin;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.settings.BlazeUserSettings;
import com.google.idea.blaze.base.settings.BuildSystemName;
Expand Down Expand Up @@ -248,6 +251,47 @@ protected BlazeSyncParams.Builder defaultSyncParams() {
.setAddProjectViewTargets(true);
}

protected boolean runQuerySync() {
final var future = QuerySyncManager.getInstance(myProject).onStartup(QuerySyncActionStatsScope.create(getClass(), null));

while (!future.isDone()) {
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue();
}

try {
return future.get();
} catch (ExecutionException e) {
fail("query sync failed " + e.getMessage());
} catch (InterruptedException e) {
fail("query sync was interrupted");
}

return false;
}

protected boolean enableAnalysisFor(VirtualFile file) throws ExecutionException {
final var manager = QuerySyncManager.getInstance(myProject);
final var targets = manager.getTargetsToBuild(file).targets();

final var future = manager.enableAnalysis(
targets,
QuerySyncActionStatsScope.createForFile(getClass(), null, file),
TaskOrigin.USER_ACTION
);

while (!future.isDone()) {
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue();
}

try {
return future.get();
} catch (InterruptedException e) {
fail("enable analysis was interrupted");
}

return false;
}

protected VirtualFile findProjectFile(String relativePath) {
final var file = myProjectRoot.findFileByRelativePath(relativePath);
assertThat(file).isNotNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ private File getCompilerExecutable(CcCompilerSettings compilerSettings) {

/** Pre-commits the project update. Should be called from a background thread. */
public void preCommit() {
modifiableOcWorkspace.preCommit();
processCompilerSettings();
modifiableOcWorkspace.preCommit();
}

/** Commits the project update. Must be called from the write thread. */
Expand Down
Loading