diff --git a/aspect/build_dependencies.bzl b/aspect/build_dependencies.bzl index a279e5b3774..4d0bae6a8f5 100644 --- a/aspect/build_dependencies.bzl +++ b/aspect/build_dependencies.bzl @@ -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 = ""): @@ -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, @@ -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, ) diff --git a/base/src/com/google/idea/blaze/base/qsync/BazelDependencyBuilder.java b/base/src/com/google/idea/blaze/base/qsync/BazelDependencyBuilder.java index 2918a371593..4a0a0e93c89 100644 --- a/base/src/com/google/idea/blaze/base/qsync/BazelDependencyBuilder.java +++ b/base/src/com/google/idea/blaze/base/qsync/BazelDependencyBuilder.java @@ -161,78 +161,76 @@ public OutputInfo build( Optional 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 ruleKindsToBuild = - Sets.difference(BlazeQueryParser.ALWAYS_BUILD_RULE_KINDS, handledRuleKinds); - String alwaysBuildParam = Joiner.on(",").join(ruleKindsToBuild); - - ImmutableSet 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 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 ruleKindsToBuild = + Sets.difference(BlazeQueryParser.ALWAYS_BUILD_RULE_KINDS, handledRuleKinds); + String alwaysBuildParam = Joiner.on(",").join(ruleKindsToBuild); + + ImmutableSet 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 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); } /** diff --git a/clwb/BUILD b/clwb/BUILD index 9a8c8e5d354..78a8d34913d 100644 --- a/clwb/BUILD +++ b/clwb/BUILD @@ -201,6 +201,12 @@ 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 = [ @@ -208,5 +214,6 @@ test_suite( ":simple_integration_test", ":virtual_includes_integration_test", ":external_includes_integration_test", + ":query_sync_integration_test", ], ) diff --git a/clwb/test_defs.bzl b/clwb/test_defs.bzl index 35ce4188a11..2d33aa4ff92 100644 --- a/clwb/test_defs.bzl +++ b/clwb/test_defs.bzl @@ -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", diff --git a/clwb/tests/integrationtests/com/google/idea/blaze/clwb/QuerySyncTest.java b/clwb/tests/integrationtests/com/google/idea/blaze/clwb/QuerySyncTest.java new file mode 100644 index 00000000000..6c208dae41b --- /dev/null +++ b/clwb/tests/integrationtests/com/google/idea/blaze/clwb/QuerySyncTest.java @@ -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); + } +} diff --git a/clwb/tests/integrationtests/com/google/idea/blaze/clwb/base/ClwbIntegrationTestCase.java b/clwb/tests/integrationtests/com/google/idea/blaze/clwb/base/ClwbIntegrationTestCase.java index 7ac8932104f..5cc1a5df8c3 100644 --- a/clwb/tests/integrationtests/com/google/idea/blaze/clwb/base/ClwbIntegrationTestCase.java +++ b/clwb/tests/integrationtests/com/google/idea/blaze/clwb/base/ClwbIntegrationTestCase.java @@ -3,6 +3,7 @@ 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; @@ -10,6 +11,8 @@ 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; @@ -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(); diff --git a/cpp/src/com/google/idea/blaze/cpp/qsync/CcProjectModelUpdateOperation.java b/cpp/src/com/google/idea/blaze/cpp/qsync/CcProjectModelUpdateOperation.java index aa584d1359b..f151e897a6c 100644 --- a/cpp/src/com/google/idea/blaze/cpp/qsync/CcProjectModelUpdateOperation.java +++ b/cpp/src/com/google/idea/blaze/cpp/qsync/CcProjectModelUpdateOperation.java @@ -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. */