使用GCC链接具有重复类名的库

时间:2010-05-04 14:13:54

标签: c++ gcc

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自动检测并报告此类情况?

4 个答案:

答案 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 ++编译器将使用类名来生成受损函数名,但是当链接器涉及时,类名本身就已经消失了。

相关问题