| // Copyright 2017 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.google.devtools.build.lib.rules.cpp; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.devtools.build.lib.analysis.ConfiguredTarget; |
| import com.google.devtools.build.lib.analysis.RuleContext; |
| import com.google.devtools.build.lib.analysis.config.CompilationMode; |
| import com.google.devtools.build.lib.analysis.util.AnalysisMock; |
| import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; |
| import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig; |
| import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.ToolPath; |
| import java.util.List; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** |
| * Unit tests for {@code CcToolchainProvider} |
| */ |
| @RunWith(JUnit4.class) |
| public class CcToolchainProviderTest extends BuildViewTestCase { |
| @Test |
| public void testSkylarkCallables() throws Exception { |
| AnalysisMock.get() |
| .ccSupport() |
| .setupCrosstool( |
| mockToolsConfig, |
| CrosstoolConfig.CToolchain.newBuilder() |
| .addCompilerFlag("-foo_compiler") |
| .addCxxFlag("-foo_cxx") |
| .setBuiltinSysroot("/usr/local/custom-sysroot") |
| .addToolPath(ToolPath.newBuilder().setName("ar").setPath("foo/ar/path").build()) |
| .buildPartial()); |
| useConfiguration("--cpu=k8", "--force_pic"); |
| scratch.file( |
| "test/rule.bzl", |
| "def _impl(ctx):", |
| " provider = ctx.attr._cc_toolchain[cc_common.CcToolchainInfo]", |
| " return struct(", |
| " dirs = provider.built_in_include_directories,", |
| " link_options = provider.link_options_do_not_use,", |
| " unfiltered_compiler_options = provider.unfiltered_compiler_options([]),", |
| " sysroot = provider.sysroot,", |
| " cpu = provider.cpu,", |
| " compiler_options = provider.compiler_options(),", |
| " cxx_options = provider.cxx_options(),", |
| " ar_executable = provider.ar_executable,", |
| " use_pic_for_dynamic_libraries = provider.use_pic_for_dynamic_libraries,", |
| " )", |
| "", |
| "my_rule = rule(", |
| " _impl,", |
| " attrs = {'_cc_toolchain': attr.label(default=Label('//test:toolchain')) }", |
| ")"); |
| |
| scratch.file("test/BUILD", |
| "load(':rule.bzl', 'my_rule')", |
| "cc_toolchain_alias(name = 'toolchain')", |
| "my_rule(name = 'target')"); |
| |
| ConfiguredTarget ct = getConfiguredTarget("//test:target"); |
| |
| @SuppressWarnings("unchecked") |
| List<String> compilerOptions = (List<String>) ct.get("compiler_options"); |
| assertThat(compilerOptions).contains("-foo_compiler"); |
| |
| @SuppressWarnings("unchecked") |
| List<String> cxxOptions = (List<String>) ct.get("cxx_options"); |
| assertThat(cxxOptions).contains("-foo_cxx"); |
| |
| assertThat((String) ct.get("ar_executable")).endsWith("foo/ar/path"); |
| |
| assertThat(ct.get("cpu")).isEqualTo("k8"); |
| |
| assertThat(ct.get("sysroot")).isEqualTo("/usr/local/custom-sysroot"); |
| |
| @SuppressWarnings("unchecked") |
| List<String> linkOptions = (List<String>) ct.get("link_options"); |
| assertThat(linkOptions).contains("--sysroot=/usr/local/custom-sysroot"); |
| |
| @SuppressWarnings("unchecked") |
| List<String> unfilteredCompilerOptions = (List<String>) ct.get("unfiltered_compiler_options"); |
| assertThat(unfilteredCompilerOptions).contains("--sysroot=/usr/local/custom-sysroot"); |
| |
| @SuppressWarnings("unchecked") |
| boolean usePicForDynamicLibraries = (boolean) ct.get("use_pic_for_dynamic_libraries"); |
| assertThat(usePicForDynamicLibraries).isTrue(); |
| } |
| |
| @Test |
| public void testDisablingMostlyStaticLinkOptions() throws Exception { |
| testDisablingLinkingApiMethod("provider.mostly_static_link_options(False)"); |
| } |
| |
| @Test |
| public void testDisablingFullyStaticLinkOptions() throws Exception { |
| testDisablingLinkingApiMethod("provider.fully_static_link_options(True)"); |
| } |
| |
| @Test |
| public void testDisablingDynamicLinkOptions() throws Exception { |
| testDisablingLinkingApiMethod("provider.dynamic_link_options(False)"); |
| } |
| |
| @Test |
| public void testDisablingLinkOptions() throws Exception { |
| testDisablingLinkingApiMethod("provider.link_options_do_not_use"); |
| } |
| |
| @Test |
| public void testDisablingMostlyStaticLinkOptionsFromConfiguration() throws Exception { |
| testDisablingLinkingApiMethod("ctx.fragments.cpp.mostly_static_link_options([], False)"); |
| } |
| |
| @Test |
| public void testDisablingFullyStaticLinkOptionsFromConfiguration() throws Exception { |
| testDisablingLinkingApiMethod("ctx.fragments.cpp.fully_static_link_options([], True)"); |
| } |
| |
| @Test |
| public void testDisablingDynamicLinkOptionsFromConfiguration() throws Exception { |
| testDisablingLinkingApiMethod("ctx.fragments.cpp.dynamic_link_options([], False)"); |
| } |
| |
| @Test |
| public void testDisablingLinkOptionsFromConfiguration() throws Exception { |
| testDisablingLinkingApiMethod("ctx.fragments.cpp.link_options"); |
| } |
| |
| private void testDisablingLinkingApiMethod(String method) throws Exception { |
| useConfiguration("--experimental_disable_legacy_cc_linking_api"); |
| scratch.file( |
| "test/rule.bzl", |
| "def _impl(ctx):", |
| " provider = ctx.attr._cc_toolchain[cc_common.CcToolchainInfo]", |
| " return struct(", |
| " link_options = " + method + ",", |
| " )", |
| "", |
| "my_rule = rule(", |
| " _impl,", |
| " fragments = [ 'cpp' ],", |
| " attrs = {'_cc_toolchain': attr.label(default=Label('//test:toolchain')) }", |
| ")"); |
| scratch.file( |
| "test/BUILD", |
| "load(':rule.bzl', 'my_rule')", |
| "cc_toolchain_alias(name = 'toolchain')", |
| "my_rule(name = 'target')"); |
| AssertionError e = |
| assertThrows(AssertionError.class, () -> getConfiguredTarget("//test:target")); |
| assertThat(e) |
| .hasMessageThat() |
| .contains( |
| "Skylark APIs accessing linking flags has been removed. " |
| + "Use the new API on cc_common."); |
| } |
| |
| @Test |
| public void testDisablingCompilerOptions() throws Exception { |
| testDisablingCompilationApiMethod("provider.compiler_options()"); |
| } |
| |
| @Test |
| public void testDisablingCxxOptions() throws Exception { |
| testDisablingCompilationApiMethod("provider.cxx_options()"); |
| } |
| |
| @Test |
| public void testDisablingCOptions() throws Exception { |
| testDisablingCompilationApiMethod("provider.c_options()"); |
| } |
| |
| @Test |
| public void testDisablingUnfilteredOptions() throws Exception { |
| testDisablingCompilationApiMethod("provider.unfiltered_compiler_options([])"); |
| } |
| |
| @Test |
| public void testDisablingCompilerOptionsFromConfiguration() throws Exception { |
| testDisablingCompilationApiMethod("ctx.fragments.cpp.compiler_options([])"); |
| } |
| |
| @Test |
| public void testDisablingCxxOptionsFromConfiguration() throws Exception { |
| testDisablingCompilationApiMethod("ctx.fragments.cpp.cxx_options([])"); |
| } |
| |
| @Test |
| public void testDisablingCOptionsFromConfiguration() throws Exception { |
| testDisablingCompilationApiMethod("ctx.fragments.cpp.c_options"); |
| } |
| |
| @Test |
| public void testDisablingUnfilteredOptionsFromConfiguration() throws Exception { |
| testDisablingCompilationApiMethod("ctx.fragments.cpp.unfiltered_compiler_options([])"); |
| } |
| |
| private void testDisablingCompilationApiMethod(String method) throws Exception { |
| useConfiguration("--experimental_disable_legacy_cc_compilation_api"); |
| scratch.file( |
| "test/rule.bzl", |
| "def _impl(ctx):", |
| " provider = ctx.attr._cc_toolchain[cc_common.CcToolchainInfo]", |
| " return struct(", |
| " compile_options = " + method + ",", |
| " )", |
| "", |
| "my_rule = rule(", |
| " _impl,", |
| " fragments = [ 'cpp' ],", |
| " attrs = {'_cc_toolchain': attr.label(default=Label('//test:toolchain')) }", |
| ")"); |
| scratch.file( |
| "test/BUILD", |
| "load(':rule.bzl', 'my_rule')", |
| "cc_toolchain_alias(name = 'toolchain')", |
| "my_rule(name = 'target')"); |
| AssertionError e = |
| assertThrows(AssertionError.class, () -> getConfiguredTarget("//test:target")); |
| assertThat(e) |
| .hasMessageThat() |
| .contains( |
| "Skylark APIs accessing compilation flags has been removed. " |
| + "Use the new API on cc_common."); |
| } |
| |
| @Test |
| public void testDisablingCompilationModeFlags() throws Exception { |
| AnalysisMock.get() |
| .ccSupport() |
| .setupCrosstool( |
| mockToolsConfig, |
| "compilation_mode_flags { mode: OPT compiler_flag: '-foo_from_compilation_mode' }", |
| "compilation_mode_flags { mode: OPT cxx_flag: '-bar_from_compilation_mode' }", |
| "compilation_mode_flags { mode: OPT linker_flag: '-baz_from_compilation_mode' }"); |
| scratch.file("a/BUILD", "cc_library(name='a', srcs=['a.cc'])"); |
| |
| useConfiguration("-c", "opt"); |
| CcToolchainProvider ccToolchainProvider = getCcToolchainProvider(); |
| assertThat(ccToolchainProvider.getCompilerOptions()).contains("-foo_from_compilation_mode"); |
| assertThat(ccToolchainProvider.getLegacyCxxOptions()).contains("-bar_from_compilation_mode"); |
| assertThat(ccToolchainProvider.getLegacyMostlyStaticLinkFlags(CompilationMode.OPT)) |
| .contains("-baz_from_compilation_mode"); |
| |
| useConfiguration("-c", "opt", "--experimental_disable_compilation_mode_flags"); |
| ccToolchainProvider = getCcToolchainProvider(); |
| assertThat(ccToolchainProvider.getCompilerOptions()) |
| .doesNotContain("-foo_from_compilation_mode"); |
| assertThat(ccToolchainProvider.getLegacyCxxOptions()) |
| .doesNotContain("-bar_from_compilation_mode"); |
| assertThat(ccToolchainProvider.getLegacyMostlyStaticLinkFlags(CompilationMode.OPT)) |
| .doesNotContain("-baz_from_compilation_mode"); |
| } |
| |
| private CcToolchainProvider getCcToolchainProvider() throws Exception { |
| ConfiguredTarget target = getConfiguredTarget("//a"); |
| RuleContext ruleContext = getRuleContext(target); |
| return CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext); |
| } |
| |
| @Test |
| public void testDisablingLinkingModeFlags() throws Exception { |
| AnalysisMock.get() |
| .ccSupport() |
| .setupCrosstool( |
| mockToolsConfig, |
| "linking_mode_flags { mode: MOSTLY_STATIC linker_flag: '-foo_from_linking_mode' }"); |
| scratch.file("a/BUILD", "cc_library(name='a', srcs=['a.cc'])"); |
| |
| useConfiguration(); |
| CcToolchainProvider ccToolchainProvider = getCcToolchainProvider(); |
| assertThat(ccToolchainProvider.getLegacyMostlyStaticLinkFlags(CompilationMode.OPT)) |
| .contains("-foo_from_linking_mode"); |
| |
| useConfiguration("--experimental_disable_linking_mode_flags"); |
| ccToolchainProvider = getCcToolchainProvider(); |
| assertThat(ccToolchainProvider.getLegacyMostlyStaticLinkFlags(CompilationMode.OPT)) |
| .doesNotContain("-foo_from_linking_mode"); |
| } |
| |
| @Test |
| public void testDisablingLegacyCrosstoolFields() throws Exception { |
| AnalysisMock.get() |
| .ccSupport() |
| .setupCrosstool( |
| mockToolsConfig, |
| "compiler_flag: '-foo_compiler_flag'", |
| "cxx_flag: '-foo_cxx_flag'", |
| "unfiltered_cxx_flag: '-foo_unfiltered_cxx_flag'", |
| "linker_flag: '-foo_linker_flag'", |
| "dynamic_library_linker_flag: '-foo_dynamic_library_linker_flag'", |
| "test_only_linker_flag: '-foo_test_only_linker_flag'"); |
| scratch.file("a/BUILD", "cc_library(name='a', srcs=['a.cc'])"); |
| |
| useConfiguration(); |
| CcToolchainProvider ccToolchainProvider = getCcToolchainProvider(); |
| assertThat(ccToolchainProvider.getLegacyCompileOptions()).contains("-foo_compiler_flag"); |
| assertThat(ccToolchainProvider.getLegacyCxxOptions()).contains("-foo_cxx_flag"); |
| assertThat(ccToolchainProvider.getUnfilteredCompilerOptions()) |
| .contains("-foo_unfiltered_cxx_flag"); |
| assertThat(ccToolchainProvider.getLegacyLinkOptions()).contains("-foo_linker_flag"); |
| assertThat(ccToolchainProvider.getSharedLibraryLinkOptions(/* flags= */ ImmutableList.of())) |
| .contains("-foo_dynamic_library_linker_flag"); |
| assertThat(ccToolchainProvider.getTestOnlyLinkOptions()).contains("-foo_test_only_linker_flag"); |
| |
| useConfiguration("--experimental_disable_legacy_crosstool_fields"); |
| ccToolchainProvider = getCcToolchainProvider(); |
| assertThat(ccToolchainProvider.getLegacyCompileOptions()).doesNotContain("-foo_compiler_flag"); |
| assertThat(ccToolchainProvider.getLegacyCxxOptions()).doesNotContain("-foo_cxx_flag"); |
| assertThat(ccToolchainProvider.getUnfilteredCompilerOptions()) |
| .doesNotContain("-foo_unfiltered_cxx_flag"); |
| assertThat(ccToolchainProvider.getLegacyLinkOptions()).doesNotContain("-foo_linker_flag"); |
| assertThat(ccToolchainProvider.getSharedLibraryLinkOptions(/* flags= */ ImmutableList.of())) |
| .doesNotContain("-foo_dynamic_library_linker_flag"); |
| assertThat(ccToolchainProvider.getTestOnlyLinkOptions()) |
| .doesNotContain("-foo_test_only_linker_flag"); |
| } |
| } |