I am working on my first makefile, so far this much done.
BUILD = build
BIN = bin
OUTPUTNAME = game.out
INCLUDE = /internalLibraries/include
SRCFILES := $(wildcard src/*.cpp)
OBJFILES := $(patsubst %.cpp,%.o,$(SRCFILES))
OBJFILES := $(foreach dir,$(OBJFILES),$(subst src/,,$(dir)))
DIR := $(dir $(OBJFILES))
$(foreach d,$(DIR),$(shell mkdir -p $(BUILD)/$(d)))
$(shell mkdir -p $(BIN))
CC = g++
CFLAGS = -g -std=c++11
LIBS=-lsfml-graphics -lsfml-window -lsfml-system
G++_VER_LT48 := $(shell expr `$(CC) -dumpversion | cut -f1-2 -d.` \< 4.8 )
ifeq ("$(G++_VER_LT48)","1")
$(error old version of g++ not supported, upgrade to 4.8 or higher)
endif
default: $(BIN)/$(OUTPUTNAME)
$(info $(OBJFILES))
$(BIN)/$(OUTPUTNAME): $(BUILD)/$(OBJFILES)
$(CC) $(CFLAGS) -o $(BIN)/$(OUTPUTNAME) $(BUILD)/main.o $(BUILD)/game.o $(BUILD)/food.o $(BUILD)/snake.o $(LIBS)
$(BUILD)/%.o: %.cpp
$(CC) -c $(CFLAGS) $< -o $# -I $(INCLUDE)
the problem is, running this produces the output:
sidhin#DRAGONHEART:/mnt/c/Users/sidhi/Desktop/Projects/sfml-snake$ make
food.o game.o main.o snake.o
make: *** No rule to make target `build/food.o', needed by `bin/game.out'. Stop.
What is the problem, I cannot make it out.
$(BUILD)/%.o: %.cpp
With BUILD set to "build", this specifies the rule for building a target called "build/food.o" from "food.cpp".
The problem is, obviously, that "food.cpp" does not exist. The actual source file is "src/food.cpp", based on your declaration:
SRCFILES := $(wildcard src/*.cpp)
Related
I have a problem while compiling my code on Windows (it depends on a huge header only library exprtk), and in particular on msys and Cygwin64 shells. I am trying to compile my code using this makefile:
#====================================================
# OS detection
#====================================================
ifeq ($(OS),Windows_NT)
O_SYSTEM = Windows
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
O_SYSTEM = Linux
else ifeq ($(UNAME_S),Darwin)
O_SYSTEM = MacOS
endif
endif
#====================================================
# VARIABLES
#====================================================
ifeq ($(O_SYSTEM),$(filter $(O_SYSTEM),MacOS Linux))
TARGET_EXEC := examples
TEST_EXEC := tests
else
TARGET_EXEC := examples.exe
TEST_EXEC := tests.exe
endif
LIB := libarsenalgear.a
CC := g++
#====================================================
# FOLDERS
#====================================================
BUILD_DIR := bin
SRC_DIR := src
OBJ_DIR := obj
TEST_DIR := test
LIB_DIR := lib
ifeq ($(O_SYSTEM),Windows)
WIN_INCLUDE := C:\include
WIN_BOOST := C:\boost\include\boost-1_79
endif
#====================================================
# SOURCE FILES
#====================================================
ifeq ($(O_SYSTEM),$(filter $(O_SYSTEM),MacOS Linux))
SRC := $(shell find $(SRC_DIR) -name '*.cpp')
SRC_LIB := $(shell find $(SRC_DIR) -type f | grep -v 'examples.cpp')
TEST := $(shell find $(SRC_DIR) -type f | grep -v 'examples.cpp') $(shell find $(TEST_DIR) -name '*.cpp')
else
SRC := $(wildcard $(SRC_DIR)/*.cpp)
SRC_LIB := $(filter-out $(SRC_DIR)/examples.cpp, $(wildcard $(SRC_DIR)/*.cpp))
TEST := $(filter-out $(SRC_DIR)/examples.cpp, $(wildcard $(SRC_DIR)/*.cpp)) $(wildcard $(TEST_DIR)/*.cpp)
endif
#====================================================
# SOURCE OBJECTS
#====================================================
OBJ := $(SRC:%=$(OBJ_DIR)/%.o)
OBJ_LIB := $(SRC_LIB:%=$(OBJ_DIR)/%.o)
TEST_OBJ := $(TEST:%=$(OBJ_DIR)/%.o)
#====================================================
# DEPENDENCIES AND FLAGS
#====================================================
DEPS := $(OBJ:.o=.d)
ifeq ($(O_SYSTEM),Linux)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR))
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
else ifeq ($(O_SYSTEM),MacOS)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR)) `pcre-config --cflags`
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
else
INC_DIR := $(SRC_DIR)
INC_FLAGS := $(addprefix -I,$(INC_DIR)) $(addprefix -I,$(WIN_INCLUDE)) $(addprefix -I,$(WIN_BOOST))
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
endif
#====================================================
# ALIASES
#====================================================
.PHONY: clean all
#====================================================
# BUILDING
#====================================================
#Building all:
all: $(BUILD_DIR)/$(TARGET_EXEC) $(BUILD_DIR)/$(TEST_EXEC) $(LIB_DIR)/$(LIB)
examples: $(BUILD_DIR)/$(TARGET_EXEC) $(LIB_DIR)/$(LIB)
tests: $(BUILD_DIR)/$(TEST_EXEC) $(LIB_DIR)/$(LIB)
#Building main executable:
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJ)
# mkdir -p $(dir $#)
$(CC) $(OBJ) -o $# $(LDFLAGS)
#Building test executable:
$(BUILD_DIR)/$(TEST_EXEC): $(TEST_OBJ)
# mkdir -p $(dir $#)
$(CC) $(TEST_OBJ) -o $# $(LDFLAGS)
#Put object files into the object dir:
$(OBJ_DIR)/%.cpp.o: %.cpp
# mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
#Create a static library from object files and put it in the library dir:
$(LIB_DIR)/$(LIB): $(OBJ_LIB)
# mkdir -p $(dir $#)
ar rcs $(LIB_DIR)/$(LIB) $(OBJ_LIB)
#====================================================
# CLEAN
#====================================================
clean:
rm -r $(OBJ_DIR) $(BUILD_DIR) $(LIB_DIR)
#====================================================
# INCLUDE
#====================================================
-include $(DEPS)
Which should be a cross-platform makefile. It perfectly works on Ubuntu and MacOS, but on Windows (Cygwin64 and msys) I got the following error:
g++ -std=c++17 -g -Isrc -IC:\include -IC:\Boost\boost_1_79_0 -MMD -MP -c src/examples.cpp -o obj/src/examples.cpp.o
C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (136542)
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Assembler messages:
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Fatal error: can't write 571 bytes to section .text of obj/src/examples.cpp.o: 'File too big'
C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (136542)
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Fatal error: can't close obj/src/examples.cpp.o: File too big
make: *** [Makefile:91: obj/src/examples.cpp.o] Error 1
I am trying to run it on codeql-analysis GitHub workflow.
What do you think?
EDIT
I tried modifing:
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP -Wa,-mbig-obj
and the error is the same.
If I modify instead:
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP -flto -Wl,-allow-multiple-definition
LDFLAGS := -fuse-linker-plugin
I got same error but the number of "too many sections" is lower (43419):
g++ -std=c++17 -g -Isrc -IC:\include -IC:\boost\include\boost-1_79 -MMD -MP -flto -Wl,-allow-multiple-definition -c src/examples.cpp -o obj/src/examples.cpp.o
C:/MinGW/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (43419)
C:\cygwin64\tmp\ccU7XjRg.s: Assembler messages:
C:\cygwin64\tmp\ccU7XjRg.s: Fatal error: can't write 3975 bytes to section .gnu.lto_.inline.6d3ed2ee of obj/src/examples.cpp.o: 'File too big'
C:/MinGW/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (43419)
C:\cygwin64\tmp\ccU7XjRg.s: Fatal error: can't close obj/src/examples.cpp.o: File too big
make: *** [Makefile:108: obj/src/examples.cpp.o] Error 1
After some hours of tests I've finally found the problem: it was due to the ExprTk library. Since it is a huge header-only library, for a reason that is not clear to me, the Cygwin and MinGW compilers failed to correctly compile it. I solved by simply ignoring this library and all the functions I defined within its objects, by simply adding this preprocessor directive:
#if defined( __linux__ ) || defined( __APPLE__ )
// code which uses ExprTk objects
#endif
In this way the program compiles correctly for Ubuntu, MacOS and Windows, but in the Windows case it ignores the ExprTk objects.
I'm currently using MinGW64, G++, and a makefile to compile my c++ project on VSCode. I have two src directories src and src/vendor/imGui containing .cpp files that I compile. As of now, the makefile is able to compile both src folders. However, the .o files are outputted in their respective src folders. How can I make it so that every .o file generated gets sent to one specific folder/directory?
Current Makefile:
CXX = g++
CXXFLAGS := -std=c++17 -Wall -Wextra -g
LFLAGS += -LC:/mingw64/x86_64-w64-mingw32/bin
LFLAGS += -LC:/mingw64/x86_64-w64-mingw32/lib
OUTPUT := output
SRC := src
SRC += src/vendor/imGui
INCLUDE := include
LIB := lib
ifeq ($(OS),Windows_NT)
MAIN := main.exe
SOURCEDIRS := $(SRC)
INCLUDEDIRS := $(INCLUDE)
LIBDIRS := $(LIB)
FIXPATH = $(subst /,\,$1)
RM := del /q /f
MD := mkdir
else
MAIN := main
SOURCEDIRS := $(shell find $(SRC) -type d)
INCLUDEDIRS := $(shell find $(INCLUDE) -type d)
LIBDIRS := $(shell find $(LIB) -type d)
FIXPATH = $1
RM = rm -f
MD := mkdir -p
endif
INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%))
INCLUDES += -IC:/Users/kimda/Desktop/Projects/C++/Libraries/glm
INCLUDES += -IC:/mingw64/x86_64-w64-mingw32/include
INCLUDES += -IC:/Users/kimda/Desktop/Projects/C++/OpenGL/src/vendor/imGui
LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%))
LIBS += -lglew32
LIBS += -lopengl32
LIBS += -lglfw3
LIBS += -lgdi32
LIBS += -lglu32
SOURCES := $(wildcard $(patsubst %,%/*.cpp, $(SOURCEDIRS)))
OBJECTS := $(SOURCES:.cpp=.o)
OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN))
all: $(OUTPUT) $(MAIN)
#echo Building complete!
$(OUTPUT):
#$(MD) $(OUTPUT)
$(MAIN): $(OBJECTS)
#$(CXX) $(CXXFLAGS) $(INCLUDES) -o $(OUTPUTMAIN) $(OBJECTS) $(LFLAGS) $(LIBS)
.cpp.o:
#$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
.PHONY: clean
clean:
#$(RM) $(OUTPUTMAIN)
#$(RM) $(call FIXPATH,$(OBJECTS))
#echo Cleanup complete!
run: clean all
#./$(OUTPUTMAIN)
#echo Executing complete!
If I understand you correctly you want to send all object files to some 'build' directory.
I usually do something like this
BUILDDIR := build
[...]
OBJECTS := $(addprefix $(BUILDDIR)/,$(SOURCES:.cpp=.o))
[...]
and then change your
.cpp.o:
#$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
to
$(BUILDDIR)/%.o: %.cpp
#$(MD) $(dir $#)
#$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
I have this makefile:
IDIR = include
SDIR = src
ODIR = obj
BDIR = build
DEPS = $(shell find $(IDIR)/ -name '*.hpp')
SRCS = $(shell find $(SDIR)/ -name '*.cpp')
OBJS = $(patsubst %.cpp,$(ODIR)/%.o,$(notdir $(SRCS)))
BIN = main
CPPC = g++
CFLAGS = -Wall -c
all: dir $(BDIR)/$(BIN)
#echo Finished compiling $(BIN)
dir:
mkdir -p $(BDIR)
mkdir -p $(ODIR)
$(BDIR)/$(BIN): $(OBJS)
$(CPPC) $^ -o $#
$(OBJS): $(SRCS)
$(CPPC) $(CFLAGS) $^ -o $#
clean:
rm -rf $(BDIR) $(ODIR)
When I try to make, I get the following error:
mkdir -p build
mkdir -p obj
g++ -Wall -c src/sdk/tcp/Tcp.cpp src/sdk/socket/Socket.cpp src/Main.cpp -o obj/Tcp.o
g++: fatal error: cannot specify ‘-o’ with ‘-c’, ‘-S’ or ‘-E’ with multiple files
compilation terminated.
make: *** [Makefile:27: obj/Tcp.o] Error 1
My question is, is it possible to achieve what I am trying with this makefile? Going through each source file in $(SRCS), and compile the object file directly inside the obj directory with just the basename. An example of obj directory after a successful compilation:
obj
/ | \
/ | \
Tcp.o Socket.o Main.o
Your $(OBJS) rule is wrong.
There are (at least) two ways to do this.
You could write a pattern rule and use vpath to locate the sources:
vpath %.cpp $(dir $(SRCS))
$(OBJS): obj/%.o: %.cpp
$(CPPC) $(CFLAGS) $^ -o $#
Or you could generate a rule for each object:
define template
$(patsubst %,obj/%.o,$(notdir $(1))): $(addsuffix .cpp,$(1))
echo $(CPPC) $(CFLAGS) $$^ -o $$#
endef
$(foreach src,$(SRCS),$(eval $(call template,$(basename $(src)))))
I have the following makefile and would like to also use the GSL library. Do you know how I should proceed?
I cannot find the right way to make my code compile for now.
INCLDIR := include
OBJDIR := obj
SRCDIR := src
BINDIR := bin
CC := g++
VPATH :=
LDFLAGS := -L/home/path/gsl/lib
LIBRARY :=
CFLAGS := -g -Wall -I $(INCLDIR)
#Source and object files (automatic)
SRCS = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(subst $(SRCDIR)/,$(OBJDIR)/, $(subst .cpp,.o, $(SRCS)))
# Define here your main source files separated by spaces (without suffix!)
EXEC = main
#Phony = do not represent a file
#.PHONY: all
all : makedir $(EXEC)
# For multiple binaries
$(EXEC) : %: %.cpp $(OBJS)
$(CC) $(CFLAGS) -o $(BINDIR)/$# $^
$(OBJDIR)/%.o : $(SRCDIR)/%.cpp
$(CC) $(CFLAGS) -c -o $# $<
#Clean: delete every binaries and object files
.PHONY: clean
clean :
rm -rf $(OBJDIR)/*
rm -rf $(BINDIR)/*
#Building folders (-p : no error if folder do not exist)
.PHONY: makedir
makedir :
mkdir -p $(BINDIR)
mkdir -p $(OBJDIR)
Your LDFLAGS is missing -lgsl. Thus far you have only told the linker, where to search in addition to the default directories.
I am trying to build excutables for multiple files which are built in the same way. When i run make all the excutables should be generated. I am getting error at prerequisites part of the macro.
CXX = g++
CXX_FLAGS = -g -Wall
LD_FLAGS =
INC_DIR = -I/my/path/include
SRC_DIR = .
LIB_DIR = -L$/my/path/lib
OBJ_DIR = obj
EXE_DIR = exe
SRCS := $(foreach s_dir, $(SRC_DIR), $(wildcard $(s_dir)/*.cpp))
OBJS := $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRCS))
EXES := $(patsubst $(SRC_DIR)/%.cpp, $(EXE_DIR)/%.out, $(SRCS))
all: create_directories create_objects create_exes
create_directories:
#echo "Creating $(OBJ_DIR) and $(EXE_DIR)..."
#mkdir -p obj
#mkdir -p exe
create_objects:
$(foreach b_dir, $(OBJ_DIR), $(eval $(call build-objects, $(b_dir))))
create_exes:
$(foreach ot, $(EXE_DIR), $(eval $(call build-exes, $(ot))))
define build-objects
$1/%.o: %.cpp
$(CXX) $(CXX_FLAGS) $(INC_DIR) -MMD -MP -c $$< -o $$#
endef
define build-exes
$1/%.out:obj/%.o
$(CXX) $(LD_FLAGS) -o $# $(OBJS) $(LIB_DIR) -lmylib
endef
Is this a right way to do generate multiple exes or any other simple way?
If I'm reading this makefile right, then it's much too complicated.
First let's have a rule to build object files:
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(CXX_FLAGS) $(INC_DIR) -MMD -MP -c $< -o $#
Now if we're not sure about the existence of obj/, we could add a rule to create it, but for the moment let's just put in a failsafe (we'll come back to this later):
$(OBJ_DIR)/%.o: %.cpp
#mkdir -p $(OBJ_DIR)
$(CXX) $(CXX_FLAGS) $(INC_DIR) -MMD -MP -c $< -o $#
And a similar rule to build the executables:
$(EXE_DIR)/%.out: $(OBJ_DIR)/%.o
#mkdir -p $(EXE_DIR)
$(CXX) $(LD_FLAGS) -o $# $^ $(LIB_DIR) -lmylib
And finally (at the top) some variables, the lists of files, and the all rule:
CXX = g++
CXX_FLAGS = -g -Wall
LD_FLAGS =
INC_DIR = -I/my/path/include
SRC_DIR = .
LIB_DIR = -L$/my/path/lib
OBJ_DIR = obj
EXE_DIR = exe
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
EXES := $(patsubst $(SRC_DIR)/%.cpp, $(EXE_DIR)/%.out, $(SRCS))
# Let the object files take care of themselves
all: $(EXES)
That's all you need. Once this is working perfectly, we can discuss refinements like rules for building directories.