Skip to content

Instantly share code, notes, and snippets.

@oquenchil
Created October 6, 2021 12:55
Show Gist options
  • Save oquenchil/3f88a39876af2061f8aad6cdc9d7c045 to your computer and use it in GitHub Desktop.
Save oquenchil/3f88a39876af2061f8aad6cdc9d7c045 to your computer and use it in GitHub Desktop.
Example cc_static_library.bzl
"""Provides a rule that outputs a monolithic static library."""
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
TOOLS_CPP_REPO = "@bazel_tools"
def _cc_static_library_impl(ctx):
output_lib = ctx.actions.declare_file("{}.a".format(ctx.attr.name))
output_flags = ctx.actions.declare_file("{}.link".format(ctx.attr.name))
cc_toolchain = find_cpp_toolchain(ctx)
lib_sets = []
unique_flags = {}
for dep in ctx.attr.deps:
if hasattr(dep[CcInfo].linking_context.libraries_to_link, "to_list"):
lib_sets.append(dep[CcInfo].linking_context.libraries_to_link)
else:
lib_sets.append(depset(direct = dep[CcInfo].linking_context.libraries_to_link))
unique_flags.update({
flag: None
for flag in dep[CcInfo].linking_context.user_link_flags
})
libraries_to_link = depset(transitive = lib_sets)
link_flags = unique_flags.keys()
libs = []
libs.extend([lib.pic_static_library for lib in libraries_to_link.to_list() if lib.pic_static_library])
libs.extend([
lib.static_library
for lib in libraries_to_link.to_list()
if lib.static_library and not lib.pic_static_library
])
script_file = ctx.actions.declare_file("{}.mri".format(ctx.attr.name))
commands = ["create {}".format(output_lib.path)]
for lib in libs:
commands.append("addlib {}".format(lib.path))
commands.append("save")
commands.append("end")
ctx.actions.write(
output = script_file,
content = "\n".join(commands) + "\n",
)
ctx.actions.run_shell(
command = "{} -M < {}".format(cc_toolchain.ar_executable, script_file.path),
inputs = [script_file] + libs + cc_toolchain.all_files.to_list(),
outputs = [output_lib],
mnemonic = "ArMerge",
progress_message = "Merging static library {}".format(output_lib.path),
)
ctx.actions.write(
output = output_flags,
content = "\n".join(link_flags) + "\n",
)
return [
DefaultInfo(files = depset([output_flags, output_lib])),
]
cc_static_library = rule(
implementation = _cc_static_library_impl,
attrs = {
"deps": attr.label_list(),
"_cc_toolchain": attr.label(
default = TOOLS_CPP_REPO + "//tools/cpp:current_cc_toolchain",
),
},
toolchains = [TOOLS_CPP_REPO + "//tools/cpp:toolchain_type"],
incompatible_use_toolchain_transition = True,
)
@Arnold1
Copy link

Arnold1 commented Jun 21, 2022

@oquenchil how to fix this issue?

ERROR: Skipping '//examples3:main': error loading package 'examples3': Every .bzl file must have a corresponding package, but '//:cc_library_static.bzl' does not have one. Please create a BUILD file in the same or any parent directory. Note that this BUILD file does not need to do anything except exist.
WARNING: Target pattern parsing failed.
ERROR: error loading package 'examples3': Every .bzl file must have a corresponding package, but '//:cc_library_static.bzl' does not have one. Please create a BUILD file in the same or any parent directory. Note that this BUILD file does not need to do anything except exist.
INFO: Elapsed time: 0.361s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (1 packages loaded)

my BUILD file:

load("//:cc_library_static.bzl", "cc_static_library")

package(
    default_visibility = ["//visibility:public"],
    licenses = ["notice"],
)

# Usage example of Yggdrasil Decision Forests as a library.
#
# Compile and run the example with:
#   bazel build //examples:beginner_cc --config=linux_cpp17 --config=linux_avx2
#   bazel-bin/examples/beginner_cc --alsologtostderr
#
# See the "Using the C++ library" section in the user manual for more details about the API.
# See the "Compile command-line-interface from source" section in the user manual for more details about the compilation flags.
#
#cc_binary(
cc_library(
    name = "mylib_a",
    srcs = [
        "lib/mylib.cc",
        "lib/mylib.hh",
    ],
    linkstatic = True,

    # Because this binary is defined in the Yggdrasil project directly, the
    # following dependencies are local. In your project you will probably use
    # a "http_archive" dependency:
    # https://docs.bazel.build/versions/master/repo/http.html#http_archive*
    #
    # See TensorFlow Decision Forests for an example (TF-DF imports YDF):
    #   https://github.com/tensorflow/decision-forests
    deps = [
        "@com_google_absl//absl/flags:flag",
        "//yggdrasil_decision_forests/dataset:all_dataset_formats",
        "//yggdrasil_decision_forests/dataset:data_spec",
        "//yggdrasil_decision_forests/dataset:data_spec_cc_proto",
        "//yggdrasil_decision_forests/dataset:data_spec_inference",
        "//yggdrasil_decision_forests/dataset:vertical_dataset_io",
        "//yggdrasil_decision_forests/learner:all_learners",
        "//yggdrasil_decision_forests/learner:learner_library",
        "//yggdrasil_decision_forests/metric",
        "//yggdrasil_decision_forests/metric:report",
        "//yggdrasil_decision_forests/model:model_library",
        "//yggdrasil_decision_forests/utils:filesystem",
        "//yggdrasil_decision_forests/utils:logging",
    ],
)

compile command:

bazel build --config=linux_cpp17 --config=linux_avx2 --incompatible_require_linker_input_cc_api=false //examples3:main
``

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment