I've got this directory structure:
.\src contains all the source code (.h and .cpp)
.\bin should have all the .o and .bin
. has Makefile
This is my current Makefile:
CFLAGS = -Wall -pedantic -g
CC = g++
EXEC = flrfile
SRC_DIR = src
BIN_DIR = bin
SOURCES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ := $(patsubst $(SRC_DIR)/%,%,$(SOURCES))
OBJ := $(patsubst %.cpp,%.o,$(OBJ))
OBJ := $(addprefix ../$(BIN_DIR)/,$(OBJ))
all: flrfile
../$(BIN_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
$(CC) $(CFLAGS) -c $(SRC_DIR)/%.cpp -o $#
$(EXEC): $(OBJ)
#mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) $(BIN_DIR)/$(OBJ) -o $(BIN_DIR)/$(EXEC)
.PHONY : clean
clean:
-rm -rf $(BIN_DIR)
When I run make I get this error:
g++ -Wall -pedantic -g -c src/%.cpp -o ../bin/FixedLengthFieldsRecord.o
g++: error: src/%.cpp: No such file or directory
g++: fatal error: no input files
compilation terminated.
make: *** [../bin/FixedLengthFieldsRecord.o] Error 4
Why is this? I have little to no understanding of Makefile to be honest...
The correct line for compiling should look like this:
$(BIN_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
$(CXX) -o $# -c $< $(CFLAGS)
Which means: "for every file matching the pattern "%.o" in $(BIN_DIR), compile it using the associated $(SRC_DIR)/%.cpp as argument (first dependency)
Additional comment: I suspect some missing dependencies: usually, a .c or cpp source file doesn't only depend on the corresponding header file, but might also include other headers from the project.
Related
The results for this topic strangely all did not work.
Finally I found a variant that is logical for me and works from the same order.
CC := g++
CFLAGS := -g -Wall
objects = test helloworld
all: $(objects)
$(objects): %: %.cpp
$(CC) $(CFLAGS) -o $# $<
I have tried a lot and probably fail to fully understand the line %: %.cpp.
My interpretation is: I take from every object the dependency which in turn is based on a file which is then traceable to a .cpp file.
My theory is test expects test.o and then test.cpp.
How do I rewrite this to directory?
I have already read some things with wildcards and a pattern replace.
Like
SRC_DIR := src
OBJ_DIR := obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
LDFLAGS := ...
CPPFLAGS := ...
CXXFLAGS := ...
main.exe: $(OBJ_FILES)
g++ $(LDFLAGS) -o $# $^
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
g++ $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
But the behavior was not the expected.
When 2 cpp files were in the folder the result was
g++ -o helloworld.o helloworld.cpp
g++ -o helloworld.o test.cpp
Or vice versa that only the cpp file was always the same.
I have the feeling to miss something extremely.
Update:
The make version is
GNU Make 4.3
Built for aarch64-unknown-linux-android
The Goal
What I would like to achieve is
src/
Test.cpp
Helloworld.cpp
Obj/
Make :
Obj/
Helloworld.out
Test.out
Try this:
CXX := g++
CXXFLAGS := -g -Wall
TARGETS=obj/test.out obj/helloworld.out
all:$(TARGETS)
obj/%.out:src/%.cpp
$(CXX) $(CXXFLAGS) -o $# $^
clean:
rm obj/*
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)
I am quite new to Make. I am attempting to write a Makefile to build a medium-sized Linux C/C++ application as below.
Making a simple Makefile by having all source files in one location and explicitly listing the source files works ok for me but I would like it to be more generic.
I have all my source files (C and C++) in the src folder in different subdirectories. I have header files inside an inc and inc/common folder, and then libs inside a lib folder.
The Makefile is run on the same level :
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
CXX := /bin/arm-linux-gnueabi-g++
EXE := $(BIN_DIR)/runfile
SRC := $(shell find $(SRC_DIR) -name *.cpp -or -name *.c)
OBJ := $(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(addsuffix .o,$(basename $(SRC))))
CPPFLAGS := -Iinc -Iinc/common -MMD -MP
CXXFLAGS := -std=c++11 -Wall
LDFLAGS := -Llib
LDLIBS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
I get lots of errors such as below when I run it, including problems opening dependency files. I think i'm almost there, but can't see my error exactly :
compilation terminated.
/bin/arm-linux-gnueabi-g++ -Iinc -Iinc/common -MMD -MP -std=c++11 -Wall -c -o obj/main.d.o
cc -Llib obj/main.d.o -o obj/main.d
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: error adding symbols: file in wrong format
I don't see how the output you show can be generated from the makefile you show here but anyway.
This is not right:
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
A pattern rule is a template that tells make "if you want to build a target that matches this pattern, then you can build it from the prerequisites that match this pattern".
Here you are listing ALL your source files as a prerequisite for EVERY object file. Suppose SRC is set to foo.c bar.c biz.c baz.c, then this expands to:
obj/%.o : foo.c bar.c biz.c baz.c | obj
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
You're telling make that every single .o target depends on ALL the source files, not just the one for that object file. Further, the automatic variable $< always expands to the first prerequisite, which here will always be foo.c. So, you're compiling foo.c four times, creating each of the object files.
The very first important rule when debugging makefiles is to look carefully at the output (command lines) that make prints. If they are not right, then your makefile is not right. If you do that you'll see all the compile lines are compiling the same source, like:
g++ -c foo.c -o obj/foo.o
g++ -c foo.c -o obj/bar.o
g++ -c foo.c -o obj/biz.o
g++ -c foo.c -o obj/baz.o
That clearly cannot work and it's why you get link errors trying to link together all these object files: they all have the same content.
You need this:
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
which tells make how to build an object file from a single source file.
You also need to create the actual output directory that the object file will go into. Just creating $(OBJ_DIR) is not enough, if the object file appears in a subdirectory.
I am trying to build a Makefile that will build a shared library with g++ and I find that it is not evaluating the OBJECTS variable. This is on Ubuntu 18.04 and all the files are in the same current directory. Secondly it is completely skipping the source file compilation and proceeding directly to evaluate the linking instruction. As a clarification I am using GNU Make 4.1
Here is what I get when I type make all
g++ -shared -pthread -o tree.so
g++: fatal error: no input files
compilation terminated.
Makefile:12: recipe for target 'tree.so' failed
make: *** [tree.so] Error 1
Here is my Makefile code
CC=g++
CFLAGS = -I/usr/local/include -Wall -std=c++17 -O3 -march=native -Ofast -ftree-vectorize
LIBS=-shared -pthread
SOURCES=$(wildcard *.cpp)
OBJECTS=$(wildcard *.o)
TARGET=tree.so
all:$(TARGET)
$(TARGET) : $(OBJECTS)
$(CC) $(LIBS) -o $(OBJECTS) $(TARGET)
$(OBJECTS):$(SOURCES)
$(CC) -c -g $(CFLAGS) $(SOURCES)
clean:
rm -f $(OBJECTS) $(TARGET)
If you only have the *.cpp files in your directories, then there is not any *.o yet, so your $(wildcard *.o) will expand to nothing.
What you want is to get the *.cpp files and compute the corresponding *.o files:
OBJECTS=$(patsubst %.cpp,%.o,$(SOURCES))
or equivalently:
OBJECTS=$(SOURCES:.cpp=.o)
Now, your compiler command is not the best one, because if you touch any source file all will be compiled. You can use instead:
$(OBJECTS): %.o: %.cpp
$(CC) -c -g $(CFLAGS) $< -o $#
So that only the touched files are actually rebuilt.
Also you have the linking command wrong. It should be:
$(TARGET) : $(OBJECTS)
$(CC) $(LIBS) -o $(TARGET) $(OBJECTS)
because the argument to the -o option is the output file, that is the target.
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 $#