Can't assign variable inside recipe - makefile

How do I make this work? It errors out with "make: somevariable: Command not found"
sometarget:
somevariable = somevalue
Full example:
CXXFLAGS = -I/usr/include/test -shared -fPIC
OBJ = main.o Server.o
blabla : $(OBJ)
ifeq ($(argsexec),true)
# Creates an executable
CXXFLAGS = -I/usr/include/test
$(CXX) -o blabla $(OBJ) $(CXXFLAGS)
else
# Creates a library
DESTDIR = /home/pc
$(CXX) -o blabla $(OBJ) $(CXXFLAGS)
./bn.sh
endif

I found a solution using the eval function:
$(eval variablename=whatever)
This works :)
(although I may now try to find an easier build system ;))
Thanks everyone for reading and also of course #eriktous for writing!

If you write it like you did, the assignment will be executed as a shell command, which gives the error you got.
I would try organising it something like this:
CXXFLAGS = -I/usr/include/test
ifneq ($(argsexec),true)
CXXFLAGS += -shared -fPIC
DESTDIR = /home/pc
endif
OBJ = main.o Server.o
blabla : $(OBJ)
$(CXX) -o blabla $(OBJ) $(CXXFLAGS)
ifneq ($(argsexec),true)
./bn.sh
endif
This should do what you want, although I'm not quite happy with using the ifneq construct twice. I'd have to think harder to come up with something that avoids that.

Related

How to efficiently write a GNU makefile with several modules with an arbitrary number of dependencies in Fortran

My makefile currently looks like this:
#Source file locations
VPATH = :../AHMCodePara
#Compiler
CC = mpifort
#Debugging Flags
#Flags =
#Regular flags
Flags = -Ofast -mkl=sequential
# File name labels
FF =
DE =
Const =
OBJDIR = OBJ
# make object directory
$(OBJDIR):
-mkdir $(OBJDIR)
CC += -module $(OBJDIR)
#Object File List
Inputs =
Tools = $(OBJDIR)/$(Const)Inputs.o
Diag$(DE) = $(Tools)
PreAnalysis = $(Tools) $(OBJDIR)/Tools.o
DOSsetupPara$(DE) = $(PreAnalysis) $(OBJDIR)/PreAnalysis.o $(OBJDIR)/Diag$(DE).o
$(Const)AHMRGv3 = $(Tools) $(OBJDIR)/Diag$(DE).o $(OBJDIR)/DOSsetupPARA$(DE).o
#Object File List
obj = $(OBJDIR)/$(Const)Inputs.o $(OBJDIR)/Diag$(DE).o $(OBJDIR)/Tools.o \
$(OBJDIR)/PreAnalysis.o $(OBJDIR)/DOSsetupPARA$(DE).o $(OBJDIR)/$(Const)AHMRGv3.o
# dependence files
$(OBJDIR)/%.o: %.f90 $(%)
# #$(%)
#-rm -f #<~
$(CC) -c $< -o $# $(Flags)
All: V3.e
# Target
V3.e: $(obj)
$(CC) $(Flags) -o $# $^
clean:
rm $(OBJDIR)/*.o $(OBJDIR)/*.mod
It used to be similar to this one:
LOC = ../../AHMCode/
CC = gfortran
#Debugging
#Flags = -O0 -g -fcheck=all -Wall -llapack
#Normal
Flags = -O3 -I/usr/lib/ -L/usr/lib/ -lblas -llapack
FF = _Old
IG = #IGNORE or nothing
TT = #TYPE or nothing
V3$(FF).e: Inputs.o Tools.o PreAnalysis.o DOSsetup$(IG).o Diag$(TT).o AHMRGv3_Manyruns.o
$(CC) $(Flags) AHMRGv3_Manyruns.o Diag$(TT).o DOSsetup$(IG).o PreAnalysis.o Tools.o Inputs.o -o V3$(FF).e
Inputs.o: Inputs.f90
$(CC) $(Flags) -c Inputs.f90
Tools.o: $(LOC)Tools.f90 Inputs.o
$(CC) $(Flags) -c $(LOC)Tools.f90
PreAnalysis.o: $(LOC)PreAnalysis.f90 Inputs.o Tools.o
$(CC) $(Flags) -c $(LOC)PreAnalysis.f90
DOSsetup$(IG).o: $(LOC)DOSsetup$(IG).f90 Inputs.o Tools.o PreAnalysis.o Diag$(TT).o
$(CC) $(Flags) -c $(LOC)DOSsetup$(IG).f90
Diag$(TT).o: $(LOC)Diag$(TT).f90 Inputs.o
$(CC) $(Flags) -c $(LOC)Diag$(TT).f90
AHMRGv3_Manyruns.o: AHMRGv3_ManyRuns.f90 DOSsetup$(IG).o Diag$(TT).o Inputs.o
$(CC) $(Flags) -c AHMRGv3_Manyruns.f90
clean:
rm *.o *.mod
The section I want to compare in these makefiles is the .o file definitions. In the second makefile, I wrote these all out by hand and it worked great. My intention with the second makefile was to do the same thing but more efficiently.
The problems arose with dependencies. When I initially made changes to my makefile, I didn't put any dependencies at all. This led to problems where I would update Inputs and the relevant files wouldn't recompile (e.g. Tools.o). This is as expected so I've been looking for ways to add dependencies in a creative and efficient way that forces the relevant files to recompile.
As you can see I tried creating variables with the same name as the .f90 and .o to use $(%). This seemed kinda janky (and I didn't really think it would work) but unfortunately didn't solve my problem.
As you can see from the original makefile, the dependencies don't follow any sort of pattern. As well you can see that I am compiling Fortran and I'm pretty sure that -gen-dep doesn't do anything and if it does I'm doing it wrong.
Existing questions on the subject have been very unhelpful since the majority uses C++ and that can be very different here.
EDIT: I "fixed" my problem. Its not the most efficient and doesn't automatically generate dependencies but I like it in that its not a lot of repetitive lines.
#Object File List
oInpt =
oTool = $(OBJDIR)/$(Const)Inputs.o
oPreA = $(oTool) $(OBJDIR)/Tools.o
oDOSs = $(oPreA) $(OBJDIR)/PreAnalysis.o $(OBJDIR)/Diag$(DE).o
oDiag = $(oTool)
oMain = $(oTool) $(OBJDIR)/Diag$(DE).o $(OBJDIR)/DOSsetupPARA$(DE).o
obj = $(OBJDIR)/$(Const)Inputs.o $(OBJDIR)/Tools.o $(OBJDIR)/PreAnalysis.o $(OBJDIR)/Diag$(DE).o \
$(OBJDIR)/DOSsetupPARA$(DE).o $(OBJDIR)/$(Const)AHMRGv3.o
# dependence files
$(OBJDIR)/$(Const)Inputs.o: $(oInpt)
$(OBJDIR)/Tools.o: $(oTool)
$(OBJDIR)/PreAnalysis.o: $(oPreA)
$(OBJDIR)/Diag$(DE).o: $(oDiag)
$(OBJDIR)/DOSsetupPARA$(DE).o: $(oDOSs)
$(OBJDIR)/$(Const)AHMRGv3.o: $(oMain)
$(OBJDIR)/%.o: %.f90
#-rm -f #<~
$(CC) -c $< -o $# $(Flags)
All: V3.e
# Target
V3.e: $(obj)
$(CC) $(Flags) -o $# $^
I just made multiple rules for each target. One a default rule that actually compiles the .o files and the other that specifies the dependencies for each .f90 file.

make error : *** missing separator. Stop

This is my makefile:
OBJECTS = main.o
CFLAGS = -g -wall
NAME = make
CC = gcc
build: $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $(NAME)
I'm getting below error when I tried to make(Applied tab before gcc command) :
makefile:6: *** missing separator. Stop.
How can I fix this?
First of all, it looks like you have spaces instead of tab.
As for the Makefile itself, I'd make it little bit simpler. For a source file main.c:
int main() {
return 0;
}
I would go with Makefile:
CFLAGS = -g -wall
CC = gcc
main: main.c
$(CC) $(CFLAGS) $< -o $#

Makefile: Adding 2nd directory for .h and .cpp files

I am adapting my Makefile to look into 4 directories, rather than 2 (it had one for source files and one for header files, but I've added a new folder for common source and include). I have something like follows:
CC = g++
FLAGS = -g -c
BUILDDIR = build
INCLUDEDIR = -Icode/inc -I../common/code/inc -I/usr/include/libxml2
SOURCEDIR = code/src ../common/code/src
SOURCES = $(wildcard $(SOURCEDIR)/*.cpp)
OBJECTS = $(patsubst $(SOURCEDIR)/%.cpp,$(BUILDDIR)/%.o,$(SOURCES))
EXECUTABLE = Exec
all: $(BUILDDIR)/$(EXECUTABLE)
$(BUILDDIR)/$(EXECUTABLE): $(OBJECTS)
$(CC) $^ -o $# -lpthread -lxml2
$(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $# -Wno-write-strings
I tried to add one entry to INCLUDEDIR as follows:
-I../common/code/inc
And added ../common/code/src to SOURCEDIR:
SOURCEDIR = code/src ../common/code/src
This is not currently working and I am wondering how to fix it please. I am getting the error:
Makefile:27: target `code/src' doesn't match the target pattern
but I cannot find how to fix it so far. Any help would be appreciated.
EDIT: After following MadScientist response below, I am getting the following output:
g++ -c -o code/src/Client.o code/src/Client.cpp
code/src/Client.cpp:1:20: fatal error: Client.h: No such file or directory
compilation terminated.
make: *** [code/src/Client.o] Error 1
Updated Makefile:
SOURCEDIR = code/src ../common/code/src
SOURCES = $(wildcard $(addsuffix /*.cpp,$(SOURCEDIR)))
OBJECTS = $(SOURCES:%.cpp=%.o)
$(BUILDDIR)/$(EXECUTABLE): $(OBJECTS)
$(CC) $^ -o $# -lpthread -lxml2
$(BUILDDIR)/%.o : ../common/code/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $# -Wno-write-strings
$(BUILDDIR)/%.o : code/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $# -Wno-write-strings
PS:
I was able to fix it using the following:
SOURCEDIR = code/src ../common/code/src
SOURCES = $(wildcard $(addsuffix /*.cpp,$(SOURCEDIR)))
TEMP_OBJ = $(SOURCES:%.cpp=%.o)
NOT_DIR = $(notdir $(TEMP_OBJ))
OBJECTS = $(addprefix $(BUILDDIR)/, $(NOT_DIR))
Sure, because now your static pattern rule expands to:
$(OBJECTS): build/%.o : code/src ../common/code/src/%.cpp
which is illegal syntax. If you avoid using static pattern rules, and instead use pattern rules, then it will just work. Replace your single static pattern rule with two pattern rules:
$(BUILDDIR)/%.o : code/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $# -Wno-write-strings
$(BUILDDIR)/%.o : ../common/code/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $# -Wno-write-strings
EDIT: you also need to change other uses of SOURCEDIR:
SOURCES = $(wildcard $(addsuffix /*.cpp,$(SOURCEDIR))
OBJECTS = $(patsubst %.cpp,$(BUILDDIR)/%.o,$(notdir $(SOURCES)))

Makefile which can generate all object files in a specific path

Somewhere I am going wrong !!
I am trying to generate the object files in ../bin/
But the below code generates in corresponding source file directory.
Below the code, which I am running.
Modified code:
LIB = $(BIN_DIR)/libutils.a
APP = $(BIN_DIR)/app
CC = gcc
AR = ar
CFLAGS = -Wall -g
LDFLAGS =
all: $(LIB) $(APP)
SRC = $(SRC_DIR)/add.c \
$(SRC_DIR)/sub.c
OBJ = $(SRC:.c=.o)
INCLUDES = -I$(INC_DIR)/
LIBS = -L../ -L/usr/local/lib -lm
LDFLAGS = -g
.SUFFIXES: .c
.c.o:
$(CC) $(INCLUDES) -c $(SRC_DIR)/$< -o $(BIN_DIR)/$#
$(LIB): $(OBJ)
$(AR) rcs $(LIB) $(OBJ)
$(BIN_DIR)/app: $(BIN_DIR)/test.o \
$(BIN_DIR)/t.o \
$(BIN_DIR)/libutils.a
$(CC) $(LDFLAGS) -o $# $^
clean:
rm -f $(LIB) $(BIN_DIR)/* $(SRC_DIR)/*.o *.o
Thank you :)
You still have the rule:
$(LIB): $(OBJ)
...
and OBJ is still src_dir/add.o src_dir/sub.o, so that's where Make will try to build these objects if your object rule works as intended. So, first step:
SRC = $(SRC_DIR)/add.c \
$(SRC_DIR)/sub.c
OBJ = $(SRC:.c=.o)
OBJ = $(patsubst $(SRC_DIR)/%.c,$(BIN_DIR)/%.o,$(SRC))
Now you'll find that your object rule,
.c.o:
...
doesn't work, because it expects to find the source file in the same place where the object file should go (i.e. $(OBJ_DIR)). So replace this rule with:
$(BIN_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(INCLUDES) -c $< -o $#
I notice that you have no provision for building $(BIN_DIR)/t.o and $(BIN_DIR)/test.o, but the app needs them. You should look into that.
Further refinements are possible, but this is a start.
Your SRC has a relative path, and your OBJ is just the SRC with the extension changed to. o
So OBJ will contain this:
../src/add.o
../src/sub.o
And there is where the .o will be created.
Make these changes and it will work:
SRC = add.c \
sub.c
.c.o:
$(CC) $(INCLUDES) -c ../src/$< -o ../bin/$#

patsubst on makefile

I have to create different *.o files from a same set of *.c using various CFLAGS. I wanted to use patsubst to generate different *.o files from same *.c. I am doing something wrong the following statement, please help (I want to generate one set of object files having ($<)_O0.o and the other ($<)_O2.o from the same set of c source files):
$(CC) $(CFLAGS_02) -c $< -o $(patsubst %.c,%_O2.o,$<)
Thanks
Use patsubst to make lists of the objects that you want to build, and then use separate rules for each type of build.
Something like this:
SRC_FILES = source1.c source2.c
OBJ_FILES_O0 = $(patsubst %.c,%_O0.o,$(SRC_FILES))
OBJ_FILES_O2 = $(patsubst %.c,%_O2.o,$(SRC_FILES))
CFLAGS_O0 := -O0
CFLAGS_O2 := -O2
all: $(OBJ_FILES_O0) $(OBJ_FILES_O2)
$(OBJ_FILES_O0): %_O0.o: %.c
$(CC) $(CFLAGS_O0) -c $< -o $#
$(OBJ_FILES_O2): %_O2.o: %.c
$(CC) $(CFLAGS_O2) -c $< -o $#
You can also use wild cards to specify all files in the directory.
eg:
#Generic Makefile.
CC := g++
LD := g++
CFLAGS := -c
LDFLAGS := -L<path to lib> -l<libname> \
-L<path to lib> -l>libname> \
......................
ifeq (${TARGETARCH}, debug)
CFLAGS += -g -O0
elif
CFLAGS += -O4 -DNDEBUG
SRCFILES := $(wildcard *.cpp)
OBJFILES := $(patsubst %.cpp, %.o, ${SRCFILES})
all: main
main: ${OBJFILES}
#echo "[Linking]"$#
${LD} ${LDFLAGS} ${OBJFILES}
%.o: %.cpp
#echo "[Compiling]"$#
${CC} ${CFLAGS} $^ -o $#

Resources