【发布时间】:2021-05-14 14:17:30
【问题描述】:
背景
我使用 cmake 构建了一个open-source library。
项目设置为执行以下操作:
- 构建一个名为
gpds-objs的cmakeOBJECT库 - 从
gpds-objs构建一个名为gpds-static的STATIC库 - 从
gpds-objs构建一个名为gpds-shared的SHARED库
此外,我正在使用 cmake 的 generate_export_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
)
库中的类定义如下所示:
#include "gpds_export.hpp"
namespace gpds
{
class GPDS_EXPORT container
{
// ...
};
}
为了完整起见,这里是 gpds_export.hpp 的相关部分,由 cmake 的 generate_export_header() 生成:
#ifdef GPDS_STATIC_DEFINE
# define GPDS_EXPORT
# define GPDS_NO_EXPORT
#else
# ifndef GPDS_EXPORT
# ifdef gpds_shared_EXPORTS
/* We are building this library */
# define GPDS_EXPORT __declspec(dllexport)
# else
/* We are using this library */
# define GPDS_EXPORT __declspec(dllimport)
# endif
# endif
# ifndef GPDS_NO_EXPORT
# define GPDS_NO_EXPORT
# endif
#endif
问题
我遇到的问题是在构建 gpds-objs 时,我收到以下消息:
C:\Users\joel\Documents\projects\gpds\lib\src\value.cpp:7:1: warning: 'gpds::value::value(const gpds::value&)' redeclared without dllimport attribute: previous dllimport ignored [-Wattributes]
7 | value::value(const value& other) :
| ^~~~~
C:\Users\joel\Documents\projects\gpds\lib\src\value.cpp:17:1: warning: 'gpds::value::value(gpds::value&&)' redeclared without dllimport attribute: previous dllimport ignored [-Wattributes]
17 | value::value(value&& other) :
| ^~~~~
C:\Users\joel\Documents\projects\gpds\lib\src\value.cpp:25:1: warning: 'virtual gpds::value::~value()' redeclared without dllimport attribute: previous dllimport ignored [-Wattributes]
25 | value::~value() noexcept
| ^~~~~
C:\Users\joel\Documents\projects\gpds\lib\src\value.cpp:33:6: warning: 'void gpds::value::from_string(std::string&&)' redeclared without dllimport attribute: previous dllimport ignored [-Wattributes]
33 | void value::from_string(std::string&& string)
我不确定如何正确解决这个问题。
据我了解,问题在于构建gpds-objs 目标没有定义任何相关的导出宏(GPDS_STATIC_DEFINE 和gpds_shared_EXPORTS 都没有)。因此,GPDS_EXPORT 被定义为 __declspec(dllimport),这是不正确的,因为我们没有使用 gpds-objs 目标构建共享库。
我能想到的一个解决方案是在gpds-objs 目标上定义gpds_shared_EXPORTS 而不是gpds-shared 目标。但是,这意味着它也在构建gpds-static 目标时定义。只要gpds-static 定义GPDS_STATIC_DEFINE,这可能没问题。
处理这个问题的正确方法是什么?
【问题讨论】: