Я новичок в построении единства. Я провел небольшое исследование и получил отличную информацию от:
Однако теперь, когда я начал вносить изменения в некоторые из моих проектов, я немного растерялся.
Для простоты, скажем, у меня есть только 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.
Мой вопрос: почему это работает, когда файлы компилируются отдельно, но не работает со сборкой Unity?
Что отличает один файл .lib от другого? Я имею в виду, технически LibProj.lib
имеет символы для VerboseMonitor::print
в обоих случаях сборки, и эти символы переопределены ExecProj. Однако дело построения единства терпит неудачу.
Одним из способов решения этой проблемы является создание другого файла lib, который содержит только Verbose.cpp, и удаление его из обоих проектов. Тем не менее, я хотел бы понять, почему это происходит в первую очередь.
Кроме того, кто-то может придумать лучший способ обойти эту проблему?
Я думаю, что знаю, что происходит.
Unity.cpp содержит Verbose.cpp и Client.cpp
-Verbose.cpp имеет значение Распечатать.
-Client.cpp включает Verbose.hpp, который вносит в реализацию Распечатать.
Таким образом, Unity.obj имеет 2 реализации Распечатать.
Это означает, что библиотека (LibProj.lib) содержит один .файл obj с Распечатать дубликаты. Поэтому, когда мы пытаемся установить ссылку на библиотеку, компилятор не знает, какая Распечатать использовать.
Причина, по которой это работает на обычных сборках, заключается в том, что обычно Verbose.cpp создает Verbose.obj, который содержит реализацию Распечатать в нем, и Client.cpp создает Client.obj, который содержит реализацию Распечатать в этом тоже. Это означает, что библиотека (LibProj.lib) содержит два .файлы obj с Распечатать определены в каждом, так что компилятор выбирает один (хотя я не знаю, как).
Чтобы проверить эту теорию, я создал 2 файла Unity.
Unity.cpp включает Verbose.cpp
Unity2.cpp включает в себя Client.cpp
С помощью этой реализации я могу построить. Это потому, что LibProj.lib теперь имеет два .файлы obj (Unity.obj & Unity2.obj), каждый из которых содержит реализацию Распечатать, так что нет столкновения символов.
Это просто обоснованное предположение, и я оставляю за собой право ошибаться :). Однако, если я ошибаюсь, поправьте меня.
Благодарю.
Других решений пока нет …