Search code examples
c++cmakecompilationincludeinclude-path

Building C++ code with components in CMake


I have a C++ project which can be compiled using cmake command with no error.

The problem is that I can't find the BaseCode.cpp.o and BaseCode.cpp.o.d in the build folder, also, when I run make command in the build folder, I get the following error:

myCode/BaseCode.h: No such file or directory

The C++ project has the current structure:

├── CMakeLists.txt
├── myComponent
│   ├── CMakeLists.txt
│   └── src
│       ├── CMakeLists.txt
│       ├── library
│       │   ├── CMakeLists.txt
│       │   └── myCode
│       │       ├── BaseCode.cpp
│       │       └── BaseCode.h
│       └── test
│           └── CMakeLists.txt
└── main.cpp

The main.cpp files looks like this:

#include <iostream>
#include <myCode/BaseCode.h>

int main()
{
    std::cout << "Hello World!" << std::endl;
    return 0;
};

The first CMakeLists.txt file in root folder (same as in main.cpp) is:

cmake_minimum_required(VERSION 3.10)

project(myTestProject)

# Set the components to build
set(components myComponent)

# Include subdirectories for each component
foreach(component ${components})
    add_subdirectory(${component})
endforeach()

# Set the output directory for the executable
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# Add the executable
add_executable(${PROJECT_NAME} main.cpp)

The CMakeLists.txt file in library folder is like this:

set( HEADERS 
   myCode/BaseCode.h
  ) 

set( SOURCES 
  myCode/BaseCode.cpp
  )

add_library( myCode SHARED ${SOURCES} ${HEADERS} )
set_property( TARGET myCode PROPERTY VERSION ${${PROJECT_NAME}_VERSION} )
target_link_libraries(myCode PRIVATE ${PROJECT_NAME})

install( DIRECTORY myCode/
        DESTINATION include/${PROJECT_NAME}
        COMPONENT devel
        FILES_MATCHING PATTERN "*.h" )

install( TARGETS myCode DESTINATION lib COMPONENT runtime )

The CMakelists in myComponent folder is:

add_subdirectory(src)

The CMakeLists in src directory is similar:

add_subdirectory(library)

Solution

  • As mentioned in the comments by Tsyvarev

    For construction #include <myCode/BaseCode.h> being worked, the directory <root>/myComponent/src/library should be among directories to be included by the compiler.

    You specify none include directories,so it doesn't work.

    In CMake include directories are specified include_directories or target_include_directories command.

    And from CMake include_directories documentation:

    include_directories

    Add include directories to the build.

    
    include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...]) 
    

    Add the given directories to those the compiler uses to search for include files. Relative paths are interpreted as relative to the current source directory.

    To fix the error you're getting, you need to add the following to your main CMakelists in your root folder:

    include_directories(myComponent/src/library)
    

    This is the CMakeLists file after adding that command:

    cmake_minimum_required(VERSION 3.10)
    
    project(Structure)
    
    # Set the components to build
    set(components myComponent)
    
    # Include subdirectories for each component
    foreach(component ${components})
        add_subdirectory(${component})
    endforeach()
    
    # Set the output directory for the executable
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
    
    include_directories(myComponent/src/library)
    
    # Add the executable
    add_executable(${PROJECT_NAME} main.cpp)
    

    That should do the trick (it did on my end).

    I got an additional error so I will mention it here just in case.

    When I tried to run it, I got the following error:

    cannot find -lmyTestProject: No such file or directory

    And to fix it, I deleted the command below from the CmakeLists file in your library folder:

    target_link_libraries(myCode PRIVATE ${PROJECT_NAME})
    

    It ran fine and displayed

    Hello World!