GCC是否有办法在链接包含具有相同名称的类的库时生成警告?例如
Port.h
class Port {
public:
std::string me();
};
Port.cpp
#include "Port.h"
std::string Port::me() { return "Port"; }
FakePort.h
class Port {
public:
std::string me();
};
FakePort.cpp
#include "FakePort.h"
std::string Port::me() { return "FakePort"; }
的main.cpp
#include "Port.h"
int main() {
Port port;
std::cout << "Hello world from " << port.me() << std::endl;
return 0;
}
建筑
# g++ -c -o Port.o Port.cpp
# ar rc Port.a Port.o
# g++ -c -o FakePort.o FakePort.cpp
# ar rc FakePort.a FakePort.o
# g++ -c -o main.o main.cpp
# g++ main.o Port.a FakePort.a
# ./a.out
Hello world from Port
更改图书馆订单
# g++ main.o FakePort.a Port.a
# ./a.out
Hello world from FakePort
根据this page:
如果在两个不同的库中定义了符号,gcc将使用它找到的第一个符号并忽略第二个,除非第二个包含在由于某些其他原因而被包含的目标文件中。
所以上述行为是有道理的。不幸的是,我继承了一个相当大的代码库,它没有使用命名空间(并且现在添加它们是不可行的)并且在多个库中使用了一些通用的类名。我想在链接时自动检测重复的名称,以确保类的错误副本不会意外地实例化。类似的东西:
# g++ -Wl,--warnLibraryDupSymbols main.o FakePort.a Port.a
Warning: Duplicate symbol: Port
但我在GCC链接器选项中找不到任何东西来做到这一点。是否有可能让GCC自动检测并报告此类情况?
答案 0 :(得分:3)
以下可能值得一试(老实说,我不知道它能做你想做的事):
--whole-archive
对于--whole-archive选项后命令行中提到的每个归档,请在链接中包含归档中的每个目标文件,而不是在归档中搜索所需的目标文件。这通常用于将存档文件转换为共享库,从而强制将每个对象包含在生成的共享库中。此选项可能不止一次使用。
我还没有尝试过,但听起来好像它会将库中的所有项目都拉进来,就好像它们是目标文件一样。您需要为每个库指定选项。
正如Neil所说,这不会给你类级别的冲突,但如果有类成员具有相同的签名,这可能会让链接器告诉你。
答案 1 :(得分:1)
或者,您可以使用利用nm
的脚本查找候选人,例如类似的东西:
import collections, subprocess, os, re, sys
def filt(s):
p = subprocess.Popen(['c++filt', s],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return p.communicate()[0].strip()
rx = re.compile('^[\\d\\w]+ T [\\w]+', re.MULTILINE)
sym = collections.defaultdict(set)
for file in sys.argv[1:]:
proc = subprocess.Popen(['nm', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for s in rx.findall(proc.communicate()[0]):
sym[s.split()[2]].add(file)
for s in filter(lambda x: len(sym[x])>1, sym):
print 'Duplicate "%s" in %s' % (filt(s), str(sym[s]))
foo:$ python dups.py *.a
Duplicate "Port::me()" in set(['Port.a', 'FakePort.a'])
答案 2 :(得分:0)
我没有看到任何你想要的选择。也许可以横向思考并使用像Doxygen这样的代码文档工具为所有类生成文档并手动查找重复项
答案 3 :(得分:0)
不,没有。这样做的原因是,就链接器而言,类名不是符号。 C ++编译器将使用类名来生成受损函数名,但是当链接器涉及时,类名本身就已经消失了。