Getting rid of QMAKE-generated makefile's output spam - makefile

If I would write makefile by hand , I can do something like this
CXX = #g++
%.o: %.cpp makefile
#echo Compiling $< ...
$(CXX) -c $(FLAGS) $<
This would hide the executed command (thanks to #) but leaves all diagnostic and compiler's output. It would remove huge lists of parameters out of output log, but also would leave a comprehensive message.
I'm unable to reproduce this behaviour with Qmake, because all I can supply is a variable named QMAKE_CXX, content of which it would paste as a compiler, no way to insert a line break to my knowledge. Using these commands results in output like this
Compiling main.cpp...; #g++ -c -o main.o main.cpp
Can I organize output similar to manual compiler while using only QMAKE project file?

Should be something like this:
QMAKE_CXX = #echo "Message" && $$QMAKE_CXX
QMAKE apparently got undocumented QMAKE_UIC and QMAKE_MOC, with former being broken in some versions. Also an undocumented CONFIG += silent which replaces command lines with similar messages and uses same principle.

Related

GNU make generate assembly first, them compile them to .o and link

SOURCE=a.c b.c c.c
ASM=$(patsubst %.c,%.s, $(SOURCE))
all:%.o
gcc -o test $^
$(ASM):%.c
gcc -S -o $# $<
%.o:%.s
gcc -c -o$# $<
I want to generate assembly code (.s) first, then compile the assembly code to object (.o), then link them.
But it seems above makefile code does not work. What is the correct code?
When asking questions, does not work is never very useful... if it worked you probably wouldn't be asking a question! :-) Instead you should always show the command you ran and the output you received (or at least the failing part of the output if it's long). Please cut and paste the actual text rather than paraphrasing messages. Also, including the version of the make program you're using (make --version) and the platform you're running on is often helpful.
Luckily this time we can figure out the problem without this information:
This:
$(ASM):%.c
gcc -S -o $# $<
where ASM is a.s b.s c.s, is not a pattern rule because the targets don't contain a pattern character %. That means the prerequisite %.c is not treated as a pattern, but as an actual file name, literally %.c which obviously doesn't exist.
Similarly, this:
all: %.o
has the same problem: all is a target, so this depends on the literal file named %.o which doesn't exist, and can't be created.
Also as a general rule every recipe that creates a target must create the actual target you told make it would, so this all rule is wrong because the target name is all but the recipe creates the target test.
Finally, it's a very bad idea to name your program test because test is a common UNIX program and a shell built-in, so if you run test it won't do the right thing (if you run ./test it will work).
You want to have all depend on the program you want to build, say mytest, and mytest should depend on the actual .o files:
all: mytest
mytest: $(SOURCE:.c=.o)
gcc -o $# $^
Next, you need to define a pattern rule that knows how to create an assembly file from a source file:
%.s : %.c
gcc -S -o $# $<
That, along with your other pattern rules, is all you need: make will figure it all out from that.
Finally, make has a built-in rule that tells it how to build object files directly from source files. It's best to get rid of this to force make to use your rules; add this to your makefile to delete it:
%.o : %.c

make is calling g++ is always re-compiles even when I do not change the source code

I am using make which calls g++ always re-compiles the code, even when I do not change the source code. That happens for all my projects, even for simple ones such as:
[code]
all: main.cpp
g++ -std=c++11 -c main.cpp
[/code]
I believe it should compare the date/time on source and object code. Could some help me with this, I am running using GNU toolchain on Ubuntu 12.04
THX
Edit: sorry guys, I do use Makefile, I edited my question accordingly.
Simplest Makefile
It was already pointed out that your Makefile is probably wrong. The 'all' target is indeed always built (although it may result in a no-op if it has no commands and all dependencies are already satisfied). All you need in your makefile is this:
all: main
Object files
If you expect to have more source file in your build, you should consider creating intermediate object files:
all: main
main: main.o
Tweak the build
Make will automatically find the main.ccp file and turn it into main which is required per the directive above. You can use special make variables to further tweak the compilation, e.g. for debug information inclusion and for warning configuration:
CXXFLAGS = -g -Wall -Werror
all: main
main: main.o
Nitpicking
If you insist on building up the compile rule yourself, you can do it like this:
%.o: %.hpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
CXX: C++ compiler
CPPFLAGS: C preprocessor flags
CXXFLAGS: C++ compiler flags
$#: Target
$<: First dependency
If you don't want to use the standard variables nor pattern matching, you can build up the whole makefile explicitly:
all: main
main: main.o
gcc -o $# $^
main.o: main.c
gcc -g -Wall -Werror -o $# -c $<
$^: Use that one if you want to include all dependencies, for example if you have multiple *.o files to build one binary.
Note: It is a bad idea to write the file names directly into the command as you might forget to update them later.
all: main.cpp
g++ -std=c++11 -c main.cpp
This seems wrong. Why does the rule for all has main.cpp as its target? Shouldn't it be something.exe or something.o? Say
all: main.exe
main.exe: main.cpp
g++ -std=c++11 main.cpp -o main.exe
clean:
del main.exe
Targets are output files and cpp files are source code which should be input to the make system.
g++ would have to "recompile" in general (what happens if you change the header but not main.cpp?)
If you are concerned about long build times, you should use something like Make (which is designed specifically to avoid recompiling when the source hasn't changed)
The compiler will always compile the code. If you want to do conditional compilation (based on file times etc) you will need to use a make system such as Make, CMake, Ant, etc. For the simplest you can set up a small "Makefile" in the directory and use the command "make" to build.
Simple Makefile for compiling "myapp.exe" from "main.cpp", "file1.cpp" and "file2.cpp"
myapp.exe: main.o file1.o file2.o
g++ -o myapp.exe main.o file1.o file2.o
(make knows to use .cpp files to build .o files)
But if you also have header files, then you will need to build dependency chains, for which you may want to look into something more sophisticated like automake, cmake, ant, etc.
---- EDIT ----
Based on your updated post, the problem is that you aren't specifying a target, so Make has to assume it needs to recompile. See my example in the above answer.

g++: fatal error: cannot specify -o with -c, -S or -E with multiple files

I am trying to compile a library file using other library files. I am using the following line in my makefile to create gameobject.o:
lib/gameobject.o: src/gameobject.cpp src/vector.hpp lib/objectevent.o lib/sprite.o
g++ $^ -c -o $# $(SFML_FLAGS)
All the dependencies comile correctly, but I get the following error when it tries to compile gameobject.o:
g++: fatal error: cannot specify -o with -c, -S or -E with multiple files
I'm still a bit new to using make/separating compilation, so I'm not quite sure what I should do. Do I just have to compile it without setting an output? Do I have to compile gameobject.o without using any of my other .o files? If that's true, wouldn't compile times get pretty big for large objects if you can't compile libraries with other libraries? Or am I just reading this error completely wrong?
You're not building a library file here. A .o file is an object file. Typically there is one object file per source file. When you use the compiler's -c option, it takes a single source file and compiles it into a single object file. You cannot add other object files into an existing object file, so adding both .o and .cpp files into the same compiler line with -c is not going to work.
If you want to create a library, that would be something like libfoo.a (the "a" here stands for "archive"). If you want to create an executable you can do that as well.
You need to be more clear about exactly what result you want before we can describe how to get it.
I had the same problem after I combined some projects of a solution to a single one. I find out there was tow .cpp files with same names and after I did rename one of them It solved.
You can create only one object .o file from one source file.
If you are using makefile to build the project. Make sure you are doing $< instead of $^
# Correct one
%.o: %.cpp
$(CPP) $(CFLAGS) -c -o $# $<
# InCorrect one
%.o: %.cpp
$(CPP) $(CFLAGS) -c -o $# $^

How to use command line argument in GNU make?

For example, I have 10 source files named ex1.c, ex2.c, ex3.c....ex10.c and maybe more in the future.
Is it possible that I can use commandline argument as a variable in GNU Make so that when I want to compile ex1.c, I can type in make 1. If I want to compile ex10.c, I can type in make 10. And I don't need to add more lines to makefile when I add more sources like ex100.c later.
This doesn't strike me as a good idea, but yes, you can do it.
To build object files (e.g. ex3.o):
%: ex%.c
$(CC) -c $< -o ex$*.o
To build executables (e.g.ex3):
%: ex%.c
$(CC) $< -o ex$*

makefiles CFLAGS

In the process of learning TinyOS I have discovered that I am totally clueless about makefiles.
There are many optional compile time features that can be used by way of declaring preprocessor variables.
To use them you have to do things like:
CFLAGS="-DPACKET_LINK" this enables a certain feature.
and
CFLAGS="-DPACKET_LINK" "-DLOW_POWER" enables two features.
Can someone dissect these lines for me and tell me whats going on? Not in terms of TinyOS, but in terms of makefiles!
CFLAGS is a variable that is most commonly used to add arguments to the compiler. In this case, it define macros.
So the -DPACKET_LINK is the equivalent of putting #define PACKET_LINK 1 at the top of all .c and .h files in your project. Most likely, you have code inside your project that looks if these macros are defined and does something depending on that:
#ifdef PACKET_LINK
// This code will be ignored if PACKET_LINK is not defined
do_packet_link_stuff();
#endif
#ifdef LOW_POWER
// This code will be ignored if LOW_POWER is not defined
handle_powersaving_functions();
#endif
If you look further down in your makefile, you should see that $(CFLAGS) is probably used like:
$(CC) $(CFLAGS) ...some-more-arguments...
Somewhere in the makefile the CFLAG will be used in compilation line like this:
$(CC) $(CFLAGS) $(C_INCLUDES) $<
and eventually in the execution will be translated to :
gcc -DPACKET_LINK -DLOW_POWER -c filename.c -o filename.o
This define will be passed to the source code as it was define in the header file
The -D option set pre-processor variables, so in your case, all code that is in the specified "#ifdef / #endif" blocks will be compiled.
I.e.
#ifdef PACKET_LINK
/* whatever code here */
#endif
The CFLAGS is a variable used in the makefile which will be expanded to it's contents when the compiler is invoked.
E.g.
gcc $(CFLAGS) source.c
-D stands for define (in gcc) at least, which lets you #define on the command line instead of a file somewhere. A common thing to see would be -DDEBUG or -DNDEBUG which respectively activate or disable debugging code.
Just for completeness in this - if you're using Microsoft's nmake utility, you might not actually see the $(CFLAGS) macro used in the makefile because nmake has some defaults for things like compiling C/C++ files. Among others, the following are pre-defined in nmake (I'm not sure if GNU Make does anything like this), so you might not see it in a working makefile on Windows:
.c.exe:
commands: $(CC) $(CFLAGS) $<
.c.obj:
commands: $(CC) $(CFLAGS) /c $<
.cpp.exe:
commands: $(CXX) $(CXXFLAGS) $<
.cpp.obj:
commands: $(CXX) $(CXXFLAGS) /c $<

Resources