// Copyright 2014 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.repository; import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.BuildType.LABEL; import com.google.devtools.build.lib.analysis.BaseRuleClasses.BaseRule; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.util.FileTypeSet; /** * Binds an existing target to a target in the virtual //external package. */ public final class BindRule implements RuleDefinition { @Override public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) { return builder /* The target to be aliased.

This target must exist, but can be any type of rule (including bind).

If this attribute is omitted, rules referring to this target in //external will simply not see this dependency edge. Note that this is different from omitting the bind rule completely: it is an error if an //external dependency does not have an associated bind rule.

*/ .add(attr("actual", LABEL).allowedFileTypes(FileTypeSet.ANY_FILE)) .setWorkspaceOnly() .canHaveAnyProvider() .build(); } @Override public Metadata getMetadata() { return RuleDefinition.Metadata.builder() .name("bind") .type(RuleClassType.WORKSPACE) .ancestors(BaseRule.class) .factoryClass(Bind.class) .build(); } } /*

Warning: use of bind() is not recommended. See "Consider removing bind" for a long discussion of its issues and alternatives.

Gives a target an alias in the //external package.

The //external package is not a "normal" package: there is no external/ directory, so it can be thought of as a "virtual package" that contains all bound targets.

Examples

To give a target an alias, bind it in the WORKSPACE file. For example, suppose there is a java_library target called //third_party/javacc-v2. This can be aliased by adding the following to the WORKSPACE file:

bind(
    name = "javacc-latest",
    actual = "//third_party/javacc-v2",
)

Now targets can depend on //external:javacc-latest instead of //third_party/javacc-v2. If javacc-v3 is released, the bind rule can be updated and all of the BUILD files depending on //external:javacc-latest will now depend on javacc-v3 without needing to be edited.

Bind can also be used to make targets in external repositories available to your workspace. For example, if there is a remote repository named @my-ssl imported in the WORKSPACE file and it has a cc_library target //src:openssl-lib, you can create an alias for this target using bind:

bind(
    name = "openssl",
    actual = "@my-ssl//src:openssl-lib",
)

Then, in a BUILD file in your workspace, the bound target can be used as follows:

cc_library(
    name = "sign-in",
    srcs = ["sign_in.cc"],
    hdrs = ["sign_in.h"],
    deps = ["//external:openssl"],
)

Within sign_in.cc and sign_in.h, the header files exposed by //external:openssl can be referred to using their path relative to their repository root. For example, if the rule definition for @my-ssl//src:openssl-lib looks like this:

cc_library(
    name = "openssl-lib",
    srcs = ["openssl.cc"],
    hdrs = ["openssl.h"],
)

Then sign_in.cc's includes might look like this:

#include "sign_in.h"
#include "src/openssl.h"
*/