Controlling the use of --whole-archive with Bazel cc_binary() rule

1.1k Views Asked by At

I would like to control the use of -whole-archive when linking a shared library (.so) using the cc_binary() rule.

The reason I'm using a cc_binary() rule to create a shared library is related to this thread: https://groups.google.com/forum/#!topic/bazel-discuss/NG4N84ar3BY

I have a liba.a that contains two function implementations: a(), a1() which are implemented in separate object files and archived into one .a file. the code is as follows:

a.c

void a() {
    puts("a");
}

a1.c

void a1() {                                                
    d();                                                   
}

BUILD file

cc_library(                                                
    name = 'a',                                            
    srcs = [ 'liba.a' ],                                   
    hdrs = [ 'a.h' ],                                      
    linkstatic = True,                                     
)

I would like to build a shared library that depends (links) with the above library:

b.c

void b() {
    a();
    puts("b");
}

BUILD file

cc_binary(                                                 
    name = 'libb.so',                                      
    srcs = [ 'b.c' ],                                      
    deps = [ ':a' ],                                       
    linkshared = True,                                     
)

What I would like to achieve is linking libb.so in such a way that it will only use liba.a for the required symbols, in this case it should only require the a.o object and link it into libb.so

I could not make this happen. When building, Bazel will use -whole-archive for liba.a which will result in containing the implementation of a1() as well when it is not required at all.

If the -whole-archive was not used, then resulted libb.so would have been built correctly, and there would have been no a1() symbol.

The reason that this is important, is that now libb.so when using -whole-archive will cause a dependency on d() for no reason.

This is the snippet output of the linkage command from running bazel build libb.so -s:

>>>>> # //:libb.so [action 'Linking libb.so']
(cd /bazel/jbasila/_bazel_jbasila/9ad84409935838f6b01d4c9936deda53/execroot/__main__ && \
  exec env - \
    PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/home/jbasila/tools/bin:/home/jbasila/tools/git-tools:/home/jbasila/.local/bin:/home/jbasila/bin:/home/jbasila/tools/bin:/home/jbasila/tools/git-tools:/home/jbasila/tools/bin:/home/jbasila/tools/git-tools:/home/jbasila/.local/bin:/home/jbasila/bin \
    PWD=/proc/self/cwd \
  /usr/bin/gcc -shared -o bazel-out/local-fastbuild/bin/libb.so '-fuse-ld=gold' -Wl,-no-as-needed -Wl,-z,relro,-z,now -B/usr/bin -B/usr/bin -pass-exit-codes -Wl,-S -Wl,@bazel-out/local-fastbuild/bin/libb.so-2.params)

The content of the file bazel-out/local-fastbuild/bin/libb.so-2.params:

-whole-archive
bazel-out/local-fastbuild/bin/_objs/libb.so/b.pic.o
-no-whole-archive
-whole-archive
liba.a
-no-whole-archive
-lstdc++
-lm

So to the question again, is there a way to make Bazel ditch the use of -whole-archive for liba.a?

1

There are 1 best solutions below

2
On BEST ANSWER

You can use --nolegacy_whole_archive to disable setting the whole-archive for dependencies of a shared library. There is a short explanation in https://docs.bazel.build/versions/master/command-line-reference.html.