d链接到有类静态库时缺少模块信息

原文
我遇见了一些问题,在运行时类型信息中,应该包含的moduleinfoclassinfo丢失了,但只在通过静态库链接时才丢失.示例:

libci.d:
module libci;

class C
{
}

extern(C) void foo()
{
    import std.stdio;
    auto c = new C;
    writeln("C的类信息", typeid(c));
    auto x = ClassInfo.find("libci.C");
    writeln("搜索:", x);
}

version(works) static this()
{
    import std.stdio;
    writeln("这里");
}

testit.d:
import std.stdio;
import libci;

void main()
{
    foo();
    auto ci = ClassInfo.find("libci.C");
    writeln("主中: ", ci);
    foreach(m; ModuleInfo)
    {
        writeln(m.name);
    }
}

dmd testit.d libci.d
//编译与用如下编译
dmd -lib libci.d
dmd -L-L. -L-lci testit.d

不一样,后者缺少libci!
因此,尽管如果直接使用它,classinfo是可用的,也未链接libciModuleInfo.exe中错误的删除了ModuleInfo.
在构建库时,如果启用version=works,则会包含ModuleInfo.
不确定这是druntime还是dmd错误,标记为dmd.
注意,该行为非常古老,在LinuxOSX上都有.早在2.064就已测试过了

它与静态库中去掉不用类/模块矛盾.
如果真想从静态库中拖入所有类,一种方法是从公共模块中引用所有类.
拥有所有类的显式列表与Object.factory的目的矛盾,都难实现.
另一种方法是为每个模块生成目标文件,并显式链接它们(链接器不会丢弃目标文件).
Dub--build-mode=singleFileIIRC形式来支持.
再或者是使用共享库

或告诉链接器包括整个归档文件,对ld,合理地命名为--whole-archive/--no-whole-archive.

可惜,dmd当前重排了链接器标志(15574#问题),所以下面方法不管用.

-L--whole-archive mystaticlib.a -L--no-whole-archive

相反,必须调用cc来自己链接.

这是因小失大.先要解决兆字节大小的模板符号名.然后,需要完整支持共享库.moduleinfo增加的几千字节不重要.删除未用的classinfo?然后,需要删除Object.factory方法.

我从模块中引用了类信息,并调用了该函数.为什么链接器排除了它?这是个真实的漏洞.

不能有Object.factory,然后修剪掉所有不直接使用的classinfo.但是在该示例中,我直接用它,它仍然被修剪掉.

不管是否需要它,它都是当前运行时的特性.不再关心现有代码了吗?
我完全赞成过时Object.factory,也赞成你更新到std.encoding.但可能有代码期望Object.factory工作,不然,它不会工作.
注意,在我给的示例中,包含模块信息未增加二进制文件的大小.ClassInfo已在二进制文件中,因此会加入类可能使用的所有其他内容.

不仅如此,用-lib开关构建,也不行,但不用它,则可以.不一致对D来说是不好的,不管Object.factory特性的实用性如何.
一些UI解析器*依赖*类列表和工厂.来避免易错的手动注册UI类.

posted @   zjh6  阅读(17)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示