Reason for having dependencies in srcs for shared objects?

512 views
Skip to first unread message

Peter Henell

unread,
Mar 5, 2019, 1:06:15 AM3/5/19
to bazel-discuss
I get this question from the users in my organization and I have no good answer. Could someone help to explain?

We use shared objects produced with cc_binary( name = A,
                                                                              linkshared = 1).

Other rules that depend on those shared objects need to put the dependency in cc_library( srcs = [A]) instead of in deps.
Why?

I also feel that the documentation in the cc_* rules are a bit unclear.


cc_library often produce .a files or .lo files? So it does not really hold as an explanation to our users that .so files must be in srcs according to bazel documentation, but cc_libraries should be in deps.



In srcs documentation is says 

--------------------------------------------------------------------

Permitted srcs file types:

  • C and C++ source files: .c.cc.cpp.cxx.c++.C
  • C and C++ header files: .h.hh.hpp.hxx.inc.inl.H
  • Assembler with C preprocessor: .S
  • Archive: .a.pic.a
  • "Always link" library: .lo.pic.lo
  • Shared library, versioned or unversioned: .so.so.version
  • Object file: .o.pic.o

...and any rules that produce those files. Different extensions denote different programming languages in accordance with gcc convention

--------------------------------------------------------------






Brian Silverman

unread,
Mar 6, 2019, 6:44:12 PM3/6/19
to Peter Henell, bazel-discuss
Peter,

I think of it as deps are for tracking dependencies (across all types of rules), while srcs are for things that just get linked into the final binary. The big difference is things like header files: those only propagate via deps, not srcs. deps can also propagate -D flags (defines) and other things, while srcs don't.

A cc_library doesn't necessarily correspond to a real file created during a build. Bazel has various modes for deciding whether to put things into intermediate shared objects, or intermediate static libraries, or just link all the .o files together, and some of what you do in CROSSTOOL affects those modes. However, when using the cc_* rules, none of that (should) matter. You just use cc_library rules to build up a dependency graph, and then everything gets linked into the final cc_binary output (in a correct order, as defined by the deps graph).

However, a cc_binary actually performs a link and produces an output file which can be consumed elsewhere. The common case (which the rule is named after) is producing a standalone binary. However, a shared object is basically just a binary without a `main`, so the same rule produces those. If you want to link a shared object created that way (or imported via a repository rule, or checked into source control, or whatever) into another bazel-linked binary, then you have to put it in srcs because it's not a cc_library-type entity with all the associated metadata. Instead, it's just a .so file which you want linked into any cc_binaries which include it.

This behavior is kind of confusing, of course. I remember seeing a design document about redoing the cc_* rules so that linking something as a shared object is just flipping an attr, but I can't find it now and I'm not sure what the current status is.

Brian

--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/e2f03c82-70ee-4e24-b1d7-be7b4fdf3a93%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Peter Henell

unread,
Mar 8, 2019, 6:05:35 AM3/8/19
to bazel-discuss
Hi!
Thank you for the explanation. I (think) that I have got the idea on how it works, but as you see it is not easy to explain. I will continue to tell the users "that is just how bazel works".
Could the documentation for the cc_* rules be updated with clearer description of this?

Kind regards 
Peter

Marcel Hlopko

unread,
Mar 8, 2019, 8:01:24 AM3/8/19
to bazel-discuss
Hi all,

thanks Brian for a very accurate explanation! I'll only add that putting things into srcs is mostly a legacy and we want to get rid of it. Instead we want to improve cc_import and use that for bringing prebuilt libraries into the dependency graph (and then put the target into deps of cc_library). Also the use case when cc_binary creates a shared library and some other C++ rules depend on that is not polished (e.g. headers are lost in the process), and long due transitive libraries should fix that.

Peter Henell

unread,
May 3, 2019, 6:38:00 AM5/3/19
to bazel-discuss
Hi!
It looks like the behaviour has changed for dependencies to shared objects.
Previously you got an error if you had a dependency to a shared object in "deps" (the shared object being created with a cc_binary() rule)
The error looked like this
"in deps attribute of cc_library rule //:t2: cc_binary rule '//:libtso.so' is misplaced here (expected cc_inc_library, cc_library, objc_library, experimental_objc_library or cc_proto_library)."

We now use bazel 0.24.1 and there is no such warning.
It looks like if you have the dependency in deps it is not linked in, it is just ignored, and you get "undefined reference" if you actually needed something from the shared object. If you have it in srcs it is linked in like before.

Is this new behaviour explained anywhere?

Example 
cc_binary(
    name = "test",
    deps = [":t3"],
)

cc_library(
    name = "t3",
    srcs = ["t3.c"],
    deps = [
        ":t2",
    ],
)

cc_library(
    name = "t2",
    srcs = [
        "t2.c",
        # ":libtso.so",  Works 
    ],
    deps = [
        # ":libtso.so",  Used to give a warning, now it is just ignored
    ],
)

cc_binary(
    name = "libtso.so",
    linkshared = 1,
    deps = [":t"],
)

cc_library(
    name = "t",
    srcs = ["t.c"],
    alwayslink = 1,
)

Marcel Hlopko

unread,
May 9, 2019, 11:44:58 AM5/9/19
to Peter Henell, Pedro Liberal Fernandez, bazel-discuss

--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discus...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


--
Marcel Hlopko | Software Engineer | hlo...@google.com | 

Google Germany GmbH | Erika-Mann-Str. 33  | 80636 München | Germany | Geschäftsführer: Geschäftsführer: Paul Manicle, Halimah DeLaine Prado | Registergericht und -nummer: Hamburg, HRB 86891

Pedro Liberal Fernandez

unread,
May 9, 2019, 12:19:53 PM5/9/19
to bazel-discuss
This started being allowed since https://github.com/bazelbuild/bazel/commit/99ff52f9ec351ad0270e5a994c6d1506d6d09e02.

It is a bug. Originally at least since 2014 cc_binary was providing the previous incarnation (CppCompilationDependency) which then got morphed into the current CcInfo.

Now the question is why did cc_binary ever provide CppCompilationDependency? From looking at the change history it looks like it was introduced by accident in Jun 13, 2014.

There is no reason for CcBinary to provide CcInfo.


To unsubscribe from this group and stop receiving emails from it, send an email to bazel-...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages