C++ Unity создает файл библиотеки, LNK2005

Я новичок в сборках Unity. Я провел некоторое исследование и получил отличную информацию от:

Однако теперь, когда я начал вносить изменения в некоторые из своих проектов, я немного запутался.

Для простоты предположим, что в моем решении всего 2 проекта. Проект библиотеки (он создает файл .lib) и исполняемый проект. Назовем их LibProj и ExecProj.

Вот так выглядит каждый проект:

LibProj
>include
>>Client.hpp<br>
>>Driver.hpp<br>
>>Verbose.hpp

>source
>>Client.cpp<br>
>>Verbose.cpp

ExecProj
>source
>>MyMainFile.cpp<br>
  Verbose.cpp

Verbose.cpp используется для целей отладки. Он оборачивает ostream, поэтому вместо cout << я использую verbose <<. Это делается для управления выводом подробного вывода на консоль. В моих вариантах выпуска весь подробный вывод пропускается.

Причина, по которой у меня есть копия Verbose.cpp в обоих проектах, заключается в том, что я могу получить подробный вывод в моем ExecProj без необходимости сборки LibProj в отладке.

Driver.hpp и Client.cpp используют verbose <<. MyMainFile.cpp вызывает функции в обоих из них.

Что и говорить, при обычном способе сборки все работает.

Теперь проблема...

Я создал Unity.cpp внутри LibProj. Его содержание:

#include "Client.cpp"
#include "Verbose.cpp"

LibProj отлично строится. Однако, когда я собираю ExecProj, он ломается во время компоновки:

LibProj.lib(Unity.obj) : error LNK2005: "public: void __thiscall VerboseMonitor::print(char const *,int)"
(?print@VerboseMonitor@@QAEXPBDH@Z) already defined in Verbose.obj
LibProj.lib(Unity.obj) : error LNK2005: "public: __thiscall VerboseStream::VerboseStream(void)" 
(??0VerboseStream@@QAE@XZ) already defined in Verbose.obj
C:\Users\\...\ExecProj.exe : fatal error
LNK1169: one or more multiply defined symbols found

По сути, он жалуется, потому что мы переопределяем подробные функции, которые уже существуют в файле lib.

Мой вопрос: почему это работает, когда файлы скомпилированы отдельно, но не работает с сборкой единства?

Чем один файл .lib отличается от другого? Я имею в виду, что технически LibProj.lib имеет символы для VerboseMonitor::print в обоих случаях сборки, и эти символы переопределяются ExecProj. Однако случай сборки единства терпит неудачу.

Один из способов обойти эту проблему — создать еще один файл библиотеки, содержащий только Verbose.cpp, и удалить его из обоих проектов. Тем не менее, я хотел бы сначала понять, почему это происходит.

Кроме того, может ли кто-нибудь придумать лучший способ обойти эту проблему?


person Pancho    schedule 03.01.2013    source источник
comment
Добро пожаловать в удовольствие от сборки Unity. Есть ли особая причина, по которой вы хотите это сделать?   -  person Retired Ninja    schedule 03.01.2013
comment
Время сборки занимает более часа. На самом деле в моем решении более 150 проектов, а в LibProj почти 1000 файлов. Я ищу способы ускорить время сборки.   -  person Pancho    schedule 03.01.2013
comment
Пожалуйста, не злоупотребляйте тегом модуля, так как он используется для Microsoft Unity. Пора сделать новый тег.   -  person Lex Li    schedule 26.01.2013


Ответы (1)


Думаю, я знаю, что происходит.

Unity.cpp содержит Verbose.cpp и Client.cpp
-Verbose.cpp имеет реализацию print.
-Client.cpp включает Verbose.hpp, который обеспечивает реализацию print.
Итак, Unity.obj имеет 2 реализации print.

Это означает, что библиотека (LibProj.lib) содержит один файл .obj с дубликатами для печати. Поэтому, когда мы пытаемся связать библиотеку, компилятор не знает, какой print использовать.

Причина, по которой это работает в обычных сборках, заключается в том, что обычно Verbose.cpp создает Verbose.obj, который содержит реализацию print, а Client.cpp создает Client.obj, который содержит реализацию распечатайте в нем. Это означает, что библиотека (LibProj.lib) содержит два файла .obj, в каждом из которых определен print, поэтому компилятор выбирает один (правда, я не знаю, как это сделать) .

Чтобы проверить эту теорию, я создал 2 файла Unity.
Unity.cpp включает Verbose.cpp
Unity2.cpp включает Client.cpp.

С этой реализацией я могу построить. Это связано с тем, что в LibProj.lib теперь есть два файла .obj (Unity.obj и Unity2.obj), каждый из которых содержит реализацию print, поэтому символы не конфликтуют.

Это всего лишь предположение, и я оставляю за собой право ошибаться :). Однако, если я ошибаюсь, поправьте меня.

Спасибо.

person Pancho    schedule 04.01.2013