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
Related
I am new to Makefiles and I have trouble with an undefined reference to a function. The directory structure is the following:
├── linkedlist.cc
├── linkedlist.h
│ ├── src
│ │ ├── main.cc
│ │ ├── removeduplicates.cc
│ │ ├── removeduplicates_unittest.cc
│ └── test
│ ├── Makefile
removeduplicates.cc and removeduplicates_unittest.cc import the declarations from linkedlist.h and the definitions from linkedlist.cc. Also removeduplicates.cc defines new functions that are declared in linkedlist.h but not defined in linkedlist.cc.
The sample Makefile file that uses GTest is taken from the GTest example in the repo and looks like the following. It is only modified to include the files above.
# A sample Makefile for building Google Test and using it in user
# tests. Please tweak it to suit your environment and project. You
# may want to move it to your project's root directory.
#
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make clean - removes all files generated by make.
# Please tweak the following variable definitions as needed by your
# project, except GTEST_HEADERS, which you can use in your own targets
# but shouldn't modify.
# Points to the root of Google Test, relative to where this file is.
# Remember to tweak this if you move this file.
GTEST_DIR = ../../../GMOCK_ROOT/GTEST_DIR/googletest/
# Where to find user code.
USER_DIR = ../src
BASE_DIR = ../..
# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
CPPFLAGS += -isystem $(GTEST_DIR)/include
# Flags passed to the C++ compiler.
CXXFLAGS += -I.. -std=c++17 -g -Wall -Wextra -pthread
# All tests produced by this Makefile. Remember to add new tests you
# created to the list.
TESTS = removeduplicates_unittest
# All Google Test headers. Usually you shouldn't change this
# definition.
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
# House-keeping build targets.
all : $(TESTS)
clean :
rm -f $(TESTS) gtest.a gtest_main.a *.o
# Builds gtest.a and gtest_main.a.
# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc
gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc
gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $# $^
gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $# $^
# Builds a sample test. A test should link with either gtest.a or
# gtest_main.a, depending on whether it defines its own main()
# function.
removeduplicates.o : $(USER_DIR)/removeduplicates.cc $(BASE_DIR)/linkedlist.h $(BASE_DIR)/linkedlist.cc $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(BASE_DIR)/linkedlist.cc $(USER_DIR)/removeduplicates.cc
removeduplicates_unittest.o : $(USER_DIR)/removeduplicates_unittest.cc $(BASE_DIR)/linkedlist.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/removeduplicates_unittest.cc
removeduplicates_unittest : removeduplicates.o removeduplicates_unittest.o gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $#
I think the error comes from this line but I'm not sure how to modify it:
CXXFLAGS += -I.. -std=c++17 -g -Wall -Wextra -pthread
The error I get (among others similar) is:
/RemoveDuplicates/test/../src/removeduplicates_unittest.cc:10: undefined reference to `LinkedList::LinkedList(std::initializer_list<int>)'
Anyone knows what am I doing wrong?
EDIT1: I followed the suggestion given by #Some programmer dude but now I have functions that are defined multiple times:
g++ -isystem ../../../GMOCK_ROOT/GTEST_DIR/googletest//include -I.. -std=c++17 -g -Wall -Wextra -pthread -lpthread removeduplicates.o removeduplicates_unittest.o ../../linkedlist.o gtest_main.a -o removeduplicates_unittest
../../linkedlist.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here
../../linkedlist.o: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.fini+0x0): first defined here
../../linkedlist.o:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.rodata.cst4+0x0): first defined here
../../linkedlist.o: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.data+0x0): first defined here
../../linkedlist.o: In function `data_start':
(.data+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o:(.data+0x0): first defined here
../../linkedlist.o: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.init+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
../../linkedlist.o:(.data+0x10): first defined here
/usr/bin/ld: error in ../../linkedlist.o(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
Makefile:82: recipe for target 'removeduplicates_unittest' failed
make: *** [removeduplicates_unittest] Error 1
At the end of your Makefile you have the dependencies for the test you're building. The last of those, where you list the test executable removeduplicates_unittest you need to list the object file $(BASE_DIR)/linkedlist.o as well:
# Added this dependency
# vvvvvvvvvvvvvvvvvvvvvvvv
removeduplicates_unittest : removeduplicates.o removeduplicates_unittest.o $(BASE_DIR)/linkedlist.o gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $#
That will lead to the linkedlist.o file being linked into the executable.
I have a somewhat complicated source directory, and have written a makefile to compile it:
├── include
│ ├── subinc
│ │ ├── test_y.h
│ │ └── test_z.h
│ ├── test_w.h
│ └── test_x.h
├── makefile
├── src
│ ├── test_w.cpp
│ └── test_x.cpp
├── src2
│ ├── test_y.cpp
│ └── test_z.cpp
└── test.cpp
The makefile as shown below is working. But, I'm a bit confused why. It doesn't seem to be using $(DEPS), since it gives paths like ./include/./include/subinc/test_y.h when I echo it in the rule. That's obvious because of the patsubst line, but changing that to patsubst %,%,$(INCLUDES) breaks it too... (maybe that's the root of the whole problem!)
But, something funky happens when I remove that constant from the dependency list of the rule %.o, so the rule is just %.o: $(SOURCES). Upon running make, it uses the first item in $(SOURCES) as the target for every call to g++ creating object files:
$ make
g++ -c -o test.o test.cpp -I./include -I./include/subinc
g++ -c -o src/test_x.o test.cpp -I./include -I./include/subinc
g++ -c -o src/test_w.o test.cpp -I./include -I./include/subinc
g++ -c -o src2/test_z.o test.cpp -I./include -I./include/subinc
g++ -c -o src2/test_y.o test.cpp -I./include -I./include/subinc
I figured that makes sense, because $< is used.
But why does this only print the first in the dependency list when I take the second constant (of header files -- some even with bad format) out of the list?
My thought is that somehow make is intelligently matching the .cpp files in the list to the corresponding .h files in the list, and then removing them from the list each time it runs the rule....
Thanks
Makefile (working version, maybe full of bad practices...)
INCDIR=./include
SRCDIR=./src
CXX=g++
CXXFLAGS=-I$(INCDIR) -I$(INCDIR)/subinc
INCLUDES=$(shell find . -name "*.h" -o -name "*.hpp")
DEPS = $(patsubst %,$(INCDIR)/%,$(INCLUDES))
EXE=testexe
SOURCES=$(wildcard *.cpp) $(wildcard **/*.cpp)
OBJ=$(SOURCES:.cpp=.o)
####RULES
%.o: $(SOURCES) $(DEPS)
$(CXX) -c -o $# $< $(CXXFLAGS)
$(EXE): $(OBJ)
g++ -o $# $^ $(CXXFLAGS)
rm $(OBJ)
EDIT
If you'd like an MCVE for this, each test_*.h defines an empty class like
class T*{
T*(); //defined in test_*.cpp to print "T* created"
~T*(); //defined in test_*.cpp to print "T* destroyed"
};
And the main test.cpp file just creates a pointer to each of the classes, and then deletes it.
There are many issues here. First:
SOURCES=$(wildcard *.cpp) $(wildcard **/*.cpp)
GNU make uses simple globbing, which does not understand **. This behaves the same as *. Since you only have one level of subdirectory this works for you but if you add another (sub-subdirectory) level, this won't match it.
Second, this is wrong:
DEPS = $(patsubst %,$(INCDIR)/%,$(INCLUDES))
As you point out this changes the dependency paths from the (correct) ./include/xy/z.h to the (incorrect) ./include/./include/xy/z.h. I'm not sure why you're trying to change anything at all here: why not just use the INCLUDES variable content directly? Using $(patsubst %,%,$(INCLUDES)) is a no-op; it has no effect.
Third, you should be using simple expansion (:=) for these types of assignments, so that they are not rerun every time the variable is used.
Next, this is wrong:
%.o: $(SOURCES) $(DEPS)
$(CXX) -c -o $# $< $(CXXFLAGS)
This will expand to something like this after SOURCES are resolved:
%.o: test.cpp src/test_w.cpp src/test_x.cpp src2/test_y.cpp src2/test_z.cpp ./include/include/subinc/test_y.h $(DEPS)
$(CXX) -c -o $# $< $(CXXFLAGS)
What this means is that every object file depends on all source files (and all $(DEPS)). So if any source or header file ever changes ALL the object files will be rebuilt. Clearly that's not what you want.
Also, the reason it always compiles the same file is that the recipe uses $<, which represents the first prerequisite, and the first prerequisite here is test.cpp, so that's what's always compiled.
When you create a pattern rule, (at least) the first source file should (almost always) be a pattern as well, so that it changes along with the target to build each object file (in this case).
So, you want your pattern rule to look like this:
%.o: %.cpp $(INCLUDES)
$(CXX) -c -o $# $< $(CXXFLAGS)
Of course this does mean that every object file depends on all header files, so if you change any header file all your object files are rebuilt. Maybe that's OK; if not you'll need to do something more advanced.
Lastly, you asked why it your makefile seems to work properly if you create bogus paths in the $(DEPS) variable. Here's why: because those paths don't exist, make decides that your pattern rule doesn't apply (since not all the prerequisites can be created) and so it ignores your pattern rule completely.
Once that happens, make's default pattern rule for how to build an object file takes over, and that default rule builds things for you properly. However, you may notice that if you modify any of the header files, make won't rebuild your object files (because it doesn't know about that prerequisite relationship).
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'm trying to learn how to write makefiles for my projects. Given that I'm using a text editor like sublime-text and the terminal.
I know how to write a makefile to compile a single file and it's relevant header files IF all files are in the same directory.
Imagine that we have a directory and some sub-directories which are structured like this:
the Headers contains all the .h files Objects is a directory to hold the .o files and Sources is a directory that has the source codes .cpp The Makefile is in the top level directory.
.
├── Headers
│ └── function.h
├── Makefile
├── Objects
│ └── main.o
└── Sources
├── function.cpp
└── main.cpp
I have tried to put together a Makefile by following the GNU make and the answer to this post.
At the moment my Makefile looks like this:
INC_DIR = Headers
SRC_DIR = Sources
OBJ_DIR = Objects
CXXFLAGS = -c -Wall -I.
CC = g++
SRCS = $(SRC_DIR)/*.cpp
OBJS = $(OBJ_DIR)/*.o
DEPS = $(INC_DIR)/*.h
output: $(OBJ_DIR)/main.o $(OBJ_DIR)/function.o
$(CC) $^ -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(DEPS)
$(CC) $(CXXFLAGS) $< -o $#
clean:
rm $(OBJ_DIR)/*.o output
Which will generate the following error when make is executed
g++ -c -Wall -I. Sources/function.cpp -o Objects/function.o
Sources/function.cpp:2:22: fatal error: function.h: No such file or directory
compilation terminated.
Makefile:30: recipe for target 'Objects/function.o' failed
make: *** [Objects/function.o] Error 1
I know that I'm doing something wrong but can't figure out what and how to fix it.
I'd appreciate any help and guidance.
Add Headers to your CXXFLAGS:
CXXFLAGS = -c -Wall -I. -IHeaders
# ^^^^^^^^^
Also you rather might want to generate header dependencies using GCC's -M<x> option family and include these into your Makefile.
Here's a pretty good explanation for the technique from GNU make's documentation:
4.14 Generating Prerequisites Automatically
more info can be also found here:
Makefile (Auto-Dependency Generation)
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)