Cmake 从对象库创建共享库&;DLL导出 背景

Cmake 从对象库创建共享库&;DLL导出 背景,cmake,shared-libraries,Cmake,Shared Libraries,我使用cmake构建一个 项目设置为执行以下操作: 构建名为gpds objs的cmake对象库 从gpds objs 从gpds objs 此外,我正在使用cmake的generate\u export\u header()生成必要的导出宏 cmake脚本的相关部分如下所示: # Set project information project(gpds VERSION 1.0.0 LANGUAGES CXX HOMEPAGE_URL "https://gp

我使用cmake构建一个

项目设置为执行以下操作:

  • 构建名为gpds objs的cmake
    对象
  • gpds objs
  • gpds objs
此外,我正在使用cmake的
generate\u export\u header()
生成必要的导出宏

cmake脚本的相关部分如下所示:

# Set project information
project(gpds
    VERSION 1.0.0
    LANGUAGES CXX
    HOMEPAGE_URL "https://gpds.simulton.com"
)

# Some bacis cmake configuration
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)

# List of private source files
set(SOURCES_PRIVATE
    # ...
)

# List of private header files
set(HEADERS_PRIVATE
    # ...
)

# List of public header files
set(HEADERS_PUBLIC
    # ...
)

# Define targets
set(NAME gpds)
set(TARGET-OBJS   ${NAME}-objs)
set(TARGET-STATIC ${NAME}-static)
set(TARGET-SHARED ${NAME}-shared)


################################################################################
# Object library                                                               #
################################################################################

add_library(${TARGET-OBJS} OBJECT)

target_compile_features(
    gpds-objs
    PUBLIC
        cxx_std_17
)

target_sources(
    ${TARGET-OBJS}
    PRIVATE
        ${SOURCES_PRIVATE}
        ${HEADERS_PRIVATE}
)

target_include_directories(
    ${TARGET-OBJS}
    INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
    PRIVATE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/gpds>
)


################################################################################
# Shared library                                                               #
################################################################################

add_library(${TARGET-SHARED} SHARED)

target_link_libraries(
    ${TARGET-SHARED}
    PUBLIC
        gpds-objs
)

target_compile_definitions(
    ${TARGET-SHARED}
    PRIVATE
        gpds_shared_EXPORTS     # We're building this library!
)


################################################################################
# Static library                                                               #
################################################################################

add_library(${TARGET-STATIC} STATIC)

target_link_libraries(
    ${TARGET-STATIC}
    PUBLIC
        gpds-objs
)

target_compile_definitions(
    ${TARGET-STATIC}
    PUBLIC
        GPDS_STATIC_DEFINE
)

# Common library properties
set_target_properties(
    ${TARGET-OBJS}
    ${TARGET-STATIC}
    ${TARGET-SHARED}
    PROPERTIES
        OUTPUT_NAME "gpds"
        ARCHIVE_OUTPUT_NAME "gpds"
        VERSION ${PROJECT_VERSION}
        POSITION_INDEPENDENT_CODE 1
)



################################################################################
# Export header                                                                #
################################################################################

include(GenerateExportHeader)
generate_export_header(
    ${TARGET-SHARED}
    BASE_NAME gpds
    EXPORT_FILE_NAME gpds_export.hpp
    DEPRECATED_MACRO_NAME "GPDS_DEPRECATED"
    NO_DEPRECATED_MACRO_NAME "GPDS_NO_DEPRECATED"
    EXPORT_MACRO_NAME "GPDS_EXPORT"
    NO_EXPORT_MACRO_NAME "GPDS_NO_EXPORT"
    STATIC_DEFINE "GPDS_STATIC_DEFINE"
    DEFINE_NO_DEPRECATED
)
为了完整起见,这里是由cmake的
generate\u export\u header()生成的
gpds\u export.hpp
的相关部分:

#ifdef GPDS_STATIC_DEFINE
#定义GPDS\U导出
#定义GPDS\u NO\u导出
#否则
#ifndef GPDS\U导出
#ifdef gpds_共享_导出
/*我们正在建造这个图书馆*/
#定义GPDS\u导出\u declspec(dllexport)
#否则
/*我们正在使用这个图书馆*/
#定义GPDS\u导出\u declspec(dllimport)
#恩迪夫
#恩迪夫
#ifndef GPDS\u无出口
#定义GPDS\u NO\u导出
#恩迪夫
#恩迪夫
问题 我遇到的问题是,在构建
gpds objs
时,我会收到以下消息:

C:\Users\joel\Documents\projects\gpds\lib\src\value.cpp:7:1:警告:“gpds::value::value(const-gpds::value&)”在没有dllimport属性的情况下重新声明:已忽略以前的dllimport[-Wattributes]
7 |值::值(常量值和其他值):
| ^~~~~
C:\Users\joel\Documents\projects\gpds\lib\src\value.cpp:17:1:警告:“gpds::value::value(gpds::value&&)”重新声明,但没有dllimport属性:忽略以前的dllimport[-Wattributes]
17 |值::值(值和其他):
| ^~~~~
C:\Users\joel\Documents\projects\gpds\lib\src\value.cpp:25:1:警告:“虚拟gpds::value::~value()”已重新声明,但没有dllimport属性:已忽略以前的dllimport[-Wattributes]
25 |值::~value()无例外
| ^~~~~
C:\Users\joel\Documents\projects\gpds\lib\src\value.cpp:33:6:警告:“void gpds::value::from_string(std::string&)”在没有dllimport属性的情况下重新声明:忽略以前的dllimport[-Wattributes]
33 | void value::from_string(std::string&&string)
我不确定如何正确解决这个问题

据我所知,问题在于构建
gpds objs
目标没有定义任何相关的导出宏(既没有
gpds\u STATIC\u define
也没有
gpds\u shared\u EXPORTS
)。因此,
GPDS\u EXPORT
被定义为
\u declspec(dllimport)
,这是不正确的,因为我们没有与
GPDS objs
目标构建共享库

我能想到的一个解决方案是在
gpds objs
目标上定义
gpds\u shared\u EXPORTS
,而不是在
gpds shared
目标上。但是,这意味着在构建
gpds静态目标时也会定义它。只要
gpds static
定义
gpds\u static\u DEFINE
,这就可以了


正确的处理方法是什么?

您不能对共享库和静态库使用相同的对象库

对象库确定应如何编译源文件。 但是源文件应该以不同的方式编译,用于静态库和共享库

描述如何将相同生成的头文件用于静态库和共享库:

add_库(shared_variant shared${lib_SRCS})
添加库(静态变量${lib\u SRCS})
生成\u导出\u头(共享\u变量基\u名称libshared\u和\u static)
设置目标属性(静态变量属性)
编译\u标志-DLIBSHARED\u和\u STATIC\u STATIC\u DEFINE)
这里为共享库生成导出头,静态库有额外的编译定义以重用该头。
再次注意,用于共享库和静态库的不同编译选项意味着您不能在这些库之间重用对象文件。您只能重用

能否详细说明为什么不能使用相同的
对象
库来构建
静态
共享
库?我相信我在官方的cmake指南中看到过这种模式(可能是非官方的tho)。你提到源代码的编译方式不同-我想知道更多。“你提到源代码的编译方式不同-我想知道更多。”-在我在问题帖中引用的代码中,目标
static\u variant
具有特定的编译定义,而目标
shared\u variant
没有它。这意味着目标的编制方式不同。你还想知道什么?我调查过了-你完全正确。谢谢