如何在MSVC中实现LD版本脚本式的通配符符号导出?
MSVC .def文件如何实现LD版本脚本的通配符符号导出?
问题背景
使用LD版本脚本可以通过通配符指定要导出的符号,比如下面的脚本可以导出getFoo和mynamespace::bar::下的所有符号,隐藏其余符号:
{ global: getFoo; extern "C++" { mynamespace::bar::*; }; local: *; };
但MSVC的模块定义(.def)文件只能通过EXPORTS语句导出getFoo,无法直接实现导出整个命名空间下符号的效果,同时使用-Wl,--version-script=libfoo.map让MSVC识别LD版本脚本的尝试也被拒绝,求可行方案。
可行解决方案
在代码中用
__declspec(dllexport)显式标记- 直接在
mynamespace::bar下的所有类、函数、变量前添加__declspec(dllexport)属性,编译时这些符号会自动被导出,无需在.def文件中逐个声明。 - 优势:无需维护.def文件的符号列表,代码层面直接控制导出;劣势:需要修改源代码。
- 直接在
自动生成.def文件的符号列表
- 先不带导出规则编译库,添加MSVC链接器选项
/MAP生成包含所有符号的.map文件。 - 用脚本(如Python、PowerShell)筛选出
mynamespace::bar::开头的符号,加上getFoo,生成完整的EXPORTS列表写入.def文件。 - 重新编译时使用这个自动生成的.def文件,即可实现只导出目标符号的效果。
- 先不带导出规则编译库,添加MSVC链接器选项
通过链接器
/EXPORT选项批量指定- 借助构建系统(如CMake、Ninja)自动收集
mynamespace::bar下的符号,为每个符号添加/EXPORT:符号名的链接器选项。 - 适合用构建系统管理的项目,避免手动维护符号列表。
- 借助构建系统(如CMake、Ninja)自动收集
注意事项
MSVC链接器完全不支持LD的版本脚本语法,-Wl,--version-script是GCC链接器的专属选项,MSVC会直接拒绝,不要尝试用这个思路解决问题。
内容的提问来源于stack exchange,提问作者Sam Karr
相关产品推荐
相关产品推荐

