aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com
diff options
context:
space:
mode:
authorGravatar Dmitry Lomov <dslomov@google.com>2015-12-10 13:48:35 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2015-12-10 20:15:38 +0000
commit20262fdf40be0ba7fc74cb03d552cadebd76af6d (patch)
treef9d19b486b6fc71f43d8270e709d3c74f0a8a05d /src/test/java/com
parent76d81db677e07ec21d21789c624bd85834cc9b21 (diff)
Open-source MockCcSupport and some tests for LibraryLinkingTest.
Also changed the setup of BazelAnalysisMock. -- MOS_MIGRATED_REVID=109890009
Diffstat (limited to 'src/test/java/com')
-rw-r--r--src/test/java/com/google/devtools/build/lib/BUILD4
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java61
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java12
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java130
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java189
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java298
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java10
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationHelper.java5
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoaderTest.java14
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/cpp/LibraryLinkingTest.java123
-rw-r--r--src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java2
11 files changed, 795 insertions, 53 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 8f2d50ce3a..e9e7afb4b4 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -535,9 +535,11 @@ java_library(
"//src/main/java/com/google/devtools/build/lib:runtime",
"//src/main/java/com/google/devtools/build/lib:util",
"//src/main/java/com/google/devtools/build/lib:vfs",
+ "//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/skyframe",
"//src/main/java/com/google/devtools/common/options",
"//src/main/protobuf:build_proto",
+ "//src/main/protobuf:crosstool_config_proto",
"//src/main/protobuf:extra_actions_base_proto",
"//third_party:guava",
"//third_party:guava-testlib",
@@ -926,12 +928,14 @@ java_test(
"//src/main/java/com/google/devtools/build/lib:bazel-rules",
"//src/main/java/com/google/devtools/build/lib:build-base",
"//src/main/java/com/google/devtools/build/lib:cmdline",
+ "//src/main/java/com/google/devtools/build/lib:common",
"//src/main/java/com/google/devtools/build/lib:util",
"//src/main/java/com/google/devtools/build/lib:vfs",
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/rules/cpp",
"//src/main/java/com/google/devtools/common/options",
"//src/main/protobuf:crosstool_config_proto",
+ "//src/test/java/com/google/devtools/build/lib:packages_testutil",
"//third_party:guava",
"//third_party:guava-testlib",
"//third_party:jsr305",
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
index 619ba2ff52..98d5a12b89 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
@@ -29,6 +29,8 @@ import com.google.devtools.build.lib.bazel.rules.BazelRuleClassProvider;
import com.google.devtools.build.lib.bazel.rules.python.BazelPythonConfiguration;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.util.BazelMockCcSupport;
+import com.google.devtools.build.lib.packages.util.MockCcSupport;
import com.google.devtools.build.lib.packages.util.MockToolsConfig;
import com.google.devtools.build.lib.rules.android.AndroidConfiguration;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
@@ -57,11 +59,11 @@ public final class BazelAnalysisMock extends AnalysisMock {
@Override
public void setupMockClient(MockToolsConfig config) throws IOException {
- String workspace = config.getPath("").getPathString();
+ String bazelToolWorkspace = config.getPath("/bazel_tools_workspace").getPathString();
ArrayList<String> workspaceContents =
new ArrayList<>(
ImmutableList.of(
- "local_repository(name = 'bazel_tools', path = '" + workspace + "')",
+ "local_repository(name = 'bazel_tools', path = '" + bazelToolWorkspace + "')",
"bind(",
" name = 'objc_proto_lib',",
" actual = '//objcproto:ProtocolBuffers_lib',",
@@ -70,12 +72,12 @@ public final class BazelAnalysisMock extends AnalysisMock {
" name = 'objc_proto_cpp_lib',",
" actual = '//objcproto:ProtocolBuffersCPP_lib',",
")",
- "bind(name = 'android/sdk', actual='//tools/android:sdk')",
- "bind(name = 'tools/cpp', actual='//tools/cpp')",
+ "bind(name = 'android/sdk', actual='@bazel_tools//tools/android:sdk')",
"bind(name = 'tools/python', actual='//tools/python')"));
config.overwrite("WORKSPACE", workspaceContents.toArray(new String[workspaceContents.size()]));
- config.create("tools/jdk/BUILD",
+ config.create(
+ "/bazel_tools_workspace/tools/jdk/BUILD",
"package(default_visibility=['//visibility:public'])",
"java_toolchain(name = 'toolchain', encoding = 'UTF-8', source_version = '8', ",
" target_version = '8')",
@@ -89,48 +91,17 @@ public final class BazelAnalysisMock extends AnalysisMock {
"filegroup(name='java', srcs = ['jdk/jre/bin/java', 'dummy'])",
"exports_files(['JavaBuilder_deploy.jar','SingleJar_deploy.jar',",
" 'JavaBuilderCanary_deploy.jar', 'ijar', 'GenClass_deploy.jar'])");
- config.create("tools/cpp/BUILD",
- "cc_library(name = 'stl')",
- "cc_library(name = 'malloc')",
- "filegroup(name = 'toolchain', ",
- " srcs = [':cc-compiler-local', ':cc-compiler-darwin', ':cc-compiler-piii',",
- " ':cc-compiler-armeabi-v7a', ':empty'],",
- ")",
- "cc_toolchain(name = 'cc-compiler-k8', all_files = ':empty', compiler_files = ':empty',",
- " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ",
- " linker_files = ':empty',",
- " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',",
- ")",
- "cc_toolchain(name = 'cc-compiler-piii', all_files = ':empty', compiler_files = ':empty',",
- " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ",
- " linker_files = ':empty',",
- " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',",
- ")",
- "cc_toolchain(name = 'cc-compiler-darwin', all_files = ':empty', ",
- " compiler_files = ':empty',",
- " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ",
- " linker_files = ':empty',",
- " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',",
- ")",
- "cc_toolchain(name = 'cc-compiler-armeabi-v7a', all_files = ':empty', ",
- " compiler_files = ':empty',",
- " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ",
- " linker_files = ':empty',",
- " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',",
- ")");
- config.create(
- "tools/cpp/CROSSTOOL", readFromResources("com/google/devtools/build/lib/MOCK_CROSSTOOL"));
ImmutableList<String> androidBuildContents = createAndroidBuildContents();
config.create(
- "tools/android/BUILD",
+ "/bazel_tools_workspace/tools/android/BUILD",
androidBuildContents.toArray(new String[androidBuildContents.size()]));
- config.create("tools/genrule/BUILD",
- "exports_files(['genrule-setup.sh'])");
config.create(
- "third_party/java/jarjar/BUILD",
+ "/bazel_tools_workspace/tools/genrule/BUILD", "exports_files(['genrule-setup.sh'])");
+ config.create(
+ "/bazel_tools_workspace/third_party/java/jarjar/BUILD",
"package(default_visibility=['//visibility:public'])",
"licenses(['notice'])",
"java_binary(name = 'jarjar_bin',",
@@ -139,13 +110,14 @@ public final class BazelAnalysisMock extends AnalysisMock {
"java_import(name = 'jarjar_import',",
" jars = [ 'jarjar.jar' ])");
- config.create("tools/test/BUILD", "filegroup(name = 'runtime')");
+ config.create("/bazel_tools_workspace/tools/test/BUILD", "filegroup(name = 'runtime')");
config.create(
- "tools/python/BUILD",
+ "/bazel_tools_workspace/tools/python/BUILD",
"package(default_visibility=['//visibility:public'])",
"exports_files(['precompile.py'])",
"sh_binary(name='2to3', srcs=['2to3.sh'])");
+ ccSupport().setup(config);
}
private ImmutableList<String> createAndroidBuildContents() {
@@ -257,4 +229,9 @@ public final class BazelAnalysisMock extends AnalysisMock {
public ImmutableList<Class<? extends FragmentOptions>> getBuildOptions() {
return BazelRuleClassProvider.BUILD_OPTIONS;
}
+
+ @Override
+ public MockCcSupport ccSupport() {
+ return BazelMockCcSupport.INSTANCE;
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java
index dbe8f37ff8..ec577ebd67 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java
@@ -19,6 +19,7 @@ import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.ConfigurationCollectionFactory;
import com.google.devtools.build.lib.analysis.config.ConfigurationFactory;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
+import com.google.devtools.build.lib.packages.util.MockCcSupport;
import com.google.devtools.build.lib.packages.util.MockToolsConfig;
import com.google.devtools.build.lib.rules.repository.LocalRepositoryFunction;
import com.google.devtools.build.lib.rules.repository.LocalRepositoryRule;
@@ -70,6 +71,12 @@ public abstract class AnalysisMock {
public abstract ImmutableList<Class<? extends FragmentOptions>> getBuildOptions();
+ public abstract MockCcSupport ccSupport();
+
+ public void setupCcSupport(MockToolsConfig config) throws IOException {
+ get().ccSupport().setup(config);
+ }
+
public ImmutableMap<SkyFunctionName, SkyFunction> getSkyFunctions(BlazeDirectories directories) {
// Some tests require the local_repository rule so we need the appropriate SkyFunctions.
RepositoryFunction localRepositoryFunction = new LocalRepositoryFunction();
@@ -110,6 +117,11 @@ public abstract class AnalysisMock {
}
@Override
+ public MockCcSupport ccSupport() {
+ return delegate.ccSupport();
+ }
+
+ @Override
public Collection<String> getOptionOverrides() {
return delegate.getOptionOverrides();
}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java
new file mode 100644
index 0000000000..fde98b6f0a
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java
@@ -0,0 +1,130 @@
+// Copyright 2015 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.packages.util;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.ByteStreams;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Bazel implementation of {@link MockCcSupport}
+ */
+public final class BazelMockCcSupport extends MockCcSupport {
+
+ public static final BazelMockCcSupport INSTANCE = new BazelMockCcSupport();
+ /** Filter to remove implicit dependencies of C/C++ rules. */
+ private static final Predicate<String> CC_LABEL_NAME_FILTER =
+ new Predicate<String>() {
+ @Override
+ public boolean apply(String label) {
+ return !label.startsWith("@blaze_tools//tools/cpp/stl");
+ }
+ };
+
+ private BazelMockCcSupport() {}
+
+ private static final ImmutableList<String> CROSSTOOL_ARCHS =
+ ImmutableList.of("piii", "k8", "armeabi-v7a");
+
+ protected static void createBasePackage(MockToolsConfig config) throws IOException {
+ config.create(
+ "base/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_library(name = 'system_malloc', linkstatic = 1)",
+ "cc_library(name = 'base', srcs=['timestamp.h'])");
+ if (config.isRealFileSystem()) {
+ config.linkTool("base/timestamp.h");
+ } else {
+ config.create("base/timestamp.h", "");
+ }
+ }
+
+ protected String getRealFilesystemCrosstoolTopPath() {
+ assert false;
+ return null;
+ }
+
+ protected String[] getRealFilesystemTools(String crosstoolTop) {
+ assert false;
+ return null;
+ }
+
+ protected ImmutableList<String> getCrosstoolArchs() {
+ return CROSSTOOL_ARCHS;
+ }
+
+ @Override
+ public void setup(MockToolsConfig config) throws IOException {
+ config.create(
+ "/bazel_tools_workspace/tools/cpp/BUILD",
+ "cc_library(name = 'stl')",
+ "cc_library(name = 'malloc')",
+ "filegroup(name = 'toolchain', ",
+ " srcs = [':cc-compiler-local', ':cc-compiler-darwin', ':cc-compiler-piii',",
+ " ':cc-compiler-armeabi-v7a', ':empty'],",
+ ")",
+ "cc_toolchain(name = 'cc-compiler-k8', all_files = ':empty', compiler_files = ':empty',",
+ " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ",
+ " linker_files = ':empty',",
+ " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',",
+ ")",
+ "cc_toolchain(name = 'cc-compiler-piii', all_files = ':empty', compiler_files = ':empty',",
+ " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ",
+ " linker_files = ':empty',",
+ " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',",
+ ")",
+ "cc_toolchain(name = 'cc-compiler-darwin', all_files = ':empty', ",
+ " compiler_files = ':empty',",
+ " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ",
+ " linker_files = ':empty',",
+ " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',",
+ ")",
+ "cc_toolchain(name = 'cc-compiler-armeabi-v7a', all_files = ':empty', ",
+ " compiler_files = ':empty',",
+ " cpu = 'local', dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ",
+ " linker_files = ':empty',",
+ " objcopy_files = ':empty', static_runtime_libs = [':empty'], strip_files = ':empty',",
+ ")");
+
+ config.create(
+ "/bazel_tools_workspace/tools/cpp/CROSSTOOL",
+ readFromResources("com/google/devtools/build/lib/MOCK_CROSSTOOL"));
+ }
+
+ protected String getMockCrosstoolVersion() {
+ return "gcc-4.4.0-glibc-2.3.6";
+ }
+
+ protected String readCrosstoolFile() throws IOException {
+ return readFromResources("com/google/devtools/build/lib/MOCK_CROSSTOOL");
+ }
+
+ public static String readFromResources(String filename) throws IOException {
+ InputStream in = BazelMockCcSupport.class.getClassLoader().getResourceAsStream(filename);
+ return new String(ByteStreams.toByteArray(in), UTF_8);
+ }
+
+ public String getMockCrosstoolPath() {
+ return "/bazel_tools_workspace/tools/cpp/";
+ }
+
+ public Predicate<String> labelNameFilter() {
+ return CC_LABEL_NAME_FILTER;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java b/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java
new file mode 100644
index 0000000000..455a43e60b
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java
@@ -0,0 +1,189 @@
+// Copyright 2015 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.packages.util;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.devtools.build.lib.vfs.Path;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A helper class to create a crosstool package containing a CROSSTOOL file, and the various
+ * rules needed for a mock - use this only for configured target tests, not for execution tests.
+ */
+final class Crosstool {
+ private static final ImmutableList<String> CROSSTOOL_BINARIES =
+ ImmutableList.of("compile", "dwp", "link", "objcopy");
+
+ private final MockToolsConfig config;
+
+ private final String crosstoolTop;
+ private String version;
+ private String crosstoolFileContents;
+ private boolean addEmbeddedRuntimes;
+ private String staticRuntimesLabel;
+ private String dynamicRuntimesLabel;
+ private ImmutableList<String> archs;
+ private boolean addModuleMap;
+ private boolean supportsHeaderParsing;
+
+ Crosstool(MockToolsConfig config, String crosstoolTop) {
+ this.config = config;
+ this.crosstoolTop = crosstoolTop;
+ }
+
+ public Crosstool setAddModuleMap(boolean addModuleMap) {
+ this.addModuleMap = addModuleMap;
+ return this;
+ }
+
+ public Crosstool setCrosstoolFile(String version, String crosstoolFileContents) {
+ this.version = version;
+ this.crosstoolFileContents = crosstoolFileContents;
+ return this;
+ }
+
+ public Crosstool setSupportedArchs(ImmutableList<String> archs) {
+ this.archs = archs;
+ return this;
+ }
+
+ public Crosstool setSupportsHeaderParsing(boolean supportsHeaderParsing) {
+ this.supportsHeaderParsing = supportsHeaderParsing;
+ return this;
+ }
+
+ public Crosstool setEmbeddedRuntimes(
+ boolean addEmbeddedRuntimes, String staticRuntimesLabel, String dynamicRuntimesLabel) {
+ this.addEmbeddedRuntimes = addEmbeddedRuntimes;
+ this.staticRuntimesLabel = staticRuntimesLabel;
+ this.dynamicRuntimesLabel = dynamicRuntimesLabel;
+ return this;
+ }
+
+ public void write() throws IOException {
+ String runtimes = "";
+ for (String arch : archs) {
+ runtimes +=
+ Joiner.on('\n')
+ .join(
+ "filegroup(name = 'dynamic-runtime-libs-" + arch + "',",
+ " licenses = ['unencumbered'],",
+ " srcs = ['libdynamic-runtime-lib-source.so'])",
+ "filegroup(name = 'static-runtime-libs-" + arch + "',",
+ " licenses = ['unencumbered'],",
+ " srcs = ['static-runtime-lib-source.a'])\n");
+ }
+
+ StringBuilder compilationTools = new StringBuilder();
+ for (String compilationTool : CROSSTOOL_BINARIES) {
+ Collection<String> archTargets = new ArrayList<>();
+ for (String arch : archs) {
+ archTargets.add(compilationTool + '-' + arch);
+ }
+
+ compilationTools.append(
+ String.format(
+ "filegroup(name = '%s', srcs = ['%s'])\n",
+ compilationTool,
+ Joiner.on("', '").join(archTargets)));
+ for (String archTarget : archTargets) {
+ compilationTools.append(
+ String.format("filegroup(name = '%s', srcs = [':everything-multilib'])\n", archTarget));
+ }
+ }
+
+ List<String> compilerRules = Lists.newArrayList();
+
+ for (String arch : archs) {
+ String compilerRule;
+ String staticRuntimesString =
+ staticRuntimesLabel == null ? "" : ", '" + staticRuntimesLabel + "'";
+ String dynamicRuntimesString =
+ dynamicRuntimesLabel == null ? "" : ", '" + dynamicRuntimesLabel + "'";
+
+ compilerRule =
+ Joiner.on("\n")
+ .join(
+ "cc_toolchain(",
+ " name = 'cc-compiler-" + arch + "',",
+ " output_licenses = ['unencumbered'],",
+ addModuleMap ? " module_map = 'crosstool.cppmap'," : "",
+ " cpu = '" + arch + "',",
+ " compiler_files = 'compile-" + arch + "',",
+ " dwp_files = 'dwp-" + arch + "',",
+ " linker_files = 'link-" + arch + "',",
+ " strip_files = ':every-file',",
+ " objcopy_files = 'objcopy-" + arch + "',",
+ " all_files = ':every-file',",
+ " licenses = ['unencumbered'],",
+ supportsHeaderParsing ? " supports_header_parsing = 1," : "",
+ " dynamic_runtime_libs = ['dynamic-runtime-libs-"
+ + arch
+ + "'"
+ + dynamicRuntimesString
+ + "],",
+ " static_runtime_libs = ['static-runtime-libs-"
+ + arch
+ + "'"
+ + staticRuntimesString
+ + "])");
+
+ compilationTools.append(compilerRule + "\n");
+ compilerRules.add(":cc-compiler-" + arch);
+ }
+
+ String build =
+ Joiner.on("\n")
+ .join(
+ "package(default_visibility=['//visibility:public'])",
+ "licenses(['restricted'])",
+ "",
+ "filegroup(name = 'everything-multilib',",
+ " srcs = glob(['" + version + "/**/*'],",
+ " exclude_directories = 1),",
+ " output_licenses = ['unencumbered'])",
+ "",
+ String.format(
+ "filegroup(name = 'everything', srcs = ['%s', ':every-file'])",
+ Joiner.on("', '").join(compilerRules)),
+ "",
+ String.format(
+ "filegroup(name = 'every-file', srcs = ['%s'%s%s])",
+ Joiner.on("', '").join(CROSSTOOL_BINARIES),
+ addEmbeddedRuntimes ? ", ':dynamic-runtime-libs-k8'" : "",
+ addEmbeddedRuntimes ? ", ':static-runtime-libs-k8'" : ""),
+ "",
+ compilationTools.toString(),
+ runtimes,
+ "",
+ // We add an empty :malloc target in case we need it.
+ "cc_library(name = 'malloc')");
+
+ config.create(crosstoolTop + "/" + version + "/x86/bin/gcc");
+ config.create(crosstoolTop + "/" + version + "/x86/bin/ld");
+ config.create(crosstoolTop + "/BUILD", build);
+ Path crosstoolPath = config.getPath(crosstoolTop + "/CROSSTOOL");
+ if (crosstoolPath.exists()) {
+ crosstoolPath.delete();
+ }
+ config.create(crosstoolTop + "/CROSSTOOL", crosstoolFileContents);
+ config.create(crosstoolTop + "/crosstool.cppmap", "module crosstool {}");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
new file mode 100644
index 0000000000..5313c403e5
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
@@ -0,0 +1,298 @@
+// Copyright 2015 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.packages.util;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Verify;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier.RepositoryName;
+import com.google.devtools.build.lib.testutil.TestConstants;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain;
+import com.google.protobuf.TextFormat;
+
+import java.io.IOException;
+
+/**
+ * Creates mock BUILD files required for the C/C++ rules.
+ */
+public abstract class MockCcSupport {
+
+ /**
+ * Filter to remove implicit crosstool artifact and module map inputs
+ * of C/C++ rules.
+ */
+ public static final Predicate<Artifact> CC_ARTIFACT_FILTER =
+ new Predicate<Artifact>() {
+ @Override
+ public boolean apply(Artifact artifact) {
+ String basename = artifact.getExecPath().getBaseName();
+ String pathString = artifact.getExecPathString();
+ return !pathString.startsWith("third_party/crosstool/")
+ && !(pathString.contains("/internal/_middlemen") && basename.contains("crosstool"))
+ && !pathString.startsWith("_bin/build_interface_so")
+ && !pathString.endsWith(".cppmap");
+ }
+ };
+
+ /**
+ * A feature configuration snippet useful for testing header processing.
+ */
+ public static final String HEADER_PROCESSING_FEATURE_CONFIGURATION =
+ ""
+ + "feature {"
+ + " name: 'parse_headers'"
+ + " flag_set {"
+ + " action: 'c++-header-parsing'"
+ + " flag_group {"
+ + " flag: '<c++-header-parsing>'"
+ + " }"
+ + " }"
+ + "}"
+ + "feature {"
+ + " name: 'preprocess_headers'"
+ + " flag_set {"
+ + " action: 'c++-header-preprocessing'"
+ + " flag_group {"
+ + " flag: '<c++-header-preprocessing>'"
+ + " }"
+ + " }"
+ + "}";
+
+ /**
+ * A feature configuration snippet useful for testing the layering check.
+ */
+ public static final String LAYERING_CHECK_FEATURE_CONFIGURATION =
+ ""
+ + "feature {"
+ + " name: 'layering_check'"
+ + " flag_set {"
+ + " action: 'c-compile'"
+ + " action: 'c++-compile'"
+ + " action: 'c++-header-parsing'"
+ + " action: 'c++-header-preprocessing'"
+ + " action: 'c++-module-compile'"
+ + " flag_group {"
+ + " flag: 'dependent_module_map_file:%{dependent_module_map_files}'"
+ + " }"
+ + " }"
+ + "}";
+
+ /**
+ * A feature configuration snippet useful for testing header modules.
+ */
+ public static final String HEADER_MODULES_FEATURE_CONFIGURATION =
+ ""
+ + "feature {"
+ + " name: 'header_modules'"
+ + " implies: 'module_maps'"
+ + " implies: 'use_header_modules'"
+ + "}"
+ + "feature {"
+ + " name: 'module_maps'"
+ + " flag_set {"
+ + " action: 'c-compile'"
+ + " action: 'c++-compile'"
+ + " action: 'c++-header-parsing'"
+ + " action: 'c++-header-preprocessing'"
+ + " action: 'c++-module-compile'"
+ + " flag_group {"
+ + " flag: 'module_name:%{module_name}'"
+ + " flag: 'module_map_file:%{module_map_file}'"
+ + " }"
+ + " }"
+ + "}"
+ + "feature {"
+ + " name: 'use_header_modules'"
+ + " flag_set {"
+ + " action: 'c-compile'"
+ + " action: 'c++-compile'"
+ + " action: 'c++-header-parsing'"
+ + " action: 'c++-header-preprocessing'"
+ + " action: 'c++-modules-compile'"
+ + " flag_group {"
+ + " flag: 'module_file:%{module_files}'"
+ + " }"
+ + " }"
+ + "}";
+
+ public static final String THIN_LTO_CONFIGURATION =
+ ""
+ + "feature { "
+ + " name: 'thin_lto'"
+ + " flag_set {"
+ + " action: 'c-compile'"
+ + " action: 'c++-compile'"
+ + " flag_group {"
+ + " flag: '-Xclang-only=-Wno-inconsistent-missing-override'"
+ + " flag: '-flto'"
+ + " flag: '-O2'"
+ + " }"
+ + " }"
+ + "}";
+
+ /** Filter to remove implicit dependencies of C/C++ rules. */
+ private final Predicate<Label> ccLabelFilter =
+ new Predicate<Label>() {
+ @Override
+ public boolean apply(Label label) {
+ return labelNameFilter().apply("//" + label.getPackageName());
+ }
+ };
+
+ public static String mergeCrosstoolConfig(String original, CToolchain toolchain)
+ throws TextFormat.ParseException {
+ CrosstoolConfig.CrosstoolRelease.Builder builder =
+ CrosstoolConfig.CrosstoolRelease.newBuilder();
+ TextFormat.merge(original, builder);
+ for (CToolchain.Builder toolchainBuilder : builder.getToolchainBuilderList()) {
+ toolchainBuilder.mergeFrom(toolchain);
+ }
+ return TextFormat.printToString(builder.build());
+ }
+
+ public abstract Predicate<String> labelNameFilter();
+
+ /**
+ * Setup the support for building C/C++.
+ */
+ public abstract void setup(MockToolsConfig config) throws IOException;
+
+ public void setupCrosstoolWithEmbeddedRuntimes(MockToolsConfig config) throws IOException {
+ createCrosstoolPackage(config, true);
+ }
+
+ /**
+ * Creates a crosstool package by merging {@code toolchain} with the default mock CROSSTOOL file.
+ *
+ * @param partialToolchain A string representation of a CToolchain protocol buffer; note that
+ * this is allowed to be a partial buffer (required fields may be omitted).
+ */
+ public void setupCrosstool(MockToolsConfig config, String partialToolchain) throws IOException {
+ CToolchain.Builder toolchainBuilder = CToolchain.newBuilder();
+ TextFormat.merge(partialToolchain, toolchainBuilder);
+ setupCrosstool(config, toolchainBuilder.buildPartial());
+ }
+
+ /**
+ * Creates a crosstool package by merging {@code toolchain} with the default mock CROSSTOOL file.
+ */
+ public void setupCrosstool(MockToolsConfig config, CToolchain toolchain) throws IOException {
+ createCrosstoolPackage(
+ config, /* addEmbeddedRuntimes= */ false, /* addModuleMap= */ true, null, null, toolchain);
+ }
+
+ /**
+ * Create a crosstool package. For integration tests, it actually links in a working crosstool,
+ * for all other tests, it only creates a dummy package, with a working CROSSTOOL file. The code
+ * here matches the declarations in {@link CrosstoolTestHelper}.
+ *
+ * <p>If <code>addEmbeddedRuntimes</code> is true, it also adds filegroups for the embedded
+ * runtimes.
+ */
+ public void setupCrosstool(
+ MockToolsConfig config,
+ boolean addEmbeddedRuntimes,
+ boolean addModuleMap,
+ String staticRuntimesLabel,
+ String dynamicRuntimesLabel,
+ CToolchain toolchain)
+ throws IOException {
+ createCrosstoolPackage(
+ config,
+ addEmbeddedRuntimes,
+ addModuleMap,
+ staticRuntimesLabel,
+ dynamicRuntimesLabel,
+ toolchain);
+ }
+
+ protected static void createToolsCppPackage(MockToolsConfig config) throws IOException {
+ config.create(
+ "tools/cpp/BUILD",
+ "cc_library(name = 'stl')",
+ "filegroup(name='toolchain', srcs=['//third_party/crosstool'])");
+ }
+
+ protected void createCrosstoolPackage(MockToolsConfig config, boolean addEmbeddedRuntimes)
+ throws IOException {
+ createCrosstoolPackage(config, addEmbeddedRuntimes, /*addModuleMap=*/ true, null, null, null);
+ }
+
+ protected String getCrosstoolTopPathForConfig(MockToolsConfig config) {
+ if (config.isRealFileSystem()) {
+ return getRealFilesystemCrosstoolTopPath();
+ } else {
+ return getMockCrosstoolPath();
+ }
+ }
+
+ public abstract String getMockCrosstoolPath();
+
+ public static PackageIdentifier getMockCrosstoolsTop() {
+ try {
+ return PackageIdentifier.create(
+ RepositoryName.create(TestConstants.TOOLS_REPOSITORY),
+ new PathFragment(TestConstants.TOOLS_REPOSITORY_PATH));
+ } catch (LabelSyntaxException e) {
+ Verify.verify(false);
+ throw new AssertionError();
+ }
+ }
+
+ protected void createCrosstoolPackage(
+ MockToolsConfig config,
+ boolean addEmbeddedRuntimes,
+ boolean addModuleMap,
+ String staticRuntimesLabel,
+ String dynamicRuntimesLabel,
+ CToolchain toolchain)
+ throws IOException {
+ String crosstoolTop = getCrosstoolTopPathForConfig(config);
+ if (config.isRealFileSystem()) {
+ config.linkTools(getRealFilesystemTools(crosstoolTop));
+ } else {
+ String crosstoolFile = readCrosstoolFile();
+ if (toolchain != null) {
+ crosstoolFile = mergeCrosstoolConfig(crosstoolFile, toolchain);
+ }
+ new Crosstool(config, crosstoolTop)
+ .setEmbeddedRuntimes(addEmbeddedRuntimes, staticRuntimesLabel, dynamicRuntimesLabel)
+ .setCrosstoolFile(getMockCrosstoolVersion(), crosstoolFile)
+ .setSupportedArchs(getCrosstoolArchs())
+ .setAddModuleMap(addModuleMap)
+ .setSupportsHeaderParsing(true)
+ .write();
+ }
+ }
+
+ protected abstract String getMockCrosstoolVersion();
+
+ protected abstract String readCrosstoolFile() throws IOException;
+
+ protected abstract ImmutableList<String> getCrosstoolArchs();
+
+ protected abstract String[] getRealFilesystemTools(String crosstoolTop);
+
+ protected abstract String getRealFilesystemCrosstoolTopPath();
+
+ public final Predicate<Label> labelFilter() {
+ return ccLabelFilter;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java
index 038b5f121b..9580205148 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockToolsConfig.java
@@ -79,8 +79,14 @@ public final class MockToolsConfig {
}
if (!newContent.toString().equals(existingContent)) {
- throw new IOException("Conflict: '" + relativePath + "':\n'" + newContent + "'\n vs \n'"
- + existingContent + "'");
+ throw new IOException(
+ "Conflict: '"
+ + relativePath
+ + "':\n'"
+ + newContent
+ + "'\n vs \n'"
+ + existingContent
+ + "'");
}
}
return path;
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationHelper.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationHelper.java
index f28af6dc0f..fa18959eea 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationHelper.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationHelper.java
@@ -14,7 +14,7 @@
package com.google.devtools.build.lib.rules.cpp;
-import com.google.devtools.build.lib.testutil.TestConstants;
+import com.google.devtools.build.lib.analysis.util.AnalysisMock;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
@@ -29,7 +29,8 @@ import java.io.IOException;
*/
public class CrosstoolConfigurationHelper {
public static Path overwriteCrosstoolFile(Path workspace, String content) throws IOException {
- Path crosstool = workspace.getRelative(TestConstants.MOCK_CROSSTOOL_PATH + "/CROSSTOOL");
+ Path crosstool =
+ workspace.getRelative(AnalysisMock.get().ccSupport().getMockCrosstoolPath() + "/CROSSTOOL");
long newMTime = crosstool.exists() ? crosstool.getLastModifiedTime() + 1 : -1;
crosstool.delete();
FileSystemUtils.createDirectoryAndParents(crosstool.getParentDirectory());
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoaderTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoaderTest.java
index fa0cc94f7b..9a1a7468ec 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoaderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoaderTest.java
@@ -31,8 +31,10 @@ import com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.util.AnalysisMock;
import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
+import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.packages.util.MockCcSupport;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -670,7 +672,7 @@ public class CrosstoolConfigurationLoaderTest extends AnalysisTestCase {
PackageIdentifier.create(
TestConstants.TOOLS_REPOSITORY,
new PathFragment(
- new PathFragment(TestConstants.MOCK_CROSSTOOL_PATH), new PathFragment(path)));
+ new PathFragment(TestConstants.TOOLS_REPOSITORY_PATH), new PathFragment(path)));
return packageIdentifier.getPathFragment();
}
@@ -989,17 +991,17 @@ public class CrosstoolConfigurationLoaderTest extends AnalysisTestCase {
+ " dynamic_runtimes_filegroup: \"dynamic-group\""
+ "}\n");
- final String ctTop = TestConstants.TOOLS_REPOSITORY + "//" + TestConstants.MOCK_CROSSTOOL_PATH;
+ final PackageIdentifier ctTop = MockCcSupport.getMockCrosstoolsTop();
CppConfiguration defaultLibs = create(loader, "--cpu=piii");
assertEquals(
- ctTop + ":static-runtime-libs-piii", defaultLibs.getStaticRuntimeLibsLabel().toString());
+ Label.create(ctTop, "static-runtime-libs-piii"), defaultLibs.getStaticRuntimeLibsLabel());
assertEquals(
- ctTop + ":dynamic-runtime-libs-piii", defaultLibs.getDynamicRuntimeLibsLabel().toString());
+ Label.create(ctTop, "dynamic-runtime-libs-piii"), defaultLibs.getDynamicRuntimeLibsLabel());
CppConfiguration customLibs = create(loader, "--cpu=k8");
- assertEquals(ctTop + ":static-group", customLibs.getStaticRuntimeLibsLabel().toString());
- assertEquals(ctTop + ":dynamic-group", customLibs.getDynamicRuntimeLibsLabel().toString());
+ assertEquals(Label.create(ctTop, "static-group"), customLibs.getStaticRuntimeLibsLabel());
+ assertEquals(Label.create(ctTop, "dynamic-group"), customLibs.getDynamicRuntimeLibsLabel());
}
/*
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/LibraryLinkingTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/LibraryLinkingTest.java
new file mode 100644
index 0000000000..9104187e76
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/LibraryLinkingTest.java
@@ -0,0 +1,123 @@
+// Copyright 2015 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 com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.Constants;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+/**
+ * Test for shared library linking {@link CppLinkAction}.
+ */
+@RunWith(JUnit4.class)
+public final class LibraryLinkingTest extends BuildViewTestCase {
+ private List<String> getLinkOpts(CppLinkAction linkAction, String... optionPatterns)
+ throws Exception {
+ // Strip the first parameter from the argv, which is the gcc command.
+ return linkAction.getRawLinkArgv().subList(1, optionPatterns.length + 3);
+ }
+
+ private void assertLinkopts(CppLinkAction linkAction, String... optionPatterns) throws Exception {
+ List<String> linkopts = getLinkOpts(linkAction, optionPatterns);
+ for (int i = 0; i < optionPatterns.length; i++) {
+ assertThat(linkopts.get(i)).matches(optionPatterns[i]);
+ }
+ }
+
+ @Test
+ public void testGeneratedLib() throws Exception {
+ ConfiguredTarget genlib =
+ scratchConfiguredTarget(
+ "genrule",
+ "thebinary.so",
+ "genrule(name = 'genlib',",
+ " outs = ['genlib.a'],",
+ " cmd = '')",
+ "cc_library(name = 'thelib',",
+ " srcs = [':genlib'],",
+ " linkstatic = 1)",
+ "cc_binary(name = 'thebinary.so',",
+ " deps = [':thelib'],",
+ " linkstatic = 1,",
+ " linkshared = 1)");
+ Artifact executable = getExecutable(genlib);
+ CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(executable);
+ assertLinkopts(
+ linkAction,
+ "-shared",
+ "-o",
+ Constants.PRODUCT_NAME + "-out/.+/genrule/thebinary.so",
+ "-Wl,-whole-archive",
+ Constants.PRODUCT_NAME + "-out/.+/genrule/genlib.a",
+ "-Wl,-no-whole-archive");
+ }
+
+ /**
+ * Tests that the shared library version of a cc_library includes linkopts settings
+ * in its link command line, but the archive library version doesn't.
+ */
+ @Test
+ public void testCcLibraryLinkopts() throws Exception {
+ scratch.overwriteFile(
+ "custom_malloc/BUILD",
+ "cc_library(name = 'custom_malloc',",
+ " srcs = ['custom_malloc.cc'],",
+ " linkopts = ['-Lmalloc_dir -lmalloc_opt']);");
+
+ ConfiguredTarget ccLib = getConfiguredTarget("//custom_malloc:custom_malloc");
+ final String linkOpt1 = "-Lmalloc_dir";
+ final String linkOpt2 = "-lmalloc_opt";
+
+ // Archive library version:
+ Artifact archiveLib =
+ Iterables.getOnlyElement(
+ Iterables.filter(
+ ccLib.getProvider(FileProvider.class).getFilesToBuild(),
+ new Predicate<Artifact>() {
+ @Override
+ public boolean apply(Artifact artifact) {
+ return artifact.getFilename().equals("libcustom_malloc.a");
+ }
+ }));
+ CppLinkAction archiveLink = (CppLinkAction) getGeneratingAction(archiveLib);
+ List<String> args = archiveLink.getArgv();
+ assertThat(args).doesNotContain(linkOpt1);
+ assertThat(args).doesNotContain(linkOpt2);
+
+ // Shared library version:
+ Artifact soLib =
+ Iterables.getOnlyElement(
+ ccLib
+ .getProvider(CcExecutionDynamicLibrariesProvider.class)
+ .getExecutionDynamicLibraryArtifacts());
+ // This artifact is generated by a SolibSymlinkAction, so we need to go back two levels.
+ CppLinkAction solibLink =
+ (CppLinkAction) getGeneratingAction(getGeneratingAction(soLib).getPrimaryInput());
+ args = solibLink.getArgv();
+ assertThat(args).contains(linkOpt1);
+ assertThat(args).contains(linkOpt2);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
index b6d3e54ee2..a2c073b67b 100644
--- a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
+++ b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
@@ -69,5 +69,5 @@ public class TestConstants {
public static final String TOOLS_REPOSITORY = "@bazel_tools";
- public static final String MOCK_CROSSTOOL_PATH = "tools/cpp";
+ public static final String TOOLS_REPOSITORY_PATH = "tools/cpp";
}