I am compiling a self-written Qt5 application, trying to auto-generate the header dependencies with
g++ -MMD -MF../deps/$*.d -MP
The manpage of g++ says:
-MMD
Like -MD except mention only user header files, not system header files.
However, the generated .d files contain stuff like:
/usr/include/qt5/QtWidgets/QDialog /usr/include/qt5/QtWidgets/qdialog.h
/usr/include/qt5/QtWidgets/qtwidgetsglobal.h
/usr/include/qt5/QtGui/qtguiglobal.h /usr/include/qt5/QtCore/qglobal.h
/usr/include/qt5/QtCore/qconfig.h
/usr/include/qt5/QtCore/qtcore-config.h
...
So basically, all the direct and indirect dependencies on Qt header files
are in the output.What am I getting wrong here?
Related
I have the following question. After a successful compilation, if I compile it again after I only change some content in one of the .h files, the computer says:
make: Nothing to be done for `all'.
Can I force the compiler to compile again even if I have only modified the .h files?
If you want your output to be updated when header files change, then you have to add it to your dependency statement:
myprogram: myprogram.cpp myprogam.h
c++ -o myprogram myprogram.cpp
Typically we don't do it this way because the code that does things stays in the cpp file. If you are on unix and want to force a rebuild, just touch a cpp file to update its timestamp (forcing a rebuild) with "touch myprogram.cpp", for example, or delete your existing executable.
If you are using make without a Makefile, letting it infer dependencies, it will probably not infer the header dependencies. In this case, either blow away your executable or touch your source file.
Sounds like your Makefile does not have dependencies configured correctly. That is what you should look into fixing.
If you really want to just force a rebuild rather than fix the underlying problem. Then you can do a make clean before your make all or, if the Makefile does not have a "clean" target, delete all the generated object files and libs/executables and then run make all again.
You can force make to rebuild everything using the --always-make command line option.
However, it sounds like you don't have your dependencies setup properly in your Makefile. If your code (.cpp files) actually include headers, then generally your target for compiling them should have a prerequisite on the header files that it includes.
There is a simpler way than the accepted answer. Simply add -MD to your compiler flags in your Makefile, and -include myfile.d at the end of the Makefile (listing all source files with a *.d extension instead). This will, respectively, generate and reference additional *.d dependency files in your build folder (wherever your *.o files go) when you make, so you do not need to explicitly add every single header file to your makefile dependencies.
This is useful for projects with a long list of header files. Furthermore, this way, you know that you can't forget to include a header file in your Makefile dependencies, preventing troubleshooting time lost later when you think your binary updated when you changed a header file, but it actually didn't because you forgot to put it in the Makefile.
For example, use gcc -MD -I. -c myfile.cpp -o obj/myfile.o, and you can keep your Makefile dependencies as just foo: myfile.cpp without myfile.h.
A shortcut way to do this so you only need to list all files once is something like the following:
# Beginning of Makefile etc. etc.
# Only need to list all files once, right here.
SRCS = myfile.cpp myfile2.cpp
OBJS = $(SRCS:%.cpp=%.o)
# put .o and .d files in ./obj/
# (Assumes 'obj' directory exists)
FULLOBJS = $(addprefix obj/,$(OBJS))
# rule to make object (*.o) files
$(FULLOBJS): obj/%.o:%.cpp
gcc -MD -I. -c %< -o $#
# rule to make binary
foo: $(FULLOBJS)
g++ -o $# $(FULLOBJS)
# rule to clean (Note that it also deletes *.d files)
.PHONY: clean
clean:
rm -rf obj/*.o obj/*.d foo
# include dependency files (*.d) if available
-include $(FULLOBJS:%.o=%.d)
Can I force the compiler to compile again even if I have only modified
the .h files?
Yes ... but you probably want to improve your make (tool).
What I do is to force the most recent compile of the file in question, where the command generated by make shows.
Example:
# ... noise
g++ -O3 -ggdb -std=c++14 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wcast-align -Wcast-qual -Wconversion -Wpointer-arith -Wunused -Woverloaded-virtual -O0 lmbm101_11.cc -o lmbm101_11 -L../../bag -lbag_i686 -lnet_i686 -lposix_i686 -lzlib_i686 -lrt -pthread
# ... more noise.
To force a build, I highlight the "command" make created (starts with "g++", and resides between noise and more noise), and invoke it instead of make.
This is trivial using emacs on Linux. Might not be so easy on other systems.
You might consider copying this command into the file, for future use.
( i.e. I bypass make until I choose to fix my make file. )
I have main.cpp file for which I want to generate dependency file main.d (to be included in Makefile).
I'm calling g++ -MM -MF src/main.d -MP -MT src/main.o src/main.cpp. It works fine unless I have some source generator. I found -MG flag for this, but it doesn't work as I expected it to work.
For example: main.cpp includes module/mod.h (#include "module/mod.h") and mod.h includes generator/gen.h (#include "generator/gen.h"), gen.h is generated. There is following structure:
-Makefile
-src
--main.cpp
--module
---mod.h
---generator
----gen.h
In Makefile I have a rule to generate src/module/generator/gen.h.
Generated by g++ dependencies for existing files are correct:
src/main.o: src/module/mod.h
But for non-existing file gen.h dependency is just generator/gen.h.
If I generate this file before generating dependencies it is correct src/module/generator/gen.h.
Is there any other option for g++ to correctly generate dependencies for non-existing files?
main.d generated when gen.h doesn't exist:
src/main.o: src/module/mod.h generator/gen.h
Correct main.d generated when gen.h exist:
src/main.o: src/module/mod.h src/module/generator/gen.h
As stated in man gcc
The dependency filename is taken directly from the "#include" directive without prepending path
actually there's no way for gcc to know the real path.
I'd recommend you to fix the include statement to keep include path in sync with make path, i.e. white in mod.h
#include <module/generator/gen.h>
put Makefile to src and add proper -I flag to gcc, e.g.
SRCDIR := $(shell pwd)
CXXFLAGS += -I$(SRCDIR)
it is a good practice to always start all non-local includes from some 'source root'
How does the gcc decide what files are to be listed as dependencies to an object file being produced, when it writes a .d file?
I'm seeing different .d files when sysroot path is absolute, and relative.
g++ --MMD --sysroot=absolute_path_to_sysroot -c -o file.o -MF file.d file.cpp
g++ --MMD --sysroot=relative_path_to_sysroot -c -o file.o -MF file.d file.cpp
I'm seeing a weird case, where,
If the compiler path and --sysroot are absolute, then 2 additional header files are being listed as dependencies in the .d file.
If the --sysroot is relative, then 2 additional header files are not being listed as dependencies in the .d file anymore.
This made me wonder, what is the criterion, other than a header being #included, based on which, the .d files are actually written by the compiler, and how would sysroot affect this?
As far as I can tell, it is based on the actual directory where the file is found
The actual "make this a dependancy" happens here, where sysp is set a few lines above based on the directory that it is found in.
http://gcc.gnu.org/viewcvs/gcc/trunk/libcpp/files.c?revision=206293&view=markup#l884
sysp gets set here:
http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/incpath.c?revision=206289&view=markup#l446
Now, it gets complicated if the same directory is both in -I and -isystem directories. In that case, it gets determined by whether the file is included with #include <name> or #include "name" - those using <> are selected only if you use -MD or -M, etc, where the -MMD will ignore anything using <> (or in a directory marked with sysp).
I use g++ -M -MF options. But this makes output about one object file in my project. How get this output for all .o files in my project?
I don't know about QTCreater, but IDEs usually handle header dependencies internally. The GCC options you mentioned are primarily useful if you write your own Makefile, with its own automatic header dependency handling.
I have code that compiles well using the following makefile
all: sample
sample: sample.o mylib.o
g++ -Wall -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -o sample -L/usr/lib sample.o mylib.o -lboost_serialization -lboost_iostreams -lz -I /usr/include/boost
sample.o: sample.cpp
g++ -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -I /usr/include/boost -c -o sample.o sample.cpp
mylib.o: mylib.cc mylib.h
g++ -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -I /usr/include/boost -c -o mylib.o mylib.cc
Now, mylib.cc and mylib.h contains a lot of useful code that I would like to share. However, it depends on Boost which my target audience might not have or know how to install properly.
Is there a way for me to distribute a mylib.o that is static with a mylib.h that my end user can just compile into their own code without needing to install Boost?
ADDITIONAL CLARIFICATION: mylib.h does not contain any BOOST headers, but mylib.cc DOES contain boost headers.
If mylib.h includes Boost header files, those will need to be present in some form on the developer's system. At a minimum, you would have to ship that part of Boost with your code.
However, if you can create a smaller header file that exposes just the pieces of your library and does not include nor reference anything in Boost, then you can. Most of Boost is header-only (the required Boost code will be compiled into your library already).
If you're able to create a "boost-free" header, you can do that.
As soon, as you have any references to boost stuff within the header (which you need to redistribute), you can't.
If your cc file uses boost classes which are not header-only, you need to distribute those files, too - either in sourcecode, or within an object-file - which however can lead to strange behavior, if an user uses another version of the boost library and tries to instantiate classes, which are already defined within your object files.
One possible solution would be to find out, which cc-files of boost are required and compile them within a different namespace, e.g. using -Dboost=my_boost:
g++ -Dboost=my_boost <put additional compiler options here> my_boost_file.cc -c my_boost_file.o
You also should compile your own object file with that define.
Finally create an archive containing all the required object files;
ar rvs my_archive.a mylib.o my_boost_file.o