66

So I'm trying trying to use a function defined in another C (file1.c) file in my file (file2.c). I'm including the header of file1 (file1.h) in order to do this.

However, I keep getting the following error whenever I try to compile my file using gcc:

Undefined symbols for architecture x86_64:
  "_init_filenames", referenced from:
      _run_worker in cc8hoqCM.o
  "_read_list", referenced from:
      _run_worker in cc8hoqCM.o
ld: symbol(s) not found for architecture x86_64

I've been told I need to "link the object files together" in order to use the functions from file1 in file2, but I have no clue what that means :(

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
adi
  • 843
  • 1
  • 8
  • 8

5 Answers5

114

I assume you are using gcc, to simply link object files do:

$ gcc -o output file1.o file2.o

To get the object-files simply compile using

$ gcc -c file1.c

this yields file1.o and so on.

If you want to link your files to an executable do

$ gcc -o output file1.c file2.c
bash.d
  • 13,029
  • 3
  • 29
  • 42
  • Can you give a more complex example (ie. linking to `librt.so`). If beyond scope of this question, can you give a link to another more complicated question? – puk Dec 02 '13 at 22:24
  • 1
    where's the `main.c` in this answer? :/ if file1.c is the main, how do you link it with other already compiled .o files? – The Student Oct 12 '14 at 19:45
  • 2
    Hi, this post is quite old... i just have a question regarding the difference the first command line and the third one. Does the compiler automatically recognize if the input is an object file or a source file? – user8469759 Nov 17 '15 at 15:36
  • I would also like to know how the compiler differentiates the different types. I tried removing the .o extension and it still works. – NenadK Oct 13 '16 at 01:14
  • @bash.d but why do we need to link the 2 object files, when we have already included the other file, that we are using in our program, by using #include... so, when we wrote #include file2.c, preprocessor already converted this #include line into sequence of code statements... so, when we compile our main program, it should compile even file2.c contents as its own... because it's no more, something separate now... then why link the file2 with our file1 ?? please guide... – Aarjavee S. Kamdar Jan 18 '17 at 08:31
  • `#include` is a preprocessor command that actually puts (copies) the contents of your include file into the file with the `#include` statement. This has nothing to do with compiling itself. I would not actually use this to include a c-file but rather only the header files. – bash.d Jan 19 '17 at 08:00
30

The existing answers already cover the "how", but I just wanted to elaborate on the "what" and "why" for others who might be wondering.

What a compiler (gcc) does: The term "compile" is a bit of an overloaded term because it is used at a high-level to mean "convert source code to a program", but more technically means to "convert source code to object code". A compiler like gcc actually performs two related, but arguably distinct functions to turn your source code into a program: compiling (as in the latter definition of turning source to object code) and linking (the process of combining the necessary object code files together into one complete executable).

The original error that you saw is technically a "linking error", and is thrown by "ld", the linker. Unlike (strict) compile-time errors, there is no reference to source code lines, as the linker is already in object space.

By default, when gcc is given source code as input, it attempts to compile each and then link them all together. As noted in the other responses, it's possible to use flags to instruct gcc to just compile first, then use the object files later to link in a separate step. This two-step process may seem unnecessary (and probably is for very small programs) but it is very important when managing a very large program, where compiling the entire project each time you make a small change would waste a considerable amount of time.

SeKa
  • 1,825
  • 12
  • 7
  • 3
    Nice explanation, however can you give concrete example how to link two files let's say a.o and b.o through the "ld" command? – Petur Subev Mar 27 '14 at 21:18
  • but why do we need to link the 2 object files, when we have already included the other file, that we are using in our program, by using #include... so, when we wrote #include file2.c, preprocessor already converted this #include line into sequence of code statements... so, when we compile our main program, it should compile even file2.c contents as its own... because it's no more, something separate now... then why link the file2 with our file1 ?? please guide... – Aarjavee S. Kamdar Jan 18 '17 at 08:30
  • @AarjaveeS.Kamdar, the include includes the *header* file, but not the *source* file. Notice the `.h` in `#include "sum.h"`, for example. If you include C source then you don't need to link. In general this is bad practice. – Greg Schmit Sep 01 '17 at 15:13
13

You could compile and link in one command:

gcc file1.c file2.c -o myprogram

And run with:

./myprogram

But to answer the question as asked, simply pass the object files to gcc:

gcc file1.o file2.o -o myprogram
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
10

Add foo1.c , foo2.c , foo3.c and makefile in one folder the type make in bash

if you do not want to use the makefile, you can run the command

gcc -c foo1.c foo2.c foo3.c

then

gcc -o output foo1.o foo2.o foo3.o

foo1.c

#include <stdio.h>
#include <string.h>

void funk1();

void funk1() {
    printf ("\nfunk1\n");
}


int main(void) {

    char *arg2;
    size_t nbytes = 100;

    while ( 1 ) {

        printf ("\nargv2 = %s\n" , arg2);
        printf ("\n:> ");
        getline (&arg2 , &nbytes , stdin);
        if( strcmp (arg2 , "1\n") == 0 ) {
            funk1 ();
        } else if( strcmp (arg2 , "2\n") == 0 ) {
            funk2 ();
        } else if( strcmp (arg2 , "3\n") == 0 ) {
            funk3 ();
        } else if( strcmp (arg2 , "4\n") == 0 ) {
            funk4 ();
        } else {
            funk5 ();
        }
    }
}

foo2.c

#include <stdio.h>
void funk2(){
    printf("\nfunk2\n");
}
void funk3(){
    printf("\nfunk3\n");
}

foo3.c

#include <stdio.h>

void funk4(){
    printf("\nfunk4\n");
}
void funk5(){
    printf("\nfunk5\n");
}

makefile

outputTest: foo1.o foo2.o foo3.o
    gcc -o output foo1.o foo2.o foo3.o
    make removeO

outputTest.o: foo1.c foo2.c foo3.c
    gcc -c foo1.c foo2.c foo3.c

clean:
    rm -f *.o output

removeO:
    rm -f *.o
Ar maj
  • 1,974
  • 1
  • 16
  • 16
5

Since there's no mention of how to compile a .c file together with a bunch of .o files, and this comment asks for it:

where's the main.c in this answer? :/ if file1.c is the main, how do you link it with other already compiled .o files? – Tom Brito Oct 12 '14 at 19:45

$ gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin

Here, main.c is the C file with the main() function and the object files (*.o) are precompiled. GCC knows how to handle these together, and invokes the linker accordingly and results in a final executable, which in our case is x0rbin.

You will be able to use functions not defined in the main.c but using an extern reference to functions defined in the object files (*.o).

You can also link with .obj or other extensions if the object files have the correct format (such as COFF).

ashmew2
  • 327
  • 3
  • 5