My C code has various files having statements that I want to execute only if a macro is defined. I have two files each having the following code:
#ifdef SOME_MACRO
printf("macro defined\n");
#else
printf("macro undefined");
#endif
My Makefile contains:
make -C /lib/modules/$(shell uname -r )/build M=$(PWD) modules $(CFLAGS)
and I am calling make as:
make all CFLAGS=SOME_MACRO=10
When I execute the resulting program, I get 'macro undefined' indicating the macro is not being defined.
I have also tried calling it as:
make all CFLAGS=SOME_MACRO
which gives me:
make[1]: *** No rule to make target `SOME_MACRO'. Stop.
make[1]: Leaving directory `/X/Y/Z'
make: *** [default] Error 2
And also calling it as:
make all CFLAGS=-DSOME_MACRO=10
as given here and here but this is not working either.
How do I make this work?
The third form is correct (make all CFLAGS=-DSOME_MACRO=10 or just make all CFLAGS=-DSOME_MACRO). But the make file that you are calling has to actually use that CFLAGS macro.
Make's implicit rules for compiling an executable or object c file will use CFLAGS, but we can't tell whether it is being invoked or overridden without seeing either the content of that makefile or the output from make.
The output from make should show the build commands. The implicit rule for making a .o from a .c file is $(CC) $(CPPFLAGS) $(CFLAGS) -c so you should see something like cc -DSOME_MACRO=2 -DFOO=99 -c -o x.o x.c given you compiling an object file, and similar if you compiling a executable.
Also make sure your cleaning you project properly make clean. And make sure the clean is actually recursive (i.e. cleans you "modules" project too)...
Edit: Oh yeah ... as #nneonneo's answer points out you also have an error in recursive the make call which is definitely an issue (I figured you were running the 2nd make command directly to debug the problem..). The above may still apply.
Your Makefile contains
make -C /lib/modules/$(shell uname -r )/build M=$(PWD) modules $(CFLAGS)
which will pass the value of the variable CFLAGS as make arguments. This is not what you want. Use CFLAGS=$(CFLAGS) instead:
make -C /lib/modules/$(shell uname -r )/build M=$(PWD) modules CFLAGS=$(CFLAGS)
to pass the CFLAGS along to the sub-make, then simply use make CFLAGS=-DSOME_MACRO=10 to build.
Related
Hi I Have this makefile:
main.o:main.c functionsLab1.c functionsLab1.h
gcc -c main.c
functionsLab1.o: functionsLab1.c functionsLab1.h
gcc-c functionsLab1.c
now when i Run the command "make" it only executes the first command in makefile.
how can I Run all the commands at once?
Thanks in advance :)
I Tried to type "make all" command and it showed an error.
make is able to build what you need, but only if you tell it the right dependencies. In particular, your current Makefile is lying about dependencies, since main.o does not at all depend on functionsLab1.c. Rather, the final executable you are trying to build depends on functionsLab1.o. You can probably make your entire Makefile:
main: main.o functionsLab1.o
(Yes, literally one line.). That ignores the dependency on the header file, but it should work for you. Let make use its default rules; they are pretty good. If you want to include the header dependency, do something like:
main: main.o functionsLab1.o
main.o: main.c functionsLab1.h
functionsLab1.o: functionsLab1.c functionsLab1.h
If for some reason you really want to be explicit (you don't!), you can do:
main: main.o functionsLab1.o
$(CC) -o $# $? # Warning: incomplete. See note below
main.o: main.c functionsLab1.h
functionsLab1.o: functionsLab1.c functionsLab1.h
Again, letting make use its default rules to construct the object files. You can override the default rules, but there is very seldom a reason to do so. Indeed, this is an excellent example where attempting to override the default rule gives you a sub-optimal recipe. The default rule would be something like $(CC) $(LDFLAGS) -o $# $? $(LOADLIBES) $(LDLIBS), and many users would reasonably expect to be able to specify LDLIBS. The example shown above ignores LDLIBS, violating the principal of least surprise.
I'm having a problem with a C Makefile.
This is the code for the Makefile in bash:
CC=gcc
CFLAGS=-g -Wall
CCLINK=$(CC)
OBJS=flight.o runway.o airport.o main.o
RM=rm -f
# Creating the executable (airport)
airport: $(OBJS)
$(CCLINK) -o airport $(OBJS)
# Creating object files using default rules
main.o: main.c airport.h ex2.h flight.h runway.h
airport.o: airport.c airport.h ex2.h flight.h runway.h
runway.o: runway.c runway.h ex2.h flight.h
flight.o: flight.c flight.h ex2.h
# Cleaning old files before new make
clean:
$(RM) airport *.o *.bak *~ "#"* core
When I make the file, it says that:
make: `airport` is up to date.
After that - I can call "airport" in bash and it lets me enter some inputs the way I want it to be.
BUT- when I'm trying to check if "airport" is compiled by:
gcc -g -Wall -c airport
I get an error says that:
gcc: airport: linker input file unused because linking not done
Does someone know what could be the problem?
Thanks!
Gavriel.
The aim of Makefile is to avoid recompiling a file if its source is unchanged; when it happens, make says that the file is up to date.
This might be annoying if you want to check again the warnings. Then, simply call make to recompile everything, by typing
make clean ; make
Another goal of Makefile is to avoid typing the gcc commands by yourself, prone to errors. For instance, at the end of your question, you ask to make an object file from an executable (option -c), which is wrong. The good way to make an object file is to call make :
make airport.o
Finally, to produce the executable, you can either type
make airport
or, since airport: is the first target, type
make
This is my absolute first time ever making a makefile, and I'm really trying to understand the process.
I'm trying to create a very simple makefile for a C++ project whose structure is as follows:
root folder
makefile
readme
src folder
...source files all here...
include folder
...header files for external libraries here...
lib folder
...external lib files all here...
bin folder
...output directory for built executable...
obj folder
...object files all here...
I followed the tutorial here.
Here's my makefile:
IDIR=include .
CC=g++
CFLAGS=-I$(IDIR)
ODIR=bin/obj
LDIR=lib
LIBS=none
SRC=src
_DEPS=hello.h
DEPS=$(patsubst %,$(IDIR)/,%(_DEPS))
_OBJ=file1.o file2.o
OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: $(SRC)/%.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS) # $(LIBS)
test_proj: $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
When I run make on this, I get the following error:
g++ -o .o
g++: fatal error: no input files
compilation terminated.
<builtin>: recipe for target '.o' failed
mingw32-make.exe: *** [.o] Error 1
I'm using GNU Make 3.82.90 built for i686-pc-mingw32, if that matters at all.
Can anyone point out whatever ridiculous error I'm making?
IDIR=include .
is the first problem. Replace it by:
IDIR=include
With your code CFLAGS is expanded as:
-Iinclude .
It does not make sense, I'm afraid. The second problem is:
DEPS=$(patsubst %,$(IDIR)/,%(_DEPS))
which should probably be:
DEPS=$(patsubst %,$(IDIR)/%,$(_DEPS))
and would expand as:
DEPS=include/hello.h
if you fix the first problem, else as:
DEPS=include ./hello.h
which does not make sense neither. The cumulated effect of these two errors are strange recipes (I didn't try to expand them by hand) that probably trigger a make implicit rule with wrong parameters.
IDIR=include .
CC=g++
CFLAGS=-I$(IDIR)
This is wrong. First, for C++ code, use CXX not CC and CXXFLAGS not CFLAGS. Run make -p to understand the builtin rules of your make.
Then -I$(IDIR) does not "distribute" the -I, and IDIR is never used elsewhere. So I suggest to start your Makefile with:
CXX=g++
MY_CXX_LANG_FLAGS= -std=c++11
MY_CXX_WARN_FLAGS= -Wall -Wextra
MY_CXX_INCL_FLAGS= -I. -Iinclude
MY_CXX_MACRO_FLAGS= -DMYFOO=32
### replace with -O2 for a release build below
MY_CXX_OPTIM_FLAGS= -g
CXXFLAGS= $(MY_CXX_LANG_FLAGS) $(MY_CXX_WARN_FLAGS) \
$(MY_CXX_INCL_FLAGS) $(MY_CXX_MACRO_FLAGS)
I won't improve your Makefile, but I do suggest to upgrade to GNU make version 4 if possible (and compiling make 4.1 from its source code is worthwhile in 2015) for that purpose. If possible enable GUILE scripting in it.
If you are forced to use make 3.82 debug your Makefile using remake (with -x); if you can afford a make version 4 use its --trace option
BTW, you might consider using automatic dependencies, that is generating dependencies by passing -M or -MG (etc) flags of g++, see that.
At last, a simple project for a small program (less than a hundred thousands of source lines) might just put all (a few dozens of) its files in the current directory (then the Makefile could be simpler); your proposed directory structure might be arcane for a simple project (but could worth the pain if you have millions of C++ source lines of code). I've given several simple examples of Makefile, e.g. this & that. And GNU make source code itself has a less complex file tree that what you want.
BTW, I strongly disagree with the opinions of that answer (which I did upvote, since it is helpful). I don't feel that GNU make is senile, but I regret that, instead of using recent features available on recent versions (4.x) of make, many people prefer to use complex and arcane Makefile generators (like cmake) instead of coding a clever Makefile (for make version 4 specifically).
At last, you could use other builders, e.g. omake, icmake, ....
I have the following simple problem in a Makefile:
%.o:: %.c
gcc -o $# -c $<
lib1.a: test.o
ar -r $# test.o
rm *.o
lib2.a: test.o
ar -r $# test.o
rm *.o
all: lib1.a lib2.a
make lib1.a or make lib2.a work properly. However, make all gives:
gcc -o test.o -c test.c
ar -r lib1.a test.o
rm *.o
ar -r lib2.a test.o
ar: test.o: No such file or directory
make: *** [lib2.a] Error 1
I need to do the rm *.o cause I want the object file to compile each time (in my real Makefile, I have a more complex use case where I compile with different flags).
How can I fix this problem? It seems that make compiles the object file only once.
I tried with .PHONY instead of doing the rm, but again, it compiles only once.
Your makefile is a bit against the make logic, this is why the result is not what you expect:
Here you define two targets (lib1.a and lib2.a) with a common dependency: test.o.
Then you define the rule all (which, by the way, should be .PHONY but this isn't a problem here) that depends on lib1.a and lib2.a.
So, in order to "do" all, make have to build lib1.a and lib2.a. They both depend on test.o, so make builds test.o once, then build lib1.a and lib2.a, expecting that the recipes you defined will just build those files, and nothing more.
The problem is that you delete test.o in the recipe for lib1.a and lib2.a, although this action is not needed to build them, this is something you want to do when cleaning, not building.
There are two solutions:
Move the deletion operation in a rule that is meant to do that (a .PHONY rule named clean for example).
The use of intermediate targets which will be deleted when they're not needed anymore. In fact, you can achieve that without even thinking about intermediate targets if you simply delete the first rule of your makefile (the %.o:: %.c one), because make already has an implicit rule that does that using intermediate targets.
Make is a rule-based system. Rules are declarative: you declare what you want built from what, you don't specify the order in which this happens (unless you can't avoid it). So a good Makefile is declarative: all results are declared like in a declarative programming language. They are like final variables in Java: you bind them to a value, you don't reassign them to a different value afterwards.
Make is also file-based: its "variables", targets and prerequisites are files.
So if you want to build two different things, don't call them by the same name! If you want two different test.o files, call them differently. The problem will go away without you needing to try and convince make that it should be like an imperative programming language, which it was specifically designed not to be. If you want an imperative build specification, use a shell script.
So I've got the following folder structure
makefile
src/my_lib.c
src/myhead.h
and I'm trying to compile *my_lib.c* with the header myhead.h as a library. This is the makefile. I attempt to put the obj files in OBJFOLDER and the compiled library in the OUTPUTFOLDER
PLUGNAME=my_lib
SOURCEFOLDER=src
OUTPUTFOLDER=bin
OBJFOLDER=bin/obj
OBJS=$(PLUGNAME).o
DEPS=myhead.h
# Configuration finishes here
_OBJS = $(patsubst %,$(OBJFOLDER)/%,$(OBJS))
_DEPS = $(patsubst %,$(SOURCEFOLDER)/%,$(DEPS))
ifeq ($(OS),Windows_NT)
EXT = .dll
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
EXT = .so
endif
endif
all : $(OUTPUTFOLDER)/$(PLUGNAME)$(EXT)
$(OUTPUTFOLDER)/$(PLUGNAME)$(EXT) : $(_OBJS)
gcc -Wl,--add-stdcall-alias -shared -o $# $(_OBJS)
$(OBJFOLDER)/%.o: $(SOURCEFOLDER)/%.c $(_DEPS)
mkdir -p $(OUTPUTFOLDER)
mkdir -p $(OBJFOLDER)
gcc $(foreach d, $(INC), -I$d) -c $< -o $#
.PHONY: clean
clean :
rm -f $(OBJFOLDER)/*.o $(OUTPUTFOLDER)/$(PLUGNAME)$(EXT) $(SOURCEFOLDER)/TSDRPlugin.h
When I do make all it fails
make: *** No rule to make target `bin/obj/my_lib.o', needed by `bin/
my_lib.dll'. Stop.
I have no idea how this could be possible since I already have defined
$(OBJFOLDER)/%.o: $(SOURCEFOLDER)/%.c $(_DEPS)
Strangely if I change the above line in the makefile, to
bin/obj/my_lib.o: $(SOURCEFOLDER)/%.c $(_DEPS)
I now get
make: *** No rule to make target `src/%.c', needed by `bin/obj/my_lib.o'. Stop.
Your second error is because by removing the % in the target you've turned this into an explicit rule, not a pattern rule. So, the % in the prerequisite is not replaced.
Your first error means that for some reason make is deciding that your pattern rule doesn't match. This means, usually, that make can't find and doesn't know how to create one of the prerequisites. I recommend you run make with the -d flag and see why make decides your rule doesn't apply.
What version of GNU make are you using? Some very old versions would not match pattern rules if the directory that the target was to be placed into didn't exist already.
The problem was that header was missing... Stupid mistake on my side.
I overlooked it, because this was a snippet from a longer makefile that was supposed to copy over the header but it didn't which means that this line was outputting the error. Stupid me...