How to check whether system has some header file using bazel build? - bazel

What I want to find is the existence of some platform specific header file.
For example, in source code there will be some #ifdef section like this.
#ifdef HAVE_XXX_H
//...do something
#else
//...do other thing
#endif
In Autoconf or Cmake, there exists dedicated macro or command for detecting platform specific header file or definition. So, I can easily set 'HAVE_XXX_H' as 1 or 0 according to the result of that macro.
Using bazel, how can I achieve this kind of thing?
Thanks.

If you are sure that the header is always present on a particular platform, use select() as elaborated by László.
If you actually need to detect the header at the build time, you will have to implement a custom repository_rule that will query the system and will generate a workspace with a header defining the macro.

You can use select().
Example: select() in cc_library.srcs. You can do the same in cc_library.hdrs.

Related

How to use --save_temps in Bazel rule instead of command line?

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.

clang-format header include guard

I'd like for the clang-format to check that each of my headers have the proper include guard.
For example, for the file dopelib/dopestuff/whatitisyo.h, I'd like the code to be formatted like this:
#ifndef DOPELIB_DOPESTUFF_WHATITISYO_H
#define DOPELIB_DOPESTUFF_WHATITISYO_H
/** Code here. **/
#endif // DOPELIB_DOPESTUFF_WHATITISYO_H
Can clnag-format check this structure and make sure that the include guard is there and that it is named appropriately with the file name in the #ifndef (sort of what cpplint does)?
As far as I know, clang-format doesn't currently support this.
However, you can do exactly this with clang-tidy (documented here). Invoke it like this:
clang-tidy -checks='-*,llvm-header-guard' -fix-errors myIncludeFile.h
Explanation:
The -* tells clang-tidy to disable all checks
The llvm-header-guard tells clang-tidy to enable the check which deals with include guards (documented here)
The -fix-errors tells clang-tidy to fix any resulting issues, even if it runs into other errors parsing the file
The llvm-header-guard expected format of the include-guards is exactly what you requested above; for example the file mydir/myfile.h would use MYDIR_MYFILE_H. I don't see any documentation which actually specifies that this is the format it uses, but I've verified at least version 6.0.0 does use that format.
Also see: clang include fixer, which does something similar.
The accepted solution may not work if
The project has a different file structure
Uses some extensions that clang does not understand
I have a script here: https://github.com/milasudril/texpainter/blob/master/devtools/include_guard_fix.py

Where can I see the actual values of BasedOnStyle?

Where can I see the actual key-value pairs set in Google style? I can't find the definition in the clang repository.
They can be found in the Format.cpp file of the clang lib.
https://github.com/llvm/llvm-project/blob/04ee232ff212b6c308e2ebc7b6125892681c54ae/clang/lib/Format/Format.cpp#L660
This is the start of the LLVM style, then the following functions after it hold the other pre-defined configuration settings. If you are looking at a different version of the code base, look for the function 'getPredefinedStyle' to find the sub-calls that are used based on the style chosen.

Does the preprocessor pass environment variables?

Does the preprocessor have a mechanism to access environment variables directly as defines, without the need to define them on the command line?
For instance,
SOME_VAR=foo gcc code.c
and
#if ENV_SOME_VAR == "foo"
#define SOME_VAR_IS_FOO
#endif
No, the standard C preprocessor has no such mechanism, and I'm not aware of any compiler extensions that provide such a feature either.
However, you can do this using a build system, such as Cmake or GNU Autoconf, the latter being a part of the GNU Autotools build system. A simple shell script would do this as well, though all of these options mean you'd need to test the environment variable to determine whether to define ENV_SOME_VAR, in which case, you might just define it using something like the following:
-DENV_SOME_VAR="${SOME_VAR:-unfoo}"
That would define ENV_SOME_VAR in your C file as the value of $SOME_VAR if it's set or to the string "unfoo" if $SOME_VAR is empty (null) or unset.

How can I check for a specified header file in Waf?

I'm using waf to build a C program. I'd like to check for the existence of a particular header file during the configuration phase. Is there a way to do that?
Ah, a bit of googling found the answer to my question: You can use the check method on Configuration objects, like so:
def configure(conf):
conf.check(header_name="stdbool.h")

Resources