CMake Include-Dependencies 项目

CMake Include-Dependencies for Projects

我正在尝试从大型 Visual Studio-based 项目(带有静态、动态库、可执行文件)切换到 CMake。它会工作得很好,但由于许多静态库都有导出库(不需要 link 将库添加到项目中),我需要一种方法来包含项目的 接口 没有 linking 静态库。

情况:

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(Test)

add_subdirectory(Projekt_B)
add_subdirectory(Projekt_A)

Projekt_A/CMakeLists.txt

add_library(Projekt_A 
    libraryContent.cpp
    libHeader.h
    libInterfaceOnly.h)

target_include_directories(Projekt_A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})  
# could be **INTERFACE** as well

Projekt_B/CMakeLists.txt

add_library(Projekt_B_Public SHARED
    libraryContentB.cpp
    libHeaderB.h
)

add_library(Projekt_B_Private SHARED
    libraryContentB.cpp
    libHeaderB.h
)

add_library(Projekt_B_Interface SHARED
    libraryContentB.cpp
    libHeaderB.h
)

## this Line works but links Projekt_A 
target_link_libraries(Projekt_B_Public PUBLIC Projekt_A)

## this Line works too, but links Projekt_A to it without passing them on
target_link_libraries(Projekt_B_Private PRIVATE Projekt_A)

## this Line works **only** if no interface of A is used in B
target_link_libraries(Projekt_B_Interface INTERFACE Projekt_A)

因此,当 Projekt_A 的接口在 [=66 中使用时,所有目标都会编译=]。当我包含 header(已通过 traget_include_directories 导出)时,Projekt_B_Interface 不会t link 了。

MsBuild 告知 Projekt_B_Interface:

ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\CL.exe 
  /c /Zi /nologo /W3 /WX- /Od /Ob0 /D WIN32 /D _WINDOWS /D _DEBUG /D 
  "CMAKE_INTDIR=\"Debug\"" /D Projekt_B_Interface_EXPORTS /D _WINDLL /D 
  _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope 
  /Fo"Projekt_B_Interface.dir\Debug\" 
  /Fd"Projekt_B_Interface.dir\Debug\vc120.pdb" /Gd /TC /errorReport:queue 
  D:\Develop\CMake\TEST\Projekt_B\libr.c    
  libr.c
D:\Develop\CMake\TEST\Projekt_B\libr.c(2): fatal error C1083: Cannot open include file: 
'libinc.h': No such file or directory      
[D:\Develop\CMake\TEST\build\Projekt_B\Projekt_B_Interface.vcxproj]

在其他 Projekt_B_* 项目中它是成功的:

ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\CL.exe 
  /c /ID:\Develop\CMake\TEST\Projekt_A /Zi /nologo /W3 /WX- /Od /Ob0 /D 
  WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" 
  /D Projekt_B_Public_EXPORTS /D _WINDLL /D _MBCS /Gm- /RTC1 /MDd /GS 
  /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Projekt_B_Public.dir\Debug\" 
  /Fd"Projekt_B_Public.dir\Debug\vc120.pdb" /Gd /TC /errorReport:queue 
  D:\Develop\CMake\TEST\Projekt_B\libr.c
  libr.c
Link:
  C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\link.exe 
  /ERRORREPORT:QUEUE /OUT:"D:\Develop\CMake\TEST\build\
  Projekt_B\Debug\Projekt_B_Public.dll" /INCREMENTAL /NOLOGO 
  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib
  oleaut32.lib uuid.lib comdlg32.lib advapi32.lib 
  ..\Projekt_A\Debug\Projekt_A.lib /MANIFEST 
  /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG
  /PDB:"D:/Develop/CMake/TEST/build/Projekt_B/Debug/Projekt_B_Public.pdb" 
  /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT     
  /IMPLIB:"D:/Develop/CMake/TEST/build/Projekt_B/Debug/Projekt_B_Public.lib" 
  /MACHINE:X64  /machine:x64 /debug /DLL Projekt_B_Public.dir\Debug\libr.obj
  Projekt_B_Public.vcxproj -> D:\Develop\CMake\TEST\build\Projekt_B\Debug\
  Projekt_B_Public.dll

关于如何获得类似内容的任何想法:

target_compile_libraries(Projekt_B HEADERS Projekt_A)

target_include_directoies 听起来像...)

我想我已经找到了解决这种情况的方法(不需要在 CMake 中设置变量):

Projekt_A/CMakeLists.txt:

...
# create a interface
add_library(IProjekt_A INTERFACE)

# add *export* headers to interface
target_include_directories(IProjekt_A INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

# bind interface to project itself (just in case)
target_link_libraries(Projekt_A INTERFACE IProjekt_A)

Projekt_B/CMakeLists.txt

...
# this will add includes *only* and reexports them within Projekt_B
target_link_libraries(Projekt_B PUBLIC IProjekt_A)

# this will add includes and library for link and reexport
target_link_libraries(Projekt_B PUBLIC Projekt_A)

# this will only add the includes for *this* project
target_link_libraries(Projekt_B PRIVATE IProjekt_A)

这使得在 构建环境中导出 headers 成为可能。在大型项目中非常有用。

我希望它也能帮助到其他人!

干杯。