0

I have a c++ project split into a few different libraries/executables in the source tree. There is a top level CMake file that includes some subdirectories. One leaf library B links against another leaf library A. However, even though A has added target_include_directories publicly, in B, I get the error C1083 - cannot open include file.

OS: Win10

Using kit GCC 7.3.0:

  • CMake Command "C:\Program Files\CMake\bin\cmake.EXE" --no-warn-unused-cli -DMOCK_SIMCONNECT:BOOL=TRUE "-DP3D_SDK_ROOT:STRING=C:/Program Files/Lockheed Martin/Prepar3D v4 SDK 4.5.14.34698" -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=C:\Qt\Tools\mingw730_64\bin\gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=C:\Qt\Tools\mingw730_64\bin\g++.exe -Hd:/repos/cmake_sample_project -Bd:/repos/cmake_sample_project/build -G "MinGW Makefiles"

  • Error Message:

[build] D:\repos\cmake_sample_project\src\B\libB.h:5:10: fatal error: libA.h: No such file or directory
[build]  #include "libA.h"
[build]           ^~~~~~~~
[build] compilation terminated.

Using kit Visual Studio Build Tools 2017 Release - amd64:

  • CMake command: "C:\Program Files\CMake\bin\cmake.EXE" --no-warn-unused-cli -DMOCK_SIMCONNECT:BOOL=TRUE "-DP3D_SDK_ROOT:STRING=C:/Program Files/Lockheed Martin/Prepar3D v4 SDK 4.5.14.34698" -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -Hd:/repos/cmake_sample_project -Bd:/repos/cmake_sample_project/build -G "Visual Studio 15 2017" -T host=x64 -A x64

  • Error Message:

d:\repos\cmake_sample_project\src\b\libB.h(5): fatal error C1083: Datei (Include) kann nicht geöffnet werden: "libA.h": No such file or directory [D:\repos\cmake_sample_project\build\src\B\libB-obj.vcxproj]
sample_cmake_project
|   CMakeLists.txt
|   
+---src
|   |   CMakeLists.txt
|   |   
|   +---A
|   |   |   CMakeLists.txt
|   |   |   libA.cpp
|   |   |   
|   |   \---public
|   |           libA.h
|   |           
|   \---B
|           CMakeLists.txt
|           libB.cpp
|           libB.h
|           
\---tests
        CMakeLists.txt

sample_cmake_project/CMakeLists.txt:

cmake_minimum_required(VERSION 3.12)

project(sample_project LANGUAGES CXX)

add_subdirectory(src)

enable_testing()
add_subdirectory(tests)

sample_cmake_project/src/CMakeLists.txt

add_subdirectory(A)
add_subdirectory(B)

sample_cmake_project/src/A/CMakeLists.txt

add_library(libA-obj OBJECT "")

target_sources(libA-obj 
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/libA.cpp
    PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/public/libA.h # <-- header is added as public source.
)

add_library(libA STATIC $<TARGET_OBJECTS:libA-obj>)

target_include_directories(libA PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/public) # <-- public dir is added to the target's PUBLIC include directories.

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/public)

sample_cmake_project/src/B/CMakeLists.txt:

add_library(libB-obj OBJECT "")

target_sources(libB-obj 
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/libB.cpp
    PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/libB.h
)

add_library(libB STATIC $<TARGET_OBJECTS:libA-obj>)

target_link_libraries(libB PRIVATE libA)

include_directories(${CMAKE_CURRENT_SOURCE_DIR})

sample_cmake_project/src/A/public/libA.h:

#ifndef __LIBA_H
#define __LIBA_H

#include <iostream>

class A 
{
    public:
    A() { std::cout << "hello" << std::endl; };
    ~A() { std::cout << "bye bye" << std::endl; };

    void saySomething();
};

#endif

sample_cmake_project/src/A/libA.cpp:

#include "libA.h"

void A::saySomething()
{
    std::cout << "something..." << std::endl;
}

sample_cmake_project/src/B/libB.h:

#ifndef __LIB_B
#define __LIB_B

#include <iostream>
#include "libA.h"

class B
{
public:
    B();
    ~B();

    void saySomething();

private:
    A _a;
};

#endif

sample_cmake_project/src/B/libB.cpp:

#include "libB.h"

B::B() :
    _a(A())
{
    std::cout << "Hello from lib B" << std::endl;
    _a.saySomething();
}

I feel I might be missing something fundamental, but I thought that by adding sample_cmake_project/A/public to the libA target's include directories, the libA.h header should be available for the libraries that link against libA, e.g. libB?

any thouhts? thanks in advance.

3
  • 1
    Can't reproduce. All targets are built successfully. You real code seems to be different. Commented Jul 1, 2021 at 19:16
  • 1
    Please, provide the exact error message. Commented Jul 1, 2021 at 19:58
  • I updated the answer and by taking another look at the error messages, I realized that the file was missing from libB-obj, the objects library used to build the static library. libB-obj wasn't being linked to libA, then it's obvious it wouldn't find the include directories. It was very easy to see after your comment and a good night's sleep. Commented Jul 2, 2021 at 7:25

1 Answer 1

0

It was trivial and kinda obvious, but I overlooked it. The error messages refer to libB-obj, the objects library used to make the static library libB. libB-obj wasn't linked to libA, hence the public include directories from libA weren't available for libB-obj.

add_library(libB-obj OBJECT "")

target_sources(libB-obj 
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/libB.cpp
    PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/libB.h
)

add_library(libB STATIC $<TARGET_OBJECTS:libA-obj>)

target_link_libraries(libB-obj PRIVATE libA) # --> link libB-obj instead of static library libB!

include_directories(${CMAKE_CURRENT_SOURCE_DIR})
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.