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.
Related
There are quite some posts about this error, but I was not able to solve it, I hope you can come up with the solution. I am on a Ubuntu machine.
~/graphmap2$
In this folder, I downloaded zlib. You can see the picture
After some Googling, I also noticed that there is no -lz parameter, so I also added that manually as you can see below
However, I still get the same error as when none of the above were done.
Might it be that the path to zlib is not clear for the compiler? However, I installed it in this same folder.
The make file looks like the below:
BIN = ./bin/graphmap2
BIN_DEBUG = ./bin/graphmap-debug
BIN_LINUX = ./bin/Linux-x64/graphmap2
BIN_MAC = ./bin/Mac/graphmap
OBJ_TESTING = ./obj_test
OBJ_TESTING_EXT = ./obj_testext
OBJ_DEBUG = ./obj_debug
OBJ_LINUX = ./obj_linux
OBJ_EXTCIGAR = ./obj_extcigar
OBJ_MAC = ./obj_mac
SOURCE = src
CODEBASE = codebase
# This finds all 'src' folders at maximum depth 2 (level one inside each submodule's folder).
CODEBASE_SRC_FOLDERS = $(shell find $(CODEBASE) -maxdepth 2 -type d -name "src" -exec echo "-I"{} \;)
# $(shell find $(CODEBASE) -maxdepth 3 -type d -name "libs" -exec echo "-I"{} \;)
# $(shell find $(CODEBASE) -maxdepth 2 -type d -name "src" -exec echo "-I"{}"/*/" \;)
# ? allows override by user using env var
GCC ?= g++
# define variables for GCC version check here
GCC_MAJOR_VERSION_GE_4 := $(shell expr `$(GCC) -dumpversion | cut -f1 -d.` \>= 4)
GCC_MINOR_VERSION_GE_7 := $(shell expr `$(GCC) -dumpversion | cut -f2 -d.` \>= 7)
GCC_MAC ?= g++
# CPP_FILES := $(wildcard $(SOURCE)/*/*.cpp) $(wildcard $(SOURCE)/*.cpp) $(wildcard $(SOURCE)/libs/*/*.cpp)
# CC_FILES := $(wildcard $(SOURCE)/*/*.cc) $(wildcard $(SOURCE)/*.cc) $(wildcard $(SOURCE)/libs/*/*.cc)
# H_FILES := $(wildcard $(SOURCE)/*/*.h) $(wildcard $(SOURCE)/*.h) $(wildcard $(SOURCE)/libs/*/*.h)
CPP_FILES := $(wildcard $(CODEBASE)/*/src/*.cpp) $(wildcard $(CODEBASE)/*/src/libs/*/*.cpp) $(wildcard $(CODEBASE)/*/src/*/*.cpp) $(wildcard $(SOURCE)/*/*.cpp) $(wildcard $(SOURCE)/*.cpp) $(wildcard $(SOURCE)/libs/*/*.cpp)
CC_FILES := $(wildcard $(CODEBASE)/*/src/*.cc) $(wildcard $(CODEBASE)/*/src/libs/*/*.cc) $(wildcard $(CODEBASE)/*/src/*/*.cc) $(wildcard $(SOURCE)/*/*.cc) $(wildcard $(SOURCE)/*.cc) $(wildcard $(SOURCE)/libs/*/*.cc)
H_FILES := $(wildcard $(CODEBASE)/*/src/*.h) $(wildcard $(CODEBASE)/*/src/libs/*/*.h) $(wildcard $(CODEBASE)/*/src/*/*.h) $(wildcard $(SOURCE)/*/*.h) $(wildcard $(SOURCE)/*.h) $(wildcard $(CODEBASE)/*/src/*.hpp) $(wildcard $(CODEBASE)/*$
OBJ_FILES := $(CPP_FILES:.cpp=.o) $(CC_FILES:.cc=.o)
OBJ_FILES_FOLDER_TESTING := $(addprefix $(OBJ_TESTING)/,$(OBJ_FILES))
OBJ_FILES_FOLDER_TESTING_EXT := $(addprefix $(OBJ_TESTING_EXT)/,$(OBJ_FILES))
OBJ_FILES_FOLDER_DEBUG := $(addprefix $(OBJ_DEBUG)/,$(OBJ_FILES))
OBJ_FILES_FOLDER_LINUX := $(addprefix $(OBJ_LINUX)/,$(OBJ_FILES))
OBJ_FILES_FOLDER_EXTCIGAR := $(addprefix $(OBJ_EXTCIGAR)/,$(OBJ_FILES))
OBJ_FILES_FOLDER_MAC := $(addprefix $(OBJ_MAC)/,$(OBJ_FILES))
LIB_DIRS = -L"/usr/local/lib"
CC_LIBS = -static-libgcc -static-libstdc++ -D__cplusplus=201103L
# INCLUDE = -I"./src/" -I"/usr/include/" -I"libs/libdivsufsort-2.0.1/build/include" -I"libs/seqan-library-1.4.2/include"
# INCLUDE = -I"./src/" -I"/usr/include/" -I"src/libs/seqan-library-1.4.2/include"
INCLUDE = -I"./src/" -I"/usr/include/" -I"$(CODEBASE)/seqlib/src/libs/seqan-library-2.0.1/include" -I"$(CODEBASE)/seqlib/src/libs/libdivsufsort-2.0.1-64bit/" $(CODEBASE_SRC_FOLDERS)
CC_FLAGS_DEBUG = -O3 -g -rdynamic -c -fmessage-length=0 -ffreestanding -fopenmp -m64 -std=c++11 -Werror=return-type -pthread -march=native -lz
CC_FLAGS_RELEASE = -DRELEASE_VERSION -g -O3 -fdata-sections -ffunction-sections -c -fmessage-length=0 -ffreestanding -fopenmp -m64 -std=c++11 -Werror=return-type -pthread -lz # -march=native
CC_FLAGS_EXTCIGAR = -DRELEASE_VERSION -DUSE_EXTENDED_CIGAR_FORMAT -g -O3 -fdata-sections -ffunction-sections -c -fmessage-length=0 -ffreestanding -fopenmp -m64 -std=c++11 -Werror=return-type -pthread -march=native -lz
CC_FLAGS_NOT_RELEASE = -g -O3 -fdata-sections -ffunction-sections -c -fmessage-length=0 -ffreestanding -fopenmp -m64 -std=c++11 -Werror=return-type -Wuninitialized -pthread -march=native -lz
CC_FLAGS_NOT_RELEASE_EXT = -g -O3 -DUSE_EXTENDED_CIGAR_FORMAT -fdata-sections -ffunction-sections -c -fmessage-length=0 -ffreestanding -fopenmp -m64 -std=c++11 -Werror=return-type -Wuninitialized -pthread -march=native -lz LD_FLAGS = -static-libgcc -static-libstdc++ -m64 -ffreestanding -lz
# LD_LIBS = -lpthread -lgomp -lm -lz -ldivsufsort64
LD_LIBS = -lpthread -lgomp -lm -lz
all: gcc_version_check linux
install: /usr/bin/graphmap
/usr/bin/graphmap: bin/Linux-x64/graphmap
cp bin/Linux-x64/graphmap /usr/bin/graphmap
modules:
git submodule update --init --recursive
# git submodule foreach git pull origin master
testing: $(OBJ_FILES_FOLDER_TESTING)
mkdir -p $(dir $(BIN))
$(GCC) $(LD_FLAGS) $(LIB_DIRS) -o $(BIN) $(OBJ_FILES_FOLDER_TESTING) $(LD_LIBS)
obj_test/%.o: %.cc $(H_FILES)
mkdir -p $(dir $#)
$(GCC) $(CC_LIBS) $(INCLUDE) $(CC_FLAGS_NOT_RELEASE) -o $# $<
obj_test/%.o: %.cpp $(H_FILES)
mkdir -p $(dir $#)
$(GCC) $(CC_LIBS) $(INCLUDE) $(CC_FLAGS_NOT_RELEASE) -o $# $<
testingext: $(OBJ_FILES_FOLDER_TESTING_EXT)
mkdir -p $(dir $(BIN)) $(GCC) $(LD_FLAGS) $(LIB_DIRS) -o $(BIN) $(OBJ_FILES_FOLDER_TESTING_EXT) $(LD_LIBS)
obj_testext/%.o: %.cc $(H_FILES)
mkdir -p $(dir $#)
$(GCC) $(CC_LIBS) $(INCLUDE) $(CC_FLAGS_NOT_RELEASE_EXT) -o $# $<
obj_testext/%.o: %.cpp $(H_FILES)
mkdir -p $(dir $#)
$(GCC) $(CC_LIBS) $(INCLUDE) $(CC_FLAGS_NOT_RELEASE_EXT) -o $# $<
gcc_version_check:
ifneq ($(GCC_MAJOR_VERSION_GE_4), 1)
$(warning "*** WARNING $(GCC) major version <4 ***")
endif
ifneq ($(GCC_MINOR_VERSION_GE_7), 1)
$(warning "*** WARNING $(GCC) minor version <7 ***")
endif
Any ideas?
Seems compiler is not able to find the file in the includes path you mentioned.
First check if zconf.h file is available on your machine and get that location. If the file is available then just give the path of the file to the compiler using -I option.
INCLUDE = -I"<YourPath>" -I"./src/" -I"/usr/include/" -I"$(CODEBASE)/seqlib/src/libs/seqan-library-2.0.1/include" -I"$(CODEBASE)/seqlib/src/libs/libdivsufsort-2.0.1-64bit/" $(CODEBASE_SRC_FOLDERS)
If the file itself is missing, then you would need to install it
sudo apt-get install libz-dev
Based on information shared by #Knud Larsen :
The Ubuntu package name is zlib1g-dev from where you can get the missing file. /usr/include/zconf.h
https://packages.ubuntu.com/focal-updates/amd64/zlib1g-dev/filelist
Just for future reference, what Altaf mentioned is correct. More than that, you can continue adding things that are not in the appropriate place exactly like this. Locate them and then add them manually.
If the makefile is not very big this will eventually be ok. It doesn't scale on the general case however, and maybe changing the makefile in a more radical way should be done.
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 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)
I'm using CODEO (Eclipse + overlay) to build an app for the ELinOS RTOS.
Thing is, I lose the ability to auto-generate the Makefile using eclipse CDT and I have a generic Makefile alreayd generated.
Instead of typing this huge Makefile (Lots and lots of include and sources directories), I tried things with addprefix patsubst and some wildcard but that didn't work out, mainly because I suck with generic makefile !
Regarding libraries, only a few are used, so I'll write them by hand.
Here is how my code is structured.
Top directory
|
---> common ---> inc/
| src/
---> pack_AAA ---> comp_AAA ---> inc/
| | src/
| ----> comp_AAB ---> inc/
| src/
---> comp_BBB ---> inc/
| src/
---> main.cpp
I'd like to enumerate only the top folders (common, pack_AAA, comp_BBB and so on, mostly because not every TOP folder has to be compiled, my Makefile is in one of these top folder).
Below there is a variable amount of subdirectories. Leafs are ALWAYS inc/ (.hpp files) and src/ (as you might guess, .cpp files) folders.
Moreover, the amount of TOP folders won't change, so I mind declaring them, but subfolders will.
Objects files can be anywhere they want (separate top build/ directory, within src/ ...) as long as the resulting executable, let's call it HUGE_PROJECT is in the top directory
Thanks in advance !
SOKS
Here is the generated makefile that I have to start with
-include makefile.init
RM := rm -rf
PROG = HUGE_PROJECT_EXECUTABLE
MODULES := common comp_AAA comp_BBB pack_AAA pack_BBB pack_CCC
SRC_DIRS := $(addprefix ../../,$(MODULES))
#BUILD_DIR := $(addprefix ../../build/,$(MODULES))
#Original non-recursive & working example
OBJS = $(patsubst %.cpp,%.o,$(wildcard ./src/*.cpp))
DEPS = $(patsubst %.cpp,%.d,$(wildcard ./src/*.cpp))
#bad attempt
#SRCS := $(foreach sdir,$(SRC_DIRS),$(wildcard $(sdir)/*.cpp))
#OBJS := $(patsubst %.cpp,%.o,$(SRCS))
#INCLUDES := $(addprefix -I,$(SRC_DIR))
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(DEPS)),)
-include $(DEPS)
endif
endif
-include makefile.defs
# All Target
all: $(PROG).tgz
$(PROG).tgz: $(PROG).mkefs $(PROG)
#echo 'Building file: $#'
#echo 'Invoking: Embeddable file system generator'
mkefs -a -s -o"$#" -f"$<"
#echo 'Finished building: $#'
#echo ' '
$(PROG): $(OBJS) $(USER_OBJS)
#echo 'Building target: $#'
#echo 'Invoking: ELinOS C/C++ Linker'
$(CXX) -o "$(PROG)" $(SRCS) $(USER_OBJS) $(LIBS)
#echo 'Finished building target: $#'
#echo ' '
clean:
-$(RM) $(OBJS) $(DEPS) $(PROG) $(PROG).tgz
-#echo ' '
./src/%.o: ./src/%.cpp
#echo 'Building file: $<'
#echo 'Invoking: ELinOS C/C++ Compiler'
$(CXX) -I./include -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -o "$#" "$<"
#echo 'Finished building: $<'
#echo ' '
.PHONY: all clean dependents
.SECONDARY:
-include makefile.targets
Here is the Makefile I ended up with.
I had to hide components name.
#Executables
RM := rm -rf
CXX=YOUR_CXX_COMPILER
CC=YOUR_CC_COMPILER
PROG=YOUR_PROGRAM
#Root directory of your program (all files should be in it)
ROOT_DIR := ../../
#####################################
########################################
# Define here all directories #
# containing src/ and inc/ folders #
########################################
#pack_AAA folders
#Modules containing both src/ and inc/.
AAA_MODULES := moduleA moduleB
#Modules with an include folder only + module with both
AAA_DIRS_INC := moduleD moduleEF $(AAA_MODULES)
#pack_BBB modules list
BBB_MODULES := comp_A comp_B comp_C comp_B/comp_D comp_B/comp_E
MMM_MODULES := comp_F comp_G comp_H
PPP_MODULES := . I
CCC_MODULES := J comp_K comp_L \
comp_L/comp_M \
$(addprefix pack_BBB/,$(BBB_MODULES)) \
$(addprefix pack_MMM/,$(MMM_MODULES)) \
$(addprefix comp_PPP/,$(PPP_MODULES))
#pack_DDD
DDD_MODULES := M comp_N comp_N/comp_O
#comp_EEE
EEE_MODULES := . P Q
OTHER_MODULES := R S comp_T
#All folders containing src/ subdir
SRC_MODULES := $(OTHER_MODULES) \
$(addprefix comp_EEE/,$(EEE_MODULES)) \
$(addprefix pack_DDD/,$(DDD_MODULES)) \
$(addprefix pack_AAA/,$(AAA_MODULES)) \
$(addprefix pack_CCC/, $(CCC_MODULES))
#All folders containing inc/ subdir
INCLUDE_MODULES := $(OTHER_MODULES) \
$(addprefix comp_EEE/,$(EEE_MODULES)) \
$(addprefix pack_DDD/,$(DDD_MODULES)) \
$(addprefix pack_AAA/,$(AAA_DIRS_INC)) \
$(addprefix pack_CCC/, $(CCC_MODULES))
#####################################
#WRAPPERS
ROOT_DIR_WRAPPERS := $(ROOT_DIR)../WRAPPERS/
LIST_WRAPPERS := WA WB WC WD
SRC_WRAPPERS := $(addprefix pack_Wrappers/csc_Wrapper,$(LIST_WRAPPERS))
#DRIVERS
LIST_DRIVERS := DA DB DC DD
DIR_DRIVERS := $(addprefix pack_Drivers/csc_Driver,$(LIST_DRIVERS))
SRC_DIRS_WRAPPERS := $(addsuffix /src,$(SRC_WRAPPERS))
INCLUDE_DIRS_WRAPPERS := $(addsuffix /inc,$(SRC_WRAPPERS)) \
$(addsuffix /inc,$(DIR_DRIVERS)) \
Common
#####################################
#LIB_1 INCLUDE
ROOT_DIR_LIB_1 := $(ROOT_DIR)../../ObjetsCompiles/LIB_1/
INCLUDE_DIRS_LIB_1 := dir1 dir2 dir3
#####################################
#LIB_2 INCLUDE
ROOT_DIR_LIB_2 := $(ROOT_DIR)../../ObjetsCompiles/LIB_2/include
INCLUDE_DIRS_LIB_2 := . dir1 dir2 dir3/subdir dir4
#####################################
#Add "." to find main.cpp
SRC_DIRS := $(addsuffix /src,$(SRC_MODULES)) .
INCLUDE_DIRS_SRC:= $(addsuffix /inc,$(INCLUDE_MODULES)) pack_ZZZ/comp_Without_Inc_Folder
#All include dirs, LIB_1 + LIB_2
INCLUDE_DIRS := $(addprefix -I$(ROOT_DIR),$(INCLUDE_DIRS_SRC)) \
$(addprefix -I$(ROOT_DIR_LIB_1),$(INCLUDE_DIRS_LIB_1)) \
$(addprefix -I$(ROOT_DIR_LIB_2),$(INCLUDE_DIRS_LIB_2))
INCLUDE_DIRS_CC := $(addprefix -I$(ROOT_DIR_WRAPPERS),$(INCLUDE_DIRS_WRAPPERS)) \
$(addprefix -I$(ROOT_DIR_LIB_2),$(INCLUDE_DIRS_LIB_2))
#All objects (all .cpp & all .c)
OBJS := $(foreach dir,$(SRC_DIRS), \
$(patsubst %.cpp,%.o,$(wildcard $(ROOT_DIR)$(dir)/*.cpp))) \
$(foreach dirs,$(SRC_DIRS_WRAPPERS), \
$(patsubst %.c,%.o,$(wildcard $(ROOT_DIR_WRAPPERS)$(dirs)/*.c)))
#All dependencies (same list as OBJS)
DEPS := $(foreach dir,$(SRC_DIRS), \
$(patsubst %.cpp,%.d,$(wildcard $(ROOT_DIR)$(dir)/*.cpp))) \
$(foreach dirs,$(SRC_DIRS_WRAPPERS), \
$(patsubst %.c,%.d,$(wildcard $(ROOT_DIR_WRAPPERS)$(dirs)/*.c)))
#Exclude files from build
#Win32 socket files + some misc
EXCLUDED_FILES_LIST := pack_AAA/comp_BBB/src/SocketWindowsOnLinuxForExample.cpp \
pack_BBB/comp_CCC/src/SomeOtherThingForWindows.cpp
EXCLUDED_FILES_PATH := $(addprefix $(ROOT_DIR),$(EXCLUDED_FILES_LIST))
#Remove some objects (compilation is done, but no link)
EXCLUDED_OBJS := $(patsubst %.cpp,%.o,$(EXCLUDED_FILES_PATH))
EXCLUDED_DEPS := $(patsubst %.cpp,%.d,$(EXCLUDED_FILES_PATH))
#Update OBJS & DEPS list with excluded files
OBJS := $(filter-out $(EXCLUDED_OBJS),$(OBJS))
DEPS := $(filter-out $(EXCLUDED_DEPS),$(DEPS))
#FLAGS for DEBUG and RELEASE compilation
CPPFLAGS := -D__CPPFLAG1__ -D__CPPFLAG2__
CFLAGS_D := -O0 -g2 -Wall -c -fmessage-length=0
CXXFLAGS_D := -O0 -g2 -Wall -c -fmessage-length=0 -m32 -mcpu=powerpc -Winline
CFLAGS_R := -O2 -g0 -Wall -c -fmessage-length=0
CXXFLAGS_R := -O2 -g0 -Wall -c -fmessage-length=0 -m32 -mcpu=powerpc -Winline
# L
LD_PATH := -L../../path_library_1 -L../../path_library_2
LD_LIBS := -lpthread_rt -lROHC -lpthread -lnative -lrtdm -lrt
MAP := $(PROG).map
# -s (to strip)
LD_FLAGS_D := -Wl,--wrap,pthread_create -Wl,--wrap,pthread_kill -Wl,-Map,$(MAP)
LD_FLAGS_R := -s -Wl,--wrap,pthread_create -Wl,--wrap,pthread_kill -Wl,-Map,$(MAP)
##################################################
#TARGETS
default: release
#Debug flags (-00 + -g2)
debug: CFLAGS := $(CFLAGS_D)
debug: CXXFLAGS := $(CXXFLAGS_D)
debug: LD_FLAGS := $(LD_FLAGS_D)
debug: all
#Release flags (-s + -02 + -g0)
release: CFLAGS := $(CFLAGS_R)
release: CXXFLAGS := $(CXXFLAGS_R)
release: LD_FLAGS := $(LD_FLAGS_R)
release: all
all: $(PROG)
# Tool invocations
$(PROG): $(OBJS)
#echo 'Building target: $#'
#$(CXX) $(LD_FLAGS) $(LD_PATH) -o "$(PROG)" $(OBJS) $(LD_LIBS)
#echo 'Finished building target: $#'
#echo ' '
# CXX compiler used by most of the code
%.o: %.cpp
#echo 'Building file: $<'
#$(CXX) $(CPPFLAGS) $(INCLUDE_DIRS) $(CXXFLAGS) -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -o "$#" "$<"
# CC compiler used by Wrappers only
%.o: %.c
#echo 'Building file: $<'
#$(CC) $(INCLUDE_DIRS_CC) $(CFLAGS) -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -o "$#" "$<"
# Other Targets
clean:
-$(RM) $(OBJS) $(DEPS) $(PROG) $(MAP)
-#echo ' '
.PHONY: all clean dependents
.SECONDARY:
I am coding to the NRF51822 bluetooth chip, in Eclipse with GCC and a makefile that I maintain myself.
My problem is that every time I press build, it will compile everything, which is beginning to take quite some time. I am not that experienced in creating and maintaining make-files, so I have no idea where to start in order to get it to build incremtal instead?
My makefile is composed like this (I know there's a lot, and I haven't created this myself - found it in a tutorial, so I don't know what's relevant and what's not :-) ):
PROJECT_NAME := my_project
export OUTPUT_FILENAME
#MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_NAME := $(MAKEFILE_LIST)
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) )
TEMPLATE_PATH = nrf51_sdk/toolchain/gcc
ifeq ($(OS),Windows_NT)
include $(TEMPLATE_PATH)/Makefile.windows
else
include $(TEMPLATE_PATH)/Makefile.posix
endif
MK := mkdir
RM := rm -rf
#echo suspend
ifeq ("$(VERBOSE)","1")
NO_ECHO :=
else
NO_ECHO := #
endif
# Toolchain commands
CC := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-gcc"
AS := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-as"
AR := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ar" -r
LD := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ld"
NM := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-nm"
OBJDUMP := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objdump"
OBJCOPY := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objcopy"
SIZE := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-size"
#function for removing duplicates in a list
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))
#source common to all targets
C_SOURCE_FILES += \
main.c \
file1.c \
file2.c \
file3.c \
file4.c \
#assembly files common to all targets
ASM_SOURCE_FILES = nrf51_sdk/toolchain/gcc/gcc_startup_nrf51.s
#includes common to all targets
INC_PATHS = -I Dir1/
INC_PATHS = -I Dir2
INC_PATHS += -I Dir3
INC_PATHS += -I Dir4
OBJECT_DIRECTORY = _build
LISTING_DIRECTORY =$(OBJECT_DIRECTORY)
OUTPUT_BINARY_DIRECTORY =$(OBJECT_DIRECTORY)
# Sorting removes duplicates
BUILD_DIRECTORIES := $(sort $(OBJECT_DIRECTORY) $(OUTPUT_BINARY_DIRECTORY) $(LISTING_DIRECTORY) )
#flags common to all targets
CFLAGS = -DSOFTDEVICE_PRESENT
CFLAGS += -DNRF51
CFLAGS += -DS110
CFLAGS += -DBOARD_PCA10028
CFLAGS += -DBLE_STACK_SUPPORT_REQD
CFLAGS += -mcpu=cortex-m0
CFLAGS += -mthumb -mabi=aapcs --std=gnu99
CFLAGS += -Wall -O0 -g3
CFLAGS += -mfloat-abi=soft
# keep every function in separate section. This will allow linker to dump unused functions
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
#CFLAGS += -flto -fno-builtin
# keep every function in separate section. This will allow linker to dump unused functions
LDFLAGS += -Xlinker -Map=$(LISTING_DIRECTORY)/$(OUTPUT_FILENAME).map
LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
LDFLAGS += -mcpu=cortex-m0
# let linker to dump unused sections
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs -lc -lnosys
# Assembler flags
ASMFLAGS += -x assembler-with-cpp
ASMFLAGS += -DSOFTDEVICE_PRESENT
ASMFLAGS += -DNRF51
ASMFLAGS += -DS110
ASMFLAGS += -DBOARD_PCA10028
ASMFLAGS += -DBLE_STACK_SUPPORT_REQD
#default target - first one defined
default: clean nrf51422_xxac_s110
#building all targets
all: clean
$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e cleanobj
$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e nrf51422_xxac_s110
#target for printing all targets
help:
#echo following targets are available:
#echo nrf51422_xxac_s110
#echo flash_softdevice
C_SOURCE_FILE_NAMES = $(notdir $(C_SOURCE_FILES))
C_PATHS = $(call remduplicates, $(dir $(C_SOURCE_FILES) ) )
C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILE_NAMES:.c=.o) )
ASM_SOURCE_FILE_NAMES = $(notdir $(ASM_SOURCE_FILES))
ASM_PATHS = $(call remduplicates, $(dir $(ASM_SOURCE_FILES) ))
ASM_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(ASM_SOURCE_FILE_NAMES:.s=.o) )
vpath %.c $(C_PATHS)
vpath %.s $(ASM_PATHS)
OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS)
nrf51422_xxac_s110: OUTPUT_FILENAME := nrf51422_xxac_s110
nrf51422_xxac_s110: LINKER_SCRIPT=ble_app_hrs_gcc_nrf51.ld
nrf51422_xxac_s110: $(BUILD_DIRECTORIES) $(OBJECTS)
#echo Linking target: $(OUTPUT_FILENAME).out
$(NO_ECHO)$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e finalize
## Create build directories
$(BUILD_DIRECTORIES):
echo $(MAKEFILE_NAME)
$(MK) $#
# Create objects from C SRC files
$(OBJECT_DIRECTORY)/%.o: %.c
#echo Compiling file: $(notdir $<)
#echo arm-none-eabi-gcc $(CFLAGS) $(INC_PATHS) -c -o $# $<
$(NO_ECHO)$(CC) $(CFLAGS) $(INC_PATHS) -c -o $# $<
# Assemble files
$(OBJECT_DIRECTORY)/%.o: %.s
#echo Compiling file: $(notdir $<)
$(NO_ECHO)$(CC) $(ASMFLAGS) $(INC_PATHS) -c -o $# $<
# Link
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out: $(BUILD_DIRECTORIES) $(OBJECTS)
#echo Linking target: $(OUTPUT_FILENAME).out
$(NO_ECHO)$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
## Create binary .bin file from the .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin: $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
#echo Preparing: $(OUTPUT_FILENAME).bin
$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin
## Create binary .hex file from the .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex: $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
#echo Preparing: $(OUTPUT_FILENAME).hex
$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex
finalize: genbin genhex echosize
genbin:
#echo Preparing: $(OUTPUT_FILENAME).bin
$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin
## Create binary .hex file from the .out file
genhex:
#echo Preparing: $(OUTPUT_FILENAME).hex
$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex
echosize:
-#echo ""
$(NO_ECHO)$(SIZE) $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
-#echo ""
clean:
$(RM) $(BUILD_DIRECTORIES)
cleanobj:
$(RM) $(BUILD_DIRECTORIES)/*.o
flash: $(MAKECMDGOALS)
#echo Flashing: $(OUTPUT_BINARY_DIRECTORY)/$<.hex
nrfjprog --reset --program $(OUTPUT_BINARY_DIRECTORY)/$<.hex)
## Flash softdevice
flash_softdevice:
#echo Flashing: s110_softdevice.hex
nrfjprog --reset --program nrf51_sdk/softdevice/s110/hex/s110_softdevice.hex
all: clean
check this line. The default (first) Target of your Makefile depends on clean, so before any build is started, the clean target is executed that likely will remove all built files, to rebuild them.
Drop the clean and you should get the incremental behaviour make was designed for.