我正在Arch Linux上使用clang-git 16.0.0创建一个简单的共享库。库名是libsum,它提供了对两个整数求和的函数。
// liba.cc
export module liba;
namespace space {
export int sum(int a, int b) { return a + b; }
}
// liba.h
namespace space {
int sum(int,int);
}
库构建无错误
clang++ -std=c++20 -fmodules-ts -fprebuilt-module-path=. --precompile -x c++-module -fimplicit-modules -fimplicit-module-maps -fPIC liba.cc
clang++ -c liba.pcm -o liba.o
clang++ -shared -Wl,-soname,libsum.so -o libsum.so liba.o
当我试图像这样使用它
#include <liba.h>
int main() { return space::sum(1, 2); }
// ./main || echo $?
使用
clang++ -I. -c main.cc
clang++ main.o -o main -Wl,-rpath,. -L. -lsum
链接器返回对space::sum(int, int)
的未定义引用。我检查了库
$ nm -D libsum.so | grep sum
00000000000010f0 T _ZN5spaceW4liba3sumEii
函数包含额外的模块名,因此我无法到达它。在我使用clang 14.0.6的另一个系统上,库构建成功并提供了一个有效的名称
$ nm -D libsum.so | grep sum
00000000000010f0 T _ZN5space3sumEii
,我可以使用它。我尝试了clang 15和clang 16的多个软件包,但都有同样的问题。我已经尝试使用-fuse-ld=lld
在链接相应的lld
版本,但它没有帮助。
如何避免库中多余的liba
名称和访问函数的问题?请给一些建议,在构建/安装clang (llvm)包时可能会出现哪些问题,以及我可能会错过哪些内容。
在一个模块的权限内声明一个名字就是声明这个模块拥有那个名字。当一个名称在模块权限之外声明时,该名称是而不是模块所拥有的。
它们表示不同的名称集,是名称空间之外的一种名称空间。也就是说,未在模块中声明的名称与在模块范围内声明的任何名称表示不同的实体,即使这些名称的字面文本相同。因此,模块是名称混淆的一部分,就像名称空间一样。
所以你的主文件包含一个头文件,声明了space::sum
这个名字。此声明不在模块的权限范围内,因此该名称将在不在模块中的名称集中查找。但是您的库编译将名称space::sum
声明为模块的一部分,并且现在将其嵌入库中。因此,当您的主文件查找space::sum
时,它找不到它,因为编译库中唯一的space::sum
是模块的一部分。
如果你在模块中放了一些东西,标准认为你是认真的。您可以设计一个可以作为模块构建或不作为模块构建的库。但是这些过程会产生不同的库文件。因此,如果您构建的库要作为模块使用,则必须将其作为模块使用。