Проблема статической связи VS2010

моя компания недавно обновилась от VS2005 до VS2010. У нас есть огромный проект, который использует множество модулей, которые статически связаны с exe. Но, похоже, есть некоторые проблемы со связью в VS2010.

Чтобы объяснить нашу проблему, мы создали минимальный примерный проект, который составлен, как показано на этом рисунке:

minimal library example

Существует приложение, использующее одну функцию из библиотеки A. Библиотека A вызывает одну функцию из каждой библиотеки B и библиотеки C. Эти две библиотеки вызывают функцию, предоставляемую библиотекой D.

Для Exe 1 в рамках Framework и ссылок мы устанавливаем все значение в false, за исключением зависимостей библиотеки библиотек, для которых установлено значение true. Добавлена ​​только ссылка на библиотеку A. Для каждой из библиотек все настройки имеют значение false. Библиотека A получает ссылки только на B и C, а также те, кто получает ссылки только на D. Библиотека D не имеет ссылок.

При создании приложения он работает без проблем. Приложение замечает, что библиотека A использует библиотеки B и C, которые используют библиотеку D, поэтому она знает, что она также должна связывать эти библиотеки. Libs связаны с exe без проблем.

Теперь мы что-то изменим, скажем, в библиотеке D. Просто небольшая разница, только одно письмо. Теперь мы пытаемся снова создать приложение, оно замечает изменение и перекомпилирует библиотеку D, но: оно больше не ссылается на него. В результате связывание ошибок в библиотеке B и C, потому что они используют библиотеку D. Сначала мы должны запустить Rebuild, чтобы принудительно создать полное здание и , затем все снова связано.

Это происходит как для минимального примера, так и для нашего основного проекта. Конечно, мы можем добавить каждую из библиотек в качестве дополнительной зависимости для exe, но было бы неплохо, если бы она работала так же, как при создании проекта в первый раз, и продолжала работать после изменений кода. Мы заметили, что при настройке Use Library Dependency Inputs на true, что он работает снова, но тогда он не связывает файлы *.lib, а файлы *.obj, которые мы не хотим, конечно.

Кто-нибудь сделал подобный опыт или у кого-нибудь есть решение этой проблемы? Является ли это ошибкой поведения VS2010?

ТИА.

p.s.: Все библиотеки и исполняемые файлы являются родными С++.


Изменить: (Обходное решение взято из этот сайт)

В файле %ProgramsFile%\MSBuild\Microsoft.cpp\v4.0\Microsoft.CPPBuild.Targets есть строка

<Target Name="GetResolvedLinkLibs" Returns="@(LibFullPath)" DependsOnTargets="$(CommonBuildOnlyTargets)">

Если вы измените эту строку на

<Target Name="GetResolvedLinkLibs" Returns="@(LibFullPath)" DependsOnTargets="$(CommonBuildOnlyTargets);ResolvedLinkLib">

ссылка работает правильно, и все необходимые библиотеки связаны с неявным образом. Выход компоновщика не только отображает lib_a.lib, но и все другие запущенные libs, lib_b, lib_c, lib_d, не добавляя их вручную в зависимости от exe.

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

Ответ 1

Посмотрите на следующие ссылки:

Visual Studio 2010 не автонастраивает статические библиотеки из проектов, зависимых от них, как и должно быть

Поведение зависимостей библиотеки ссылок в 2010 году

Unresolved Externals при создании проекта VС++ с привязанными статическими зависимостями Lib

Гибкие ссылки на проект-проект

Ответ 2

Я знаю только, что у меня были подобные ситуации из-за неправильного использования библиотек с одним и тем же именем, но с различной архитектурой. скажем, у меня есть Dll (давайте назовем его mydll.dll) для x86 и импортируем его в мой проект, он будет работать. Если я сделаю то же самое с dll x64 (то же имя mydll.dll), он будет работать. Но если я хочу включить обе библиотеки, не разрешается переименовывать его только в mydllx86.dll/mydllx64.dll. Я могу теперь включить обе библиотеки в Visual Studio. Но при компиляции или перезапуске визуальной студии одна из двух библиотек будет больше недоступна.

В этом случае, возможно, это помогает взглянуть на библиотечную архитектуру и использовать имена namespaces/Api.

Привет

Ответ 3

В этом диалоговом окне вы потерялись довольно сильно, если вы возитесь с Framework и ссылками, это настройки, которые применяются только к управляемому коду. Термин "ссылка" применяется только к сборкам .NET. Компилятор не поддерживает сохранение скомпилированного управляемого кода в .lib. Я буду работать из предположения, что вы на самом деле меняете настройки компоновщика. Если вы внесете изменения в библиотеку D, вам также придется изменить его заголовочный файл. Который сам по себе будет достаточным для восстановления B и C, так как один или несколько из файлов исходного кода должны # включать этот заголовок.

Единственное, что Зависимости Библиотеки ссылок делает, автоматически делает зависимость .lib, такую ​​же, как Linker + Input, Additional Dependency. Однако для этого требуется явно указать зависимости проекта. Щелкните правой кнопкой мыши проект B, выберите "Зависимости проекта" и отметьте D. Повторите для C. Повторите для A и отметьте B и C. Повторите для EXE и отметьте A.

Это редко вы хотите, это делает библиотеку D встроенной в библиотеки B и C. И B и C встроены в A. EXE теперь имеет только зависимость от A. Это работает, но делает файлы .lib излишне мудрыми. И у вас есть проблема, которую вы описываете, если вы не задали зависимостей проекта должным образом, перестройка D не приводит к повторному подключению B и C.

Что вам нужно сделать, это не устанавливать зависимости между .libs, их нет. Каждый из них может быть построен без наличия других .libs. A.lib - это всего лишь мешок файлов .obj. Все, что требуется, это то, что вы выполняете все 4 проекта .lib-проектов проекта EXE. Это гарантирует, что они будут созданы до того, как компоновщик попытается связать EXE.

Ответ 4

Мы снова увидим эту проблему после перехода на Visual Studio 2015 (а также в VS2017). Проблема, похоже, существует только в следующей конфигурации:

Project (EXE)
  --> Static Library A (Reference)
    --> Static Library B (Specified in Linker->Additional Dependencies)
      --> Static Library C (Not in solution, specified in Linker->Additional Dependencies)

В решении есть несколько других проектов, которые используют A и B. Когда что-то в проектах B или C изменяется, многие из этих проектов предоставляют предупреждения LNK4099. В нашем случае решение должно использовать следующее:

Генерация кодa > Выходные файлы > Имя файла базы данных программы: $(TargetDir) $(TargetName).pdb

Библиотекарь > Общие > Выходной файл: $(TargetDir) $(TargetName) $(TargetExt)

$(TargetDir) использует абсолютный путь по умолчанию $(OutDir), который в нашем случае был относительным. Кажется, что правильный путь теряется с несколькими уровнями косвенности.

Интересно, если вы переключите количество компилируемых потоков на 1, это, похоже, не произойдет (возможно, какое-то состояние гонки в Visual Studio?).