// Copyright 2016 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 com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedMap; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.actions.CreateIncSymlinkAction; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; import java.util.Arrays; /** * An inclusion library that maps header files into a different directory. This * is mostly used for third party libraries that have version-specific sub-directories, * and also for libraries that provide architecture-dependent header files. * In both cases, we want normal code to be able to include files without requiring * the version number or the architecture name in the include statement. * *
Example: a cc_inc_library
rule in
* third_party/foo
has the name bar
. It will create a
* symlink in include_directory/third_party/foo/bar/third_party/foo
* pointing to third_party/foo/1.0
. This results in the include
* directory include_directory/third_party/foo/bar
to be used for
* compilations, which makes inclusions like
* #include "third_party/foo/header.h"
work.
*/
public abstract class CcIncLibrary implements RuleConfiguredTargetFactory {
private final CppSemantics semantics;
protected CcIncLibrary(CppSemantics semantics) {
this.semantics = semantics;
}
@Override
public ConfiguredTarget create(final RuleContext ruleContext)
throws RuleErrorException, InterruptedException {
FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext);
PathFragment packageFragment = ruleContext.getPackageDirectory();
// The rule needs a unique location for the include directory, which doesn't conflict with any
// other rule. For that reason, the include directory is at:
// configuration/package_name/_/target_name
// And then the symlink is placed at:
// configuration/package_name/_/target_name/package_name
// So that these inclusions can be resolved correctly:
// #include "package_name/a.h"
//
// The target of the symlink is:
// package_name/targetPrefix/
// All declared header files must be below that directory.
String expandedIncSymlinkAttr = ruleContext.attributes().get("prefix", Type.STRING);
// We use an additional "_" directory here to avoid conflicts between this and previous Blaze
// versions. Previous Blaze versions created a directory symlink; the new version does not
// detect that the output directory isn't a directory, and tries to put the symlinks into what
// is actually a symlink into the source tree.
PathFragment includeDirectory = new PathFragment("_")
.getRelative(ruleContext.getTarget().getName());
PathFragment includePath = ruleContext.getConfiguration()
.getIncludeDirectory(ruleContext.getRule().getRepository()).getExecPath()
.getRelative(packageFragment)
.getRelative(includeDirectory);
// For every source artifact, we compute a virtual artifact that is below the include directory.
// These are used for include checking.
PathFragment prefixFragment = packageFragment.getRelative(expandedIncSymlinkAttr);
if (!prefixFragment.isNormalized()) {
ruleContext.attributeWarning("prefix", "should not contain '.' or '..' elements");
}
ImmutableSortedMap.Builder