need help creating a static c++ library using make - c++

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

Related

Newbie question about project structures and makefiles

I have a project with this structure
/project
Makefile
.gitignore
/bin
/src
file1.cpp
file2.cpp
file3.cpp
/include
definitions.h
/obj
I played around with the Makefile but I couldn't seem to get what I wanted, first I tried:
CC = g++
CFLAGS = -std=c++2b -Wno-parentheses -Iinclude/
All: build
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -c $^
build:
$(CC) $(CFLAGS) file1.o file2.o file3.o -o bin/main$(compiler)
but this returned the error
make: *** No rule to make target 'file1.o', needed by 'build'. Stop.
so I tried
CC = g++
CFLAGS = -std=c++2b -Wno-parentheses -Iinclude/
All: build
%.o: src/%.cpp
$(CC) $(CFLAGS) -c $^
build:
$(CC) $(CFLAGS) file1.o file2.o file3.o -o bin/main$(compiler)
and it compiled, putting all the .o files in the main directory, which is unideal. Furthermore, I can't run the binary file unless I specifically opened a terminal in the main directory and enter ./bin/maing++, opening a terminal in the bin folder and entering ./maing++ doesn't work, and so does running the .exe file manually, what did I do wrong? what I want is all the .o files made in obj/ and to be able to run the executable manually
UPDATE:
I changed the makefile to
CC = g++
CFLAGS = -std=c++2b -Wno-parentheses -Iinclude/ -Idoc/
SOURCES := $(wildcard src/*.cpp)
OBJECTS := $(patsubst src/%.cpp, obj/%.o, $(SOURCES))
All: build
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -c $< -o $#
build: $(OBJECTS)
$(CC) $(CFLAGS) $^ -o bin/is$(compiler)
this will put all obj files in the correct folder, its a simple program so running the executable would pop up a terminal window and print some text, I'm going to reiterate that I had to specifically open a terminal in the main directory and enter ./bin/maing++, opening a terminal in the bin folder and entering ./maing++ doesn't work, and so does running the .exe file manually

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: 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 $#

makefile: how to generate object files to upper directory

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.

How to build library and link it with sources with Make

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.