I have the following makefile:
CPP_COMPILER = g++
CPP_COMPILER_FLAGS = -g -O0 -Wall -Wextra -Wpedantic -Wconversion -std=c++17
EXECUTABLE_NAME = mainDebug
CPP_COMPILER_CALL = $(CPP_COMPILER) $(CPP_COMPILER_FLAGS)
INCLUDE_DIR = include
SOURCE_DIR = src1
BUILD_DIR = build
CPP_SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp)
CPP_OBJECTS = $(patsubst $(SOURCE_DIR)/%.cpp, $(BUILD_DIR)/%.o, $(CPP_SOURCES))
build: $(BUILD_DIR)/$(EXECUTABLE_NAME)
TARGET_DEPS = $(CPP_OBJECTS)
$(BUILD_DIR)/$(EXECUTABLE_NAME): $(TARGET_DEPS)
$(CPP_COMPILER_CALL) $^ -o $#
execute:
.$(BUILD_DIR)/$(EXECUTABLE_NAME)
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp
$(CPP_COMPILER_CALL) -I $(INCLUDE_DIR) -c $< -o $#
clean:
rm -rf $(BUILD_DIR)/*.o $(BUILD_DIR)/$(EXECUTABLE_NAME)
And the following folder structure:
.
├── build
├── include
│ ├── mylib.h
│ └── test.h
├── Makefile
├── src1
│ ├── main.cc
│ └── mylib.cc
└── src2
└── test.cc
This works correctly with src1 but when adding src2 to SOURCE_DIR,
SOURCE_DIR = src1\
src2
I get the following error:
/usr/bin/ld: cannot find src1: file format not recognized
collect2: error: ld returned 1 exit status
make: *** [Makefile:22: build/mainDebug] Error 1
What am I doing wrong here ?
Look at how you use SOURCE_DIR:
SOURCE_DIR = src1
...
CPP_SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp)
CPP_OBJECTS = $(patsubst $(SOURCE_DIR)/%.cpp, $(BUILD_DIR)/%.o, $(CPP_SOURCES))
...
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp
$(CPP_COMPILER_CALL) -I $(INCLUDE_DIR) -c $< -o $#
After you define it, you use it three times, each time as a single directory name. You cannot simply add a second name to the variable and expect Make to iterate properly over the list.
First, use addsuffix to get the right pattern for wildcard:
CPP_SOURCES = $(wildcard $(addsuffix /*.cpp,$(SOURCE_DIR)))
Then use CPP_SOURCES instead of SOURCE_DIR:
CPP_OBJECTS = $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(notdir $(CPP_SOURCES)))
Then use vpath to find the sources:
vpath %.cpp $(SOURCE_DIR)
$(BUILD_DIR)/%.o: %.cpp
$(CPP_COMPILER_CALL) -I $(INCLUDE_DIR) -c $< -o $#
Related
I'm triying to write a makefile that can take any amount of sources dirs and create their object files in a tidy way. I found this post that tries more or less the same, I'm at the point that the object dirs are created correctly. But getting the make: *** No rule to make target error when triying to create the objects.
This is my makefile at the moment
INCLUDES = -I includes/ \
-I mlx
EXECPT_DIRS = /mlx
OBJDIR = objs
SRCDIR = src
SRCDIRS := $(shell find . -name '*.c' -exec dirname {} \;| uniq | sed 's/\/$(SRCDIR)//g' | sed 's/\$(EXECPT_DIRS)//g' | cut -d . -f 2)
SRCS := $(shell find $(SRCDIR) -name '*.c')
OBJS := $(patsubst $(SRCDIR)%.c,$(OBJDIR)%.o, $(SRCS))
#############################################
#.SILENT:
all: $(NAME)
$(NAME) : buildtree $(OBJS)
$(CC) $(OBJS) $(CFLAGS) $(INCLUDES) libraries/*
$(OBJDIR)%.o: $(SRCDIR)%.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
clean:
rm -rf $(OBJDIR)
fclean: clean
$(RM) $(NAME)
re: fclean all
buildtree:
#$(call mk_dir)
define mk_dir
mkdir -p $(OBJDIR)/; \
for dir in $(SRCDIRS); \
do \
mkdir -p $(OBJDIR)/$$dir; \
done
endef
.PHONY: all clean fclean re bonus ext
My tree before make
looks like this:
├── includes
├── libraries
├── mlx
│ └── man
│ └── man3
└── src
├── 42lib
└── cub3d
after
.
├── includes
├── libraries
├── mlx
│ └── man
│ └── man3
├── objs
│ ├── 42lib
│ └── cub3d
└── src
├── 42lib
└── cub3d
I did manage to get the object created using this makefile from the post:
APP = Hello
SRCDIR = Sources
OBJDIR = Objects
SRCS := $(shell find $(SRCDIR) -name '*.c')
SRCDIRS := $(shell find . -name '*.c' -exec dirname {} \; | uniq)
OBJS := $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
CFLAGS = -Wall -pedantic -ansi
LDFLAGS =
all: $(APP)
$(APP) : buildrepo $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $#
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) $(APP)
buildrepo:
#$(call make-repo)
define make-repo
for dir in $(SRCDIRS); \
do \
mkdir -p $(OBJDIR)/$$dir; \
done
endef
But the objects got created in the objs/src/dir instead of objs/dir and it relinked too.
Some help with the relink would be really appreciated :)
I've been looking into building cpp applications with make and looking at various sources online. While it works, I'm trying to build my object files and place those into a particular directory rather then have them go into the same src/ as my source files. Ideally, I would like them to go into the OUT_O_DIR location, but they're being generated and placed in the src/, which I don't want.
I want a structure like this:
.
|- Makefile
|- include/
| |- *.h
|- src/
| |- *.c
|- output/
| |- App
|- obj/
| |- *.o
My make version:
GNU Make 4.1
Built for x86_64-pc-linux-gnu
My Makefile:
OUT_O_DIR := $(OUT_DIR)/obj
PROJ = hello
SOURCE = $(wildcard src/*.cpp)
INC = $(wildcard include/*.h)
OBJS = $(SOURCE:.cpp=.o)
CFLAGS = -I include
CC = g++
.PHONY: directories
all : directories $(OUT_DIR)$(PROJ)
directories: $(OUT_DIR)
$(OUT_DIR)$(PROJ) : $(OBJS)
$(CC) -o $# $(OBJS)
.cpp.o: $(INC)
#echo $#
$(CC) -c $(CFLAGS) $< -o $#
clean :
rm -rf $(OUT_DIR)
$(OUT_DIR):
mkdir -p $(OUT_DIR)
The '.cpp.o' does not extend to cover multiple folders. Two options
Modify OBJS and rule to build object.
#OBJS = $(SOURCE:.cpp=.o)
OBJS = $(SOURCE:src/%.cpp=$(OUT_O_DIR)/%.o)
...
#.cpp.o: $(INC)
${OUT_O_DIR}/%.o: src/%.cpp $(INC)
$(CC) -c $(CFLAGS) $< -o $#
Or use vpath to specify the .cpp files are in src
#OBJS = $(SOURCE:.cpp=.o)
OBJS = $(SOURCE:src/%.cpp=$(OUT_O_DIR)/%.o)
vpath %.cpp src
${OUT_O_DIR}/%.o: %.cpp $(INC)
$(CC) -c $(CFLAGS) $< -o $#
I have the following directory structure for a C++ project:
.
├── bin
├── build
├── include
│ ├── dir1
│ │ ├── file1.hpp
│ │ └── file2.hpp
│ ├── dir2
│ │ ├── file3.hpp
│ │ └── file4.hpp
│ └── third_party
│ └── catch.hpp
├── Makefile
├── src
│ ├── dir1
│ │ ├── file1.cpp
│ │ └── file2.cpp
│ └── dir2
│ ├── file3.cpp
│ └── file4.cpp
└── test
├── dir1
│ ├── file1.test.cpp
│ └── file2.test.cpp
└── dir2
├── file3.test.cpp
└── file4.test.cpp
How can I write the Makefile to compile the code in src and test directories and obtain the object files in the build directory and the binaries in the bin directory, maintaining the same directory structure within them, without having to name every file and its dependency explicitly? Would it be better to use multiple Makefiles in each dir* within src and test?
My Makefile currently looks like this: (it's probably nonsensical, sorry about that!)
binaries_dir = bin
build_dir = build
sources_dir = src
include_dir = include
compile_flags = -std=c++14 -Wall
binaries := $(wildcard *.out)
objects := $(wildcard *.o)
sources := $(wildcard *.cpp)
headers := $(wildcard *.hpp)
objects: $(sources)
g++ $(compile_flags) -c $(sources_dir)/$(sources) -I $(include_dir)
binaries: $(objects)
for object in $(objects); do
g++ $(compile_flags) -o $(binaries_dir)/ $(build_dir)/$object
done
I don't think this is fool proof but I think it pretty much does what you are after. You should study up on building Makefiles because it this turns out not to quite fit your needs, how are you going to fix it?
CXX := g++
RM := rm -f
MD := mkdir -p
# don't change, this is for dependencies
CXXFLAGS += -MMD -MP
# add compiler flags here
CXXFLAGS += -std=c++14 -pedantic-errors
CXXFLAGS += -Wall -Wextra
CXXFLAGS += -g3 -O0
# add external includes here
CPPFLAGS += -Iinclude
# add library flags here
LDFLAGS +=
DIRS := $(patsubst src/%, %, $(wildcard src/*))
DIRS += $(patsubst test/%, %, $(wildcard test/*))
PROG_SOURCES := $(wildcard src/*/*.cpp)
TEST_SOURCES := $(wildcard test/*/*.cpp)
OBJECTS := $(patsubst src/%.cpp, build/%.o, $(PROG_SOURCES))
OBJECTS += $(patsubst test/%.cpp, build/%.o, $(TEST_SOURCES))
EXECUTABLES := $(patsubst src/%.cpp, bin/%, $(PROG_SOURCES))
EXECUTABLES += $(patsubst test/%.cpp, bin/%, $(TEST_SOURCES))
DEPENDENCIES := $(patsubst src/%.cpp, build/%.d, $(PROG_SOURCES))
DEPENDENCIES += $(patsubst test/%.cpp, build/%.d, $(TEST_SOURCES))
all: dirs $(EXECUTABLES)
build/%.o: src/%.cpp
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $# $<
build/%.o: test/%.cpp
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $# $<
bin/%: build/%.o
$(CXX) $(CXXFLAGS) -o $# $< $(LDFLAGS)
-include $(DEPENDENCIES)
clean:
#echo Removing build files
#$(RM) $(EXECUTABLES) $(OBJECTS) $(DEPENDENCIES)
dirs:
#$(MD) $(patsubst %, build/%, $(DIRS)) $(patsubst %, bin/%, $(DIRS))
.PHONY: show dirs
You might find some inspiration from this: https://github.com/jschmerge/DasBuild
Based on this link, I created a Autotools-based build system that accepts Qt UI and RSC files without the need to call QMAKE.
I however wish to separate the source, headers and ui-files into folders in the the following fashion:
${srcdir}
├── Makefile.am
├── main.cc
├── include
│ └── mainwidget.h
├── src
│ └── mainwidget.cc
└── ui
└── mainwidget.ui
And have the build directory ordered in the following way
${builddir}
├── include
│ └── ui_mainwidget.h
├── Makefile
├── main.o
├── mainwidget.o
└── moc_mainwidget.o
My Makefile.am currently looks like this:
moc_%.cc: %.h
#MOC# -o$# $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(MOC_CPPFLAGS) $<
ui_%.h: %.ui
#UIC# -o $# $<
qrc_%.cc: %.qrc
#RCC# -o $# $<
bin_PROGRAMS = qthello
BUILT_SOURCES = ui_mainwidget.h
qthello_CXXFLAGS = -I$(srcdir)/include -I$(builddir)/include
qthello_CPPFLAGS = $(QT_CPPFLAGS)
qthello_LDFLAGS = $(QT_LDFLAGS)
qthello_LDADD = $(QT_LIBS)
qthello_SOURCES = \
moc_mainwidget.cc \
mainwidget.cc \
main.cc
Which works fine if the ui-class files are located in $(srcdir), but simply moving them to the desired directories and changing the expected lines in the Makefile.am does not yeld the desired result. That is, doing these changes does not work:
BUILT_SOURCES = include/ui_mainwidget.h
[ ... ]
qthello_SOURCES = \
src/moc_mainwidget.cc \
src/mainwidget.cc \
main.cc
It occurs to me that some changes have to be made to the build rules to ensure that the include, src, ui -directories exist in $(builddir), and that the correct input files are passed. I am however inexperienced in writing such build rules and google does not seem to have the answer.
Are there any easy portable ways of achieving this?
So I did eventually find a solution to this thanks to this post.
Following is the final Makefile.am
moc_%.cc: ../include/%.h
$(MKDIR_P) $(#D)
#MOC# -o$# $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(MOC_CPPFLAGS) $<
ui_%.h: ../ui/%.ui
$(MKDIR_P) $(#D)
#UIC# -o $# $<
qrc_%.cc: %.qrc
$(MKDIR_P) $(#D)
#RCC# -o $# $<
clean-local:
rm -rf ui/ include/
bin_PROGRAMS = qthello
BUILT_SOURCES = \
include/ui_mainwidget.h
qthello_CXXFLAGS = \
-I$(srcdir)/include \
-I$(builddir)/include
qthello_CPPFLAGS = $(QT_CPPFLAGS)
qthello_LFLAGS = $(QT_LDFLAGS)
qthello_LDADD = $(QT_LIBS)
qthello_SOURCES = \
ui/moc_mainwidget.cc \
src/mainwidget.cc \
main.cc
Keep in mind that AC_PROG_MKDIR_P must be added to configure.ax.
I am trying to create a makefile for a project with the following structure:
├──bin/
├──build/
│ ├──foo.d
│ └──bar.d
├──include/
│ └──foo.h
│
├──lib/
├──src/
│ ├──foo.cc
│ └──bar.cc
│
├──Makefile
Here is the makefile:
# Define the compiler and the linker.
CXX = g++
CC = g++
# Folders
srcdir = src
builddir = build
out = bin
# Define preprocessor, compiler, and linker flags.
CPPFLAGS = -I include -std=c++11
LDFLAGS = -g -Llib
# Phony targets
.PHONY: all clean test
# Targets
all : $(out)/bar
$(out)/bar : $(addprefix $(builddir)/,bar.o foo.o)
# Standard clean
clean :
rm -f $(builddir)/*.o $(builddir)/*.d
# Generate dependencies in *.d files
$(builddir)/%.d: $(srcdir)/%.cc
#set -e; rm -f $#; \
$(CPP) -MM $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,$(builddir)/\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$;
deps = $(patsubst $(srcdir)/%.cc,$(builddir)/%.d,$(wildcard $(srcdir)/*.cc))
include $(deps)
The dependency files contain the following:
foo.d
build/foo.o build/foo.d : src/foo.cc include/foo.h
bar.d (depends on foo)
build/bar.o build/bar.d : src/bar.cc include/foo.h
Is there any way to generate the .d files in the build/ directory, compile the object files into the very same folder then compile the bin/bar program? Any help appreciated.
EDIT:
The problem was that I was expecting
all : $(out)/foo
$(out)/foo : $(addprefix $(builddir)/,foo.o bar.o)
$(builddir)/%.o : $(srcdir)/%.cc
$(CXX) -c $< -o $# -MP -MMD -MF $(#:.o=.d)
to magically compile the program foo (it works when all files are in the same folder).
Instead I had to specify the recipe:
all : $(out)/foo
$(out)/foo : $(builddir)/foo.o $(builddir)/bar.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $#
$(builddir)/%.o : $(srcdir)/%.cc
$(CXX) -c $< -o $# -MP -MMD -MF $(#:.o=.d)
Drop all of the sed nonsense. gcc can generate everything in one go:
$(builddir)/%.o : $(srcdir)/%.cc
$(CPP) -c $< -o $# -MP -MMD -MF $(#:.o=.d)
That will in one go build build/foo.o and build/foo.d, where build/foo.d will have the autogenerated dependencies for build/foo.o.