3

I am a newbie in C. I have two simple source code files f1.c and f2.c.

f1.c looks like:

#include <stdio.h>
#include "f.h"

void f1(void) {
    // some code ...
}

function f2() in f2.c relies on f1() in f1.c.

#include <stdio.h>
#include "f.h"

void f2(void) {
    f1();
}

f1.c and f2.c share a same header f.h,

void f1(void);
void f2(void);

There are no main() access, I just want to compile these two file into a .o file without linker (using -c option),

gcc -c f1.c f2.c -o f2.o

then I got,

clang: error: cannot specify -o when generating multiple output files

but when I mentioned only f2.c, it works well,

gcc -c f2.c -o f2.o

So what's the problem? Thanks!

  • You can only have one `.c` file per `.o` file – M.M Sep 18 '17 at 22:10
  • Without `-c`, the `-o` flag is telling it where to put the final executable, after linking everything together. With `-c`, `-o` is saying where to put the `.o` file that goes with the `.c` file. But if you said `-c`, *and* you said `-o`, *and* you specified two `.c` files, which `.c` file does the `-o` go with? – Steve Summit Sep 18 '17 at 22:17
  • Thx @SteveSummit ! So if I compile only `f2.c` with command `gcc -c f2.c -o f2.o`, the compiler will automatically find function `f1()` mentioned in `f.h` header? –  Sep 18 '17 at 22:44
  • Have a look at https://stackoverflow.com/questions/311882/what-do-statically-linked-and-dynamically-linked-mean/311889#311889. – paxdiablo Sep 19 '17 at 00:41
  • @wei If you don't want to link, then yes, having the `#include "f.h"` line in `f2.c` gives the *compiler* everything it needs to know to compile `f2.c` into `f2.o`. But, later, when you do link, you *are* going to have to tell it where to find the compiled code for function `f()`, which will probably be in the separately-compiled `f1.o`. But you also need to think more about what "linking" means, because if you're not linking, you are *not* going to "compile these two files into a `.o` file", as you said; you are presumably going to compile those two files into *two* `.o` files. – Steve Summit Sep 19 '17 at 11:26
  • It is possible to link two object files together into one object file, without performing a full, final link (that is, incorporating all necessary libraries and everything) and producing an executable file. But this (a) *does* involve running the linker, and (b) is a comparatively obscure thing to do, and I doubt it's what you really want to do – Steve Summit Sep 19 '17 at 14:44
  • Thanks for your explanation @SteveSummit . Now I understand that if `f2()` in `f2.c` call function `f1()` in `f1.c`, compiler will not add address of `f1()` function into the object file `f1.o`. So `f1.c` is not necessary when we run `gcc -c f2.c -o f2.o`. Correct me if I am wrong. –  Sep 19 '17 at 16:42
  • @wei That's basically correct. When the compiler compiles `f2.c`, it does not know, and does not need to know, the address of function `f1()`. That gets filled in later (by the linker, in fact). – Steve Summit Sep 19 '17 at 17:24
  • @SteveSummit Thx :> –  Sep 19 '17 at 18:05

1 Answers1

1

You should look into the compilation process for C. The first stage is compiling the .c source code into .o object files. The .c files do not need to see the other .c files; they are accepting as fact what you've told them about the existence of external functions. It's not until the linker comes in that it really needs to see the function because the implementation details don't matter to your .c file, just the interface, which you've presumably given it in the header.

What you can do, if you like, is drop the -o flag specifying the output file you want to create. Just compile with gcc -c f1.c f2.c and it will know to create f1.o and f2.o which will be able to link against each other when the time comes that you do want to go through with the linking process.

I am curious, however, what your intentions may be for wanting to compile these without linking. I only ask as you refer to yourself as a newbie, so I am wondering if maybe there is an end goal you have in mind and perhaps aren't asking the right question.

Christian Gibbons
  • 4,272
  • 1
  • 16
  • 29
  • Thanks for your answer @ChristianGibbons ! Because I have many module , ex `a.c`,`b.c`,...,`z.c`. Some of them can be grouped together as a `.exe` executable file. I prefer to compile each `.c` file into `.o` file just once, and reuse object files. I am tending to find a best practice to compile my c project. As you mentioned `gcc -c f1.c f2.c` is a good. –  Sep 19 '17 at 17:06
  • Okay, so it looks like what you might really want is a build system. I usually whip up a `Makefile` whenever I'm putting a little project together, but I gather you are using Windows rather than a Unix derivative. I'm not intimately familiar with the options on Windows, but maybe try starting with `nmake` as it seems to be their version of `make`. Build systems like these are able to avoid recompiling source files that are already up-to-date with the latest changes, so even if you make changes to the project, it will know to only recompile the parts affected by the changes. – Christian Gibbons Sep 19 '17 at 17:26
  • Nice tips. I just want to figure out how `gcc` exactly works before using the `Makefile` :> –  Sep 19 '17 at 19:27