Связывание библиотек с именами Duplicate Class с использованием 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
Согласно эта страница:
Если символ определен в двух разных библиотеках, gcc будет использовать первый, который он найдет и проигнорирует второй, если только второй не включен в объектный файл, который включается по какой-либо другой причине.
Таким образом, вышеизложенное поведение имеет смысл. К сожалению, я наследую значительную базу кода, которая не использует пространства имен (и добавление их сейчас практически невозможно) и использует некоторые общие имена классов в нескольких библиотеках. Я хотел бы автоматически обнаруживать повторяющиеся имена во время ссылки, чтобы убедиться, что неправильная копия класса не случайно создается. Что-то вроде:
# g++ -Wl,--warnLibraryDupSymbols main.o FakePort.a Port.a
Warning: Duplicate symbol: Port
но я не могу найти что-либо в настройках компоновщика GCC для этого. Можно ли заставить GCC автоматически обнаруживать и сообщать о таких случаях?
Ответы
Ответ 1
Возможно, стоит попробовать (я честно не знаю, будет ли он делать то, что вы хотите):
--whole-archive
Для каждого архива, указанного в командной строке после опции -whole-archive, включайте каждый объектный файл в архив в ссылке, а не поиск в архиве для требуемых объектных файлов. Обычно это используется для превращения архивного файла в общую библиотеку, заставляя каждый объект быть включенным в итоговую общую библиотеку. Эта опция может использоваться несколько раз.
Я не пробовал, но звучит так, как будто он будет тянуть все элементы в библиотеке, как если бы они были объектными файлами. Вам нужно указать опцию для каждой библиотеки.
Как сказал Нил, это не даст вам конфликтов на уровне классов, но если есть члены класса с одной и той же сигнатурой, это может заставить компоновщик рассказать вам.
Ответ 2
В качестве альтернативы вы можете использовать script используя 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'])
Ответ 3
Я не вижу никаких вариантов делать то, что вы хотите. Возможно, подумайте в поперечном направлении и используйте инструмент документации по документации, такой как Doxygen, для создания документации для всех ваших классов и поиска в ручном режиме дубликатов.
Ответ 4
Нет, нет. Причина этого в том, что имя класса не является символом в отношении компоновщика. Компилятор С++ будет использовать имя класса для генерации названий функциональных функций, но само название класса не исчезнет к тому времени, когда задействуется компоновщик.