Error:
LINK : warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of other libs; use /NODEFAULTLIB:library
I am trying to depend on libsodium: https://download.libsodium.org/libsodium/releases/libsodium-1.0.17-stable-msvc.zip
Using the following Bazel configuration:
# WORKSPACE
new_local_repository(
name = "org_libsodium_sodium",
build_file = "third_party/sodium.BUILD",
path = "third_party/sodium",
)
# sodium.BUILD
config_setting(
name = "windows_dbg_build",
constraint_values = ["#bazel_tools//platforms:windows"],
values = {"compilation_mode": "dbg"},
)
config_setting(
name = "windows_fastbuild_build",
constraint_values = ["#bazel_tools//platforms:windows"],
values = {"compilation_mode": "fastbuild"},
)
config_setting(
name = "windows_opt_build",
constraint_values = ["#bazel_tools//platforms:windows"],
values = {"compilation_mode": "opt"},
)
cc_library(
name = "sodium",
srcs = select({
":windows_dbg_build": ["lib/dbg/libsodium.lib"],
":windows_fastbuild_build": ["lib/dbg/libsodium.lib"],
":windows_opt_build": ["lib/opt/libsodium.lib"],
"//conditions:default": ["lib/opt/libsodium.a"],
}),
hdrs = glob(["sodium/**/*.h"]),
defines = ["SODIUM_STATIC"],
visibility = ["//visibility:public"],
)
Is it correct to use the /MT and /MTd Runtime Library for Windows precompiled static libraries?
Any idea what I am doing wrong?
Kind regards,
Ryan
Related
I'm including a repository that has an extra_deps rule of the form:
maybe(
http_file,
name = "external_dependency",
downloaded_file_path = "foo.h",
sha256 = "<some_sha>",
urls = ["https://example.com/foo.h"],
)
If I have an existing repository, foo_repo, that provides foo.h, how can I substitute the target for it in place of external_dependency? http_file apparently provides #external_dependency//file, so I can't simply define an alias.
Using https://github.com/bazelbuild/bazel/blob/master/tools/build_defs/repo/http.bzl as a reference, you can define a custom repository rule that provides #external_dependency//file. For example:
def _repository_file(ctx):
ctx.file("WORKSPACE", "workspace(name = \"{name}\")".format(name = ctx.name))
ctx.file("file/BUILD.bazel", """
filegroup(
name = "file",
srcs = ["{}"],
visibility = ["//visibility:public"],
)
""".format(ctx.attr.source))
repository_file = repository_rule(
attrs = {"source": attr.label(mandatory = True, allow_single_file = True)},
implementation = _repository_file,
doc = """Analogue of http_file, but for a file in another repository.
Usage:
repository_file(
name = "special_file"
source = "#other_repo//path/to:special_file.txt",
)
""",
)
Now use:
repository_file(
name = "external_dependency",
source = "#foo_repo//path/to:foo.h",
)
I have the following in a BUILD file:
proto_library(
name = "proto_default_library",
srcs = glob(["*.proto"]),
visibility = ["//visibility:public"],
deps = [
"#go_googleapis//google/api:annotations_proto",
"#grpc_ecosystem_grpc_gateway//protoc-gen-openapiv2/options:options_proto",
],
)
genrule(
name = "generate-buf-image",
srcs = [
":buf_yaml",
":buf_breaking_image_json",
":protos",
],
exec_tools = [
":proto_default_library",
"//buf:generate-buf-image-sh",
"//buf:generate-buf-image",
],
outs = ["buf-image.json"],
cmd = "$(location //buf:generate-buf-image-sh) --buf-breaking-image-json=$(location :buf_breaking_image_json) $(location :protos) >$#",
)
While executing $(location //buf:generate-buf-image-sh), glob(["*.proto"]) of proto_default_library can be seen in the sandbox but the proto files of #go_googleapis//google/api:annotations_proto and #grpc_ecosystem_grpc_gateway//protoc-gen-openapiv2/options:options_proto cannot. The same goes for the dependencies of //buf:generate-buf-image-sh.
Do I need to explicitly list out all transitive dependencies so they can be processed by generate-buf-image? Is there a programmatic way to do that?
Since genrules are pretty generic, a genrule sees only the default provider of a target, which usually just has the main outputs of that target (e.g., for java_library, a jar of the classes of that library, for proto_library, the proto files of that library). So to get more detailed information, you would write a Starlark rule to access more specific providers. For example:
WORKSPACE:
load("#bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_proto",
sha256 = "66bfdf8782796239d3875d37e7de19b1d94301e8972b3cbd2446b332429b4df1",
strip_prefix = "rules_proto-4.0.0",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
"https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
],
)
load("#rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
rules_proto_dependencies()
rules_proto_toolchains()
defs.bzl:
def _my_rule_impl(ctx):
output = ctx.actions.declare_file(ctx.attr.name + ".txt")
args = ctx.actions.args()
args.add(output)
inputs = []
for src in ctx.attr.srcs:
proto_files = src[ProtoInfo].transitive_sources
args.add_all(proto_files)
inputs.append(proto_files)
ctx.actions.run(
inputs = depset(transitive = inputs),
executable = ctx.attr._tool.files_to_run,
arguments = [args],
outputs = [output],
)
return DefaultInfo(files = depset([output]))
my_rule = rule(
implementation = _my_rule_impl,
attrs = {
"srcs": attr.label_list(providers=[ProtoInfo]),
"_tool": attr.label(default = "//:tool"),
},
)
ProtoInfo is here: https://bazel.build/rules/lib/ProtoInfo
BUILD:
load(":defs.bzl", "my_rule")
proto_library(
name = "proto_a",
srcs = ["proto_a.proto"],
deps = [":proto_b"],
)
proto_library(
name = "proto_b",
srcs = ["proto_b.proto"],
deps = [":proto_c"],
)
proto_library(
name = "proto_c",
srcs = ["proto_c.proto"],
)
my_rule(
name = "foo",
srcs = [":proto_a"],
)
sh_binary(
name = "tool",
srcs = ["tool.sh"],
)
proto_a.proto:
package my_protos_a;
message ProtoA {
optional int32 a = 1;
}
proto_b.proto:
package my_protos_b;
message ProtoB {
optional int32 b = 1;
}
proto_c.proto:
package my_protos_c;
message ProtoC {
optional int32 c = 1;
}
tool.sh:
output=$1
shift
echo input protos: $# > $output
$ bazel build foo
INFO: Analyzed target //:foo (40 packages loaded, 172 targets configured).
INFO: Found 1 target...
Target //:foo up-to-date:
bazel-bin/foo.txt
INFO: Elapsed time: 0.832s, Critical Path: 0.02s
INFO: 5 processes: 4 internal, 1 linux-sandbox.
INFO: Build completed successfully, 5 total actions
$ cat bazel-bin/foo.txt
input protos: proto_a.proto proto_b.proto proto_c.proto
I have a bazel file that has to load two different requirements files:
load("#python_turing_libs//:requirements.bzl", "requirement")
or
load("#python_ampere_libs//:requirements.bzl", "requirement")
I was hoping to use bazel platforms to do this via:
# Define GPU constraint values
constraint_setting(name = "gpu")
constraint_value(name = "turing", constraint_setting = "gpu")
constraint_value(name = "ampere", constraint_setting = "gpu")
constraint_value(name = "none", constraint_setting = "gpu")
# Platform
platform(
name = "gpu_server",
constraint_values = [
"#platforms//os:linux",
"#platforms//cpu:x86_64",
":gpu",
],
)
select({
"#platforms//os:linux":
load("#python_perception_libs//:requirements.bzl", "requirement")
,
"//conditions:default": [],
})
syntax error at 'load': expected expression
or something, but clearly this syntax does not work
There isn't a mechanism to conditionally load from other bzl files, so instead, load both files, and use selects to select the different things within those files.
One issue is that the symbols have the same name in each file, and to address that you can have different symbols in the file that's doing the loading like this:
load("#python_turing_libs//:requirements.bzl", turing_requirement = "requirement")
load("#python_ampere_libs//:requirements.bzl", ampere_requirement = "requirement")
your_rule(
...
some_attribute = select({
":turing_condition": turing_requirement,
":ampere_condition": ampere_requirement,
})
...
)
When I try to compile a bazel project that uses gRPC reflection, I get the following error.
fatal error: external/com_github_grpc_grpc/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h: No such file or directory
In my WORKSPACE, I have the following bindings:
def _com_github_grpc_grpc():
external_http_archive("com_github_grpc_grpc")
external_http_archive("build_bazel_rules_apple")
# Rebind some stuff to match what the gRPC Bazel is expecting.
native.bind(
name = "protobuf_headers",
actual = "#com_google_protobuf//:protobuf_headers",
)
native.bind(
name = "libssl",
actual = "//external:ssl",
)
native.bind(
name = "cares",
actual = "//external:ares",
)
native.bind(
name = "grpc",
actual = "#com_github_grpc_grpc//:grpc++",
)
In my BUILD file, I have the following deps:
deps = [
"//external:protobuf_headers",
"//external:grpc",
],
What additional incantations do I need for the include at the top of the question?
After a spelunking through issues, I figured out that I need the following WORKSPACE
workspace(name = "xxx")
load("#bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "com_github_grpc_grpc",
strip_prefix = "grpc-master",
urls = ["https://github.com/grpc/grpc/archive/master.tar.gz"],
)
load("#com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
grpc_deps()
load("#com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")
grpc_extra_deps()
and the following BUILD:
cc_binary(
name = "ReflectionPlay",
copts = ["-std=c++17"],
srcs = ["reflection_play.cc"],
deps = [
"#com_github_grpc_grpc//:grpc++",
"#com_github_grpc_grpc//:grpc++_reflection",
"#com_github_grpc_grpc//:grpcpp_admin",
],
)
In the Bazel official documentation there is an example explaining how to create a Java library built from regular java files and files generated by a :gen_java_srcs rule. I rewrite this code here for ease of reading:
java_library(
name = "mylib",
srcs = glob(["*.java"]) + [":gen_java_srcs"],
deps = "...",
)
genrule(
name = "gen_java_srcs",
outs = [
"Foo.java",
"Bar.java",
],
...
)
Now in a C++ perspective, I am in a scenario where the genrule generates two kind of files: .hpp and .cpp:
genrule(
name = "gen_cpp_srcs",
outs = [
"myFile_1.hpp","myFile_2.hpp",...,"myFile_N.hpp",
"myFile.cpp","myFile_2.cpp",...,"myFile_N.cpp",
],
...
)
where N is some tens.
My problem/question is: how to write the cc_library rule, with an automatic dispatching of the hpp and cpp files into hdrs and srcs field?
I want something like:
cc_library(
name = "mylib",
srcs = glob(["*.cpp"]) + (howto: .cpp files of [":gen_cpp_srcs"]),
hdrs = glob(["*.hpp"]) + (howto: .hpp files of [":gen_cpp_srcs"]),
...
)
Some magic like:
output_filter(":gen_cpp_srcs","*.cpp")
would be perfect, but I do not know enough of Bazel to make it real.
Globs only get expanded when they're passed into rules, so you'll need to write a simple rule. I would package it like this (in a file named filter.bzl):
# The actual rule which does the filtering.
def _do_filter_impl(ctx):
return struct(
files = set([f for f in ctx.files.srcs if f.path.endswith(ctx.attr.suffix)]),
)
_do_filter = rule(
implementation = _do_filter_impl,
attrs = {
"srcs": attr.label_list(
mandatory = True,
allow_files = True,
),
"suffix": attr.string(
mandatory = True,
),
},
)
# A convenient macro to wrap the custom rule and cc_library.
def filtered_cc_library(name, srcs, hdrs, **kwargs):
_do_filter(
name = "%s_hdrs" % name,
visibility = ["//visibility:private"],
srcs = hdrs,
suffix = ".hpp",
)
_do_filter(
name = "%s_srcs" % name,
visibility = ["//visibility:private"],
srcs = srcs,
suffix = ".cpp",
)
native.cc_library(
name = name,
srcs = [ ":%s_srcs" % name ],
hdrs = [ ":%s_hdrs" % name ],
**kwargs
)
This is what my demo BUILD file looks like (I changed the globs so they both include *.cpp and *.hpp files; using the label of a genrule will work the same way):
load("//:filter.bzl", "filtered_cc_library")
filtered_cc_library(
name = "mylib",
srcs = glob(["*.*pp"]),
hdrs = glob(["*.*pp"]),
)
This is easy to extend to more sophisticated filtering by changing _do_filter_impl. In particular, changing suffix to an attr.string_list so you can accept multiple C/C++ source/header extensions seems like a good idea.
Depending on the genrule by name (:gen_cpp_srcs) will give you all of the outputs of the genrule, as you have noted. Instead, you can depend on the individual outputs of the genrule (e.g. hdrs = [:myFile.hpp] and srcs = [:myFile.cpp]).
See also the answer to Bazel & automatically generated cpp / hpp files.
Looks like you know the total number of files that should be generated. Can you put those in their own variables and then reuse them in both targets. Something like this in your BUILD file:
output_cpp_files = [
"myFile_1.cpp",
"myFile_2.cpp",
"myFile_3.cpp"
]
output_hpp_files = [
"myFile_1.hpp",
"myFile_2.hpp",
"myFile_3.hpp"
]
genrule(
name = "gen_cpp_srcs",
outs = output_cpp_files + output_hpp_files,
cmd = """
touch $(OUTS)
"""
)
cc_library(
name = "mylib",
srcs = output_cpp_files,
hdrs = output_hpp_files
)