Связывание библиотек с повторяющимися именами классов с помощью GCC - PullRequest
11 голосов
/ 04 мая 2010

Есть ли способ для 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

Согласно этой странице :

Если символ определен в двух разных библиотеках, gcc будет использовать первую найденную и игнорировать вторую, если только вторая не включена в объектный файл, который включается по какой-либо другой причине.

Так что вышеупомянутое поведение имеет смысл. К сожалению, я наследую значительную базу кода, которая не использует пространства имен (и добавить их сейчас невозможно) и использует некоторые общие имена классов в нескольких библиотеках. Я хотел бы автоматически обнаруживать дубликаты имен во время ссылки, чтобы убедиться, что неправильная копия класса не была случайно создана. Что-то вроде:

# g++ -Wl,--warnLibraryDupSymbols main.o FakePort.a Port.a
  Warning: Duplicate symbol: Port

но я не могу найти ничего в настройках компоновщика GCC, чтобы сделать это. Можно ли заставить GCC автоматически обнаруживать и сообщать о таких случаях?

Ответы [ 4 ]

3 голосов
/ 04 мая 2010

Следующее может стоить попробовать (честно говоря, я не знаю, будет ли это делать то, что вы хотите):

--whole-archive

Для каждого архива, упомянутого в командной строке после параметра --whole-archive, включайте каждый объектный файл в архив в ссылку, а не ищите в архиве требуемые объектные файлы. Обычно это используется для преобразования архивного файла в общую библиотеку, заставляя каждый объект включаться в результирующую общую библиотеку. Эта опция может быть использована более одного раза.

Я не пробовал, но звучит так, как будто он вытянет все элементы библиотеки, как если бы они были объектными файлами. Вам нужно будет указать опцию для каждой библиотеки.

Как сказал Нейл, это не вызовет конфликтов на уровне класса, но если есть ученики с одинаковой подписью, это может заставить компоновщика сказать вам.

1 голос
/ 04 мая 2010

В качестве альтернативы вы можете использовать скрипт, использующий 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'])
0 голосов
/ 04 мая 2010

Нет, нет. Причина этого заключается в том, что имя класса не является символом в том, что касается компоновщика. Компилятор C ++ будет использовать имя класса для получения искаженных имен функций, но само имя класса исчезнет к тому времени, когда компоновщик включится.

0 голосов
/ 04 мая 2010

Я тоже не вижу вариантов делать то, что вы хотите. Возможно, подумайте со стороны и используйте инструмент документирования кода, такой как Doxygen, для создания документации для всех ваших классов и поиска дубликатов вручную

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...