【问题标题】:Why is my shared library not linking correctly when using CMake?为什么我的共享库在使用 CMake 时链接不正确?
【发布时间】:2014-12-17 04:49:44
【问题描述】:

这是一个非常微不足道的问题,可能是由于我对 CMake 缺乏经验。我已按照http://fabzter.com/blog/cmake-tutorial-1 的教程进行操作,但遇到链接问题。

基本上我有一个库 MathFuncs 和一个使用 MathFuncs 的可执行文件。 MathFuncs 的 CMakeLists 是:

cmake_minimum_required(VERSION 2.8)
project(MathFuncs)

include_directories(${PROJECT_SOURCE_DIR})

SET (HEADER_FILES mysqrt.hpp)
add_library(MathFuncs SHARED mysqrt.cpp ${HEADER_FILES})

而可执行的 CMakeLists 是:

cmake_minimum_required (VERSION 2.6)
project (Tutorial)

set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
set (Tutorial_VERSION_BUGFIX 0)

#configure header file to pass some of the CMake settings 
#to the source code
configure_file(
    "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
    "${PROJECT_BINARY_DIR}/TutorialConfig.h"
) 

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")

# add the include directories necessary to build library
include_directories("${PROJECT_SOURCE_DIR}/MathFuncs}")
add_subdirectory(MathFuncs)

SET (MATHFUNCTIONS_DIR ${PROJECT_SOURCE_DIR}/MathFuncs)
add_executable(tutorial tutorial.cpp ${MATHFUNCTIONS_DIR}/mysqrt.hpp)

target_link_libraries(tutorial MathFuncs)

CMake 运行良好。但是,当我尝试使用 Visual Studio 进行编译时,我收到一个链接器错误,指出它无法打开 MathFuncs.lib。当我从 MathFuncs CMakeList 中删除“SHARED”选项时,它会运行,因为它正在构建一个静态库,但是对于我的应用程序,我想要一个共享库 DLL。

如何让 CMake 将库引用设置为共享?

谢谢,

【问题讨论】:

  • 在这一行:include_directories("${PROJECT_SOURCE_DIR}/MathFuncs}") 是不是多了一个}?
  • 您是否验证过 MathFuncs 构建? (构建失败不会使教程停止尝试构建,但链接文件将不存在)。
  • MathFuncs 仅在 dll 中构建没有问题。我现在按照 Frasers 的回答理解,第一步需要导出定义,但是我仍然在生成 .lib 时遇到问题。谢谢

标签: c++ cmake


【解决方案1】:

您似乎没有正确地从 DLL 中导出类/函数。详细说明见this article。

这并不完全简单,但幸运的是 CMake 可以在这里提供一些帮助。您可以使用 GenerateExportHeader 模块自动生成包含正确导出库的公共函数所需的所有预处理器定义的标头。

以下是我将如何更改您的文件的示例。希望每个都得到足够的评论,让您了解正在发生的事情。如果没有,请添加评论,我会展开。

顶级 CMakeLists.txt:

cmake_minimum_required (VERSION 3.0)
project(Tutorial)

add_subdirectory(MathFuncs)

set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
set(Tutorial_VERSION_BUGFIX 0)

# Configure header file to pass some of the CMake settings to the source code.
set(TutorialConfigHeader "${PROJECT_BINARY_DIR}/TutorialConfig.h")
configure_file(TutorialConfig.h.in "${TutorialConfigHeader}")

# Include the output file of 'configure_file' to ensure it gets configured.
add_executable(tutorial tutorial.cpp "${TutorialConfigHeader}")

# Add TutorialConfig.h's path to include dirs for 'tutorial'.
target_include_directories(tutorial PRIVATE "${PROJECT_BINARY_DIR}")

target_link_libraries(tutorial MathFuncs)

# If 'MathFuncs' is a shared lib, copy it to 'tutorial's bin dir so
# it can be found at runtime.
get_target_property(MathFuncsType MathFuncs TYPE)
if(MathFuncsType STREQUAL "SHARED_LIBRARY")
  add_custom_command(TARGET tutorial POST_BUILD
                     COMMAND ${CMAKE_COMMAND} -E copy_if_different
                         $<TARGET_FILE:MathFuncs> $<TARGET_FILE_DIR:tutorial>
                     COMMENT "Copying MathFuncs shared lib alongside tutorial."
                     VERBATIM)
endif()


MathFuncs/CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)
project(MathFuncs)

add_library(MathFuncs SHARED
            mysqrt.cpp
            mysqrt.hpp
            "${PROJECT_BINARY_DIR}/mathfuncs_export.h")

# Write appropriate export PP definitions in a file called
# 'mathfuncs_export.h' in the current binary dir
include(GenerateExportHeader)
generate_export_header(MathFuncs)

# Add the current source dir as a PUBLIC include dir
# (to allow mysqrt.hpp to be found by dependent targets)
# Add the current binary dir as a PUBLIC include dir
# (to allow mathfuncs_export.h to be found by dependent targets)
target_include_directories(MathFuncs PUBLIC
                           ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})


然后要使用生成的导出标头,您只需要让 mysqrt.hpp 包含以下内容:

#ifndef MYSQRT_HPP_
#define MYSQRT_HPP_

#include "mathfuncs_export.h"

double MATHFUNCS_EXPORT MySqrt(double input);

#endif  // MYSQRT_HPP_


现在这应该会导致 VS 创建一个导出库 ${CMAKE_BINARY_DIR}/MathFuncs/Debug/MathFuncs.lib(修复链接器问题)和实际的 DLL ${CMAKE_BINARY_DIR}/MathFuncs/Debug/MathFuncs.dll。

【讨论】:

  • 感谢您的帮助!不幸的是 .lib 文件不是由 VS 生成的。一切都编译得很好,.dll 仍在生成,但是我仍然收到相同的链接器错误。
  • 我很确定,如果 VS 没有生成 .lib,那是因为您没有从库中导出任何内容。您至少需要将一个函数或类声明为__declspec(dllexport),这是生成的“mathfuncs_export.h”应该出现的地方 - 它应该包含#define MATHFUNCS_EXPORT __declspec(dllexport),这意味着您可以在函数/类声明中使用MATHFUNCS_EXPORT .您的构建树中是否有“mathfuncs_export.h”,它是否包含此定义?
  • mathfuncs_export.h 在构建树中 - MATHFUNCS_EXPORT 也被定义为 __declspec(dllexport)。我什至在 mathfuncs.cpp 中实现了导出的 MySqrt,但仍然没有生成 lib 文件
  • 您在原始问题中没有提到 mathfuncs.cpp 或 mathfuncs.hpp - 您确定将所有文件都包含在您的库中吗?
  • 我的错误 - 我的意思是 mysqrt.hpp/cpp
猜你喜欢
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 2021-04-28
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
相关资源
最近更新 更多