Как установить OutputFile компоновщика (в .vcxproj) из внешнего списка - PullRequest
0 голосов
/ 20 сентября 2019

У меня есть несколько проектов C ++ (.vcxproj) для VS2017, которые производят динамические библиотеки (DLL), которые обрабатываются как «плагины» (т.е. они динамически загружаются приложением).

ИногдаЯ хочу изменить имена созданных DLL-файлов на основе какого-либо списка в текстовом файле (формат может быть изменен):

ProjName1;DLL1
ProjName2;DLL2
...

В первом столбце указано имя проекта ($(ProjectName)), а во втором - для желаемогоИмя DLL ($(TargetName)).

Я хочу, чтобы этот файл анализировался во время сборки, поэтому каждое прочитанное имя DLL входит в $(OutputFile) соответствующего проекта.

Например,ProjName1.vcxproj будет иметь следующий фрагмент (во время сборки):

<Link>
  <OutputFile>$(OutDir)DLL1$(TargetExt)</OutputFile>
</Link>

Я предполагаю, что для этого могут быть использованы определенные возможности msbuild (например, ReadLinesFromFile task и Задача FindInList ), но я не уверен, как соединить эти кусочки).

Есть несколько примеров такой автоматизации, которые следует рассмотреть, хотя я сомневаюсь, что они имеют отношение к формату .vcxproj:

Простой подход заключается в изменении содержимого каждого файла .vcxproj для соответствия списку (либо вручную, либо с помощью какого-либо сценария).

Есть ли другие варианты?


Обновление 1 : мне удалось реализовать частичное решение, основанное на отдельном файле с именем DLL ( имя модуля ) для каждого проекта (см. Функции свойств для получения дополнительных советов).

С помощью таблиц свойств в моем случае было легко «внедрить» исправление во все проекты:

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
  <PropertyGroup Condition="exists('$(MSBuildProjectDirectory)\_MODULE.name')">
    <ModuleName>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\_MODULE.name'))</ModuleName>
    <TargetName>$(ModuleName)</TargetName>
  </PropertyGroup>
...
</Project>

Хотяон работает довольно хорошо, подход не отвечает моим потребностям - я бы хотел, чтобы все имена модулей были в одном файле.

1 Ответ

0 голосов
/ 21 сентября 2019

После некоторых исследований и испытаний мне наконец-то удалось найти рабочее решение для моего случая.По сути, оно построено поверх моего предыдущего частичного решения с использованием магических сил Regex .Подсказка, как обращаться с регулярным выражением в моем контексте, была найдена в другой ответ на подобный вопрос .

Я также немного настроил формат списка:

DLL1=ProjName1
DLL2=ProjName2
...

Я поместил изменения в лист свойств, чтобы их можно было легко найти во всех зависимых проектах:

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
  <PropertyGroup Condition="exists('$(MSBuildThisFileDirectory)..\_MODULES.txt')">
    <ModulesNames>$([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\_MODULES.txt'))</ModulesNames>
    <ModuleName>$([System.Text.RegularExpressions.Regex]::Match($(ModulesNames), '\W?(\w*)\W?=\W?$(MSBuildProjectName)\W?').get_Groups().get_Item(1))</ModuleName>
    <TargetName>$(ModuleName)</TargetName>
  </PropertyGroup>
...
</Project>

Если проект не указан в _MODULES.txt, его $(TargetName) не влияет.

Если вы видите $(ModuleName) в настройках проекта, то все настроено правильно: VS2017 project settings

Решение, кажется, работает нормальноза исключением одного незначительного недостатка : система сборки (VS2017 v.15.9.15) довольно "ленива" при обнаружении изменений в _MODULES.txt, пока решение открыто, поэтому вам придется закрыть его ивозобновлять.И шансы высоки, потребуется пересборка после того, как вы измените список.

...