using an ifdef conditional to set a Make flag - makefile

I have a simple gnu makefile:
ifdef $(DEBUGGING)
CFLAGS = -g -O0 -Wall
else
CFLAGS = -O3 -Wall
endif
test:
#echo DEBUGGING is $(DEBUGGING)
#echo $(CFLAGS)
When I invoke it like this, I see that DEBUGGING is set to true, but ifdef $DEBUGGING appears to be false:
$ DEBUGGING=true make test
DEBUGGING is true
-O3 -Wall
I would expect that CFLAGS would be set to "-g -O0 -Wall". What am I missing?

You use the NAME of the variable in the ifdef:
ifdef DEBUGGING
The value given to ifdef is expanded first, and the result is considered a variable name.

Related

how can I access makefile variable in xv6?

Now I am trying to access makefile variable in my user program in xv6.
In other linux system, it can be easily achieved by doing that
in makefile, define gcc -D MYVARIABLE=1 ...
in my linux user program, by defining #include <stdio.h>, I can access MYVARIABLE.
but in xv6, there is no <stdio.h>. so I can't access MYVARIABLE.
How can I do for access MYVARIABLE??
Guessing you use this repo: https://github.com/mit-pdos/xv6-public, you can define MYVARIABLE in CFLAGS declaration, near line 83.
CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
# Your macro here
CFLAGS += -DMYVARIABLE=1
In that makefile, there is no %.o: %.c rule: implicit rules are used:
n.o is made automatically from n.c with a command of the form $(CC) -c $(CPPFLAGS) $(CFLAGS)

Make refuses to expand my variables in the g++ compilation line

Here is my simple Makefile. I am trying to set the C macro "GIT_COMMIT" in my Makefile and pass it to the C program.
all: control
control: control.cpp serial_port.cpp
GIT_COMMIT=5
g++ -g -DGIT_COMMIT=$(GIT_COMMIT) -Wall $^ -o control -lpthread
Unfortunately, when I run make, I see this and make is completely ignoring my GIT_COMMIT variable. What am I doing wrong? Thanks.
GIT_COMMIT=5
g++ -g -DGIT_COMMIT= -Wall control.cpp serial_port.cpp -o control -lpthread
placing the setting of GIT_COMMIT as an action inside the 'control' rule will, as you discovered, not work to produce a macro. suggest:
all: control
GIT_COMMIT := 5
control: control.cpp serial_port.cpp
g++ -g -DGIT_COMMIT=$(GIT_COMMIT) -Wall $^ -o control -lpthread

CXXFLAGS changes not being honored?

I have the following in my GNU makefile:
# CXXFLAGS ?= -DNDEBUG -g2 -O3
CXXFLAGS ?=
# Add -DNDEBUG if nothing specified
ifeq ($(filter -DDEBUG -DNDEBUG,$(CXXFLAGS)),)
$(info Adding -DNDEBUG to CXXFLAGS)
CXXFLAGS += -DNDEBUG
endif
# Add a symolize if nothing specified
ifeq ($(filter -g -g1 -g2 -g3 -Oz,$(CXXFLAGS)),)
$(info Adding -g2 to CXXFLAGS)
CXXFLAGS += -g2
endif
# Add an optimize if nothing specified
$(info Adding -O3 to CXXFLAGS)
ifeq ($(filter -O -O0 -O1 -O2 -O3 -Og -Os -Oz -Ofast,$(CXXFLAGS)),)
CXXFLAGS += -O3
endif
When I run it:
$ make CXXFLAGS="-g3"
Adding -DNDEBUG to CXXFLAGS
Adding -O3 to CXXFLAGS
g++ -g3 -c foo.cpp
...
In fact, if I uncomment the CXXFLAGS ?= -DNDEBUG ..., then I can append again. But that's not very helpful since I'm trying to make arguments optional (but with sane defaults).
And if I type just make, then it works (-fPIC -march=native -Wall -Wextra -pipe is added later by the same makefile, and it has always worked):
$ make
Adding -DNDEBUG to CXXFLAGS
Adding -g2 to CXXFLAGS
Adding -O3 to CXXFLAGS
g++ -DNDEBUG -g2 -O3 -fPIC -march=native -Wall -Wextra -pipe -c serpent.cpp
...
According to the manual and 6.6 Appending More Text to Variables:
Often it is useful to add more text to the value of a variable already defined. You do this with a line containing ‘+=’, like this:
objects += another.o
Why is make not adding the values to the variable? How can I achieve the behavior I want?
By passing a variable via command-line, you're telling make that you are overriding any definitions in the file, which allows a user to compile as they intend rather than as you intend. Ignoring the restriction of user freedom, you can use the override directive:
To append more text to a variable defined on the command line, use:
override variable += more text
Variable assignments marked with the override flag have a higher priority
than all other assignments, except another override. Subsequent
assignments or appends to this variable which are not marked override
will be ignored.
I would discourage you from using override when possible because it's annoying to realize that -O0 was needed to disable the optimizations that you enabled when I don't want them enabled (after all, I specify my own flags for a reason). Of course, if no flags were specified at all, then defaults are perfectly reasonable. In fact, Automake projects seem to default to -g -O2 when no compilation flags are specified.
There are exceptions to this advice of course, such as adding a directory to search for includes/libs or preprocessor definitions for compiling a conditional section of code on a certain platform.

In a Makefile, how do I define wildcard patterns?

My directory has many files with similar names: test1.cpp, test2.cpp, test3.cpp, etc. I want to compile all test files into executables test1, test2, test3, etc. They don't have to be linked to each other.
CC = clang++
CXX = clang++
INCLUDES =
CFLAGS = -g -Wall $(INCLUDES)
CXXFLAGS = -g -Wall $(INCLUDES)
LDFLAGS = -g
LDLIBS =
.PHONY: default
default: test1 test2
test1:
test2:
Instead of specifying test1, test2, I want to use wildcards or pattern matching or something along those lines. How do I do this?
David Rodgriquez has the right idea: make has built-in rules that will handle this for you. However I would recommend using a makefile rather than setting variables in your environment, so you can easily perform the build as another user etc. where the environment is not set up properly. Also you can use a makefile to create the default target.
This is good enough:
CC = clang++
CXX = clang++
INCLUDES =
CFLAGS = -g -Wall $(INCLUDES)
CXXFLAGS = -g -Wall $(INCLUDES)
LDFLAGS = -g
LDLIBS =
.PHONY: default
default: $(basename $(wildcard test*.cpp))
That's all you need!

makefile which get also the name of the file compile

I need a makefile which get also the name of the file compile
For example:
make foo
and the makefile should compile foo.c to foo.
This is my makefile. How to change it?
all: out
out: out.o
gcc -g -m32 -Wall -o out out.o
out.o: out.c
gcc -m32 -g -Wall -ansi -c -o out.o out.c
.PHONY: clean
#Clean the build directory
clean:
rm -f *.o out
There is no direct way where you can pass arguments to the Makefile but instead you can take advantage of variables to achieve what you want. Check the modifications done to the Makefile below
NAME ?=out #Default binary generated is out if you dont pass any argument
${NAME}: ${NAME}.o
gcc -g -m32 -Wall -o ${NAME} ${NAME}.o
${NAME}.o: ${NAME}.c
gcc -m32 -g -Wall -ansi -c -o ${NAME}.o out.c
.PHONY: clean
#Clean the build directory
clean:
`rm -f *.o ${NAME}`
And you should call the Makefile by typing
$ make NAME=foo
$ make clean NAME=foo
Passing arguments directly to Make is trivially easy.
Your current makefile can be invoked with make foo, and will compile foo.c to produce foo, because Make has implicit rules for handling cases like foo.c => foo; there will be no error even though "foo" is not the target of any rule. (At least, this is the case with GNU Make 3.81, which is what I am using.)
If you want to control the choice of compiler and flags (as in your out rule), there is more than one way to do it. The simplest (though not strictly the best) is to modify a couple of variables in the makefile:
CC = gcc
CFLAGS = -g -m32 -Wall -ansi
Another option is to override the implicit rule with a pattern rule of your own:
%: %.c
gcc -g -m32 -Wall -ansi -o $# $<
If you want it to build foo.o in a separate step, you must split the rule into two rule-- and also put in a rule with no recipe to cancel Make's implicit rule:
%: %.o
gcc -g -m32 -Wall -o $# $^
%.o: %.c
gcc -m32 -g -Wall -ansi -c -o $# $<
%: %.c
Further refinements are possible, once you have mastered the basics.

Resources