# Copyright 2019 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. """Example C++ API usage""" load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") def _filter_none(input_list): filtered_list = [] for element in input_list: if element != None: filtered_list.append(element) return filtered_list def _cc_lib_impl(ctx): cc_toolchain = find_cpp_toolchain(ctx) feature_configuration = cc_common.configure_features( ctx = ctx, cc_toolchain = cc_toolchain, requested_features = ctx.features, unsupported_features = ctx.disabled_features, ) compilation_contexts = [] linking_contexts = [] for dep in ctx.attr.deps: if CcInfo in dep: compilation_contexts.append(dep[CcInfo].compilation_context) linking_contexts.append(dep[CcInfo].linking_context) (compilation_context, compilation_outputs) = cc_common.compile( name = ctx.label.name, actions = ctx.actions, feature_configuration = feature_configuration, cc_toolchain = cc_toolchain, public_hdrs = ctx.files.public_hdrs, private_hdrs = ctx.files.private_hdrs, srcs = ctx.files.srcs, includes = ctx.attr.includes, quote_includes = ctx.attr.quote_includes, system_includes = ctx.attr.system_includes, defines = ctx.attr.defines, user_compile_flags = ctx.attr.user_compile_flags, compilation_contexts = compilation_contexts, ) (linking_context, linking_outputs) = cc_common.create_linking_context_from_compilation_outputs( name = ctx.label.name, actions = ctx.actions, feature_configuration = feature_configuration, cc_toolchain = cc_toolchain, language = "c++", compilation_outputs = compilation_outputs, linking_contexts = linking_contexts, ) library = linking_outputs.library_to_link files = [] files.extend(compilation_outputs.objects) files.extend(compilation_outputs.pic_objects) files.append(library.pic_static_library) files.append(library.static_library) files.append(library.dynamic_library) return [ DefaultInfo( files = depset(_filter_none(files)), ), CcInfo( compilation_context = compilation_context, linking_context = linking_context, ), ] cc_lib = rule( implementation = _cc_lib_impl, attrs = { "public_hdrs": attr.label_list(allow_files = [".h"]), "private_hdrs": attr.label_list(allow_files = [".h"]), "srcs": attr.label_list(allow_files = [".cc"]), "deps": attr.label_list( allow_empty = True, providers = [[CcInfo]], ), "user_compile_flags": attr.string_list(), "user_link_flags": attr.string_list(), "includes": attr.string_list(), "quote_includes": attr.string_list(), "system_includes": attr.string_list(), "defines": attr.string_list(), "alwayslink": attr.bool(default = False), "_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"), }, fragments = ["cpp"], toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], ) def _cc_bin_impl(ctx): cc_toolchain = find_cpp_toolchain(ctx) feature_configuration = cc_common.configure_features( ctx = ctx, cc_toolchain = cc_toolchain, requested_features = ctx.features, unsupported_features = ctx.disabled_features, ) compilation_contexts = [] linking_contexts = [] for dep in ctx.attr.deps: if CcInfo in dep: compilation_contexts.append(dep[CcInfo].compilation_context) linking_contexts.append(dep[CcInfo].linking_context) (_compilation_context, compilation_outputs) = cc_common.compile( name = ctx.label.name, actions = ctx.actions, feature_configuration = feature_configuration, cc_toolchain = cc_toolchain, srcs = ctx.files.srcs, compilation_contexts = compilation_contexts, ) output_type = "dynamic_library" if ctx.attr.linkshared else "executable" user_link_flags = [] for user_link_flag in ctx.attr.user_link_flags: user_link_flags.append(ctx.expand_location(user_link_flag, targets = ctx.attr.additional_linker_inputs)) malloc = ctx.attr._custom_malloc or ctx.attr.malloc linking_contexts.append(malloc[CcInfo].linking_context) linking_outputs = cc_common.link( name = ctx.label.name, actions = ctx.actions, feature_configuration = feature_configuration, cc_toolchain = cc_toolchain, language = "c++", compilation_outputs = compilation_outputs, linking_contexts = linking_contexts, user_link_flags = user_link_flags, link_deps_statically = ctx.attr.linkstatic, stamp = ctx.attr.stamp, additional_inputs = ctx.files.additional_linker_inputs, output_type = output_type, ) files = [] if output_type == "executable": files.append(linking_outputs.executable) elif output_type == "dynamic_library": files.append(linking_outputs.library_to_link.dynamic_library) files.append(linking_outputs.library_to_link.resolved_symlink_dynamic_library) return [ DefaultInfo( files = depset(_filter_none(files)), runfiles = ctx.runfiles(files = ctx.files.data), ), ] cc_bin = rule( implementation = _cc_bin_impl, attrs = { "srcs": attr.label_list(allow_files = [".cc"]), "additional_linker_inputs": attr.label_list( allow_empty = True, allow_files = [".lds"], ), "deps": attr.label_list( allow_empty = True, providers = [CcInfo], ), "data": attr.label_list( default = [], allow_files = True, ), "user_link_flags": attr.string_list(), "linkstatic": attr.bool(default = True), "linkshared": attr.bool(default = False), "stamp": attr.int(default = -1), "malloc": attr.label( default = "@bazel_tools//tools/cpp:malloc", providers = [CcInfo], ), # Exposes --custom_malloc flag, if you really need behavior to match # native.cc_binary and have that override the malloc attr. "_custom_malloc": attr.label( default = configuration_field( fragment = "cpp", name = "custom_malloc", ), providers = [CcInfo], ), "_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"), }, fragments = ["cpp"], toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], )