Are static library dependencies supposed to be linked in the correct order?

60 views
Skip to first unread message

Marco Nilsson

unread,
Mar 12, 2025, 9:16:34 AMMar 12
to gn-dev
Does gn resolve the dependency tree so static libraries are linked in the correct order?

We're trying to build with clang now, as opposed to gcc, and are seeing some unresolved symbols despite Crypto having a dependency on OS in our case:

undefined first referenced symbol in file --------- ---------------- OS::Mutex::WithLocked(unsigned int) obj/app_sdk/components/Crypto/lib_Crypto_lib.a<lib_Crypto_lib.AesGcm.o> OS::Mutex::Mutex() obj/app_sdk/components/Crypto/lib_Crypto_lib.a<lib_Crypto_lib.AesGcm.o> OS::detail::FreeRTOSSemaphore::~FreeRTOSSemaphore() [subobject] obj/app_sdk/components/Crypto/lib_Crypto_lib.a<lib_Crypto_lib.AesGcm.o>

With gcc we worked around having to bother by using --start-group and --end-group, but clang does not allow that if the group, {{inputs}}, also contains object files.

 Thanks /Marco

Dirk Pranke

unread,
Mar 12, 2025, 12:25:40 PMMar 12
to Marco Nilsson, gn-dev
I suppose it depends on what you mean by "correct order". Here's how GN does it (or at least is supposed to do it):


-- Dirk

To unsubscribe from this group and stop receiving emails from it, send an email to gn-dev+un...@chromium.org.

Marco Nilsson

unread,
Mar 13, 2025, 1:10:06 AMMar 13
to gn-dev, dpr...@google.com, gn-dev, Marco Nilsson
This is for deps that are built as static libraries. Can I assume they behave the same way as explicit libs?
I was under the impression, or hoped, that gn would sort the built static libraries in the dependency order so the linker could resolve the symbols.

 /Marco

Dirk Pranke

unread,
Mar 13, 2025, 8:08:22 PMMar 13
to Marco Nilsson, gn-dev
I would expect GN to topologically sort the dependencies to put things in the right order. I have not actually tested GN to confirm that this is what it's doing, nor have I looked at the code to confirm this, though :).

-- Dirk

Marco Nilsson

unread,
Mar 14, 2025, 1:12:24 AMMar 14
to gn-dev, dpr...@google.com, gn-dev, Marco Nilsson
I just did a test and it seems to link dependencies in the order they are defined. Given these components:

static_library("core") {
}

static_library("os") {
  public_deps = [
    ":core",
  ]
}

static_library("crypto")  {
  public_deps = [
    ":os",
    ":core",
  ]
}


I get different link orders depending on how I depend on them:

  deps = [
    ":crypto",
    ":core",
  ]
[1/2] g++ -Wl,-rpath=\$ORIGIN/ -Wl,-rpath-link= -o hello obj/hello.hello.o libhello_shared.so obj/libhello_static.a obj/libcrypto.a obj/libos.a obj/libcore.a  


or:

  deps = [
    ":core",
    ":crypto",
  ]
[1/2] g++ -Wl,-rpath=\$ORIGIN/ -Wl,-rpath-link= -o hello obj/hello.hello.o libhello_shared.so obj/libhello_static.a obj/libcore.a obj/libcrypto.a obj/libos.a


  Is this considered a bug/design flaw? Manually managing dependency order becomes very difficult in a large project if you're unable to use linker groups.

 /Marco

Dirk Pranke

unread,
Mar 14, 2025, 8:23:01 PMMar 14
to Marco Nilsson, gn-dev
Having done some digging, I see the same behavior you see.

I think this is not a problem for Chromium because we use LLD (the LLVM linker), which automatically deals with this problem. As you say, `-Wl,--start-group`/`-Wl,--end-group` also solves the problem.

It seems that if you just have a single chain of dependencies, things would work correctly. I.e., in your example if :crypto only depended on :core and :core on :os, the ordering is correct. However, having :crypto also depend on :os directly messes this up.

Which I agree is awfully fragile. To make the problem worse, `gn format` will automatically sort your dependencies, meaning it could break the ordering at any time unless you use `# NOSORT`. 

As I said, I would've expected GN to topologically sort the dependencies, but I guess it doesn't. I'm also not sure that attempting to do so would even work reliably or would solve the problem. I'd have to do some digging to figure out (a) why things are the way they are and (b) if we can do anything useful enough about it. I've filed https://crbug.com/gn/403663745 to track this.

-- Dirk

Marco Nilsson

unread,
Mar 15, 2025, 1:17:15 AMMar 15
to gn-dev, dpr...@google.com, gn-dev, denra...@gmail.com
I have done some digging on my end as well. The constraint of not being able to mix and match libraries and object files inside linker groups is not a thing in neither gcc nor clang. This is _only_ a problem when using the Texas Instruments fork tiarmclang.
I am currently in contact with them to figure out why this constraint was added in the first place.

Seeing as the amount of users using both gn and tiarmclang is going to be minimal I'd put this at a really low priority, possibly even won't fix. Especially when the minimal example, probably the base for most new users, uses linker groups so people won't even be aware that gn doesn't do deep sorting.

 /Marco
Reply all
Reply to author
Forward
0 new messages