I want to create *.o for each cpp file inside variable "CPPS" (in Ubuntu)
CPPS := file1.cpp \
file2.cpp \
file3.cpp \
folder1/file4.cpp \
folder2/file5.cpp \
folder2/folder21/file6.cpp
OBJS := file1.o \
file2.o \
file3.o \
file4.o \
file5.o \
file6.o
test:$(OBJS)
$(CXX) $(FLAG) -o m $(OBJS)
I want to create *.o for each cpp automatically. And I want to create *.o inside the same folder of Makefile.
If all the cpps are in the same folder as Makefile, we can use
%.o:%.cpp
$(CXX) $(FLAG) -c -o $# $< $(INC)
But the problem is they are in different folders, currently I have to write a script to create a lnk for each file. Is there a way to iterator over each file inside a variable? or it there an another way to do that?
Using source files in different directories is what the vpath directive is for:
CPPS := file1.cpp ...
OBJS := file1.o ...
vpath %.cpp folder1 folder2 folder2/folder21
all: $(OBJS)
And you can generate the vpath and OBJS from CPPS, rather than typing them all in by hand:
CPPS := file1.cpp ...
OBJS := $(notdir $(CPPS:.cpp=.o))
SRCDIRS := $(dir $(CPPS))
vpath %.cpp $(SRCDIRS)
all: $(OBJS)
Related
I have to make a XC8 project in Ubuntu terminal with makefile.
The directory structure is like this
Project/lib/GPIO/gpio.c
Project/lib/GPIO/gpio.h
Project/main.c
Project/Makefile
Project/build/lib/GPIO
The makefile is generating intermediate files in the Project directory itself. Actually makefile will goto each location and generates intermediate files for each .c file.
Like this
Project/gpio.d
Project/gpio.p1
Project/gpio.pre
Project/<other files>
But I wanted to generate them in Project/build/lib/GPIO instead.
i.e
Project/build/lib/GPIO/gpio.d
Project/build/lib/GPIO/gpio.p1
Project/build/lib/GPIO/gpio.pre
Project/build/<other files>
Makefile:
CHIP := 18F4580
CC := xc8
INCLUDE_PATH := /opt/microchip/xc8/v2.10/include/
PROG := /usr/share/tinybldlin/tinybldlin.py
PORT := /dev/ttyUSB0
AR := libr
SRC_DIR := $(wildcard *.c)
INC_DIR := $(wildcard *.h)
LIB_DIR := \
. \
lib \
lib/GPIO
BUILD_DIR := \
build/ \
build/lib/GPIO
TARGET := pic${CHIP}
FLASH_REGION := 0-3000
ifeq (${SRCS},)
SRCS := $(foreach libdir, $(LIB_DIR), $(wildcard $(libdir)/*.c))
endif
ifeq (${INCS},)
INCS := $(foreach libdir, $(LIB_DIR), $(wildcard $(libdir)/*.h))
endif
ifeq (${OBJS},)
OBJS := $(SRCS:.c=.obj)
endif
ifeq (${P1},)
OBJS := $(SRCS:.c=.p1)
endif
MIN_CFLAGS := --chip=${CHIP} -I${INCLUDE_PATH} --ROM=${FLASH_REGION}
# The following MSG_CFLAGS controls the compiler messages
MSG_CFLAGS := -Q
# The following OPT_CFLAGS reduces the code size
OPT_CFLAGS := --opt=all
# The following OUT_CFLAGS controls the generated outputs
OUT_CFLAGS := --asmlist --summary=psect,mem -M${TARGET}.map
EXTRA_CFLAGS += ${MSG_CFLAGS} ${OPT_CFLAGS} ${OUT_CFLAGS}
CFLAGS := ${MIN_CFLAGS} ${EXTRA_CFLAGS} -DCOMPILER=${COMPILER}
ARFLAGS := r
${TARGET}.hex: ${OBJS}
${CC} ${CFLAGS} -intel $^ -o$#
${MAKE} xclean
${TARGET}.bin: ${OBJS}
${CC} ${CFLAGS} -bin $^ -o$#
${MAKE} xclean
%.p1: %.c ${INC_DIR}
${CC} ${CPPFLAGS} ${CFLAGS} --pass1 $<
%.obj: %.c ${INC_DIR}
${CC} ${CPPFLAGS} ${CFLAGS} -C $<
%.as: %.c ${INC_DIR}
${CC} ${CPPFLAGS} ${CFLAGS} -S $<
%.lib: %.obj
${AR} ${ARFLAGS} $# $<
The first thing I'll say is that this answer relies on your using GNU make. You don't say for sure that you are but since you're using pattern rules I will assume so. Note that what you want to do is not possible with standard POSIX make (unless you want to write out explicit rules for every target to be built).
You need two things:
Tell your compiler what you want to do
Tell make what you want to do
For #1, by default the compiler will generate the output which is the input file name, minus the extension (e.g. .c) plus a specific extension (e.g. .as). Since your input file is lib/GPIO/gpio.c the compiler generates gpio.as. Most compilers support a -o option which allows you to rename the output: you'll have to check your compiler's documentation if this doesn't work. So, you'd want to write your rule:
%.as: %.c ${INC_DIR}
${CC} ${CPPFLAGS} ${CFLAGS} -S -o $# $<
(etc.). Now when you compile lib/GPIO/gpio.c into lib/GPIO/gpio.as, make will set $# to lib/GPIO/gpio.as and invoke your compiler such that it creates lib/GPIO/gpio.as not gpio.as.
But you wanted to put the output files in a build subdirectory. Now that you've convinced your compiler to write files where make tells it to, you have to tell make where to put the output.
So first, when you generate the output files to be created you have to create them with the correct path:
OBJS := $(SRCS:.c=.p1)
That converts lib/GPIO/gpio.c into lib/GPIO/gpio.p1 which isn't what you want. You need this:
OBJS := $(SRCS:%.c=build/%.p1)
Now, make knows you want to build build/lib/GPIO/gpio.p1 instead. However now you'll get an error because make doesn't know how to create that file. You've told it how to build a %.p1 from %.c, but the % must be an exact text match between the target and prerequisite, and here the target % matches build/lib/GPIO/gpio but there's no build/lib/GPIO/gpio.c so the rule doesn't match. You need to rewrite the rule like this:
build/%.p1: %.c ${INC_DIR}
${CC} ${CPPFLAGS} ${CFLAGS} --pass1 -o $# $<
Now it should work. You might also want to add in a mkdir to ensure the directory exists:
build/%.p1: %.c ${INC_DIR}
#mkdir -p ${#D}
${CC} ${CPPFLAGS} ${CFLAGS} --pass1 -o $# $<
Compiling with Makefile tells me that it can't find path to some include files.
Here's my directory layout:
build (empty directory)
include (directory)
tpu_uarch (directory)
buffer.hpp common.hpp controller.hpp cpu.hpp
dram.hpp interconnect.hpp mmu.hpp unit.hpp weightfetcher.hpp
obj (directory)
tpu_uarch (empty directory)
src (directory)
test_mmu.cpp test_tile.cpp
buffer.cpp common.cpp controller.cpp cpu.cpp
dram.cpp interconnect.cpp mmu.cpp weightfetcher.cpp
Makefile
And here's what Makefile looks like:
TESTTILE := ./build/testtile.exe
TEST3 := ./build/test3.exe
CC := g++
CPP_SUFFIX := cpp
INCLUDE_DIR := -I./include
SRC_DIR = ./src
OBJ_DIR = ./obj
CFLAGS := -g -Wall -std=c++11
LDFLAGS :=
LIBS :=
# all sources
SRC = $(wildcard $(SRC_DIR)/*.$(CPP_SUFFIX))
SRC += $(wildcard $(SRC_DIR)/**/*.$(CPP_SUFFIX))
# objects
OBJ = $(patsubst $(SRC_DIR)/%.$(CPP_SUFFIX), $(OBJ_DIR)/%.o, $(SRC))
DIR = $(dir $(OBJ))
# executables
testtile: dir $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(TESTTILE) $(LIBS)
test3: dir $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o $(TEST3) $(LIBS)
dir:
mkdir -p $(DIR)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(CPP_SUFFIX)
$(CC) $(INCLUDE_DIR) $(CFLAGS) -c $< -o $#
clean:
rm -rf $(OBJ_DIR)
rm $(TESTTILE)
rm $(TEST3)
When I write make test3 in command line, I get the following error.
mkdir -p ./obj/ ./obj/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/ ./obj/tpu_uarch/
g++ -I./include -g -Wall -std=c++11 -c src/test_tile.cpp -o obj/test_tile.o
src/test_tile.cpp:1:22: fatal error: common.hpp: No such file or directory
compilation terminated.
Makefile:44: recipe for target 'obj/test_tile.o' failed
make: *** [obj/test_tile.o] Error 1
In all of the *.cpp files, they add include files like #include "common.hpp" without adding directory information. As I understand, adding the -I flag in INCLUDE_DIR should solve problems of finding the include files.
I've checked earlier that the code compiles if I put all .cpp and .hpp files in one directory and type g++ -g -Wall -std=c++11 -o test3.exe buffer.cpp common.cpp controller.cpp cpu.cpp dram.cpp interconnect.cpp mmu.cpp weightfetcher.cpp test_mmu.cpp in the command line interface.
In making test3.exe, test_tile.cpp is not used but I don't think that should be a problem.
Is there something I'm missing or should look into?
Any help or push in the right direction would be greatly appreciated.
[Moved from comments]
You're telling g++ to look in ./include but, according to the directory hierarchy shown, common.hpp and the other headers are actually under ./include/tpu_uarch. You need...
INCLUDE_DIR := -I./include/tpu_uarch
For those who came to find an answer... Even after fixing the issue that G.M. pointed out, I still had some minor issues. (Such as conflict in that both test files include the main() function, etc.)
After that, I managed to fix the code to work.
Here is the working version of Makefile.
TESTTILE := ./build/testtile.exe
TESTMMU := ./build/testmmu.exe
CC := g++
CPP_SUFFIX := cpp
INCLUDE_DIR := -I./include/tpu_uarch
SRC_DIR = ./src
OBJ_DIR = ./obj
BUILD_DIR = ./build
CFLAGS := -g -Wall -std=c++11
LDFLAGS :=
LIBS :=
# all sources
SRC = $(wildcard $(SRC_DIR)/*.$(CPP_SUFFIX))
SRC += $(wildcard $(SRC_DIR)/**/*.$(CPP_SUFFIX))
# objects
OBJ = $(patsubst $(SRC_DIR)/%.$(CPP_SUFFIX), $(OBJ_DIR)/%.o, $(SRC))
DIR = $(dir $(OBJ))
# for tests
TESTTILE_OBJ := ./obj/test_tile.o
TESTMMU_OBJ := ./obj/test_mmu.o
# executables
testtile: dir $(OBJ) $(TESTTILE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) $(TESTTILE_OBJ) -o $(TESTTILE) $(LIBS)
testmmu: dir $(OBJ) $(TESTMMU_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) $(TESTMMU_OBJ) -o $(TESTMMU) $(LIBS)
dir:
mkdir -p $(DIR)
obj/test_tile.o: $(BUILD_DIR)/test_tile.cpp
$(CC) $(INCLUDE_DIR) $(CFLAGS) -c ./build/test_tile.cpp -o ./obj/test_tile.o
obj/test_mmu.o: $(BUILD_DIR)/test_mmu.cpp
$(CC) $(INCLUDE_DIR) $(CFLAGS) -c ./build/test_mmu.cpp -o ./obj/test_mmu.o
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(CPP_SUFFIX)
$(CC) $(INCLUDE_DIR) $(CFLAGS) -c $< -o $#
clean:
rm -rf $(OBJ_DIR)
rm $(TESTTILE)
rm $(TEST3MMU)
The directory topology is as follows:
build (directory)
test_mmu.cpp test_tile.cpp
testmmu.exe testtile.exe (executables created after running make)
include (directory)
tpu_uarch (directory)
buffer.hpp common.hpp controller.hpp cpu.hpp
dram.hpp interconnect.hpp mmu.hpp unit.hpp weightfetcher.hpp
obj (directory, all contents here including directory are created after running make)
tpu_uarch (directory)
buffer.o common.o controller.o cpu.o
dram.o interconnect.o mmu.o weightfetcher.o
test_mmu.o
test_tile.o
src (directory)
tpu_uarch (directory)
buffer.cpp common.cpp controller.cpp cpu.cpp
dram.cpp interconnect.cpp mmu.cpp weightfetcher.cpp
Makefile
Hope this helps.
I wrote a MakeFile, but I need it to create folder OBJ, so, for this, I tried a lot of things... based on this link:
https://stackoverflow.com/questions/ask
So, that is my makefile
IDIR =.
CC=gcc
CFLAGS=-I$(IDIR) -Wall -g
SRCDIR=src
ODIR=obj
LIBS=-ltest
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
OUTPUTDIR = ../bin
$(ODIR)/%.o: $(SRCDIR)/%.c
$(CC) -c -o $# $< $(CFLAGS)
$(OUTPUTDIR)/test: $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
I need to create the obj folder, I tried that idea:
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir -p $(OBJDIR)
and this:
MKDIR_P = mkdir -p
.PHONY: directories
all: directories program
directories: ${OUT_DIR}
${OUT_DIR}:
${MKDIR_P} ${OUT_DIR}
But apparently every time I called the makefile, it ignored the command to create the directory OBJ and began compiling directly...
How I can make to makefile create the directory?
Another approach is to have a dummy variable that evaluates early in the parse of the Makefile and produces the required folder.
ODIR = obj_64
dummy_build_folder := $(shell mkdir -p $(ODIR))
Then the rest of the Makefile can safely assume that $(ODIR) exists.
I've used this on various Linux flavors, and Solaris, with GNU Make 3.81.
Try this:
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR): FORCE
mkdir -p $(OBJDIR)
FORCE:
I am trying to create a Makefile in order to generate object files in a subdirectory rather than let them in the src/ folder.
Here is the structure of the project:
Trunk
- Server
- src/
- include/
- Common
- src/
- include/
The Makefile is located in Trunk/Server. Source files are located both in Server/src and Common/src, so the Makefile currently has something like this:
SRC = src/main.cpp \
src/Network.cpp \
../Common/src/SQLManager.cpp \
../Common/src/Utils.cpp
I woud like to put generated object files in respective obj folders, so Trunk/Server/obj and Trunk/Common/obj. How can I achieve this? I've found many ways to generate object files in subdirectories (vpath, patsubst and many more) but I can't make any of them work for this folder organization.
Edit: If there is a way to put all object files in Server/obj/, that would be ok too.
Here's the complete Makefile (minus some source files and linked libraries):
Edit2: Updated with Didier Trosset's changes
CXX = g++
RM = rm -vf
NAME = Server
SRC = src/main.cpp \
src/Network.cpp \
../Common/src/SQLManager.cpp \
../Common/src/Utils.cpp
OBJ = $(subst src/,obj/, $(subst .cpp,.o, $(SRC)))
LDFLAGS = -lpthread -lm
CPPFLAGS = -std=c++0x -pedantic -Wextra -Wall -Wconversion -Iinclude -I../Common/include
all: Server
%.o: %.cpp
$(CXX) $< -o $#
Server: $(OBJ)
$(CXX) -o $(NAME) $(OBJ) $(LDFLAGS)
clean:
$(RM) $(OBJ) *~
fclean: clean
$(RM) $(NAME)
re: fclean Server
.PHONY: all clean fclean Server
Given these definitions, subst should be used to substitute the src part of the directory, and the file extension.
OBJ = $(subst src/,bin/,$(subst .cpp,.o,$(SRC)))
Then, you have to add new pattern rules to compile your source files. (You have to write one pattern rule per directory where your source files are.)
obj/%.o: src/%.cpp
$(CXX) -c $< -o $#
../Common/obj/%.o: ../Common/src/%.cpp
$(CXX) -c $< -o $#
I'm not sure that this will work, but I would try something like:
OBJ := $(join $(addsuffix ../obj/,$(dir $(SRC))),$(notdir $(SRC))
# or, as Didier suggested:
# OBJ := $(subst src/,obj/,$(SRC))
%.o: ../src/%.cpp
$(CXX) $< -o $#
It's not clear exactly what you're trying to do, but this should come close:
OBJ = $(subst src/,obj/,$(SRC:.cpp=.o))
obj/%.o : src/%.cpp
$(CXX) $< -o $#
../Common/obj/%.o : ../Common/src/%.cpp
$(CXX) $< -o $#
I need to create Makefile that compiles .c files with a lot of subdirs (sources directory goes in around 5 level depth) and I need to place the object files in the mirrored build directory. So far, I have created this Makefile:
CC := gcc.exe
AS := as.exe
CFLAGS = -DCORE_SW_VERSION='"$(CORE_SW_VERSION)"' -Wall -mA6 -c -fmessage-length=0 -Hsdata0
CFLAGS += -fgnu89-inline -mno-volatile-cache $(INCLUDE) -Hon=each_function_in_own_section -Xcrc -std=c99 -O1
CORE_SW_VERSION:=CORE.07.01.04.01.03.01.R
HAL_SW_VERSION:=16.01.06.01.06.00
MODE_CORE := dev
MODE_HAL := dev
OBJDIR := $(shell pwd)/$(TARGET12) #TARGET12 is a make parameter
INCLUDE := $(shell cat ./$(TARGET12)_include.txt)
SOURCEDIR := ../sources
CSRC := $(shell find $(SOURCEDIR) -name '*.c')
EXCLUDES := $(shell cat ./$(TARGET12)_exclude.txt)
OBJ := $(CSRC:.c=.o)
OBJS := $(patsubst ../%.c,$(OBJDIR)/%.o,$(CSRC))
.PHONY: $(TARGET12)
$(TARGET12): $(OBJS)
$(AR) -r $(CORE_SW_VERSION).a $(OBJS)
$(OBJS): $(CSRC)
mkdir -p $(dir $#)
$(CC) $(CFLAGS) $< -o $(patsubst ../%,$(OBJDIR)/%,$#)
If I define rule for $(OBJS) this way, $< is always the first .c file in $(CSRC).
If I define $(OBJS) this way:
$(OBJS): %.o: %.c
mkdir -p $(dir $#)
$(CP) $< $#
I get error that there is no rule to make target for .c file. But I see that make is looking for .c file in build mirrored directory, and it should look at the source dir. Do you maybe know how this could be arranged?
Thanks you in advance!
The rule $(OBJS): %.o: %.c means something like this: when trying to create a .o file, use this rule if the corresponding .c file exists. For example: when make is looking for a way to create $(OBJDIR)/foo.o, it will look for $(OBJDIR)/foo.c.
In your case this file does not exists, so the rule is ignored.
What you want is rather something like this:
$(OBJS): $(OBJDIR)/%.o: $(SOURCEDIR)/%.c
mkdir -p $(dir $#)
$(CP) $< $#
The first rule for $(OBJS) you tried, states that every object file individually depends on all source files. Surely that's not correct.
Your second attempt is better, although the recipe is weird. Fix that and use VPATH to make make find the sources.