英文:
How can I define the switch macro that switches between my dllexport and dllimport attribute macros with CMake?
问题
在我的根CMakeLists.txt
文件中,我已经添加了以下内容:
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
这将使默认情况下隐藏所有符号,无论是在Windows(它默认会这样做)还是Linux上。这将需要我手动导出公共API的符号。为了帮助实现这一点,我在项目的utils/
目录中编写了一个名为defines.hpp
的头文件,其中包含以下内容:
#ifndef __DEFINES_H_
#define __DEFINES_H_
#if defined(linux) || defined(__linux__)
#define EXPORT __attribute__((visibility("default")))
#elif defined(_WIN64) || defined(__WIN32__)
#if defined(COMPILE_LIB)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
#endif
#endif
然后,我可以在包含需要导出(以及随后导入)的声明的任何头文件中包含此头文件:
#include "utils/defines.hpp"
class EXPORT MyCoolClass();
EXPORT void MyCoolFunction();
(我尚未测试这个,如果我写的有任何明显问题,请告诉我!)
我的问题是,对我来说不太清楚如何定义COMPILE_LIB
宏,因为库和可执行文件都是使用相同的CMake设置进行构建/链接的。我如何确保库使用dllexport
构建,然后在相同的CMake构建中使用dllimport
链接到可执行文件?或者我需要采取不同的方法吗?
在此前的Stack Overflow帖子中接受的答案似乎表明应使用编译器参数并分别构建每个库,这并不是我要找的。另一篇回答指出,应该使用CMake定义的projectname
,因为在编译DLL时它将定义宏projectname_EXPORTS
。但我不确定这是否仍然适用,因为我的共享库和可执行文件都是在同一个CMake项目中构建的。(相关的CMakeLists.txt
文件):
可执行文件的CMakeLists.txt
:
add_executable(quick-render quick_render.cpp)
target_link_libraries(quick-render ${PROJECT_NAME})
INSTALL(TARGETS quick-render DESTINATION bin)
...
库的CMakeLists.txt
:
...
add_library(${PROJECT_NAME} SHARED
...
)
target_link_libraries(${PROJECT_NAME} PUBLIC
...
)
...
这种方法在这里是否仍然适用,还是我的CMake设置对于以这种方式多种用途使用项目不合适?
英文:
So I have a project (meant to be supported on MacOS, Linux, and Windows) where I am building a shared library and a set of executables linked to that library. In my root CMakeLists.txt
I have added:
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
So that all symbols are hidden by default regardless of on Windows (which does this by default) or Linux. This will require me to manually export symbols of the public API. To help facilitate this, I've written a defines.hpp
header in my project's utils/
directory which contains the following:
#ifndef __DEFINES_H_
#define __DEFINES_H_
#if defined(linux) || defined(__linux__)
#define EXPORT __attribute__((visibility("default")))
#elif defined(_WIN64) || defined(__WIN32__)
#if defined(COMPILE_LIB)
#define EXPORT __declspec(dllexport)
#elif
#define EXPORT __declspec(dllimport)
#endif
#endif
#endif
The idea being then I would include this header into any header that contains declarations that need to be exported (and subsequently imported as well) via:
#include "utils/defines.hpp"
class EXPORT MyCoolClass();
EXPORT void MyCoolFunction();
(I have not tested this yet so if there are any glaring issues with what I've written please let me know!)
My question is, it is not entirely clear to me how to define the COMPILE_LIB
macro, given that the library and exectuables are built/linked with the same CMake setup. How can I ensure that the library is built using dllexport
and then linked to the executables using dllimport
within the same CMake build? Or would I need to take a different approach?
The accepted answer in this previous SO post seems to indicate using a compiler argument and building each separately, which isn't exactly what I am looking for. A separate answer indicates you should use the CMake defined projectname
as when compiling the DLL it will define the macro projectname_EXPORTS
. I'm also not sure that this will work again my shared library and the executables are all built within the same CMake project. (Relevant CMakeLists.txt
files):
CMakeLists.txt
for executables:
add_executable(quick-render quick_render.cpp)
target_link_libraries(quick-render ${PROJECT_NAME})
INSTALL(TARGETS quick-render DESTINATION bin)
...
CMakeLists.txt
for library:
...
add_library(${PROJECT_NAME} SHARED
...
)
target_link_libraries(${PROJECT_NAME} PUBLIC
...
)
...
Would this approach still work here, or is it my CMake setup bad for using the project in multiple ways like this?
答案1
得分: 2
如Tsyvarev在评论中所说,使用target_compile_definitions
命令以PRIVATE
关键字定义宏。这样,宏只在库自身编译时定义。
此外,补充一下Tsyvarev的说法,如果你只是使用GenerateExportHeader
模块,这部分将会自动完成。它还会负责为你配置构建系统的编译器生成C++属性。另请参阅https://stackoverflow.com/q/75432240/11107541。
英文:
As Tsyvarev said in the comments,
> Define the macro by using target_compile_definitions
command with PRIVATE
keyword. That way, the macro will be defined only when the library itself is compiled.
Adding to what Tsyvarev said, if you just use the GenerateExportHeader
module, that part will be done for you automatically. It will also take care of generating C++ attributes for the compiler you configured the buildsystem to use. See also https://stackoverflow.com/q/75432240/11107541.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论