Wanderung

Using CMake to Build a Project with Source Files in Multiple Subdirectories

Introduction

Creating a project with source files located in multiple subdirectories can be a difficult task, especially if you are using a build system like CMake. In this blog post, you will learn how to use CMake to create a project that contains source files from multiple subdirectories and how to add custom macros to CMake to make this task easier.

Example

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

This line specifies the minimum version of CMake that is required to build the project.

MACRO(REC_DIRECTORIES return_list root_folder)
    FILE(GLOB_RECURSE new_list ${root_folder})
    SET(dir_list "")
    FOREACH(file_path ${new_list})
        GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
        SET(dir_list ${dir_list} ${dir_path})
    ENDFOREACH()
    LIST(REMOVE_DUPLICATES dir_list)
    SET(${return_list} ${dir_list})
ENDMACRO()

This block of code defines a custom macro called REC_DIRECTORIES that takes two arguments: a return list and a root folder. It uses the GLOB_RECURSE command to find all the files in the specified root folder and its subfolders, and then iterates over each file to extract the directory path. It stores all the unique directory paths in a list called dir_list, and sets the value of the return_list argument to this list.

SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED True)

This block of code specifies that the project should use C++17 as the language standard, and that it is required.

PROJECT(PROJECT_NAME VERSION 1.0)
SET(PROJECT_ROOT_DIR "src")

This block of code sets the name and version of the project, and specifies the root directory of the project.

REC_DIRECTORIES(HEADERS "${PROJECT_ROOT_DIR}/*.h")
MESSAGE(STATUS "Your message: ${HEADERS}") 
INCLUDE_DIRECTORIES(${HEADERS})

This block of code calls the REC_DIRECTORIES macro to find all the directories that contain header files, and then outputs the HEADERS variable to the console. It also adds these directories to the list of directories that will be searched for header files.

FILE(GLOB_RECURSE SOURCES "${PROJECT_ROOT_DIR}/*.c*")
MESSAGE(STATUS "Compiling the following sources: ${SOURCES}") 

This block of code uses the GLOB_RECURSE command to find all the source files in the PROJECT_ROOT_DIR directory and its subfolders, and stores them in the SOURCES variable. It then outputs the SOURCES variable to the console.

FILE(GLOB_RECURSE LIBRARIES "${PROJECT_ROOT_DIR}/*.lib")
MESSAGE(STATUS "Including the following libraries: ${LIBRARIES}") 
LINK_DIRECTORIES(${LIBRARIES})

This block of code uses the GLOB_RECURSE command to find all the library files in the PROJECT_ROOT_DIR directory and its subfolders, and stores them in the LIBRARIES variable. It then outputs the LIBRARIES variable to the console, and adds the directories containing the library files to the list of directories that will be searched when linking the project.

ADD_EXECUTABLE(MY_PROJECT MY_PROJECT.cpp ${SOURCES})

This line creates an executable called MY_PROJECT from the MY_PROJECT.cpp file and the source files in the SOURCES variable.

Conclusion

In this blog post, we learned how to use CMake to build a project with source files located in multiple subdirectories. We also learned how to add custom macros to CMake to make this task easier. By following the steps outlined in this blog post, you should be able to build a project with source files located in multiple subdirectories using CMake with ease.

#build #cmake #cpp #multiple subdirectories