makefile: how to generate object files to upper directory - c++

I have a makefile as below, which can compile and link all cpp files in a same directory:
g++1x:=g++ -std=c++14 -stdlib=libc++ -MMD -MP
cflags:= -Wall -lncurses
TARGET:=matrix.out
CPPFILES:=$(wildcard *.cpp)
OBJDIRECTORY:=.obj
OBJFILES:=$(addprefix $(OBJDIRECTORY)/,$(notdir $(CPPFILES:.cpp=.o)))
.PHONY: install
install: $(OBJDIRECTORY) $(TARGET)
$(OBJDIRECTORY):
mkdir -p $(OBJDIRECTORY)
$(TARGET): $(OBJFILES)
$(g++1x) $(cflags) -o $# $^ -g
$(OBJDIRECTORY)/%.o: %.cpp
#%.o: %.cpp
$(g++1x) -c -o $# $< -g
-include $(addprefix $(OBJDIRECTORY)/,$(notdir $(CPPFILES:.cpp=.d)))
.PHONY: clean
clean:
rm -f $(TARGET)
rm -rf $(OBJDIRECTORY)
When I execute make, a .obj will be created and all of obj files are in it. Also an executable file will be generated too. For now everything's fine.
Now I'm trying to organise my project. My plan is to create some subdirectories and each of them contains a makefile. When I execute a makefile, it will generate obj files at some fixed path. Finally, I can execute a makefile to link main.cpp and all of obj files to get the executable file.
But I don't know how to write such a makefile for subdirectory. I've made a try as below but it doesn't work.
project
|--- main.cpp
|--- makefile
|--- subdir
|--- test.h
|--- test.cpp
|--- makefile
Here is my makefile in project/subdir:
g++1x:=g++ -std=c++14 -stdlib=libc++ -MMD -MP
cflags:= -Wall -lncurses
CPPFILES:=$(wildcard *.cpp)
OBJDIRECTORY:=../.obj
TARGET:=$(OBJDIRECTORY)/%.o
OBJFILES:=$(addprefix $(OBJDIRECTORY)/,$(notdir $(CPPFILES:.cpp=.o)))
.PHONY: install
install: $(OBJDIRECTORY) $(TARGET)
$(OBJDIRECTORY):
mkdir -p $(OBJDIRECTORY)
$(TARGET): %.cpp
#%.o: %.cpp
$(g++1x) -c $# $< -g
-include $(addprefix $(OBJDIRECTORY)/,$(notdir $(CPPFILES:.cpp=.d)))
.PHONY: clean
clean:
rm $(OBJDIRECTORY)/%.o
Error:
make: *** No rule to make target ../.obj/%.o', needed byinstall'.
Stop.

Don't place files in the path's parent; turn the problem around: Have a Makefile in the root directory that $(MAKE)s the subdirs and uses the obj files there.

You have several problems here.
In your original makefile, the variable TARGET contained the string "matrix.out", and all was well.
In your subdir/makefile, the variable TARGET contains the string "../.obj/%.o", and you're asking Make to build that. The only rule it can find:
$(TARGET): %.cpp
...
doesn't help, because there is no file called "%.cpp" anywhere.
I suggest you try something like this:
install: $(OBJFILES)
$(OBJFILES): $(OBJDIRECTORY)/%.o: %.cpp $(OBJDIRECTORY)
$(g++1x) -c $# $< -g
Once you get that working, you can worry about the problem of getting the master makefile to invoke the sun-makes.

Related

Makefile target with wildcard is not working

I have a simple project, whose folder structure is something like:
ls -R
.:
build include makefile src
./build:
./include:
myfunc.h
./src:
main.cpp myfunc.cpp
I want to compile the .cpp sources into .o object files, which should end into ./build folder. Using the GNUmake documentation and other sources (e.g. Proper method for wildcard targets in GNU Make), I wrote this makefile:
CXX := g++
CXXFLAGS += -I./include
CXXFLAGS += -Wall
OBJDIR := ./build
SRCDIR := ./src
PROGRAM = release
DEPS = myfunc.h
SRC = $(wildcard $(SRCDIR)/*.cpp)
OBJ = $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(SRC))
all: $(PROGRAM)
$(PROGRAM): $(OBJ)
$(CXX) $(CXXFLAGS) -o $(PROGRAM) $(OBJ)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm $(PROGRAM) $(OBJ)
But I get the error message: make: *** No rule to make target 'build/main.o', needed by 'release'. Stop.. I tried a lot of different ways but I cannot manage to have my .o files end up in the ./build directory. Instead, everything works if I put them in the root directory of the project. I can also make it work by specifying a rule for each object file, but I'd like to avoid that. What am I missing?
(I am using GNUmake version 4.3)
The problem is here:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -c $< -o $#
See the $(DEPS)? That expands to myfunc.h. The compiler knows where to find that file (or would if this recipe were executed), because you've given it -I./include, but Make doesn't know where to find it (so it passes over this rule).
Add this line:
vpath %.h include
P.S. If you want to be really clean, you can add a variable:
INCDIR := ./include
CXXFLAGS += -I$(INCDIR)
vpath %.h $(INCDIR)

Makefile with different source folder for test target

I am very new to C++ makefiles and I have the makefile below which I mostly copied from somewhere on the internet. My contribution to the makefile is the "test" target, which is the problem.
My code is organized in include (for headers), src (for sources) and test (for test sources) directories. For the standard target I want to build all files in the src folder which also includes the main.cpp file. To make the test build I want to build all files in the src folder except main.cpp and additionally all files in the test folder. I hoped that my test target would achieve that, but it fails. It just build the files from the standard target.
How can I correct my mistakes.
Thank you
The makefile I use:
APP=myappname
SRC_DIR=src
INC_DIR=include
OBJ_DIR=obj
BIN_DIR=bin
TEST_SRC_DIR=test
MAIN_CPP_NAME=main.cpp
CC=g++
LD=g++
CFLAGS=-O2 -c -Wall -std=c++17
LFLGAS=
DFLAGS=-g3 -O0 -DDEBUG
INCFLAGS=-I$(INC_DIR)
SOURCES=$(wildcard $(SRC_DIR)/*.cpp)
HEADERS=$(wildcard $(INC_DIR)/*.hpp)
OBJECTS=$(SOURCES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
DEPENDS=$(OBJ_DIR)/.depends
.PHONY: all
all: $(BIN_DIR)/$(APP)
.PHONY: debug
debug: CFLAGS+=$(DFLAGS)
debug: all
.PHONY: test
test: SOURCES=$(wildcard $(SRC_DIR)/*.cpp)
test: SOURCES=$(filter-out $(SRC_DIR)/$(MAIN_CPP_NAME), $(SOURCES))
test: OBJECTS=$(SOURCES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
test: TEST_SOURCES=$(wildcard $(TEST_SRC_DIR)/*.cpp)
test: OBJECTS+=$(TEST_SOURCES:$(TEST_SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
test: all
$(BIN_DIR)/$(APP): $(OBJECTS) | $(BIN_DIR)
$(LD) $(LFLGAS) -o $# $^
$(OBJ_DIR)/%.o: | $(OBJ_DIR)
$(CC) $(CFLAGS) $(INCFLAGS) -o $# $<
$(DEPENDS): $(SOURCES) | $(OBJ_DIR)
$(CC) $(INCFLAGS) -MM $(SOURCES) | sed -e 's!^!$(OBJ_DIR)/!' >$#
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPENDS)
endif
$(BIN_DIR):
mkdir -p $#
$(OBJ_DIR):
mkdir -p $#
.PHONY: clean
clean:
rm -rf $(BIN_DIR) $(OBJ_DIR)
You're trying to write a sophisticated makefile without understanding the basics, which is almost impossible. Let's try a very simple approach.
First, suppose the source files are
src/main.cpp
src/func.cpp
test/unit.cpp
test/global.cpp
Now we need a list of the object files that test will need.
SOURCES:=$(wildcard $(SRC_DIR)/*.cpp) # this will be src/main.cpp src/func.cpp
NON_MAIN_SOURCES:=$(filter-out $(SRC_DIR)/$(MAIN_CPP_NAME), $(SOURCES)) # this will be src/func.cpp
TEST_DIR_SOURCES:=$(wildcard $(TEST_SRC_DIR)/*.cpp) # this will be test/unit.cpp test/global.cpp
TEST_SOURCES:=$(notdir $(NON_MAIN_SOURCES) $(TEST_DIR_SOURCES)) # this will be func.cpp unit.cpp global.cpp
TEST_OBJECTS:=$(patsubst %.cpp,$(OBJ_DIR)/%.o,$(TEST_SOURCES)) # this will be obj/func.o obj/unit.o obj/global.o
(Note that you must avoid name collisions between src/ and test/, e.g. having a src/func.cpp and also a test/func.cpp. This is a consequence of your directory structure; there's no way for the makefile to work around it.)
Now we must tell Make how to build those object files. We can start with a rule for the sources in src:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $(INCFLAGS) -o $# $<
(I have omitted the $(OBJ_DIR) prerequisite for simplicity. For now, you will be responsible for making sure that obj/ exists.)
Now for the sources in test. A crude but effective approach is to add a rule for them:
$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp
$(CC) $(CFLAGS) $(INCFLAGS) -o $# $<
There are more sophisticated ways, but you must master the basics first.
Finally, the rule to build bin/mytestname:
$(BIN_DIR)/mytestname: $(TEST_OBJECTS)
$(LD) $(LFLAGS) -o $# $^
That's enough for now.

Makefile: compile objects to different directory and build from there

My Makefile:
CXX = clang++
CXXFLAGS = -g -Wall -std=c++14
LDFLAGS = -lboost_system -lcrypto -lssl -lcpprest -lpthread
OBJDIR = obj
SRCDIR = .
SRC := $(shell find $(SRCDIR) -name "*.cpp")
OBJ := $(SRC:%.cpp=%.o)
APP = run
all: $(APP)
$(APP): $(OBJ)
#echo "== LINKING EXECUTABLE $(APP)"
#$(CXX) $^ $(LDFLAGS) -o $(APP)
%.o: %.cpp
#echo "COMPILING SOURCE $< INTO OBJECT $#"
#$(CXX) -c $(CXXFLAGS) $< -o $#
clean:
find . -name *.o -delete
rm -f $(APP)
Directory structure:
Makefile
sources/
directory1
...cpp
directory2
...cpp
...
main.cpp
obj/
I try to make make create *.o files in a directory obj/ and then compile the final executable from there. I tried various approaches and they fail because of the project structure that stores *.cpp files in sub-directories. Particularly, I've tried the following: https://stackoverflow.com/a/26032630/2042546
I've also tried to manipulate the command itself clang++ $< -o obj/$# but it breaks whole idea of make and it's dependency management.
If I modify OBJ via patsubstr and notdir, make becomes unable to deduce dependency of a *.o on a corresponding *.cpp by it's path, cause *.o's path loses it's directory part and becomes unable to find it's *.cpp file when executing %.o:%.cpp rule (I hope I managed to write down my thoughts correctly).
If you want objects to live in the same source directory structure but under obj, then simply change your pattern rule (and how you generate the object files). And you should create the directory first:
OBJ := $(SRC:%.cpp=$(OBJDIR)/%.o)
...
$(OBJDIR)/%.o: %.cpp
#echo "COMPILING SOURCE $< INTO OBJECT $#"
#mkdir -p '$(#D)'
#$(CXX) -c $(CXXFLAGS) $< -o $#

Build (make) lib every time, recompile project only if lib is newer

I have the following project structure:
lib/
Makefile
src/...
inc/...
build/
inc/...
lib/libmylib.a
subproj1/
src/main.cpp
Makefile
The Makefile in the lib folder is designed to create the file libmylib.a and copy the relevant header files to the build/inc folder.
I want the Makefile in subproj1 to always call make -C ../lib, but only re-compile file if headers have changed, and re-link only if necessary (one object file or libmylib.a is newer).
I have the following (non-defined variables such as CC are defined in another file):
LIBDIR = ../lib
SRCDIR = src
OBJDIR = obj
SRCS = $(SRCDIR)/main.cpp
MAIN=myexe
OBJS = $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEPS = $(OBJS:.o=.d)
all: $(MAIN)
debug: CFLAGS += -g -DDEBUG
debug: LFLAGS += -g
debug: $(MAIN)
$(MAIN): $(OBJS) $(LIBDIR)/build/lib/libmylib.a
$(CC) $^ -o $# $(LIBS) $(LFLAGS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(LIBDIR)/build/lib/libmylib.a
mkdir -p $(OBJDIR)
$(CC) -c -o $# $(CFLAGS) $(INCS) -MD -MF $(patsubst %.o, %.d, $#) $<
$(LIBDIR)/build/lib/libmylib.a:
make -C $(LIBDIR)
-include $(DEPS)
.PHONY: clean $(LIBDIR)/build/lib/libmylib.a
clean:
$(RM) obj/* $(MAIN)
The above will re-compile main.cpp even if nothing has changed in the lib folder. If I remove $(LIBDIR)/build/lib/libmylib.a from the $(OBJDIR)/%.o rule, the .cpp file will not be re-compiled if a header changed (I would need to run make twice).
Is there a way to have the .cpp files in subproj1 being compiled only if the header files in lib have changed (or if the .cpp files themselves have changed), and to get myexe built only if one of the .cpp has been re-compiled (newer .o) or if libmylib.a is newer?
With recursive makefiles you need to execute the sub-project makefiles in correct order because the dependency tree is incomplete (e.g. this makefile does not know that updating $(LIBDIR)/build/lib/libmylib.a also updates those headers). It is easy to do that with a shell script or a top-level makefile.
Alternatively, your makefile must execute the sub-makefiles unconditionally in correct order, which can be done with shell function, e.g.:
LIBDIR := ../lib
pid := $(shell ps -o ppid= $$$$)
$(shell ${MAKE} -C ${LIBDIR} >/proc/$(pid)/fd/1 2>/proc/$(pid)/fd/2)
That $(LIBDIR)/build/lib/libmylib.a rule should be removed, the object files should not depend on the .a and it should not be marked as .PHONY.
This makes sure that building in ${LIBDIR} happens before this makefile analyzes file timestamps in ${LIBDIR}.
Now your auto-generated header dependencies should just work.
This might be a bit cleaner.
LIBDIR = ../lib
SRCDIR = src
OBJDIR = obj
SRCS = $(SRCDIR)/main.cpp
MAIN=myexe
OBJS = $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEPS = $(OBJS:.o=.d)
all: makelib
$(MAKE) $(MAIN)
debug: CFLAGS += -g -DDEBUG
debug: LFLAGS += -g
debug: $(MAIN)
$(MAIN): $(OBJS)
$(CC) $^ -o $# $(LIBS) $(LFLAGS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
mkdir -p $(OBJDIR)
$(CC) -c -o $# $(CFLAGS) $(INCS) -MD -MF $(patsubst %.o, %.d, $#) $<
makelib:
make -C $(LIBDIR)
-include $(DEPS)
.PHONY: clean makelib
clean:
$(RM) obj/* $(MAIN)
The main target all requires makelib to be built, and then it recursively calls itself for the target $(MAIN) (so all of $(MAIN)'s dependencies will be recalculated after makelib has finished building).

need help creating a static c++ library using make

I am trying to create a static library based on the file layout given below.
/library
Makefile
/include
.h files
/src
.cpp files
/build
.o files
/lib
.a file
When I run make all with the current code in my makefile given below it gives me the error:
make: *** No rule to make target src/%.cpp', needed bybuild/BaseGfxApp.o'. Stop.
CPP_FILES = $(wildcard src/*.cpp)
OBJ_FILES = $(addprefix build/,$(notdir $(CPP_FILES:.cpp=.o)))
CC_FLAGS = -c -Wall
all: libphoto.a
libphoto.a: $(OBJ_FILES)
ar rcs lib/$# $^
build/%.o: src/%.cpp
g++ $(CC_FLAGS) $# $<
I am fairly new to 'make' and I honestly have no clue where to go from here. I would appreciate some input or help. Thanks!
It could be that you are missing a makefile in your src/ directory.
dont put paths in the rules
%.o: %.cpp
g++ $(CC_FLAGS) $# $<
I think the main problem is you are not giving the proper path to the files you are trying to build. But also you missed some flags for g++. I think the following changes should work (not properly tested).
CPP_FILES = $(wildcard src/*.cpp)
OBJ_FILES = $(patsubst src/%.cpp,build/%.o,$(CPP_FILES))
CXXFLAGS = -Wall
all: prereqs lib/libphoto.a
lib/libphoto.a: $(OBJ_FILES)
ar rcs $# $^
build/%.o: src/%.cpp
g++ -c $(CXXFLAGS) -o $# $<
prereqs:
mkdir -p lib
mkdir -p build
.PHONY: prereqs
clean:
rm $(OBJ_FILES) lib/libphoto.a