Search code examples
c++gccldbazel

How can I control what symbols are exported from a shared library in Bazel?


I'm learning Bazel, because I have to use it at work. I have a simple build rule that creates a library from a single file and I would like control what is exported by the linker by using a linker version file. (I'm on Linux)

So I tried:

cc_library (
    name ="thelib",
    srcs = ["lib.cpp"],
    linkopts = ["-Wl,--version-script,lib.ver"]
)

And it tells me "No such file or directory".

What have I tried:

  • I tried a path relative to the directory I issue the bazel build command with no avail.
  • cc_library()'s documentation says "linkopts" support make variable substitution so I listed the make variables with bazel info --show_make_env it showed me a variable called workspace so I then tried $(workspace)/lib/lib.ver but then it says $(workspace) not defined so Bazel is a liar.
  • The only thing that works is spelling the absolute path to the linker script but I don't want to push that.
  • cc_library() has a win_def_file option but guess what, that's Windows only.
  • A self-closed github issue suggests that I should pass the filename as a separate argument, it doesn't work either.
  • Using -fvisiblity=hidden and export using __attribute__ to export is not an option because the standard C++ library overrides it and forces exporting of the symbols you don't want to appear on the interface (the library is used using extern "C" interface only I don't want any other garbage appear on it).
  • There doesn't seem to be an option in Bazel to specify the symbols to export natively.

At this point I completely ran out of ideas. Any help is appreciated.


Solution

  • First of all, shared libraries are generally declared with cc_binary in conjunction with its linkshared attribute rather than cc_library. This is counterintuitive but reflects the intention that cc_binary creates a transitive link while cc_library declares an intermediate library. (More adventurous folks may try out cc_shared_library

    Second of all, it's possible to use version scripts (and other linker scripts) by using them in linkopts and declaring them as a dependency in deps.

    So, all together:

    cc_binary(
       name = 'mylib.so',
       linkshared = True,
       srcs = ['mylib.cc'],
       linkopts = ['-Wl,-version-script=$(location version-script.lds)'],
       deps = [
          'version-script.lds',
       ]
    )