I am running GNU gmake for my build process. I use file extensions as the following:
.pc: pro*c code (compiled by using oracle's proc compiler)
.cpp : c++ code (compiled by GNU g++ compiler)
.o: object file
.mc: c++ code (compiled by GNU g++ compiler)
.mo: object file
A .pc file gets compiled by Oracle proc compiler and output is having extension .cpp or that gets compiled by g++ compiler to generate .o file. All .o files eventually get linked together to make the executable file.
For some other requirement, I need to have some special code block within .pc file as below.
#ifdef SPCL_BLCK
// some code
#endif // end of SPCL_BLCK
I need to have to different paths to have my executable variants, with and without special code part.
Without special code part, the paths are:
.pc -> .cpp -> .o -> executable
With special code part, the paths are:
.pc -> .mc -> .mo -> executable
I have my PROC flags defined as:
PROCFLAGS := code=cpp 'include=(<<list of comma-separated include dirs>>)'
normal rules (for path without special code):
.pc.c:
proc $(PROCFLAGS) $<
%.o: %.c
g++ -c $(CCFLAGS) $<
where, CCFLAGS are usual C++ compiler flags
rules (for path with special code):
%.mo: %.mc
$(CC) -c $(CCFLAGS) -DSPCL_BLCK -o $# -x c++ $<
%.mc: %.pc
$(PROC) $(PROCFLAGS) define=SPCL_BLCK oname=$# $<
All is well, but after the successful build, the .mc files gets deleted.
I see that's done by rm command, but is there any implicit rule that is driving the removal of the .mc files?
Can I have some command that could stop firing implicit rules?
I need to define the following in gmakefile:
.PRECIOUS:%.c %.mc
Otherwise, GNU gmake thinks that .mc files are intermediate files and drives the removal of these .mc files
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 am writing a cpp library for myself and I have put the deader files in a folder <root>/include and the cpp files in <root>/src folder. To add my include path to the environment, I have appended <root>/include to CPLUS_INCLUDE_PATH. Now, the problem I am facing is that I am getting an error during the linking step because the linker is unable to find the implementation of my class. Is there any environment variable where I can mention this like the way I have done for the header files?
You cannot do that. The linker needs compiled code and cannot deal with your source files. What you can do is to write a Makefile that will compile all your source files in the /src folder and link compiled files to the target. Example of a Makefile doing this:
ROOT = YOUR_ROOT_DIRECTORY_HERE
LDFLAGS = OPTIONS_TO_LINKER_HERE
CPPFLAGS = OPTIONS_TO_COMPILER_HERE
SRC=$(wildcard $(ROOT)/src/*.cpp)
your_app: $(SRC)
g++ $(CPPFLAGS) $(LDFLAGS) -o $# $^
Compile your application using: make your_app, or make.
I have this makefile which I don't understand.
build_sources:=$(wildcard *.cpp)
depends:=$(build_sources:.cpp=.d)
build_targets:=$(build_sources:.cpp=)
.PHONY: all
all: $(build_targets)
.PHONY: clean
clean:
rm -f $(build_targets) *.{a,o,d}
#build the list of header file dependencies automatically
%.d: %.cpp
#echo building include dependencies for $(*F)
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; } > $#
-include $(depends)
I understand that the executables created are build_target. So if I have Foo.cpp and Bar.cpp, the executables created would be Foo and Bar.
But how does it do that? I only see 1 rule, and it is %.d: %.cpp. So it's saying the Foo.d file depends on Foo.cpp. But what about the rule to actually compile Foo?
This makefile works, so it's not actually missing anything. But how come I don't see the rule? Is there some implicit rule?
EDIT - i did make debug, and saw the following
No need to remake target `foo.d'.
Considering target file `foo'.
File `foo' does not exist.
Looking for an implicit rule for `foo'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.o'.
Found an implicit rule for `foo'. ## WHAT EXACTLY IS THIS?
Considering target file `foo.o'.
File `foo.o' does not exist.
Looking for an implicit rule for `foo.o'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.c'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.cc'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.C'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.cpp'.
Found an implicit rule for `foo.o'.
Pruning file `foo.cpp'.
Pruning file `foo.cpp'.
Finished prerequisites of target file `foo.o'.
Must remake target `foo.o'.
g++ -I../../include -Wall -std=c++11 -O3 -Wsign-compare -Wno-strict-aliasing -s -c -o foo.o foo.cpp
That's great. This must be the rule that's getting called. But where is this rule from? How do I know what default rules exist?
What you probably miss to understand this Makefile is the concept of pattern rule and automatic variables.
This part finds .cpp files:
build_sources:=$(wildcard *.cpp)
And this part creates targets with the same name (using the variable build_sources defined above) except the extension is replaced by .d:
depends:=$(build_sources:.cpp=.d)
The same kind of construction defines the build targets (same file name with extension removed):
build_targets:=$(build_sources:.cpp=)
Then the default target is defined to require build_targets, i.e the executable corresponding to the .cpp`
all: $(build_targets)
This rule defines how to build a .d from a .cpp:
#build the list of header file dependencies automatically
%.d: %.cpp
#echo building include dependencies for $(*F)
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; } > $#
gcc -MM produce rules to know on which headers a .c or .cpp file depend. Typically if test.cpp includes test1.h and test2.h the output will be:
test.o: test.cpp test1.h test2.h
The .d will contain dependencies of each cpp file and will create a ruleto build a .o file and an executable from each cpp. $# is the target of the rule (the .d file) and will contain, unless I'm mistaken, a rule looking like this (written by the sed expression):
filename.o filename.d : filename.cpp <list of headers>
%.h:;
The first rule give dependencies of the .o files. It has no recipe which means it simply adds dependencies to any existing rule. An implicit rule will be used to build them.
The second one is here in case you suppress a header. In this case, make will use this rule that says that there's simply nothing to do (it has an empty recipe).
Then all the .d files are included as part of the makefile:
-include $(depends)
Finally, the implicit rule to link a single .o file kicks in:
Linking a single object file
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
Edit: To build objects in a subdirectory obj you would have to modify each filename:
depends:=$(foreach file,$(build_sources:.cpp=.d),"obj/$(file)")
To build binaries in a separate subdirectory bin you would need to do the same for build_targets:
build_targets:=$(foreach file,$(build_sources:.cpp=), "bin/$(file)")
Then you need to write the rule to build it because the default rule wont work anymore (the .o is not in the same directory). What you want is to add a rule like this:
bin/foo: obj/foo.o
$(CC) $(LDFLAGS) obj/foo.o $(LOADLIBES) $(LDLIBS) -o bin/foo
which can be done with the right modification of the long shell command:
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; obj=`echo $< | sed 's/.cpp/.o/'` ; bin=`echo $< | sed 's/.cpp//'` ; echo "$bin: $obj" ; echo -e "\t\$(CC) \$(LDFLAGS) $obj \$(LOADLIBES) \$(LDLIBS) -o $bin" ; } > $#
Your make package includes a large number of default rules, which this Makefile depends on. Try running your make with -d (debug info). I believe that will show you everything that is in play.
Many rules are built in to Make. If you are using GNU Make, you can get it to print its built-in rules like this:
make -f /dev/null -p
You can make it ignore the built-in rules with -r; if you do this with your Makefile, you'll find that it complains that it doesn't know how to make your targets.
The makefile is't complete in itself. It automatically creates the files .d which are snippets included into that makefile at the end. These files are created with the %.d-rule.
So have a look at those generated .d files to see rules for each individual object file. The rule generation script is written with sed and kind of hard to read, but in fact very simple. At first, the compiler is invoked on the .cpp file with the -MM flag, which will output something like
foo.o: foo.cpp foo.h bar.h
if foo.cpp includes its own header file foo.h as well as bar.h, for example (directly or indirectly).
The sed regex replacement command now simply adds the name of the file, in which the generated rules are about to be written (the .d file) right after the .o in the above rule, so it is also marked as depending on the sources, just like the object file. That's important when the includes in one of the sources is changed later. The sed command also adds a rule for all header files to do nothing.
foo.o foo.d: foo.cpp foo.h bar.h
%.h:;
The resulting object files .o are then linked using one of the implicit rules:
Linking a single object file
n is made automatically from n.o by
running the linker (usually called ld) via the C compiler. The precise
recipe used is $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).
[...]
I have the following code generation scheme:
The original file is *.c.macro
It is processed by a special program that generates the *.c file. The program uses external XML files mentioned in the original .c.macro file. Somthing along this line:
macroprocess foo.c.macro -o foo.c
Then the *.c file is compiled to *.o normally
What I want to do is to make the .c file dependant on the XML files. So that if the XML changes, macroprocessing is automatically redone when 'make' command is invoked.
I can modify the code of the macroprocessor so that it would generate a list of all XMLs and write it somewhere, but I have no idea how to incorporate it into a makefile. Apparently I would need to play with 'include' command in the makefile, but usually it's employed to add dependencies on actual code like .h files.
If you can get your macroprocess to write a dependency file (e.g. *.xmldep) for each *.c.macro file you can do:
-include $(C_MACRO:.c.macro=.xmldep)
where $(C_MACRO) is a variable that contains your *.c.macro files.
The - in front will ensure that the first time, the make will not fail when it cannot locate the dependency files.
You can add foo.xml as a dependency of foo.c and use a filter command to get only the %.c.macro file as arguments for macroprocess.
Something like this:
# Basic targets
all: foo
foo: foo.o
gcc -o $# $^
foo.o: foo.c
gcc -o $# -c $<
# Special target with filter
foo.c: foo.c.macro
macroprocess -o $# $(filter %.c.macro,#^)
# Adding foo.xml as a dependency of foo.c
foo.c: foo.xml
.PHONY: all foo
Does anyone have a complete makefile that can do the following:
Rebuilds the project if a HEADER file changes
The cpp files are listed in the makefile
The header files are NOT listed in the makefile
The header files are allowed to have different names than the cpp files
Some of the cpp files do not have header files
I have seen instructions for figuring out how to make the make tool figure out header dependencies, but none of these instructions provide anything remotely resembling a working example. A simple example would be as follows: main.cpp C1.cpp C1.h C2.cpp C2.h
CXX = g++
OBJECTS := main.o C1.o C2.o
all: $(OBJECTS)
%.o : %.cpp
$(CXX) $(CPPFLAGS) -Wall -MMD -c $< -o $#
-include *.d
EDIT: As TobySpeight points out, this won't work if you build an object file, rename or delete one of the prerequisite source or header files, then try to rebuild the object file; the .d file will still require the missing file, and the build will fail. I neglected to include lines to deal with that case:
%.h: ;
%.cpp: ;
(This is effective, but crude. The more precise approach is to put some sed commands in the %.o rule, so as to add specific null rules to the .d file, one for each prerequisite, but the sed commands are ugly, and the approach above is good enough for almost all cases.)
You can also use CMake for this. Everything you need to write is:
add_executable (exec main.cpp C1.cpp C2.cpp)