Compilation order and compilation dependencies - c

Suppose I have a C program separated into several smaller files and include each other as follows :
Now I have the following queries as to what extent I am correct. Please correct me wherever I am wrong:
1. Which files have to recompiled after I make changes to process1.c?
main.c ?
2. Which files have to recompiled after I make changes to process1.h?
main.c and process1.c?
3. Which files have to recompiled after I make changes to list.h?
input.c and process2.c?

This is really easy. If X gets changed, any .c file that includes X (or is X) needs to get recompiled. The answers are:
process1.c
process1.c, main.c
process2.c, input.c

I think the best answer to your question is to write a Makefile and then to check which files are compiled after changing one like your question.

Simply put:
A file has to be recompiled if any of the files it depends on has been changed.
Note that this is recursive, so if any of the object files has changed because they have been recompiled, the program file (which normally depends on all object files) has to be re-built (i.e. linked, not compiled), too.
You might try SCons as an easier and more powerful alternative to good ol' make.

Related

Makefile, better understanding rules

Reading the official documentation
A prerequisite is a file that is used as input to create the target. A
target often depends on several files.
If my source file already includes the header, should I list the header in the rule?
src.c
#include <stdio.h>
#include "myheader.h"
int main()
{
printMessage();
return 0;
}
myheader.h
void printMessage()
{
printf("a message to screen\n");
}
makefile
src : src.o
cc -o src src.o
src.o : src.c
cc -c src.c
If I add myheader.h in the prerequisite it changes nothing, the same message is printed to screen. If a header is explicitly included, should it appear in the prerequisite?
The header file should be included in the dependency list.
The first time you use make to build your program, it will compile just the same whether you include myheader.h as a dependency or not. The difference is what happens when one of the files changes.
If you run make again without changing anything, it will say that "src" is up to date and won't compile anything. However, if you were to modify myheader.h and you didn't include it as a dependency, then make will say that the target is up to date. It doesn't look at the source file to see what files it includes. The make utility doesn't know anything about C or C++ source code (or any other source code). It looks only at whether the given files have changes without looking at their content.
When you include myheader.h as a dependency, if you later modify that file then running make will rebuild the program.
If you want to know all the non-system header files that a given source file depends on, you can run gcc with the -MM option. This will output a make rule listing the header dependencies of a source file.
For example, if you run gcc -MM src.c, you'll get the following output:
src.o: src.c myheader.h
You can then include that in your makefile.
Yes, you should.
The make program uses the list of files to figure out if a dependency changed and the the target should be rebuilt as a result. It needs you to specify that dependency explicitly.
It does not see the inclusion, it only sees the rules you specified. So there is a theoretical possibility that you change the header in a way that may require a re-compilation of src.o, but make will not know you did that unless you tell it to watch out.

How do I generate included files using cmake?

I've got a tool that generates files that contain definitions and declarations. These files need to be included from other source files or headers - they aren't usable standalone.
The obvious thing to do is have a custom command to generate them. My CMakeLists.txt that does this is as follows. I'm currently using this with the GNU makefile generator.
project(test_didl)
cmake_minimum_required(VERSION 3.0)
add_custom_command(
OUTPUT test_didl_structs.h test_didl_structs.c
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/didl.py --decls=test_didl_structs.h --defs=test_didl_structs.c ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/didl.py ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py)
add_executable(test_didl test_didl.c)
target_include_directories(test_didl PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(test_didl shared_lib)
test_didl.c is very simple:
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "test_didl_structs.h"
#include "test_didl_structs.c"
int main(void) {
}
But on the first build, make tries to build test_didl.c, which of course fails, because test_didl_structs.* haven't been generated yet. Naturally, before the first successful build of test_didl.c, the dependency information isn't known, so make doesn't know to run the python command first.
I tried a custom target, but that's no good, because custom targets are assumed to be always dirty. This means the C file is recompiled on every build and the EXE is linked. This approach won't scale.
My eventual solution was to make the output .h file an input to the executable:
add_executable(test_didl test_didl.c test_didl_structs.h)
.h file inputs are treated as dependencies, but don't otherwise do anything interesting for makefile generators. (I am not currently interested in other generators.)
So that works, but it feels a bit ugly. It doesn't actually state explicitly that the custom commands need to be run first, though in practice this seems to happen. I'm not quite sure how, though (but I'm not up to speed on reading the CMake-generated Makefiles just yet).
Is this how it's supposed to work? Or is there something neater I'm supposed to be doing instead?
(What I'm imagining, I suppose, is something like a Visual Studio pre-build step, in that it's considered for running on every build, before the normal dependency checking. But I want this pre-build step to have dependency checking, so that it's skipped if its inputs are older than its outputs.)
My eventual solution was to make the output .h file an input to the executable.
This way is correct.
It actually states, that building executable depends on given file, and, if that file is OUTPUT for some add_custom_command(), this command will be executed before building executable.
Another way is to generate needed headers at configuration stage using execute_process(). In that case there is no need to add header files as sources for add_executable(): CMake has notion of autodetecting dependencies for compiling, so test_didl will be rebuilt after regeneration of test_didl_structs.h.
execute_process(COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/didl.py --decls=test_didl_structs.h --defs=test_didl_structs.c ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py)
# ...
add_executable(test_didl test_didl.c)
Drawback of this approach is that you need manually rerun configuration stage after changing your .py files. See also that question and answer to it.
Another problem is that header file will be updated every time configuration is run.
You can try tell cmake that you are using an external source, see docs about set_source_files_properties, see this past post

Including header files in C

I am working on a project in which If I could include a header file at runtime, it would save some programming effort. I google'd about it, but all in vain. My question is :
Can we include header files in a C program at runtime ?
If yes, how?
If not, why?
In C the source files are only read compile-time, so the answer to your question is not. Runtime there is only the executable binary, which has nothing to do with your source code headers.
Not really, no. Header files are brought in by the compiler to satisfy symbols needed during compilation.
If you simply want values unrelated to compilation, you can always put them in a configuration file which is read at runtime.
Other possible solutions are command line arguments or environment variables but, since you're discussing putting them into a file, the first option is probably the best.
No header files can't be added at run-time as,
The four stages for a C program to become an executable are the following:
1) Pre-processing
2) Compilation
3) Assembly
4) Linking
and Pre-processing is the very first stage through which a source code passes. In this stage the following tasks are done:
1) Macro substitution
2) Comments are stripped off
3) **Expansion of the included files**
and observation from intermediate file shows that we can get by passing argument to gcc as gcc -Wall -save-temps hello.c -o hello :
1) All the macros are expanded in the preprocessing stage.
2) All the comments are stripped off.
3) The third observation is that beside the line ‘#include’ is missing and instead of that we see whole lot of code in its place. So its safe to conclude that stdio.h and header files has been expanded and literally included in our source file.
and then compilation of code takes place ..
So including header files before compilation is needed.

Compile and link .h header files which many .c source programs use

I work for a group in which our test bucket has hundreds of .c source programs. The .c programs are fairly small and they all include the same 10 .h header files. These .h files are fairly large.
Each time we get a new library file to link our test programs to test, we run a script to recompile and run our test bucket against. The problem is that the compiling takes fairly long, especially if the environment is virtual.
Is there a way to compile the .h header files once, put in a separate object file and have those many .c source files link to said object file? I think this will speed up compiling time. I am willing to change/remove all the #include in the .c source programs.
Any suggestions to speeding up compile time is greatly appreciated.
Also, I should say that a script executes a makefile PER .c source test program! The makefile is not told to compile all programs in the current directory. Each test program is compiled into its own executable.
You could use precompiled header feature. See http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html
You've asked further suggestions to speed up your compilation.
One way can be using ccache. Basically, ccache keeps a cache of the object files compiled so far and returns them (instead of re-compiling again over and over) when it recognises that the same source file is being compiled again.
Using it should be as simple as
Install ccache
Prefix your gcc/cc/g++ command with ccache
Rewrite your headers. Strip off all definition and leave in header. Strip off all implementation and put in new .c. Compile as library. Link with solution. Distribute library on runtime system.
If I understand correctly, the way libraries typically work is by using precompiled code in object files ( .so on Linux systems? ), while providing header files ( .h ) for use in projects.
What happens is when you compile, the #include <library.h> directive finds that header and pastes its contents in the source file being compiled. Then, once the source file is compiled, it is linked to the precompiled object file. That way, the library can be included in a huge number of projects without it needing to be compiled from source each time. The only part that must be recompiled when linking to a library is the ( relatively ) small amount of code in the headers, which essentially makes library functions and variables accessible to the source code.
All this means is that to drastically speed up compilation, your best bet is to take all of the functions out of the 10 .h files, and instead leave only the function prototypes in the headers. Once you have all of the functions in separate .c source files, you can compile them into an object file ( typically -c flag ). Then, whenever you need to compile a new program against the 10 headers you typically use, you can instead include your stripped down version of the headers, and link to the precompiled object. Since only the new code in the .c file has to be compiled, instead of all of the code in the headers, the process should be much faster.

Can the object files output by gcc vary between compilations of the same source with the same options?

Does the gcc output of the object file (C language) vary between compilations? There is no time-specific information, no change in compilation options or the source code. No change in linked libraries, environmental variables either. This is a VxWorks MIPS64 cross compiler, if that helps. I personally think it shouldn't change. But I observe that sometimes randomly, the instructions generated changes. I don't know what's the reason. Can anyone throw some light on this?
How is this built? For example, if I built the very same Linux kernel, it includes a counter that is incremented each build. GCC has options to use profiler information to guide code generation, if the profiling information changes, so will the code.
What did you analyze? The generated assembly, an objdump of object files or the executable? How did you compare the different versions? Are you sure you looked at executable code, not compiler/assembler/linker timestamps?
Did anything change in the environment? New libraries (and header files/declarations/macro definitions!)? New compiler, linker? New kernel (yes, some header files originate with the kernel source and are shipped with it)?
Any changes in environment variables (another user doing the compiling, different machine, different hookup to the net gives a different IP address that makes it's way into the build)?
I'd try tracing the build process in detail (run a build and capture the output in a file, and do so again; compare those).
Completely mystified...
I had a similar problem with g++. Pre 4.3 versions produced exactly the same object files each time. With 4.3 (and later?) some of the mangled symbol names are different for each run - even without -g or other recordings. Perhaps the use a time stamp or random number (I hope not). Obviously some of those symbols make it into the .o symbol table and you get a difference.
Stripping the object file(s) makes them equal again (wrt. binary comparison).
g++ -c file.C ; strip file.o; cmp file.o origfile.o
Why should it vary? It is the same result always. Try this:
for i in `seq 1000`; do gcc 1.c; md5sum a.out; done | sort | uniq | wc -l
The answer is always 1. Replace 1.c and a.out to suit your needs.
The above counts how many different executables are generated by gcc when compiling the same source for 1000 times.
I've found that in at least some environments, the same source may yield a different executable if the source tree for the subsequent build is located in a different directory. Example:
Checkout a pristine copy of your project to dir1. Do a full rebuild from scratch.
Then, with the same user on the same machine, checkout the same exact copy of your source code to dir2 (dir1 != dir2). Do another full rebuild from scratch.
These builds are minutes apart, with no change in the toolchain or any 3rd party libs or code. Binary comparison of source code is the same. However, the executable in dir1 has different md5sum than the executable in dir2.
If I compare the different executables in BeyondCompare's hex editor, the difference is not just some tiny section that could plausibly be a timestamp.
I do get the same executable if I build in dir1, then rebuild again in dir1. Same if I keep building the same source over and over from dir2.
My only guess is that some sort of absolute paths of the include hierarchy are embedded in the executable.
My gcc sometimes produces different code for exactly the same Input. The output object files differ in exactly one byte.
Sometimes this causes linker Errors, because one possible object file is invalid. Recompiling another version usually fixes the linker error.
The gcc Version is 4.3.4 on Suse Linux Enterprise.
The gcc Parameters are:
cc -std=c++0x -Wall -fno-builtin -march=native -g -I<path1> -I<path2> -I<path3> -o obj/file.o -c file.cpp
If someone experiences the same effect, then please let me know.

Resources