// Copyright 2014 Google Inc. 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.workspace; import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.Type.LABEL; import com.google.devtools.build.lib.analysis.BaseRuleClasses.BaseRule; import com.google.devtools.build.lib.analysis.BlazeRule; 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; /** * Binds an existing target to a target in the virtual //external package. */ @BlazeRule(name = "bind", type = RuleClassType.WORKSPACE, ancestors = {BaseRule.class}, factoryClass = Bind.class) 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).

*/ .add(attr("actual", LABEL).allowedFileTypes()) .setWorkspaceOnly() .build(); } } /* ${ATTRIBUTE_SIGNATURE}

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

${ATTRIBUTE_DEFINITION}

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 could 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 binding 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 refer to external repositories' targets. For example, if there is a remote repository named @my-ssl imported in the WORKSPACE file. If the @my-ssl repository has a cc_library target //src:openssl-lib, you could make this target accessible for your program to depend on by using bind:

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

BUILD files cannot use labels that include a repository name ("@repository-name//package-name:target-name"), so the only way to depend on a target from another repository is to bind it in the WORKSPACE file and then refer to it by its aliased name in //external from a BUILD file.

For example, in a BUILD file, the bound target could 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 by 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 first lines might look like this:

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