Well, project has:
-include directory /* for header files */
-src dir. /* for source code */
-build dir. /* for object and executable files */
Makefile:
1 BUILD_DIR = $(CURRENT_DIR)/build
2 INCLUDE_DIR = $(CURRENT_DIR)/include
3 SRC_DIR = $(CURRENT_DIR)/src
4
5 CC = gcc
6 CFLAGS = -Wall -g -I
7
8 $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(INCLUDE_DIR)/%.h
9 #$(CC) $(CFLAGS) $(INCLUDE_DIR) -c $< -o $#
10
11 SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
12 HEADER_FILES= $(wildcard $(INCLUDE_DIR)/*.h)
13
14
15 OBJECT_FILES= $(BUILD_DIR)/module_1.o \
16 $(BUILD_DIR)/module_2.o \
17 $(BUILD_DIR)/module_3.o
18
19
20 prog: $(SRC_DIR)/main.c $(OBJECT_FILES)
21 #$(CC) $(CFLAGS) $(INCLUDE_DIR) $^ -o $(BUILD_DIR)/$#
How to avoid enumeration of object files, smth like:
OBJECT_FILES = $(wildcard $(BUILD_DIR)/*.o)
but this line produce "undefined reference" error.
You can't use $(wildcard $(BUILD_DIR)/*.o) because those files don't exist when the makefile is read in: they are built by the makefile. So this will be empty when you start to build.
Generally what people do is convert the list of source files into object files, since that's what the compiler does. So:
OBJECT_FILES := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRC_FILES))
Related
I'm using DJGPP make under DOS.
This is my main Makefile:
BIN_DIR = bin
OBJ_DIR = obj
DIRS_FOR_CREATION = $(BIN_DIR) $(OBJ_DIR)
SOURCE_DIRS = argparse logger transmission tests
EXECUTABLE_NAME = $(notdir $(shell pwd))
EXECUTABLE_FILE = $(BIN_DIR)/$(EXECUTABLE_NAME)
CC = cc
CFLAGS =
INCLUDES =
LFLAGS =
LIBS =
MAIN_SOURCE = main.c
MAIN_OBJ = $(OBJ_DIR)/main.o
all: directories submodules main $(EXECUTABLE_FILE)
#echo $(EXECUTABLE_NAME) was compiled
directories:
mkdir -p $(DIRS_FOR_CREATION)
submodules:
$(MAKE) -C $(word 1, $(SOURCE_DIRS))
$(MAKE) -C $(word 2, $(SOURCE_DIRS))
$(MAKE) -C $(word 3, $(SOURCE_DIRS))
$(MAKE) -C $(word 4, $(SOURCE_DIRS))
main:
$(CC) $(CFLAGS) $(INCLUDES) -c $(MAIN_SOURCE) -o $(MAIN_OBJ)
$(EXECUTABLE_FILE): $(MAIN_SOURCE)
$(CC) $(CFLAGS) $(INCLUDES) -o $(EXECUTABLE_FILE) $(MAIN_OBJ) $(LFLAGS) $(LIBS)
And this is works perfectly on QNX, but in DOSBox I'm getting the following error:
makefile:19: *** multiple target patterns. Stop.
19 line is all: directories submodules main $(EXECUTABLE_FILE). What should I do to fix this?
You should add:
$(info EXECUTABLE_NAME = '$(EXECUTABLE_NAME)')
$(info EXECUTABLE_FILE = '$(EXECUTABLE_FILE)')
so you can see what that variable contains. My suspicion is that it contains a colon (:) which is special to make.
I have the following makefile in the root of the project:
Makefile
# Board version
# Available: 3
PI ?= 3
# Kernel binaries
ifeq ($(PI), 3)
KERNEL_IMG := kernel8.img
else ifeq ($(PI), 2)
KERNEL_IMG := kernel7.img
else ifeq ($(PI), 1)
KERNEL_IMG := kernel.img
else
$(error Unsupported Raspberry Pi version)
endif
KERNEL_ELF := $(patsubst %.img,%.elf,$(KERNEL_IMG))
# Directories/paths
BUILD_DIR := build
# Toolchain
TOOLCHAIN ?= aarch64-elf
OBJCOPY := $(TOOLCHAIN)-objcopy
LD := $(TOOLCHAIN)-ld
CC := $(TOOLCHAIN)-gcc
# Misc
LINKER_SCRIPT := linker.ld
# Flags
LDFLAGS := -T $(LINKER_SCRIPT)
ASFLAGS :=
CFLAGS :=
# Source files
C_SRC := $(wildcard *.c)
ASM_SRC := $(wildcard *.S)
# Include
include pi/$(PI)/mod.mk
# Object files
OBJECTS := $(patsubst %,$(BUILD_DIR)/%.o,$(C_SRC))
OBJECTS += $(patsubst %,$(BUILD_DIR)/%.o,$(ASM_SRC))
# Targets
.PHONY: all builddirs clean
all: $(BUILD_DIR)/$(KERNEL_IMG)
$(BUILD_DIR)/$(KERNEL_IMG): $(BUILD_DIR)/$(KERNEL_ELF)
$(OBJCOPY) $< -O binary $#
$(BUILD_DIR)/$(KERNEL_ELF): $(LINKER_SCRIPT) $(OBJECTS)
$(LD) $(OBJECTS) $(LDFLAGS) -o $#
$(OBJECTS): | builddirs
builddirs: $(BUILD_DIR)/pi/$(PI)
$(BUILD_DIR)/pi/$(PI):
mkdir -p $#
$(BUILD_DIR)/%.S.o: %.S
$(CC) -c $< $(ASFLAGS) -o $#
$(BUILD_DIR)/%.c.o: %.c
$(CC) -c $< $(CFLAGS) -o $#
clean:
$(RM) -r $(BUILD_DIR)
It includes pi/3/mod.mk
C_SRC +=
ASM_SRC += pi/3/start.S
$(BUILD_DIR)/pi/3/start.S.o: pi/3/start.S pi/3/include/cpu/sysregs.h
$(CC) -c $< $(ASFLAGS) -o $#
Now here's the problem: whenever I run 'make' in the root of a project, '$(BUILD_DIR)/pi/3/start.S.o' rule invokes, instead of 'all'. If I move 'include pi/$(PI)/mod.mk' to the very bottom of the root makefile, and replace 'C_SRC' and 'ASM_SRC' variables in 'pi/3/mod.mk' with 'OBJECTS += $(BUILD_DIR)/pi/3/start.S.o' and invoke 'make', this rule isn't even invoked, so I get an error that make doesn't know how to build start.S.o.
What am I doing wrong and what is the best way to handle this?
Make's default goal is the first target in your Makefile. In your case the first target is the one defined in the included Makefile: $(BUILD_DIR)/pi/3/start.S.o. Either invoke make all or move the all rule in your Makefile such that it becomes the first one, or tell make that the default goal is all:
.DEFAULT_GOAL := all
(see GNU make manual).
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.
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/$#
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 $#