如何将已编译的模块接口与目标文件链接起来?

编程语言 2026-07-09

为了举个简单的例子,我有这样的一个项目:

.
├── animals.cpp
├── animals.cppm
├── gcm.cache
│   ├── animals.gcm
│   └── std.gcm
└── main.cpp

它可以像下面这样编译和链接:

g++ -std=c++26 -Wall -O2 -fmodules animals.cppm animals.cpp main.cpp -o animals

现在我想把对象文件的编译和链接分开进行,我已经尝试过:

g++ -std=c++26 -Wall -O2 -fmodules animals.cppm animals.cpp main.cpp -c

这一步成功,并产生 animals.omain.o。对于链接,我尝试了:

g++ -fmodules animals.o main.o -o animals

这会导致诸如以下所示的错误:

/usr/bin/x86_64-linux-gnu-ld.bfd: main.o: warning: relocation against `_ZTIN7animalsW7animals3CatE' in read-only section `.text.startup'
/usr/bin/x86_64-linux-gnu-ld.bfd: animals.o: in function `animals::Animal@animals::Animal(std::basic_string_view<char, std::char_traits<char> >)':
/home/dode/BeginningC++23/12-objects/animals.cpp:12:(.text+0x606): undefined reference to `vtable for animals::Animal@animals'
[...]
/usr/bin/x86_64-linux-gnu-ld.bfd: main.o: in function `_GLOBAL__sub_I_main':
/home/dode/BeginningC++23/12-objects/main.cpp:68:(.text.startup+0x1): undefined reference to `initializer for module animals'
/usr/bin/x86_64-linux-gnu-ld.bfd: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status

我想我可能漏掉了一些非常基础的东西,以至于链接器没有“看到”已编译的模块接口?

解决方案

编译一个模块除了会生成一个BMI之外,还会生成一个对象文件,因此你必须链接该对象文件。

我猜在你的情况下那个对象文件丢失了,因为 animals.cppmanimals.cpp 都生成 animals.o,因此它的先前版本被后面的版本覆盖。

我在这里写了关于C++20模块如何编译的详细描述 在这里

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章