无法 link 外部 git CMake 项目的输出(静态库)到 CMake 项目

Unable to link the output (static library) of an external git CMake project to a CMake project

我在尝试 link 我最近推送到 Git 的库到我的 CMake 项目时遇到了问题。

我已将库命名为 octal (GitHub) and am trying to link it to my other library bulletframe (GitHub)。这两个项目都是我创建的。

我预料到 link 第一次使用库不会起作用,所以我只从 octal 中的几个源文件开始。 octal的文件夹结构如下:

.gitignore
CMakeLists.txt
.git/
build/ # generated project files go here, but right now it's empty
src/
    CMakeLists.txt
    octal.h # this is empty
    octal/
        vector/
            vector.h
            vector.cpp

octal/CMakeLists.txt

#...

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}")

add_subdirectory("src")

octal/src/CMakeLists.txt

macro(add_include)
    set(ALL_INCLUDES ${ALL_INCLUDES} ${ARGV})
endmacro(add_include)

add_include("octal.h")
add_include("octal/vector/vector.cpp" "octal/vector/vector.h")

add_library(${PROJECT_NAME} STATIC ${ALL_INCLUDES})

install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})

octal/src/vector/vector.h

#pragma once

namespace octal
{
    class Vector
    {
        // ...
        Vector Add(Vector other);
        Vector Subtract(Vector other);
        Vector Multiply(Vector other);
        Vector Multiply(double x);
        Vector Divide(Vector other);
        Vector Divide(double x);
        // ...
    }
}

这些配置成功地构建了一个 liboctal.a 文件,但是我不确定它们是否 link 与 bulletframe 正确。有多个文件使用 octal 中的 类,但这是它在尝试编译第一个源文件 entity.cpp:

后给出的第一个错误
fatal error: octal/vector/vector.h: No such file or directory
 #include "octal/vector/vector.h"
                                 ^
compilation terminated.
src\CMakeFiles\bulletframe.dir\build.make:57: recipe for target 'src/CMakeFiles/bulletframe.dir/entity.cpp.obj' failed
mingw32-make.exe[3]: *** [src/CMakeFiles/bulletframe.dir/entity.cpp.obj] Error 1
CMakeFiles\Makefile2:121: recipe for target 'src/CMakeFiles/bulletframe.dir/all' failed
mingw32-make.exe[2]: *** [src/CMakeFiles/bulletframe.dir/all] Error 2
CMakeFiles\Makefile2:133: recipe for target 'src/CMakeFiles/bulletframe.dir/rule' failed
mingw32-make.exe[1]: *** [src/CMakeFiles/bulletframe.dir/rule] Error 2
Makefile:130: recipe for target 'bulletframe' failed
mingw32-make.exe: *** [bulletframe] Error 2

bulletframe 具有与 octal

相似的文件夹结构

bulletframe/CMakeLists.txt:

include(ExternalProject)
set(EXPROJ_DIR    "${CMAKE_HOME_DIRECTORY}/external")
set(LIB_DIR       "${CMAKE_HOME_DIRECTORY}/lib")

set(OCTAL_NAME          "octal-git")
set(OCTAL_GIT           "https://github.com/TheOctopod/octal-cpp.git")
set(OCTAL_PREFIX        "${EXPROJ_DIR}/${OCTAL_NAME}")
set(OCTAL_SOURCE_DIR    "${EXPROJ_DIR}/${OCTAL_NAME}")
set(OCTAL_BUILD_DIR     "${EXPROJ_DIR}/${OCTAL_NAME}/build")
set(OCTAL_INSTALL_DIR   "${LIB_DIR}")

ExternalProject_Add(${OCTAL_NAME}
    PREFIX          ${OCTAL_PREFIX}
    TMP_DIR         ${OCTAL_PREFIX}-tmp
    STAMP_DIR       ${OCTAL_PREFIX}-stamp
    # - Download Step ------------------
    GIT_REPOSITORY  ${OCTAL_GIT}
    # - Update Step --------------------
    UPDATE_COMMAND  ""
    # - Configure Step -----------------
    SOURCE_DIR      ${OCTAL_SOURCE_DIR}
    # - Build Step ---------------------
    BINARY_DIR      ${OCTAL_BUILD_DIR}
    # - Install Step ------------------
    INSTALL_COMMAND ""
    CMAKE_ARGS
    "-DCMAKE_BUILD_TYPE=Release"
)

add_library("octal" STATIC IMPORTED)
set_target_properties("octal" PROPERTIES
    # this is where ExternalProject built liboctal.a at
    IMPORTED_LOCATION "${OCTAL_BUILD_DIR}/src"
)

add_subdirectory(src)

bulletframe/src/CMakeLists.txt

macro(add_include)
    set(ALL_INCLUDES ${ALL_INCLUDES} ${ARGV})
endmacro(add_include)

add_include("entity.cpp")

add_library(${PROJECT_NAME} STATIC ${ALL_INCLUDES})

target_link_libraries(${PROJECT_NAME} "octal")

就目前而言,我当前的配置无法使用 Visual Studio 10 2013MinGW Makefiles 生成器构建 bulletframe

当我看到编译器每次都给出类似的错误时,我想到了一些问题:

看起来你正在构建八进制,但没有提供正确的源路径(为了 bulletframe 能够 #include 它),也没有提供到它的编译库。

修复包含问题很简单;只需将路径添加到导入库的 INTERFACE_INCLUDE_DIRECTORIES 属性。但是,修复库的路径有点棘手。

使用 MSVC,八进制库的完整路径将是

${OCTAL_SOURCE_DIR}/lib/<build type>/octal.lib

其中 <build type> 是 "Debug"、"Release" 等。但是,对于其他编译器,路径将是

${OCTAL_SOURCE_DIR}/lib/liboctal.a

为了解决这个问题,我会做类似的事情:

add_library(octal STATIC IMPORTED)
if(MSVC)
  set_target_properties(octal PROPERTIES
      IMPORTED_LOCATION_DEBUG "${OCTAL_SOURCE_DIR}/lib/Debug/octal.lib"
      IMPORTED_LOCATION_RELEASE "${OCTAL_SOURCE_DIR}/lib/Release/octal.lib"
      INTERFACE_INCLUDE_DIRECTORIES "${OCTAL_SOURCE_DIR}/src")
else()
  set_target_properties(octal PROPERTIES
      IMPORTED_LOCATION "${OCTAL_SOURCE_DIR}/lib/liboctal.a"
      INTERFACE_INCLUDE_DIRECTORIES "${OCTAL_SOURCE_DIR}/src")
endif()