Adam Snaider
Adam Snaider

Reputation: 198

Bazel cc_library with no srcs doesn't compile on its own

I have a cc_library that is header-only. Whenever I try to compile such library by itself, it won't actually compile anything. I purposely put some errors to try to get such errors on compilation, but bazel doesn't actually compile anything. Here's a small example.

// test.h

This should not compile fdsafdsafdsa
int foo() { return 1; }
# BUILD

cc_library(
  name = 'test',
  hdrs = ['test.h']
)
// bazel build :test
INFO: Analyzed target //:test (2 packages loaded, 3 targets configured).
INFO: Found 1 target...
Target //:test up-to-date (nothing to build)
INFO: Elapsed time: 0.083s, Critical Path: 0.00s
INFO: 0 processes.
INFO: Build completed successfully, 1 total action

Is this behavior intended?

I also ran the same experiment but splitting the .h and .cc files, and in that case, I got the error when I compiled.

Upvotes: 2

Views: 2728

Answers (2)

Ondrej K.
Ondrej K.

Reputation: 9664

cc_library (other rules as well incl. pkg_tar for instance) does not have to have any sources. This is also valid:

cc_library(
    name = "empty",
    srcs = [],
)

And it is actually quite useful too. You may have configurable attributes such as deps (or srcs) where actual content is only applicable for certain conditions:

cc_binary(
    name = "mybinary",
    srcs = ["main.c"],
    deps = select({
        ":platform1": [":some_plat1_only_lib"],
        ":platform2": [":empty"],  # as defined in the above snippet
    }),
)

Or (since above you could have just as well used [] for :platform2 deps) where you have a larger tree and you expect developers to just depend on //somelib:somelib, you could use this empty library through an alias to give them a single label without having to worry about all the platform specific details and how providing certain function is handled where:

# somelib/BUILD:
alias(
    name = "somelib",
    actual = select({
        ":platform1": [":some_plat1_only_lib"],
        ":platform2": [":empty"],  # as defined in the above snippet
    }),
    visibility = ["//visibility:public"],  # set appropriately
)

And mybinary or any other target could now say:

cc_binary(
    name = "mybinary",
    srcs = ["main.c"],
    deps = ["//somelib"],
)

And of course, as the other answer here states, there are header only libraries.

Also in the example you've used in your question. (bazel or not) you would normally not (and it would not be very useful either) compile a header file on its own. You would only use its content and only then see the compiler fails as you attempt to build a source the header is #included from. That is for bazel build to fail, another target would have to depend on test and #include "test.h".

Upvotes: 3

DeducibleSteak
DeducibleSteak

Reputation: 1498

A header only library means that you don't need to build anything. Simply include the headers you need in your program and use them.

Upvotes: 2

Related Questions