VC ++ заменяет определения различных объектов, GCC и т. Д., А не - PullRequest
0 голосов
/ 13 января 2010

У меня большое приложение, использующее много статических библиотек, которое не зависит от платформы и развернуто под Windows и Linux.

Все статические библиотеки и сам main () скомпилированы с двумя определениями:

-DVERSION=1.0.0 -DBUILD_DATE=00.00.0000

Эти определения используются макросами внутри каждой статической библиотеки и внутри основной для хранения текущей версии библиотеки внутри класса, подобного реестру.

В GCC / Linux это работает очень хорошо - вы можете перечислить все связанные модули и отобразить их реальную версию и дату сборки, например ::10000

  • ImageReader 0.5.4 (12.01.2010)
  • Компресс 1.0.1 (03.01.2010)
  • SQLReader 0.3.3 (22.12.2009)

Но: когда я связываю точно такой же код с VisualStudio 2005 SP1, я получаю только версию и дату сборки последнего скомпилированного модуля:

  • ImageReader 0.5.4 (12.01.2010)
  • Компресс 0.5.4 (12.01.2010)
  • SQLReader 0.5.4 (12.01.2010)

У кого-нибудь есть идея? Это проблема «оптимизации» компоновщика VC ++?

Ответы [ 6 ]

2 голосов
/ 13 января 2010

Ну, Visual Studio поддерживает решения с несколькими проектами. И его механизм зависимостей способен обнаруживать, что измененное значение макроса требует перекомпиляции проекта. Бритва Оккама говорит, что библиотеки просто перестроились и приобрели новое значение макроса VERSION.

0 голосов
/ 13 января 2010

"Эти определения используются макросами внутри каждой статической библиотеки и внутри главной для хранения текущей версии библиотеки внутри класса, похожего на реестр."

Ты случайно не нарушаешь Правило Единого Определения? Если у вас есть один класс, он должен иметь одно определение для всех библиотек. Похоже, определение класса зависит от макроса версии, этот макрос определяется по-разному в разных частях вашей программы, и поэтому вы нарушаете ODR. Наказанием за это является неопределенное поведение.

Кажется, что компоновщик MS использует преимущества ODR, игнорируя все, кроме первого определения. В конце концов, если все определения X одинаковы, вы можете игнорировать все, кроме первого.

0 голосов
/ 13 января 2010

Это может быть проблемой, если вы используете предварительно скомпилированные заголовки. Попробуйте создать приложение, отключив параметр предварительно скомпилированных заголовков.

0 голосов
/ 13 января 2010

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

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

Кроме того, лучший способ создания версий этих двоичных файлов заключается в использовании макросов непосредственно в заголовках / источнике и присвоении им всех уникальных имен для каждой библиотеки. Таким образом, они не могут мешать друг другу (если вы не клонируете один из заголовков в приложение, дублируя определения макросов), и вы больше не зависите от компилятора, чтобы сделать это правильно.

0 голосов
/ 13 января 2010

Это не имеет ничего общего с компоновщиком Visual Studio; это просто вопрос макросов препроцессора, поэтому проблема уже в самом начале, до того, как компилятор даже заработает.

Как выглядит строка компиляции в вашей сборке Visual Studio? Моя первая идея заключается в том, что по какой-то причине определения (-D аргументы) добавляются в одну командную строку, а последняя всегда побеждает.

0 голосов
/ 13 января 2010

Определения препроцессора разрешаются на этапе препроцессора компилятора, а не компоновщика.

Возможно, проблема в скомпилированных заголовках в VC ++.

В противном случае, чтобы действительно сказать, я хотел бы видеть исходный код, делающий фактическую печать версии (даты).

...