Home > Enterprise >  Can't the gcc linker just find my other files?
Can't the gcc linker just find my other files?

Time:10-23

So here's something I don't understand : Every single time you include something in c, you have to do #include "dir/subdir/file.h". Since the .c file is in the exact same place, why do I also have to do gcc main.c dir/subdir/file.c -o main ?

It doesn't seem to make sense, every single other language I've used (arguably not that many, but still, several) was able to make sense of imports on its own. Am I missing something ? Is there a way to tell gcc to "just find them yourself" ?

CodePudding user response:

gcc main.c dir/subdir/file.c -o main is not the typical command form for most projects. It is used only for simple projects, such as student assignments.

Much commercial code consists of dozens, hundreds, or thousands of source files. It is not compiled all at once. Build tools such as make or Xcode are used to manage the project, and they will compile each source file separately to its own object file.

Object files may be grouped by subproject, may be collected into libraries, and may be further processed before being linked into an executable file or other product.

When the project is built, there is no need to compile all of the source files because they have been compiled previously. It is only necessary to compile source files for object files that may change due to source edits that have been made since the last time the project was built. Thus, the build tool may compile only a few of the hundreds of source files in the project, using an individual compile command for each. Having a single command that compiled all of the source files would be wasteful.

In some projects, there may be several variants of the source file for one header file. One header file may declare common interfaces, but several different source files may provide different implementations for those interfaces, to target different types of destination systems or to provide different characteristics, such as prioritizing speed over memory or vice-versa. In such a situation, knowing the header file does not identify which source file is to be compiled.

If you want your project to compile all source files that are implied by header files, you can write your own program that scans the main.c file to find included header files (possibly recursively) and generate commands to compile the associated source files.

CodePudding user response:

C is a product of early 1970s, and this is one of the areas where that really shows. An #include statement simply loads the contents of the specified file before it gets compiled - the path of the included file isn't being analyzed or preserved anywhere. Similarly, gcc isn't preserving the path of any of the files on the command line - it just loads the source from the specified file, translates it, and spits out an object file at the end.

C doesn't specify any kind of package management semantics. Each file on the gcc command line is compiled separately, and gcc doesn't know anything about the environment other than what's specified on the command line.

Yes, you could build a compiler that does all that analysis and tries to be smart about paths and such, but it's a crapload of work, there's no specification for it, no two compilers would do it the same way, and it kind of violates the spirit of C (the programmer is assumed to always know what they're doing, even when they don't).


Having said all that...

With gcc, you can use the -I option to specify additional include paths:

gcc -o main -I /dir/subdir main.c /dir/subdir/file.c 

so in your source you don't need to use an explicit path in the #include:

#include "file.h"  // no need for /dir/subdir path

Similarly, you can use -L to specify additional directories to search for libraries (linked with -l):

gcc -o main -I /dir/subdir main.c /dir/subdir/file.c -L /anotherdir/subdir/libs -lmylib.a

Like Eric says, if you're having to manage source across multiple directories, you should be using make or a similar tool - doing all this manually on the command line rapidly gets unscalable.

  • Related