Why is bazel still using -std=c++0x when I explicitly passed something else?
Linkopts are options given to the linker: https://docs.bazel.build/versions/master/be/c-cpp.html#cc_binary.linkopts
Have a look at this duplicate answer: https://stackoverflow.com/a/43388168/461597
For single executables you can use copts.
Related
I've set up my bazel crosstool so that I can specifically select the compiler that I want: gcc9, gcc10, ..., clang12, clang13... This works great.
bazel build --compiler=clang13 //:target
I'm scratching my head wondering how I achieve this with platforms! It seems to want to select whatever compiler you specify for the given platform, and if you want to change it, you have to edit the file!
In particular, if I want my compiler to be used by dependencies, whatever I do needs to be compatible with, for example, absl, and grpc.
Is there anyway to coerce toolchain selection via --config, --define, or other flags?
# In Workspace
register_toolchains("//toolchains:gcc12",
"//toolchains:clang13",
"//toolchains:clang14",
...)
# But how do I tell it that I want clang13, or clang14???
bazel build --platform=linux_x86 //:target
Here are two ideas that could help you:
do not use register_toolchains() to make all toolchains known to bazel, but use https://bazel.build/reference/command-line-reference#flag--extra_toolchains (maybe based on a --config via the .bazelrc). This lets bazel only know about one compiler toolchain available for resolution. Of course with this approach you can't use different compiler toolchains for different targets.
make use of the constraint_setting()s defined here. https://bazel.build/configure/windows#clang references how this is done:
platform(
name = "x64_windows-clang-cl",
constraint_values = [
"#platforms//cpu:x86_64",
"#platforms//os:windows",
"#bazel_tools//tools/cpp:clang-cl",
],
)
Is there a way to control the Bazel build to generate wanted temp files for a list of source files instead of just using the command line option "--save_temps"?
One way is using a cc_binary, and add "-E" option in the "copts", but the obj file name will always have a ".o". This kind of ".o" files will be overwriten by the other build targets. I don't know how to control the compiler output file name in Bazel.
Any better ideas?
cc_library has an output group with the static library, which you can then extract. Something like this:
filegroup(
name = "extract_archive",
srcs = [":some_cc_library"],
output_group = "archive",
)
Many tools will accept the static archive instead of an object file. If the tool you're using does, then that's easy. If not, things get a bit more complicated.
Extracting the object file from the static archive is a bit trickier. You could use a genrule with the $(AR) Make variable, but that won't work with some C++ toolchains that require additional flags to configure architectures etc.
The better (but more complicated) answer is to follow the guidance in integrating with C++ rules. You can get the ar from the toolchain and the flags to use it in a custom rule, and then create an action to extract it. You could also access the OutputGroupInfo from the cc_library in the rule directly instead of using filegroup if you've already got a custom rule.
Thanks all for your suggestions.
Now I think I can solve this problem in two steps(Seems Bazel does not allow to combine two rules into one):
Step1, add a -E option like a normal cc_libary, we can call it a pp_library. It is easy.
Step2, in a new rules, its input is the target of pp_library, then in this rule find out the obj files(can be found via : action.outputs.to_list()) and copy them to the a new place via ctx.actions.run_shell() run_shell.
I take Bazel: copy multiple files to binary directory as a reference.
We're starting to use gRPC and are currently using bazel as our build tool. After an engineer pulls in updates to proto definitions, they'll need to proto compile. Due to the structure of our repository, the proto compile targets will be scattered in the repo.
The only option I'm seeing is to use a target naming convention so engineers just need to do something like bazel build //...:compile-proto. Are there other ways to make it easy for engineers to proto compile all updated proto definitions?
If you add a specific tag to each of them, you can use --build_tag_filters.
For example:
a_proto_library(
name = "compile-proto",
tags = ["a_proto"],
[...]
)
and then bazel build --build_tag_filters=a_proto //....
You can also wrap the rule in a macro to add the tag automatically.
I don't think //...:compile-proto is a valid target pattern, so unfortunately I'm not sure that that would work (not that you necessarily really want to rely on naming conventions anyway). See https://docs.bazel.build/versions/main/guide.html#specifying-targets-to-build
One option is to let bazel do all the updating for you. If you're already doing builds like bazel build //... to build everything, then once you pull in updates to proto definitions, another bazel build //... should rebuild only what has changed.
Another option is to find all rules using bazel query:
https://docs.bazel.build/versions/main/query.html
https://docs.bazel.build/versions/main/query-how-to.html
https://docs.bazel.build/versions/main/query.html#kind
Something like:
targets=$(bazel query "kind('java_proto_library', //...)")
bazel build $targets
Note that query with //... will load every build file in the workspace, but not build anything.
I have a qmake project in which I cannot debug because something adds -O2 -g to the end of the compiler flags in debug mode, overriding all my debug and optimization flags. I have greped the whole project for -O2 and there is none (I removed the one I had for release). Deleting the build folder and running qmake again didn't help. I'm trying to track down what adds compiler flags, but I'm missing something.
Known things that can add compiler flags:
QMAKE_CXXFLAGS - Adds flags as given in all builds.
QMAKE_CXXFLAGS_DEBUG - Adds flags as given in debug builds.
QMAKE_CXXFLAGS_RELEASE - Adds flags as given in release builds.
CONFIG - Adds flags that are difficult to trace. CONFIG += strict_c++ and CONFIG += c++17 managed to not have my -std=c++17 overwritten, but I can't tell what other flags that adds. Also the qmake call contains CONFIG+=debug which may or may not add other flags. I can't tell from the documentation.
mkspec - In projects->build it lists the effective qmake call which includes for example -spec linux-g++ which I think includes /usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++/qmake.conf which includes more files which add platform-dependent flags. Removing the spec flag didn't remove the undesired -O2 flag though. Also it works for other projects, so it's probably not the culprit.
TEMPLATE - Specifies how the project is organized. Normally it's just APP, but this one uses subdirs which may override flags as all sub projects need to have the same flags.
An ideal answer would list all ways to add compiler flags, in which order they are added, an explanation how to check what flags they add and how to change them.
What qmake does it simply produces a makefile. A generated Makefile only uses compiler flags from CXXFLAGS (plus DEFINES) and INCPATH make variables, unless you have some handcrafted rules. It is clearly viewable from a generated makefile.
And these make variables come directly from qmake vars, such as QMAKE_CXXFLAGS, DEFINES and INCLUDEPATH. (This is done internally in qmake source code; well, actually the stuff could be more complicated on some platforms, so refer to qmake source code too).
Now, QMAKE_CXXFLAGS is just a qmake's variable. So, in principle, it can be modified at any line of any qmake script. Given that these scripts depend on OS/arch/compiler/Qt build options/App options etc. your expectations of "an ideal answer" are overstretched too far.
But, roughly speaking, qmake sources its scripts in the following order (hint: see full dependency list in a generated makefile):
features/spec_pre.prf
<QMAKE-SPEC>/qmake.conf (usually includes features/qt_config.prf and a ton of Qt-related stuff)
features/spec_post.prf
features/default_pre.prf
<user project>
features/default_post.prf
all features/xxx.prf according to the final CONFIG value (note: order reversed!)
So if you miss some flag in your project, it probably originates either from default_post.prf (like release flags for release build), or from CONFIG (i.e. features/xxx.prf).
I was wondering if its possible for platform-specific default Bazel build flags.
For example, we want to use --workspace_status_command but this must be a shell script on Linux and must point towards a batch script for Windows.
Is there a way we can write in the tools/bazel.rc file something like...
if platform=WINDOWS build: --workspace_status_command=status_command.bat
if platform=LINUX build: --workspace_status_command=status_command.sh
We could generate a .bazelrc file by having the users run a script before building, but it would be cleaner/nicer if this was not neccessary.
Yes, kind of. You can specify config-specific bazelrc entries, which you can select by passing --config=<configname>.
For example your bazelrc could look like:
build:linux --cpu=k8
build:linux --workspace_status_command=/path/to/command.sh
build:windows --cpu=x64_windows
build:windows --workspace_status_command=c:/path/to/command.bat
And you'd build like so:
bazel build --config=linux //path/to:target
or:
bazel build --config=windows //path/to:target
You have to be careful not to mix semantically conflicting --config flags (Bazel doesn't prevent you from that). Though it will work, the results may be unpredictable when the configs tinker with the same flags.
Passing --config to all commands is tricky, it depends on developers remembering to do this, or controlling the places where Bazel is called.
I think a better answer would be to teach the version control system how to produce the values, like by putting a git-bazel-stamp script on the $PATH/%PATH% so that git bazel-stamp works.
Then we need workspace_status_command to allow commands from the PATH rather than a path on disk.
Proper way to do this is to wrap your cc_library with a custom macro, and pass hardcoded flags to copts. For full reference, look at envoy_library.bzl.
In short, your steps:
Define a macro to wrap cc_library:
def my_cc_library(
name,
copts=[],
**kwargs):
cc_library(name, copts=copts + my_flags(), **kwargs)
Define my_flags() macro as following:
config_setting(
name = "windows_x86_64",
values = {"cpu": "x64_windows"},
)
config_setting(
name = "linux_k8",
values = {"cpu": "k8"},
)
def my_flags():
x64_windows_options = ["/W4"]
k8_options = ["-Wall"]
return select({
":windows_x86_64": x64_windows_options,
":linux_k8": k8_options,
"//conditions:default": [],
})
How it works:
Depending on --cpu flag value my_flags() will return different flags.
This value is resolved automatically based on a platform. On Windows, it's x64_windows, and on Linux it's k8.
Then, your macro my_cc_library will supply this flags to every target in a project.
A better way of doing this has been added since you asked--sometime in 2019.
If you add
common --enable_platform_specific_config to your .bazelrc, then --config=windows will automatically apply on windows hosts, --config=macos on mac, --config=linux on linux, etc.
You can then add lines to your .bazelrc like:
build:windows --windows-flags
build:linux --linux-flags
There is one downside, though. This works based on the host rather than the target. So if you're cross-compiling, e.g. to mobile, and want different flags there, you'll have to go with a solution like envoy's (see other answer), or (probably better) add transitions into your graph targets. (See discussion here and here. "Flagless builds" are still under development, but there are usable hacks in the meantime.) You could also use the temporary platform_mappings API.
References:
Commit that added this functionality.
Where it appears in the Bazel docs.