When compiling C source files, we include header files for example using #include "myheader.h".
The pre-processor will expand this header file before compiling the file. However, how does it find this header file exactly? I believe, the path of the header files is passed as an argument to the linker using -I for example to gcc.
I always thought that the linker only runs after compilation. So does the linker actually run before, to find stuff such as header files, and after compilation to combine various object files etc. ? Thanks
Headers mostly declare meta symbols, and function prototypes that allow the compiler to match/check cross compilation unit calling of functions.
All actual symbols interesting to a linker are defined in C files. The compiler can use preprocessor symbols (#defines) during codegeneration, but they are then inlined in the generated code.
Likewise, in the case of C++ inline methods or templates, code is generated by the compiler on the place where they are used.
This means the linker does not need anything from the headers, anything that would be needed is already processed by the compiler into the generated code stream (to the assembler or object file compiler output).
So no, includefiles are not relevant to the linker.
Below a stripped down version of the way from sources to executables.
+-------------------------------+
| sources (typical .c/.h files) |
+-------------------------------+
|
V
pre-processor
|
V
+-------------------------------+
| intermediate sources |
+-------------------------------+
|
V
compiler
|
V
+-------------------------------+
| object files (.o) |
+-------------------------------+
|
V
linker
|
V
+-------------------------------+
| executables/shared libraries |
+-------------------------------+
Related
Let's assume the following project structure composed of one executable in src and two libraries, lib1 and its dependency lib1_dep:
+--src/
| |
| +--Makefile.am
| +--main.c
|
+--lib/
| |
| +--Makefile.am
| +--library1.c
| +--library1.h
+--lib_dep/
| |
| +--Makefile.am
| +--library1_dep.c
| +--library1_dep.h
+--Makefile.am
+--configure.ac
The contents of the files are
configure.ac
# Add libraries dependance
AC_CONFIG_SUBDIRS([lib_dep])
AC_CONFIG_SUBDIRS([lib])
# Add src files
AC_CONFIG_FILES([Makefile
lib_dep/Makefile
lib/Makefile
src/Makefile
])
Makefile.am
SUBDIRS = lib_dep lib src
lib1_dep/Makefile.am
lib_LTLIBRARIES = lib_libdep.la
# Dynamic library
lib_libdep_la_SOURCES = library1_dep.c library1_dep.h
lib_libdep_la_LIBADD =
# Compiler options.
lib_libdep_la_CPPFLAGS = $(AM_CPPFLAGS)
lib1/Makefile.am
lib_LTLIBRARIES = lib_lib.la
# Dynamic library
lib_lib_la_SOURCES = library1.c library1.h
lib_lib_la_LIBADD = $(top_builddir)/lib_dep/lib_libdep.la
# Compiler options.
lib_lib_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib_dep/lib_dep.h
src/Makefile.am
bin_PROGRAMS = main
main_SOURCES = main.c
main_LDADD = $(AM_LDADD) $(top_builddir)/lib/lib_lib.la $(top_builddir)/lib_dep/lib_libdep.la
# Compiler options.
main_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib_dep/lib_dep.h -I$(top_srcdir)/lib/lib_lib.h
Observation
The build and install work well but I doubt I do it properly. The main program only uses functions defined in lib (not in lib_dep), so it looks strange that I have to also diretly link the main program to lib_dep. I would like your feedbacks on this please.
Question
Is there a way to build/compile lib so that I don't have to add the LDAPP and CPPFLAGS related to lib_dep when I build y main program (src/Makefile.am) ?
Thanks
The build and install work well but I doubt I do it properly. The main program only uses functions defined in lib (not in lib_dep), so it looks strange that I have to also diretly link the main program to lib_dep. I would like your feedbacks on this please.
It is system-dependent whether indirect shared-library dependencies need to be included in the link. On Linux, they do. Compare to the situation with static library dependencies, which absolutely need to be included in the final link, on any system.
However, since you are using libtool, in a context where you can rely on its generated .la files to be available, you shouldn't need to provide explicitly for linking indirect dependencies. Libtool can handle that for you.
Is there a way to build/compile lib so that I don't have to add the LDAPP and CPPFLAGS related to lib_dep when I build y main program (src/Makefile.am) ?
That's actually two separate questions, one for LDADD and one for CPPFLAGS.
The CPPFLAGS are relevant only for compilation, not linking. Roughly speaking, if the main program's sources #include any headers from lib_dep/, whether directly or indirectly, then it is necessary for its CPPFLAGS to contain an -I flag for that directory. Otherwise, not.
An indirect inclusion would be if main.c includes library1.h and library1.h includes library1_dep.h.
Since you are using libtool to build both libraries, and consistently declaring link dependencies by putting the appropriate libtool archives in the LIBADD / LDADD variables, you do not need to specify the indirect library dependency in the main program's LDADD. libtool can and will figure out the indirect library dependency and add it to the main program's link if needed, and at the correct location in the link command.
Thus, if the main program has neither a compile-time dependency nor a direct link dependency on libdep, then its Makefile.am could look like this:
bin_PROGRAMS = main
main_SOURCES = main.c
main_LDADD = $(top_builddir)/lib/lib_lib.la
main_CPPFLAGS = -I$(top_srcdir)/lib
NOTE: it is not wrong to add $(AM_LDADD) to main_LDADD or to add $(AM_CPPFLAGS) to main_CPPFLAGS, as in the version of this Makefile.am presented in the question, but that is useful only if you've actually defined values for those AM_* variables.
NOTE2: Your -I flags should specify directories to search for header files, not the names of specific header files.
In problem set 4 of cs50, there is a main function filter.c, which uses header file helper.h. The latter contains the prototypes of a few functions, and these complete functions are written out in helper.c
My question is: since filter.c only connects to helper.h, how does it connect to the code of the functions? Or does filter.c automatically also look for a .c file with the same name as the linked header file?
I hope this is somewhat clear!
The compilation of a C program involves three basic steps listed below shortly:
Preprocessing:
the preprocessor takes a C source code file and deals with the #includes, #defines and other preprocessor directives. also clean all the comments and expand all the macros in those files. (it performs both on c and h files) The output of this step is a "pure" C file without pre-processor directives.
Compilation:
the compiler takes the pre-processor's output and produces an object file from it. written in assembly that suits the cpu your code will run on it.
Linking:
the linker takes the object files produced by the compiler and produces either a library or an executable file. which have all the information and a process terms to be run directly by the os (.out or .elf are examples of the linker output).
your case
In filter.c or in each .c file (including the helper.c), where you #includes "helper.h", this step ended with all functions signature declared in helper.h copy paced in filter.c (only signatures). now this happen in preprocessor time. now in main.c where (i suppose) you #includes "filter.h", the preprocessor will copy all the nested .h files (tell reaching last .h file in the chain) into main.c (in our case its only filter.h that contains the helper.h). when compiler comes to compile the .c files, he compiles helper.c, 'filter.c and main.c and generates object files (.o or .obj - binary files suited for current cpu) at end he triggers the linker to link all these objects together to become and fully executable (linker also links all functions that came from predefined libs like printf for e.g.)
preprocessor compiler linker
------------ -------- --------
+------------+ copy helper.h to +----------+
+ helper.h +------------------> + filter.c + -------> filter.o + +--------+
+------------+ | +----------+ | + +
| | + .elf +
| +---> + +
+---------> +-----------+ + or +
+ helper.c + ------> helper.o ----> + .out +
+-----------+ +---> +--------+
| ^
+-------------+ | |
+ filter.h +---------> +-------------+ | |
+-------------+ + main.c + -----> main.o---+ |
+-------------+ |
|
+-------------------+
+ libs (e.g. stdio) +
+-------------------+
I know that every header file, i.e. string.h, should have an object file in which
there is the proper implementation.
I also know that for GCC and glibc there is a libc.a or libc.so containing object files.
I tried to open libc.a to see if I could find, i.e., string.o but I didn't find it.
Why? Where can I find for every header the correspondent object file?
It may be implementation dependant. A single .h file may correspond to many .o or the opposite, you might have many .h for a single .o
For example, in my libc.a, I can see about one module per string function :
$ ar t libc.a | grep '^str' | sort
strcasecmp.o
strcasestr.o
strcat.o
strchr.o
strcmp.o
strcoll.o
strcpy.o
strcspn.o
strdup.o
strerror.o
strfmon.o
strftime.o
stringlist.o
strlcat.o
strlcpy.o
strlen.o
strmode.o
strncat.o
strncmp.o
strncpy.o
strndup.o
strnlen.o
strnstr.o
strpbrk.o
strptime.o
strrchr.o
strsep.o
strsignal.o
strspn.o
strstr.o
strtofflags.o
strtoimax.o
strtok.o
strtol.o
strtoll.o
strtonum.o
strtoq.o
strtoul.o
strtoull.o
strtoumax.o
strtouq.o
strxfrm.o
well, in my system, libc.so shows up in /lib
[sourav#braodsword temp]$ ls -l /lib/libc*
-rwxr-xr-x 1 root root 1611564 Mar 10 2010 /lib/libc-2.5.so
However, if you're looking for the source code, you'll not find that in .so file, anyway.
Again, don't expect, every header file declaration will have a defferent object file. They are taken together to form the shared library .so.
I am working on a C project and I like to keep myself organised. Thus, I have got multiple header files, files with functions for that header files and a main file.
|- Header Files
| |- hash_table.h
| |- linked_list.h
| |- dictionary.h
|- Source Files
| |- main.c
| |- hash_functions.c
| |- list_functions.c
| |- dictionary_functions.c
Will it be any problem if I include libraries such as #include <stdio.h> in each of that function file? Will it affect by any means the efficiency of my program?
No, there would not be any problem if you include same header file in multiple files.
When any header file is written it is written to avoid multiple inclusion.
To avoid multiple inclusion, macro pre-processors are often used. One such mostly used way is given below.
#ifndef SOME_SYMBOL
#define SOME_SYMBOL
// actual code goes here.
#endif
For example see the code of stdio.h file for Linux at : https://github.com/torvalds/linux/blob/master/arch/powerpc/boot/stdio.h
All modern headers use header guards. This means that the header checks if it has been included before and then skips it. Also the compiler is smart enough to figure out which functions defined in a header you actually use and only include those in object code.
No, the include file is a description of the library. The library itself is a separate binary file that is linked in the final stages of program assembly
No problems.
Standard header files are written that way.
See: http://en.wikipedia.org/wiki/Include_guard
Mutliple file Inclusion will not effect you untill you have a INCLUSION GAURD.So by thi sYou can also do one easy thing, That is by having Single header file (suppose includes.h) which will have all include files So that you can eliminate the Order of Inclusion problem with the cost of compilation time.
I'm getting multiple definition link errors after conditionally compiling platform-specific code.
My project is laid out like this:
/
|__+ include/
| |__+ native/
| | |__ impl.h
| |
| |__ general.h
|
|__+ src/
|__+ native/
| |__ impl.linux.c
| |__ impl.win32.c
|
|__ general.c
At the top of the general.c file:
#if defined(LIBRARY_PLATFORM_LINUX)
#include "native/impl.linux.c"
#elsif defined(LIBRARY_PLATFORM_WIN32)
#include "native/impl.win32.c"
#endif
I set up introspection in CMake in order to detect the operating system and define the corresponding constants. The thing is, I didn't want to maintain one CMakeLists.txt file in every directory, so I simply globbed all the .c files as suggested in this answer:
file(GLOB_RECURSE LIBRARY_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/*.c")
Apparently, this is what is causing the problem. It seems to be compiling the code #included in general.c as well as the individual src/native/impl.*.c files.
CMakeFiles/lib.dir/src/native/impl.linux.c.o: In function `declared_in_impl_h':
impl.linux.c:(.text+0x0): multiple definition of `declared_in_impl_h'
CMakeFiles/lib.dir/src/general.c.o:general.c:(.text+0x0): first defined here
How can I untangle this situation?
The best practice for that sort of cross-platform situation is to create two libraries, one for linux and one for windows and stop doing conditional includes. Each platform only compiles and links the relevant library.
The recommended way to do that with cmake is to stop globbing and just include each file. There are some situations where it can get confused and not realize that it needs to recompile. You can make an argument that non-changing legacy code won't have that problem.
If you really want to avoid doing either of these things, I would put the included code in a header instead of a c file. You don't really want the include guards so that people don't get it confused for something that should be used like a regular header. Put a bunch of comments in the file to warn them off of said behavior as well.