0

Im trying to compile a C++ project using MinGW and can compile a simple main.cpp file with hello world without problems using g++ main.cpp -o main and also with external libraries using main.cpp extlib.cpp -o main. But say im working on a rather large project with 10s of .cpp files organised inside of different files, how can I get the compiler to find all the cpp files that are needed? I know i can use main.cpp libs/*.cpp -o main but this will only compile all the source files inside of libs but not inside folders in libs.

Ive looked into make and cmake but dont understand how those automate the process if you still have to manually enter the directories. Is there no way to simply hit compile or at least a command line command to compile all the needed files inside a directory? This seems to work with #include without issues?

drescherjm
  • 10,365
  • 5
  • 44
  • 64
  • Please use formatting to highlight commands like this: `g++ main.cpp -o main` – Expurple Jan 04 '22 at 13:37
  • I use CMake for my projects at work which are developed over a period of years and have several hundred source files and more than a dozen libraries and utilities. I don't glob I list every single file in the CMakeLists.txt however with that said it's not like I often add 20 source files in a single day. – drescherjm Jan 04 '22 at 13:37
  • Well, at least in Eclipse CDT, the IDE creates a makefile for you, which you can later run from CLI with `make all`. – ofey Jan 04 '22 at 13:56

3 Answers3

1

If you want to stick with MinGW and GNU Make I would probably use a Makefile that looks something like this to start with. You basically only need to maintain the srcs-variable by adding your source-files there. Usually you can use the wildcard-function for this if you have sub dirs. The rest of the Makefile (which can be left alone) sets up a build of an executable main.exe that depends on all the object-files. I also included dependency-handling via the deps-variable and the compiler flag -MMD which comes in handy when the project grows.

srcs := $(wildcard *.cpp) $(wildcard dir1/*.cpp) $(wildcard dir2/*.cpp)
objs := $(srcs:.cpp=.o)
deps := $(objs:.o=.d)
app  := main.exe

CXXFLAGS := -MMD -Og -g -Wall -Werror -Wpedantic -std=c++2a

$(app): $(objs)
    $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS)

-include $(deps)

.PHONY: clean

clean:
    rm -f $(objs) $(deps)
krueger
  • 211
  • 3
  • 4
  • Looks good. I'd also add `-MP`. And there are ways to do recursive wildcards, if you need them: https://stackoverflow.com/q/2483182/2752075 – HolyBlackCat Jan 04 '22 at 14:00
1

I use CMake for simple projects. Here's the simplest example I came with (CMakeLists.txt to put along your main.cpp in the root of your project):

cmake_minimum_required(VERSION 3.1)
SET(CMAKE_APP_NAME "Project")

project (${CMAKE_APP_NAME})
# list here your directories
INCLUDE_DIRECTORIES(dir1)
INCLUDE_DIRECTORIES(dir2)

# add an executable and list all files to compile
add_executable(${CMAKE_APP_NAME} main.cpp 
dir1/file1.cpp 
dir1/file1.h 
dir2/file2.h 
dir2/file2.cpp 
)

Once your project becomes more complex, you could use file(GLOB*) to avoid writing all the files.

fern17
  • 467
  • 6
  • 20
  • 1
    In general I wouldn't recommend `include_directories()`. `target_include_directories` does the same job and has the added added benefits of not polluting the include directories for additional targets created in the same file or in a subdirectory after adding the command. Furthermore if the project indeed gets big and libraries are added, it's definetly more convenient to simply link the library target and "get the include dirs for free". Furthermore multiple directories can be specified in both cases using a single command. Also it's weird to mix uppercase and lowercase usage of commands. – fabian Jan 04 '22 at 18:23
0

Overall, the most "automated" way to build a larger project is to use CMake. Keep learning it. You can use file(GLOB) to avoid listing every file in CMakeLists.txt. This is not recommended (see discussion here), but I do it anyway and never had any issues.

Expurple
  • 877
  • 6
  • 13