I started working on a small project to implement a todo app in C++.
I wrote a Makefile to compile my C++ files but , the Makefile Only compiles main.cc and nothing else.
Here is my MakeFile
#MakeFile for Building the ToDoList App
# Compile CXX Files
CXX := g++-4.9
CXXFLAGS := -std=c++11
CXXFILES := $(wildcard src/*.cc src/lexer/*.cc)
CXXOBJECTS := $(CXXFILES:.cc=.o)
CXXHEADERS := $(wildcard *.h)
# Link all Object Files
LD := ld
LDFLAGS :=
# Declare Clean and Run as Phony Targets
.PHONY: clean run
# The Final Product will be the To-Do APP
all: TedO.app
# Compile the ToDO APP
TedO.app: $(CXXOBJECTS)
$(LD) $(LDFLAGS) -o build/$# $^
# Run the APP from the Build Folder
run: TedO.app
./build/$^
# Compile the CC files into Object files and place it into the same directory.
%.o: %.cc
$(CXX) $(CXXFLAGS) -o $# $<
# Clean all the Objects
clean: $(CXXOBJECTS)
rm $^
Here is my Directory Structure
.
├── Makefile
├── Makefile.swp
├── build
│ ├── tedo
│ └── tedo.txt
├── doc
├── src
│ ├── lexer
│ │ ├── lexer.cc
│ │ └── lexer.h
│ └── main.cc
└── tree.txt
4 directories, 8 files
Here is my Output from the Console when running Make
g++-4.9 -std=c++11 -o src/main.o src/main.cc
Undefined symbols for architecture x86_64:
"lexer::lexer()", referenced from:
_main in ccmWqgIU.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [src/main.o] Error 1
Get rid of your compilation pattern rule
%.o: %.cc
$(CXX) $(CXXFLAGS) -o $# $<
Make already has a built-in rule for .cc files that works (you forgot to add the -c flag to stop GCC from linking).
There are a few more issues with your makefile: your rule for Ted0.app is wrong because you are actually linking build/Ted0.app, and your clean rule will remake all the object files before deleting them.
CXX := g++-4.9
CXXFLAGS := -std=c++11
CXXFILES := $(wildcard src/*.cc src/lexer/*.cc)
CXXOBJECTS := $(CXXFILES:.cc=.o)
.PHONY: all run clean
all: build/TedO.app
build/TedO.app: CC := $(CXX)
build/TedO.app: $(CXXOBJECTS)
$(LINK.o) $(LDFLAGS) -o $#
run: build/TedO.app
$<
clean: ; $(RM) $(CXXOBJECTS)
Related
I have a small project for school and I want to write a decent Makefile, I have seen some examples of using Makefile with multiple source directories and multiple executables but still could not implement it properly to my Makefile.
Here is the directory structure:
.
├── bin (this is where i want the executables)
├── build (this is where i want the .o)
├── extern
│ └── doctest.h
├── include
│ ├── file1.hpp
│ └── file2.hpp
├── src
│ ├── file1.cpp
│ └── file2.cpp
├── tests
│ ├── file1-test.cpp
│ └── file2-test.cpp
└── Makefile
PS: I'm using doctest for the unit testing (and i can't change).
Here is my Makefile for the moment:
BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/
CXX = clang++-7
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR)
EXEC_FILES = file1 file2
BIN = $(addprefix $(BIN_DIR), $(EXEC_FILES))
all: $(BIN)
$(BIN_DIR) $(BUILD_DIR):
mkdir -p $#
$(BUILD_DIR)%.o: $(SOURCE_DIR)%.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -c -o $# $^
$(BUILD_DIR)%.o: $(TESTS_DIR)%.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -I$(EXTERN_DIR) -c -o $# $^
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file1-test.o | $(BIN_DIR)
$(CXX) -o $# $^
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2-test.o | $(BIN_DIR)
$(CXX) -o $# $^
clean:
rm -f $(BIN_DIR)* $(BUILD_DIR)*
It's working well but I feel like it's doing useless stuff that i could avoid with more knownledge in the Makefile art, sadly I don't have much time.
My goal:
I want to run make and compile all the units tests (all the .cpp in the tests/ directory) and the main program (see PS below).
I want all the executables in the bin/ directory and all the binary files in the build/ directory.
PS: I don't have my main executable yet but it should be stored in the src/ directory at the very end (and be compiled as well while running make).
EDIT 1:
Basically, my question is: How can I write generic rules to prevent copying this (see below) for every new executable in my project ?
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2 test.o | $(BIN_DIR)
$(CXX) -o $# $^
EDIT 2:
After some changes, I ended up with this:
BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/
vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)
CXX = clang++-7
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)
EXEC_FILES = file1-test file2-test
BIN = $(addprefix $(BIN_DIR), $(EXEC_FILES))
all: $(BIN) | $(BIN_DIR)
$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR)
#$(CXX) $(CXXFLAGS) -c -o $# $^
# The problem is here
$(BIN_DIR)%: $(BUILD_DIR)%.o
#$(CXX) -o $# $^
$(BIN_DIR) $(BUILD_DIR):
#mkdir -p $#
clean:
-#rm -f $(BIN_DIR)* $(BUILD_DIR)*
I understand this rule (see below) like this: Compile every target in EXEC_FILES to the bin/ directory, from his equivalent .o (obj) in the build/ directory.
$(BIN_DIR)%: $(BUILD_DIR)%.o
#$(CXX) -o $# $^
But in fact I need a rule that will: Compile every target in EXEC_FILES to the bin/ directory, from all their related .o (obj) in the build/ directory.
I have a project for school and I want to write a Makefile, I have seen some examples of using Makefile with multiple source directories and multiple executables but still could not implement it properly to my Makefile.
PS: I'm using doctest for the unit testing (and I can't change it).
Here is the project structure (and I can't change it):
.
├── bin
├── build
├── extern
│ └── doctest.h
├── include
│ ├── file1.hpp
│ └── file2.hpp
├── src
│ ├── file1.cpp
│ └── file2.cpp
├── tests
│ ├── file1-test.cpp
│ └── file2-test.cpp
└── Makefile
I have the following directories:
bin: for all the executables.
build: for all the objects (.o).
extern: for the doctest header (this is where I would have stored any other library)
include: for all the headers (.hpp).
src: for all the classes (.cpp).
tests: for all the unit tests (also .cpp)
You can see file1.cpp as a class, file1.hpp as the class header and file1-test.cpp as the unit tests for the class.
In the exemple above I have 2 tests files but at the very end of the project I'll have a lot more, and for each test file I'll have an executable.
My goals:
I want to run make and compile all the units tests (all the .cpp in the tests/ directory).
And I want all the executables to be stored in the bin/ directory and all the binary files in the build/ directory.
Here is my Makefile:
BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/
vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)
CXX = clang++
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)
EXEC_FILES = file1-test file2-test
BIN = $(addprefix $(BIN_DIR), $(EXEC_FILES))
all: $(BIN) | $(BIN_DIR)
$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -c -o $# $^
$(BIN_DIR) $(BUILD_DIR):
mkdir -p $#
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file1-test.o
$(CXX) -o $# $^
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2-test.o
$(CXX) -o $# $^
clean:
-rm -f $(BIN_DIR)* $(BUILD_DIR)*
It's working well but I feel like it's doing redondant stuff that i could avoid with more knownledge in the Makefile art, especially here:
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file1-test.o
$(CXX) -o $# $^
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2-test.o
$(CXX) -o $# $^
For the moment this Makefile is correct because I only have 2 executables, but I'll end up with 15+ and I dont want to have 15 times this for each executable:
$(BIN_DIR)xxx-test: $(BUILD_DIR)xxx.o etc.
$(CXX) -o $# $^
What I exactly need ...:
Basically, I need to write a generic rule that will fetch all the appropriated dependencies for a given target.
After reading multiple posts I think it's all about auto-dependencies.
I'm pretty sure the final result would look like this, but sadly I can't make it works in my case:
$(BIN_DIR)%: ???
#$(CXX) -o $# $^
I already looked at this (and many other posts about the subject): http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/, but I still can't figure it out.
So how can I write an expression that will do the job, can someone give me a working exemple or something similar ?
EDIT 1:
Based on this post: Makefile (Auto-Dependency Generation).
I added these lines to my Makefile:
SRC = $(wildcard $(SOURCE_DIR)*.cpp)
SRC += $(wildcard $(TESTS_DIR)*.cpp)
The idea is to fetch all the .cpp from the source directories (src and tests). Then I added -MDD option to my CXXFLAGS variable to create a .d file for each target (atleast it's what I thought it's doing):
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR) -MMD
And finally, I added this:
$(BIN_DIR)%: $(SRC)
$(CXX) -o $# $^
-include $(SRC:.cpp=.d)
What I expect it to do:
Create a .d file with all the dependencies for each target.
Fetch the dependencies in the .d file and transform them to .o to get all the objects needed for the given target.
But it seems that it's not doing what I'm expecting.
EDIT 3:
After some changes I end up with this Makefile:
BIN_DIR := bin/
BUILD_DIR := build/
EXTERN_DIR := extern/
INCLUDE_DIR := include/
SOURCE_DIR := src/
TESTS_DIR := tests/
DEP_DIR := .dep/
DEPENDS := $(patsubst %.o, $(BUILD_DIR)$(DEP_DIR)%.d, $(notdir $(wildcard $(BUILD_DIR)*.o)))
EXE := $(addprefix $(BIN_DIR), Coord-test Fourmi-test)
OBJS_1 := $(addprefix $(BUILD_DIR), Coord.o)
OBJS_2 := $(addprefix $(BUILD_DIR), Coord.o Fourmi.o)
CXX := clang++
CXXFLAGS := -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)
vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)
all: $(EXE)
$(BUILD_DIR):
mkdir -p $# $#/$(DEP_DIR)
$(BIN_DIR):
mkdir -p $#
$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -MMD -MP -MF $(BUILD_DIR)$(DEP_DIR)$(notdir $(basename $#).d) -c $< -o $#
$(BIN_DIR)%: $(BUILD_DIR)%.o | $(BIN_DIR)
$(CXX) -o $# $^
$(BIN_DIR)Coord-test: $(OBJS_1)
$(BIN_DIR)Fourmi-test: $(OBJS_2)
.PRECIOUS: $(BUILD_DIR)%.o
-include $(DEPENDS)
clean:
-rm -f $(BIN_DIR)* $(BUILD_DIR)* $(BUILD_DIR)$(DEP_DIR)*
It's working but I'll have to add OBS_X for each new executable.
I also wanted factorize this, but I don't know if it's possible ? If someone could tell me.
$(BIN_DIR)%: $(BUILD_DIR)%.o | $(BIN_DIR)
$(CXX) -o $# $^
$(BIN_DIR)Coord-test: $(OBJS_1)
$(BIN_DIR)Fourmi-test: $(OBJS_2)
Since you know that you will always have a foo-test.o to build a foo-test program, you can write your pattern rule like this:
$(BIN_DIR)%: $(BUILD_DIR)%.o
$(CXX) -o $# $^
However, there's no way make can infer what OTHER objects might be needed to build these executables. You'll just have to tell it. So for the above examples you can add this:
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o
You don't need to put the recipe here, this is just adding more prerequisites to these targets. You also don't have to put in the $(BUILD_DIR)file1-test.o etc. because this is inferred from the pattern rule.
But, if you do have other object files you need to use you'll have to list them explicitly, there's no way around it.
Given I have a project with a straightforward Makefile like so:
all: foobar
foobar: foo.o bar.o
that I can build to target different architectures:
$ CC=clang make # or
$ CC=x86_64-w64-mingw32-gcc make # or
$ CC=arm-linux-gnueabihf-gcc make
This works but I want to be able to maintain outputs for multiple configurations at the same time, for example on a build server.
What would be a good, clean way to go about this? I've considered the following:
Use autotools or another build tool, but I want to see what's possible without
Create build directories with Makefiles in them that set VPATH and include the root Makefile
Write a script that moves the output after building each architecture
Modify the Makefile to build multiple configurations. I don't like this solution because you end up with a sort of meta-Makefile that's complex and tightly coupled to your specific build environment
Add a variable to the Makefile to set the output directory. This could work but it means I can't use implicit Makefile rules. Pattern rules would get messy too
I would go with something like that:
# User configuration
BINARY := hello
SOURCES := main.c
# Create the output paths
out ?= out
outdir := $(out)/$(CC)
outbin := $(outdir)/$(BINARY)
objects := $(outdir)/$(SOURCES:.c=.o)
# Default target
all: $(outbin)
# Binary target
$(outbin): $(objects)
$(CC) -o $# $^
# Objects target
$(objects): $(outdir)/%.o: %.c
mkdir -p $(#D)
$(CC) -o $# -c $<
# The cleanning targets
clean:
$(RM) -r $(outdir)
mrproper:
$(RM) -r $(out)
# Declare phony targets
.PHONY: all clean mrproper
Note that the objects target is using static pattern to be able to get the source files in the current directory and the object files in the output directory.
It is also as easy to use as a basic Makefile:
$ make
mkdir -p out/cc
cc -o out/cc/main.o -c main.c
cc -o out/cc/hello out/cc/main.o
$ make
make: Nothing to be done for 'all'.
$ tree
.
├── main.c
├── Makefile
└── out
└── cc
├── hello
└── main.o
2 directories, 4 files
$ CC=gcc make
mkdir -p out/gcc
gcc -o out/gcc/main.o -c main.c
gcc -o out/gcc/hello out/gcc/main.o
$ tree
.
├── main.c
├── Makefile
└── out
├── cc
│ ├── hello
│ └── main.o
└── gcc
├── hello
└── main.o
3 directories, 6 files
I have 2 directories in my project, one called Builds, who has the Makefile and a test program ( test-P0-consola.cpp ) and other one directory called P0 who constains the classes I use, cadena (string) and fecha (date).
test-P0-consola.cpp includes both of them, but Make doesn't find them.
CPP = g++
CPPFLAGS = -std=c++14 -g -Wall -pedantic
VPATH = ../P0:.:..
test-consola: test-P0-consola.o fecha.o cadena.o
${CPP} ${CPPFLAGS} -o $#.ex $^
test-P0-consola.o: test-P0-consola.cpp fecha.hpp cadena.hpp
${CPP} -c ${CPPFLAGS} $< -o $#
fecha.o: fecha.hpp
cadena.o: cadena.hpp
It throws the fatal error "cadena.hpp doesn't exist the file or directory" when it tries to compile test-P0-consola.o, but It find them out when I force it to compile cadena or fecha. I'm using GCC and Ubuntu.
..
├── Builds
│ ├── makefile.mak
│ └── test-P0-consola.cpp
├── P0
│ ├── cadena.cpp
│ ├── cadena.hpp
│ ├── fecha.cpp
│ └── fecha.hpp
EDIT
Error:
g++ -std=c++14 -g -Wall -pedantic -c test-P0-consola.cpp
test-P0-consola.cpp:7:21: fatal error: fecha.hpp: There is no file or directory
compilation terminated.
makefile.mak:9: Failure in the instructions for the objective 'test-P0-consola.o'
make: *** [test-P0-consola.o] Error 1
Look closely at your error:
test-P0-consola.cpp:7:21: fatal error: fecha.hpp: There is no file or directory
You probably have something like:
// test-P0-consola.cpp
#include "fetcha.hpp"
But fetcha.hpp is not in that directory, so it can't find it. You either need to change the way you include the file directly (via #include "../P0/fetcha.hpp") or to change the build rule to pass in an additional include path (via -I../P0).
Note: I'm not sure there's a reason to add . to VPATH. That's kind of implicit.
Note 2: this is a bad idea:
test-consola: test-P0-consola.o fecha.o cadena.o
${CPP} ${CPPFLAGS} -o $#.ex $^
~~~~~
Don't lie to Make. The result of running a recipe should be the target file, except for PHONY targets. The recipe here should be -o $#. If you want the .ex suffix, you should change the target to be test-consola.ex. If you still want the rule to be named test-consola, you'll want:
test-consola : test-consola.ex
test-consola : .PHONY
You should put in the makefile the include path of the .hpp files you need the compiler to use. You should use the -Ipath compiler directive, where path is the path of your include files.
See `Makefile: How to correctly include header file and its directory?
and
How to define several include path in Makefile
Something like:
CPP = g++
CPPFLAGS = -std=c++14 -g -Wall -pedantic
INC = -Iyourincludebasepath/P0
VPATH = ../P0:.:..
test-consola: test-P0-consola.o fecha.o cadena.o
${CPP} ${CPPFLAGS} ${INC} -o $#.ex $^
test-P0-consola.o: test-P0-consola.cpp fecha.hpp cadena.hpp
${CPP} -c ${CPPFLAGS} ${INC} $< -o $#
fecha.o: fecha.hpp
cadena.o: cadena.hpp
Note that there are similar questions on SO, however I think my situation is different, moreover my Makefile is extremely simple and straight forward. I am new to Makefile.
Suppose I need to compile a project, that looks like this --
.
├── [4.0K] bin
├── [ 517] Makefile
├── [4.0K] obj
└── [4.0K] src
├── [ 117] func1.cpp
├── [ 76] func2.cpp
├── [ 137] global.h
└── [ 97] main1.cpp
and my Makefile looks like this --
CC := g++
CFLAGS := -g -Wall -std=c++0x
LDFLAGS := -lm
NAMES := func1.cpp func2.cpp main1.cpp
SRC := $(addprefix src/,$(NAMES))
OBJ := $(addprefix obj/,$(NAMES:.cpp=.o))
DEPS := $(OBJ:.o=.d)
.PHONY: clean all debug
all: prog
debug:
$(info $$SRC: ${SRC})
$(info $$OBJ: ${OBJ})
$(info $$DEPS: ${DEPS})
prog: bin/prog
bin/prog: $(OBJ)
$(CC) $^ -o $#
$(OBJ): $(SRC)
$(CC) $(CFLAGS) -I/src/global.h -c $(addprefix src/,$(notdir $(#:.o=.cpp))) -o $#
-include $(DEPS)
clean:
rm -rf bin/*
rm -rf obj/*
Suppose I opened a file func1.cpp and made some changes. When I invoke make it compiles all files, but it was supposed to compile only one (func1.cpp).
How do I fix this ?
Note: I need prog, bin/prog for a different reason, also I can't do recipes like obj/%.o: src/%.c because I might have different target from the subset of the same objects.
When you write a rule like:
$(OBJ): $(SRC)
cmd
which in your case is
obj/func1.o obj/func2.o obj/main.o : src/func1.cpp src/func2.cpp src/main1.cpp
cmd
The prerequisites don't get zipped across. That generates one rule for each target, with all of the prerequisites. That is:
obj/func1.o : src/func1.cpp src/func2.cpp src/main1.cpp
cmd
obj/func2.o : src/func1.cpp src/func2.cpp src/main1.cpp
cmd
obj/main.o : src/func1.cpp src/func2.cpp src/main1.cpp
cmd
Since src/func1.cpp is a prereq for all of the object files, they all get recompiled.
What you want instead is to use a static pattern rule:
obj/%.o : src/%.cpp
$(CC) $(CFLAGS) -I/src -c $< -o $#
Note that -I is for include directories, not include files.