How to build library and link it with sources with Make - c++

I'm still quite new to make. I am trying to compile a project in which maketest.cpp and maketest.hpp rests on Users/wen/Projects/maketest with the Makefile itself. Problem is, I want to also compile and link the source files (.cc and .hh) in Users/wen/Projects/include/bigint.
# Macros
INCLUDE = -I/Users/wen/Projects/include/bigint
LIBS =
CC = g++
override FLAGS += -O2
HEADERS= $(wildcard *.hpp) $(wildcard Users/wen/Projects/include/bigint/*.hh)
# EXE Name
INSTALL = maketest
CC_FILES = %.cpp Users/wen/Projects/include/bigint/%.cc
OBJ_FILES = maketest.o $(wildcard Users/wen/Projects/include/bigint/*.o)
# Rules
$(INSTALL): $(OBJ_FILES)
$(CC) $(FLAGS) $^ -o $# $(LIBS)
%.o: $(CC_FILES) $(HEADERS)
$(CC) $(FLAGS) $(INCLUDE) -c $< -o $#
# Installation types
install: $(INSTALL)
release:
#echo "Re-run with parameter:"
#echo "FLAGS=-D_RELEASE"
debug:
#echo "Re-run with parameter:"
#echo "FLAGS=-D_DEBUG"
# Cleaning up
clean:
rm -f $(OBJ_FILES) $(INSTALL)
The code compiles maketest.cpp and links it, but not bigint.
What will be the right way to build and link the files from Users/wen/Projects/include/bigint? Many thanks!

I figured it out at the end, thank you Jay. The problem was I forgot a slash at the front of Users/wen/Projects/include/bigint, so it was not searching from root but instead the project folder. Now it works!
Try explicitly specifying one of the files from bigint in OBJ_FILES (perhaps "bigint.o" ?). I don't think your wildcard is getting what you want.

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)

Getting wrong file name while pattern matching in makefile

The directory structure of my project is something like this:
|-build
|-src
|-lib
|-libfile1.hpp
|-libfile1.cpp
|-libfile2.hpp
|-libfile2.cpp
|-libfile3.hpp
|-Makefile(lib)
|-examples
|-pingpong
|-main.cpp
|-ping.cpp
|-ping.hpp
|-Makefile(ping)
My goal is to have many examples in the examples folder which all use the libfiles but are independent of each other. Hence I wanted to use separate makefiles in each of the example folders to link to objects of libfiles.
To that goal, here's makefile(lib):
SRC = .
BLD = ../../build
SOURCE = $(wildcard $(SRC)/*.cpp)
INCLUDE = $(wildcard $(SRC)/*.hpp)
OBJECT = $(patsubst %,$(BLD)/%, $(notdir $(SOURCE:.cpp=.o)))
CC = g++
#flags went here, removed for brevity
all: $(OBJECT)
$(BLD)/%.o: $(SRC)/%.cpp $(SRC)/%.hpp
mkdir -p $(dir $#)
$(CC) -c $< -o $#
.PHONY: clean
clean:
$(RM) -r $(BLD)
And here's makefile(ping), where I try to build local objects and pass the library object build pattern to makefile(lib):
TARGET = mainpingpong.out
SRC = ../../actorlib
BLD = ../../../build
LIBSOURCE = $(wildcard $(SRC)/*.cpp)
LIBINCLUDE = $(wildcard $(SRC)/*.hpp)
LIBOBJECT = $(patsubst %,$(BLD)/%, $(notdir $(LIBSOURCE:.cpp=.o)))
LOCSOURCE = $(wildcard *.cpp)
LOCINCLUDE = $(wildcard *.hpp)
LOCOBJECT = $(patsubst %,$(BLD)/%, $(notdir $(LOCSOURCE:.cpp=.o)))
CC = g++
$(TARGET) : $(LIBOBJECT) $(LOCOBJECT)
$(CC)-o $# $^
$(LOCOBJECT): $(LOCSOURCE) $(LOCINCLUDE)
mkdir -p $(dir $#)
$(CC) -c $< -o $#
$(LIBOBJECT): $(LIBSOURCE) $(LIBINCLUDE)
cd $(SRC) && $(MAKE)
.PHONY: clean
clean :
cd $(SRC) && $(MAKE) clean
The error occurs in my local file matching, where it associates both main.o and ping.o with main.cpp (everything else works fine):
mkdir -p ../../../build/
g++ -c main.cpp -o ../../../build/main.o
mkdir -p ../../../build/
g++ -c main.cpp -o ../../../build/ping.o
How do I correctly do what I'm trying to do? Should I have a different rule or target? Or is there a correct way to get the filename from the variable?
I want the .o files to end up in the same place but the executable to stay in the examples directory.
The problem is here:
$(LOCOBJECT): $(LOCSOURCE) $(LOCINCLUDE)
mkdir -p $(dir $#)
$(CC) -c $< -o $#
LOCSOURCE contains main.cpp ping.cpp, so this rule makes both source files prerequisites of each target. Whether Make is trying to build main.o or ping.o, the prerequisite list is the same: main.cpp ping.cpp ping.hpp. So the automatic variable $< always expands to main.cpp (since that is the first filename in the list).
One way to solve this is by means of a static pattern rule:
$(LOCOBJECT): $(BLD)/%.o: %.cpp $(LOCINCLUDE)
mkdir -p $(dir $#)
$(CC) -c $< -o $#
This is still imperfect, in that all local header files are prerequisites of each object from a local source. If you have a paddle.cpp and you modify ping.hpp, Make will rebuild paddle.o, even if paddle.cpp does not depend on ping.hpp in any way. This is not a serious problem, it simply means that Make will do some extra work, rebuilding things when there is no reason to. If you want to solve it, you can either write the dependencies into the makefile by hand, or use a more sophisticated method like automatic dependency generation.

Makefile Confusion

I'm new to makefiles, but I finally managed to get one working for a project I'm working on. The original goal was to search the folder "Source" for any CPP files, then create an Object file in the folder Products/Objs. Instead, it finds the CPP files, but OBJECT_FILES is the same as SOURCE_FILES, and I'm not sure how it's working. It doesn't generate any .o files (that I could see), but still compiles successfully. Super confused but would love some help. Thanks!
##########################################
# Editable options #
##########################################
# Program Name
EXECUTABLE=net
# Compiler options
CC=g++
CFLAGS=
LDFLAGS=
# Folders
SRC=Source
OBJ=Products/Objs
#########################################################
# Do Not Touch This #
#########################################################
SOURCE_FILES := $(shell find $(SRC)/ -type f -name '*.cpp')
## This should not work
OBJECT_FILES := $(SOURCE_FILES: $(SRC)/%.cpp=%.o)
## Like at all --> It's the same as SOURCE_FILES
## But I guess???
build: $(EXECUTABLE)
## Deletes the executable (assumes small compile time)
clean:
#rm -r -f $(shell find $(SRC)/ -type f -name '*.o')
#rm $(EXECUTABLE)
.PHONY: build clean
$(EXECUTABLE): $(OBJECT_FILES)
#$(CC) $(LDFLAGS) -o $# $^
#echo "Build successful!"
$(OBJECTS_FILES): %.o : $(SRC)/%.cpp
#$(CC) $(CFLAGS) -o -c $# $^
Well first you have a typo; you create a variable OBJECT_FILES:
OBJECT_FILES := $(SOURCE_FILES: $(SRC)/%.cpp=%.o)
Also you shouldn't use spaces here (after the :). Then you use a variable named OBJECTS_FILES instead:
$(OBJECTS_FILES): %.o : $(SRC)/%.cpp
That variable is empty so this is essentially a no-op.
Your compiler invocation is wrong. The word after the -o option is the file the output should go to; yours is:
#$(CC) $(CFLAGS) -o -c $# $^
which means that the output of this command is going to the file -c. Then the input is an object file that doesn't exist... most likely you'll get an error. Also you only want to pass the source file to the compiler, not all the other prerequisites (headers etc.) This should be:
#$(CC) $(CFLAGS) -c -o $# $<

Error when executing make

I am trying to create a makefile for my project, but i seem to run into some errors, as I am testing new things. My file structure is as such:
~/main #root project folder
~/main/include #header files (mostly class headers)
~/main/src #source files
~/main/src/obj #object files
Makefile
(Makefile is in the root project folder)
Makefile:
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
CFLAGS=-Wall -std=c++11 -I$(IDIR)
$(OBJS): $(SRCS) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: $(OBJS)
gcc -o run $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(OBJS)
For testing purposes I have a single main.cpp in src folder and a random header file in include folder. The error I am getting when running the simple make command is the following:
make: *** No rule to make target `src/obj/%.o', needed by `all'. Stop.
EDIT : With the help of the guys below i came up with the solution
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
CFLAGS=-Wall -std=c++11 -I$(IDIR)
_DEPS = yo.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
_SRC = main.cpp
SRC = $(patsubst %,$(SDIR)/%,$(_SRC))
$(ODIR)/%.o: $(SRC) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: $(OBJ)
$(CC) -o run $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJS)
There is a difference in using % in your two cases. When you write:
$(ODIR)/%.o : $(SDIR)/%.cpp $(IDIR)/%.h
that will do pattern substitution, and create a bunch of rules like:
$(ODIR)/foo.o : $(SDIR)/foo.cpp $(SDIR)/foo.h
So it's fine there, although you should use the % explicitly there so it's clear to see what the rule is doing.
But when you use it here:
all : $(ODIR)/%.o
That is literally looking for the target $(ODIR)/%.o for which you don't have a rule. There's no substitution. And you don't have a rule to make that target - hence the error. What you meant to do was have all depend on all the actual objects, for which you'll want to use the wildcard function:
SOURCES = $(wildcard $(SDIR)/*.cpp)
OBJECTS = $(SOURCES:$(SDIR)/%.cpp=$(ODIR)/%.o)
all : $(OBJECTS)
gcc -o run $^ $(CFLAGS)
When you use
OBJS=$(ODIR)/%.o
The %.o part does not expand to anything meaningful. It just remains as the literal value %.o. Same problem exists for DEPS and SRCS as well.
You need to use the wildcard and patsub functions. Instead of
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
use
DEPS=$(wildcard $(IDIR)/*.h)
SRCS=$(wildcard $(SDIR)/*.cpp)
OBJS=$(patsub %.cpp,%.o,$(SRCS))

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