After an error occurred because of a missing flag or incorrectly set environment variable, is it possible to continue compiling once the mistake has been fixed?
I regularly use CMake and make to compile toolkits that take quite a while to compile and, also regularly, I accidentally set variables incorrectly in the process. Just now for example, I was attempting to include OpenInventor headers which on my machine are located in the directory /Users/user/software/prod/coin/include/Inventor.
I mistakenly passed
-DINVENTOR_INCLUDE_DIR=/Users/user/software/prod/coin/include/Inventor
rather than the correct
-DINVENTOR_INCLUDE_DIR=/Users/user/software/prod/coin/include
This only became an issue after 30 minutes when about 95% of the compilation was completed. Because I knew that reconfiguring using CMake would force a recompilation from scratch, I tried to add -I/Users/user/software/prod/coin/include to CMAKE_CXX_FLAGS in CMakeCache.txt but to no avail–it still recompiled from scratch. Since only a single source file actually includes the headers in question, it would be desirable if I could start compiling from the point where it exited with an error once the relevant path has been corrected. How can I do this and, as an aside, why does it force the compiler to start from scratch?
I'm using CMake version 3.11.1 and clang (Apple LLVM version 9.1.0) on macOS 10.13
CMake does not need to recompile everything just because it regenerates its makefiles. It will still perform normal make avoidance operations. However CMake does track the compiler options used to build each target, so if you make a change in the compiler options for all the targets then they'll all need to be rebuilt.
If this compiler option is only needed for one target, you can add it to just that target an no others, with something like this:
set_property(SOURCE my_source.c APPEND PROPERTY
COMPILE_FLAGS -I/foo/bar)
then it should only rebuild that one source file.
CMake looks for files' "last modified" times to decide which files need recompilation. But if you change the input to CMake itself, then it needs to regenerate the Makefiles and therefore recompile everything. But still, one hack may be possible...
CMake stores information about the include directories and the libraries to be linked in various text files in the build directory. So one hack (not recommended, but works) can be to modify these text files.
In the particular example that you mentioned, the hack would be to search and replace all occurrences of /Users/user/software/prod/coin/include/Inventor with /Users/user/software/prod/coin/include in all the files of the build directory.
(As an aside, if you don't already know, you can use make -j <n> to build using multiple threads which can considerably decrease the build times.)
Related
I'm learning GNU make . Suppose I have a hello_world.c file and a Makefile:
hello_world.c:
#include <stdio.h>
int main() {
printf("Hello World!\n");
return 0;
}
Makefile:
hello: hello_world.c
gcc hello_world.c -o hello_world
Now, I think hello is my target and hello_world.c is its dependency. If make somehow detects that hello_world.c is newer than its object-file, it executes the corresponding command.
1- How does make manage file version control and how does it detect something is newer than something else and needs updating?
2- If I change hello_world.o using an editor and corrupt the file, it obviously does not execute but make hello reports that nothing needs to be done!
I mean, make only checked that the dependency is older than the target and exited doing nothing. I think it should have detected that this target is not the one corresponding to its latest invocation. Somehow, it should have compared the "combination of dependency AND target" history instead of just comparing dependency's history w.r.t. target.
3- Is this the limitation of make? How can I circumvent this issue? Because there maybe some external apps messing with the target of my make operation.
1- How does make manage file version control and how does it detect something is newer than something else and needs updating?
You already know the answer to this question. You said it in your next paragraph: "I mean, make only checked that the dependency is older than the target and exited doing nothing." That's right. make updates dependent targets when the dependencies of targets are newer.
2- If I change hello_world.o using an editor and corrupt the file, it obviously does not execute but make hello reports that nothing needs to be done! I mean, make only checked that the dependency is older than the target and exited doing nothing. I think it should have detected that this target is not the one corresponding to its latest invocation. Somehow, it should have compared the "combination of dependency AND target" history instead of just comparing dependency's history w.r.t. target.
You are asking make to do a lot more than what it was intended to do.
3- Is this the limitation of make? How can I circumvent this issue? Because there maybe some external apps messing with the target of my make operation.
From your point of view, it does seem like it is a limitation of make. However, I want to point out that you are sabotaging the workings of make by updating a target manually.
How can you circumvent it?
Don't manually modify targets that are built by make.
Manually update the time stamp of one of the dependencies and then run make. You can use the command touch for that.
Provide a dummy target named clean that will remove all the dependent targets. Then, run make clean followed by make.
Provide a dummy target named rebuild. Forcefully build whatever you need to build in that target. Then, run make rebuild.
The make program simply compare the modification time-stamps of the target (hello) and the dependency (hello_world.c) files.
If the time-stamp of a dependency file is newer than the targets, then it execute the commands.
How does make manage file version control and how does it detect something is newer than something else and needs updating?
Very simple: make does not care about file versions.
Detecting if something is newer than something else is simply done by comparing time stamps from file system.
If I change hello_world.o using an editor and corrupt the file, it obviously does not execute but make hello reports that nothing needs to be done! I mean, make only checked that the dependency is older than the target and exited doing nothing. I think it should have detected that this target is not the one corresponding to its latest invocation. Somehow, it should have compared the "combination of dependency AND target" history instead of just comparing dependency's history w.r.t. target.
You did not tell make anything about your .o file. Why should make check the timestamp of that file?
Checking the dependency is exactly what make is expected to do.
How should this tool possibly know that a file calles hello_world.o is involved in the process if you don't tell it? There is no magic happening but only the rules of your Makefile are followed.
Is this the limitation of make? How can I circumvent this issue? Because there maybe some external apps messing with the target of my make operation.
You can specify hierarchical dependencies:
all: hello
hello: hello_world.o
<gcc linker command...>
hello_world.o: hello_world.c
gcc hello_world.c -o hello_world
I have a project which uses Makefiles. On a branch, I have CMake based build system. Now some team-members wants the OLD make-files based system intact, when cmake is added. But this is not possible after cmake . command overwrites the old Makefile.
Now I can easily avoid it if I can tell CMake to generate makefiles with some non-standard names e.g. makefile.cmake etc. Is it possible?
I am open to consider other options as well. In any case, old Makefiles must not be touched.
Cmake creates a build system in the working directory. So create any empty directory, and run cmake <path-to-source> from there.
Unfortunately, the name "Makefile" in hard-coded several times, in the sources of CMake. You cannot change it. As Peter has pointed out in the other answer, that change is not necessary, because CMake support out-of-source builds.
I am currently working on a project on a student job and writing some code. Whenever I want to compile my file, my supervisor told me to first do gmake clean and then do gmake. Otherwise,some errors from previous gmake may not be solved in the fresh gmake.
My project has a lot of unnecessary files that I am not editing but since i gmake clean everytime, the compiler compiles them again everytime which takes a lot of time.
So, if I am not changing the other files, then I don't need to recompile them and the only file that I change is always recompiled simply with gmake, right? So why should I gmake clean everytime?
Is my supervisor just telling me a good programming practice or am I missing some important concept of gmake clean?
The difference between gmake and gmake clean is that the former builds the default target while the latter "builds" the specific target clean, which usually consists of clean-up instructions to remove files that were created during the build process (object files, temporary files, generated code, …). gmake clean should restore the source tree to a clean state. However, if it actually succeeds depends on how the source tree looks like and what instructions the target contains.
definitely not a best practice... this is usually the quick and dirty solution when the makefile contains a few mistakes and the dependencies are not ok
do gmake clean before gmake in case you have difficulties to compile. just to check if the problem does not come from an old compiled file.
otherise do only gmake in orther to compile your newest changed files.
you superior gived you an advice to handle difficult and strange compilation behavior.
A small change in a 1000's of lines of code leads to running the ./configure again on the entire software.
Is there any alternative, where we can compile only the changed file and the files associated with it?
If you have a sane Makefile.am with proper dependencies, running ./configure and make should only recompile files that depend on the touched file. So make already does what you are asking for.
If your Makefiles are not sane (e.g. they only work if you run make clean) and you are compiling C or C++ sources, using ccache might give you a speed gain. With ccache only the preprocessor part is run and its output compared to a cache of compile outputs. If nothing changed in the file or its includes it won't be recompiled. Properly installed it is run in a transparent way.
I develop C/C++ using the Eclipse IDE. Eclipse also generates a makefile which I don't want to edit as it will simply be overwritten.
I want to use that makefile for nightly build within Hudson.
How do I pass #defines which are made in the project file of the IDE to the makefile ? (and why doesn't Eclipse already include them in the generated makefile?)
I actually had this figured out once, then accidentally overwrote it :-( But at least I know that it can be done...
If you are running make from the command line, use
make CPPFLAGS=-DFOO
which will add -DFOO to all compilations. See also CFLAGS, CXXFLAGS, LDFLAGS in the make manual.
You could write a small program to include the headers and write a makefile fragment which you include in the main makefile (requires GNU make).
This is a fairly ugly solution that requires a fair amount of hand hackery. More elegant would be to parse the project file and write the makefile fragment.
For GCC use -D define.
OP commented below that he wants to pass the define into make and have it pass it on to GCC.
Make does not allow this. Typically you just add another make rule to add defines. For instance 'make release' vs 'make debug'. As the makefile creator you make the two rules and have the defines right in the make file. Now if Eclipse is not putting the defines into the makefile for you, I would say Eclipse is broken.
If you're using autotools another options is to have 2 directories 'bin/debug' and 'bin/release'.
# Simple bootstrap script.
# Remove previously generated filed and call autoreconf.
# At the end configure 2 separate builds.
echo "Setting up Debug configuration: bin/debug"
../../configure CXXFLAGS="-g3 -O0 -DDEBUG=1"
echo "Setting up Release configuration: bin/release"
cd bin/release/
../../configure CXXFLAGS="-O2"
Setup Eclipse. Open the project's properties (Project->Properties->C/C++ Build->Builder Settings) and set the Build Location->Build Directory to
${workspace_loc:/helloworld/bin/debug}
Replacing 'helloworld' with your project's directory relative to the workspace (or you can supply an absolute path ${/abs/path/debug}). Do the same thing with the Release config, replacing "/debug" with "release" at the end of the path.
This method seems like a waste of disk space, but a valid alternative to achieve completely separate builds.