Ошибка C1083 (файл не найден) с CMAKE target_include_directories

avatar
aapa320
1 июля 2021 в 16:31
238
1
0

У меня есть проект C++, разделенный на несколько разных библиотек/исполняемых файлов в дереве исходного кода. Существует файл CMake верхнего уровня, который включает в себя несколько подкаталогов. Одна конечная библиотека B связывается с другой конечной библиотекой A. Однако, несмотря на то, что A публично добавил target_include_directories, в B я получаю сообщение об ошибке C1083 — не удается открыть включаемый файл.

ОС: Win10

Использование комплекта GCC 7.3.0:

  • Команда CMake "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"

  • Сообщение об ошибке:

[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.

Использование комплекта Visual Studio Build Tools 2017 Release — amd64:

  • Команда CMake: "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

  • Сообщение об ошибке:

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();
}

Я чувствую, что могу упустить что-то фундаментальное, но я подумал, что если добавить sample_cmake_project/A/public в целевые каталоги включения libA, заголовок libA.h должен быть доступен для библиотек, которые ссылаются на libA, например. libB?

есть мысли? заранее спасибо.

Источник
273K
1 июля 2021 в 19:16
1

Не могу воспроизвести. Все цели построены успешно. Ваш реальный код кажется другим.

Tsyvarev
1 июля 2021 в 19:58
1

Пожалуйста, предоставьте точное сообщение об ошибке.

aapa320
2 июля 2021 в 07:25
0

Я обновил ответ и, еще раз взглянув на сообщения об ошибках, понял, что файл отсутствует в libB-obj, библиотеке объектов, используемой для создания статической библиотеки. libB-obj не был связан с libA, тогда очевидно, что он не найдет включаемые каталоги. Это было очень легко увидеть после вашего комментария и хорошего сна.

Ответы (1)

avatar
aapa320
2 июля 2021 в 07:29
0

Это было банально и вроде бы очевидно, но я проглядел. Сообщения об ошибках относятся к libB-obj, библиотеке объектов, используемой для создания статической библиотеки libB. libB-obj не был связан с libA, поэтому общедоступные включаемые каталоги из libA были недоступны для 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})