CMakelists.txt; nested Folder header file Not found error

Viewed 562

I have the following folder structure:

demo_main
|
|---- demo_use
|       |
|        --- demo_use_main.c
 ---- demo_1.0
        |
         --- demo_sample
                |
                 ---zmq_sample
                       |
                        --- HelloWorld.h
                        --- HelloWorld.cpp

In the file demo_main\demo_use\demo_use_main.c I need to call function defined in HelloWorld.cpp located in another folder.

demo_use_main.c
    #include "HelloWorld.h"

    ...
    int main(int argc, char *argv[])
    {
        ...
        HelloWorldPrint();
        return 0;
    }

HelloWorld.h
    void HelloWorldPrint(void);

HelloWorld.cpp
    #include<iostream>
    #include "HelloWorld.h"

    void HelloWorldPrint()
    {
       std::cout << "function Hello World!" << std::endl;    
    }

But while compiling I get an error:

demo_use_main.c:4:10: fatal error: HelloWorld.h: No such file or directory

My Cmakelists.txt looks like:

demo_main\CMakeLists.txt
    cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
        add_subdirectory(demo_use)
        add_subdirectory(demo_1.0)


demo_main\demo_use\CMakeLists.txt
    cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
    include_directories(${CMAKE_CURRENT_LIST_DIR}/../demo_1.0/demo_sample/zmq_sample/)

    add_sources(
        ${CMAKE_CURRENT_LIST_DIR}/demo_use_main.c
        ...
    )


demo_main\demo_1.0\CMakeLists.txt
    cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
        add_subdirectory(demo_sample)


demo_main\demo_1.0\demo_sample\CMakeLists.txt
    cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
        add_subdirectory(zmq_sample)


demo_main\demo_1.0\demo_sample\zmq_sample\CMakeLists.txt
    cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
    project (zmq_demo)
    add_sources(${CMAKE_CURRENT_LIST_DIR}/HelloWorld.cpp)
    add_executable(${PROJECT_NAME} HelloWorld.cpp)

What is missing that the header file is not found by the demo_use_main.c? How to rectify it?

1 Answers

As commented, the header is not found because the include_directories call only applies to targets defined in the current directory (demo_main\demo_use) or in child directories. You have no targets defined in the current directory, so the include directory isn't actually applied to anything!

There are few other issues with the CMake code.

  1. Your main function is defined in demo_use_main.c, so your add_executable call should include that file.
  2. You should upgrade your CMake version to something more recent than 2.8.12. The commands in modern CMake are more intuitive from a software engineering perspective, and should make it easier to use.
  3. Your top-level CMake file is missing a call to project. It is typically good practice to include this, and you can add subsequent sub-projects under it by calling project again later on. Furthermore, you only need the cmake_minimum_required call once, in your top-level CMake file.
  4. You don't need a CMake file in every sub-directory, but this is a design decision.

With those changes, something like this may work better:

demo_main\CMakeLists.txt:

cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
# Add top-level project call.
project(DemoProject)
# Add the sub-directories more directly.
add_subdirectory(demo_use)
add_subdirectory(demo_1.0\demo_sample\zmq_sample)

demo_main\demo_use\CMakeLists.txt:

project(zmq_demo)
# Add the executable here.
add_executable(zmq_demo demo_use_main.c)

demo_main\demo_1.0\demo_sample\zmq_sample\CMakeLists.txt:

# Add the HelloWorld.cpp source file to the executable's compilation.
target_sources(zmq_demo PRIVATE HelloWorld.cpp)

# Prefer target-based command here to include directories, if CMake version supports it.
target_include_directories(zmq_demo PRIVATE
    ${CMAKE_CURRENT_LIST_DIR}
)

I recommend spending some time to understand the benefits of using modern CMake, as it may make maintenance easier in the long run.

Related