0

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

Gianluca Bianco
  • 656
  • 2
  • 11
  • I recommend you Google for the error `too many sections` when using MinGW. There are plenty of hits. Maybe one will help. – MadScientist Jun 16 '22 at 15:46
  • @MadScientist It's all the day that I am trying to solve this problem searching on google. I didn't find any suitable solution yet. – Gianluca Bianco Jun 16 '22 at 15:49
  • First hit for me: https://digitalkarabela.com/mingw-w64-how-to-fix-file-too-big-too-many-sections/#:~:text=When%20you%20compile%20large%20source,the%20%2Dmbig%2Dobj%20flag. Third hit for me: https://stackoverflow.com/questions/31890021/mingw-too-many-sections-bug-while-compiling-huge-header-file-in-qt If you tried these already, you should add this to your question and show the results of trying them. Else people will just recommend things you already tried. – MadScientist Jun 16 '22 at 15:50
  • @MadScientist my question has been edited – Gianluca Bianco Jun 16 '22 at 16:03

1 Answers1

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.

Gianluca Bianco
  • 656
  • 2
  • 11