98

How does one combine two GCC compiled .o object files into a third .o file?

$ gcc -c  a.c -o a.o
$ gcc -c  b.c -o b.o
$ ??? a.o b.o -o c.o
$ gcc c.o other.o -o executable

If you have access to the source files the -combine GCC flag will merge the source files before compilation:

$ gcc -c -combine a.c b.c -o c.o

However this only works for source files, and GCC does not accept .o files as input for this command.

Normally, linking .o files does not work properly, as you cannot use the output of the linker as input for it. The result is a shared library and is not linked statically into the resulting executable.

$ gcc -shared a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable
./executable: error while loading shared libraries: c.o: cannot open shared object file: No such file or directory
$ file c.o
c.o: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
Quonux
  • 2,975
  • 1
  • 24
  • 32
Lucian Adrian Grijincu
  • 2,491
  • 2
  • 18
  • 18
  • 2
    gcc does not currently have a `-combine` option. It exists in gcc 4.1.2 and does not exist in gcc 6.3.0 (someone else can figure out just when it was removed). – Keith Thompson Jul 11 '19 at 23:05

2 Answers2

113

Passing -relocatable or -r to ld will create an object that is suitable as input of ld.

$ ld -relocatable a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable

The generated file is of the same type as the original .o files.

$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
$ file c.o
c.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

For an in-depth explanation see MaskRay's Relocatable linking article.

Lucian Adrian Grijincu
  • 2,491
  • 2
  • 18
  • 18
  • 2
    Is it possible to do the inverse operation? i.e. produce a.o and b.o from c.o? – Bert Regelink Feb 01 '14 at 22:19
  • 9
    @BertRegelink no, because there's no unique inverse, In maths terms, doesn't forma group :P – Alec Teal Feb 23 '14 at 08:03
  • 7
    Warning: `--relocatable` seems to be less portable. The ld that comes with Android NDK only recognizes `-relocatable`. If you need portability, stick to `-r`. – Martin Bonner supports Monica Jun 20 '17 at 15:27
  • @Martin, your comment seems to contradict itself. I presume you mean Android NDK does *not* recognize `--relocatable`? – Matthijs Kooijman Sep 23 '17 at 10:14
  • 3
    @matthijs The word is the same; the difference is one minus or two. – Martin Bonner supports Monica Sep 23 '17 at 19:36
  • 1
    Ah, didn't see that. So, the Android NDK only recognizes `-relocatable` *and* `-r`, but not `--relocatable`. Thanks for clarifying! – Matthijs Kooijman Sep 25 '17 at 08:53
  • 1
    There's side effect of using `ld` to combine multiple `.o` files. If `a.o` has some weak functions which happen to be defined in `b.o` , these weak functions will become strong functions in the final `c.o`. And this may beat some purpose. – smwikipedia Aug 07 '21 at 08:33
  • @BertRegelink You can combine 3 and 4 and figure out that their sum is 7, but if you take 7 and want to figure out what their summands are, they could be 3 and 4, or they could be something like 2 and 5. – Aurora Sep 04 '21 at 11:40
10

If you want to create an archive of two or more .o files (i.e.. a static library) use the ar command:

ar rvs mylib.a file1.o file2.o
  • @Lucian But why would you want to do this? A static library is much more convenient to link against than a .o file. –  Jun 05 '10 at 11:31
  • 7
    I need to run `objcopy` on the resulting file and make some kinds of symbols local to the file so that they are not visible externally. Some of the symbols that need be localized are referenced between the `a.o` and `b.o` files. I can't localize individual files – as the symbols would not be found at linker time – and I can't localize symbols from the static archive either. – Lucian Adrian Grijincu Jun 05 '10 at 11:39