1

I'm getting a failure when I try to compile glog with gflags support using Bazel. A github repo reproducing this problem and showing the compilation error message is here: https://github.com/dionescu/bazeltrunk.git

I suspect that the problem occurs because glog is finding and using the "config.h" file published by gflags. However, I do not understand why this happens and why the current structure of the build files results in such errors. One solution I found was to provide my own BUILD file for gflags where the config was in a separate dependency (just how glog does it in my example).

I would appreciate any help with understanding the issue in this example.

1 Answers1

1

The problem is that gflag's BUILD file is including its own config. Adding -H to glog.BUILD's copts yields:

. external/glog_archive/src/utilities.h
.. external/glog_archive/src/base/mutex.h
... bazel-out/local-fastbuild/genfiles/external/com_github_gflags_gflags/config.h
In file included from external/glog_archive/src/utilities.h:73:0,
                 from external/glog_archive/src/utilities.cc:32:
external/glog_archive/src/base/mutex.h:147:3: error: #error Need to implement mutex.h for your architecture, or #define NO_THREADS
 # error Need to implement mutex.h for your architecture, or #define NO_THREADS
   ^

If you take a look at gflag's config.h, it went with a not-very-helful approach of commenting out most of the config:

// ---------------------------------------------------------------------------
// System checks

// Define if you build this library for a MS Windows OS.
//cmakedefine OS_WINDOWS

// Define if you have the <stdint.h> header file.
//cmakedefine HAVE_STDINT_H

// Define if you have the <sys/types.h> header file.
//cmakedefine HAVE_SYS_TYPES_H
...

So nothing is defined.

Options:

The easiest way is probably to generate the config.h in your glog.BUILD:

genrule(
    name = "config",
    outs = ["config.h"],
    cmd = "cd external/glog_archive; ./configure; cd ../..; cp external/glog_archive/src/config.h $@",
    srcs = glob(["**"]),
)

# Then add the generated config to your glog target.
cc_library(
    name = "glog",
    srcs = [...],
    hdrs = [
        ":config.h",
        ...

This puts the .h file at a higher-precedence location than the gflags version.

Alternatively, you could do something like this in the genrule, if you want to use your //third_party/glog/config.h (@// is shorthand for your project's repository):

genrule(
    name = "config",
    outs = ["config.h"],
    cmd = "cp $(location @//third_party/glog:config.h) $@",
    srcs = ["@//third_party/glog:config.h"],
)

You'll have to add exports_files(['config.h']) to the third_party/glog/BUILD file, too.

kris
  • 23,024
  • 10
  • 70
  • 79
  • Thanks, Kristina! What I still don't understand is why gflags' config.h file is visible to glog at all. The gflags cc library rule has includes = ["include/"], and its config.h is not in the "include/" directory, so I would not expect it to be visible to other third party packages. Instead, I would have expected glog to find and use the config I give in glog.BUILD ("//external:glog_config"). If every config of every third party library in a repo would be visible to all other third_party libraries, then we would have a mess. So what am I missing here? – Dragos Ionescu Jul 25 '17 at 21:31
  • cc_library documentation mentions that "the compilation of a .cc file may transitively include any header file in the hdrs or srcs in any cc_library in the transitive deps closure." So maybe that's why glog can see gflags config file? Is using deps to specify the config bad practice because you cannot guaranteed precedence over config files from other 3p libraries? – Dragos Ionescu Jul 25 '17 at 22:43
  • `includes` is about the -I paths Bazel generates on the command line, it doesn't affect the files exposed. gflag's config.h is generated by the build rules, so it ends up in bazel-genfiles/external/com_github_gflags_gflags/config.h. Because you depend on anything from `@com_github_gflags_gflags`, `genfiles/external/com_github_gflags_gflags` is added to the `-I` paths (so you can refer to includes from the root of that repository). And config.h is in the sources of the `:gflags` target, so if it's available in the sandbox. – kris Jul 27 '17 at 14:14