cmake生成跨平台的动态库和静态库

对于window平台,默认不导出函数符号,要显示去指定

  • __declspec(dllexport)来声明编译成库要对外暴露的函数,
  • __declspec(dllimport) 来声明使用时调用动态库的函数。

可以通过宏的定义与否来区分编译的是导出函数还是调用动态库函数。

在头文件中声明即可

// mylib.h

#pragma once

#ifdef MYLIB_EXPORTS // 导出
	#define MYLIB_API __declspec(dllexport)
#else // 调用
	#define MYLIB_API __declspec(dllimport)
#endif

MYLIB_API void hello(); // 声明hello函数导出

编译库时 cmakelist中要定义MYLIB_EXPORTS宏,使用时不用

# 定义 MYLIB_EXPORTS 宏,用于导出符号
target_compile_definitions(MyLibrary
    PRIVATE MYLIB_EXPORTS
)
cmake_minimum_required(VERSION 3.10.0)
project(mylib VERSION 0.1.0 LANGUAGES C CXX)

add_library(mylib SHARED mylib.cpp mylib.h)# 默认静态库,SHARED 动态库 

# 定义 MYLIB_EXPORTS 宏,用于导出符号
target_compile_definitions(mylib
    PRIVATE MYLIB_EXPORTS
)

set_target_properties(mylib PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" # 可执行文件输出路径
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" # 动态库输出路径(与可执行文件同路径或在系统变量中)
    ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" # 静态库输出路径
)

跨平台

linux默认导出所有符号,所以为了代码通用性,可以定义一个一样的空导出宏

// mylib.h

#pragma once

#if defined(_WIN32) || defined(_WIN64)
    #ifdef MYLIB_EXPORTS
        #define MYLIB_API __declspec(dllexport)
    #else
        #define MYLIB_API __declspec(dllimport)
    #endif
#else
    #define MYLIB_API // 空的导出宏
#endif


MYLIB_API void hello();

兼容生成静态库

生成静态库时,win和linux一样,不需要导入导出宏,可以添加一个MYLIB_STATIC宏,编译时屏蔽导入导出宏

// mylib.h

#pragma once

#ifdef MYLIB_STATIC

#else
	#ifdef MYLIB_EXPORTS // 导出
		#define MYLIB_API __declspec(dllexport)
	#else // 调用
		#define MYLIB_API __declspec(dllimport)
	#endif
#endif

MYLIB_API void hello(); // 声明hello函数导出
# 定义 MYLIB_EXPORTS 宏,用于导出符号
target_compile_definitions(mylib
    PRIVATE MYLIB_STATIC
)

这也是 GLFW 的做法,使用静态库要添加GLFW_STATIC

库的动静无传导性

动静态库的划分是基于自身代码的链接方式,与引用的库无关。自身是静态引用的库是动态则编译后的文件还是要动态加载三方库。动态库静态库是对于自身代码生成的库而言

posted @ 2025-07-18 18:50  丘狸尾  阅读(49)  评论(0)    收藏  举报