1

In my c/c++ mixed project, I'm building the source files of individual folders, archiving them with ar into their own .a files and then linking them all together at the final stage. So far so good. My question is, is it possible to hint any dynamic library dependencies at the ar stage so, they don't have to be specified explicitly at the linking stage?

I mean, if a component depends on pthread and the final binary will need to link against it, possibly dynamically, can it not add this dependency to the archive, to be resolved later by the linker?

Would using the linker instead of ar to create partially linked objects rather than archives provide any such facility to hint dynamic lib dependencies to be satisfied at the final linking stage?

abdus_salam
  • 738
  • 2
  • 7
  • 19
  • `ar` is really just a tool for concatenating multiple files into a single file, and allow you to extract them, possibly with an index. It is not a tool that knows anything about the C++ or C build process or dynamic libraries. –  Oct 09 '18 at 23:08
  • @NeilButterworth yes, I appreciate that. So, I'm more after an option to add something to a section in the archive/elf headers which then to be parsed and processed by the linker. A bit like the compiler passing whatever goes after -Wl, to the linker, without having to understand what it means. – abdus_salam Oct 09 '18 at 23:16
  • Modifying the headers? At build phase (when an *.elf* might not even be generated)? Please check [\[SO\]: How to create a Minimal, Complete, and Verifiable example (mcve)](https://stackoverflow.com/help/mcve) and then reduce the problem you think you're having into an answerable one. – CristiFati Oct 09 '18 at 23:44
  • Shared libraries allow you to relay that information if you're careful; static libraries do not. If you want the convenience, use shared libraries. If you can't use shared libraries, I believe you'll have to accept the inconvenience of knowing which other libraries to link without being able to record it in the archive library files in a way that the compiler/linker can use. – Jonathan Leffler Oct 09 '18 at 23:54
  • this link http://www.kaizou.org/2015/01/linux-libraries/ provides a very detailed, all around explanation to different options and consequences. – abdus_salam Oct 10 '18 at 09:44
  • You could look and see whether `libtool` handles dependencies for static libraries; it might, but I'm not sure and am feeling too lazy to research it right now. – Jonathan Leffler Nov 28 '18 at 08:14

1 Answers1

2

You can use the 'l' option of GNU ar.
As the man pages say:

l   Specify dependencies of this library.  The dependencies must immediately
    follow this option character, must use the same syntax as the
    linker command line, and must be specified within a single argument.
    I.e., if multiple items are needed, they must be quoted to form
    a single command line argument.  For example
    L "-L/usr/local/lib -lmydep1 -lmydep2"

ar stores this data in a member "__.LIBDEP" which is embedded in the .a file and can be accessed with ar p mylib.a __.LIBDEP

$ cat static_lib_test.c

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h>

_Noreturn void *start(void *arg)
{
    fprintf(stderr, "child (%d) won!\n", gettid());
    syscall(SYS_exit_group, EXIT_SUCCESS);
}

int main(int argc, const char *argv[])
{
    pthread_t thread;
    if (pthread_create(&thread, NULL, start, (void *) 0) < 0)
    {
        fprintf(stderr, "error: unable to create new thread\n");
        exit(EXIT_FAILURE);
    }
    fprintf(stderr, "Race begin!\n");
    fprintf(stderr, "parent (%d) won!\n", gettid());
    syscall(SYS_exit_group, EXIT_SUCCESS);
}

Compile:
$ gcc -Wall -c static_lib_test.c -o static_lib_test.o
Archive:
$ ar rcvsl "-L/usr/lib -lpthread" static_lib_test.a static_lib_test.o
Link:
$ gcc $(ar p static_lib_test.a __.LIBDEP | tr '\0' '\n') -o static_lib_test static_lib_test.a
Example run: $ ./static_lib_test

Race begin!
parent (13547) won!

Tested on: Linux arch 5.11.13-zen1-1-zen, GNU ar (GNU Binutils) 2.36.1

pro-gramer
  • 166
  • 1
  • 3
  • 14