Подтвердить что ты не робот

Как я могу заставить MSBUILD оценивать и печатать полный путь при предоставлении относительного пути?

Как я могу заставить MSBuild оценивать и печатать в задаче <Message /> абсолютный путь, заданный относительным путем?

Группа свойств

<Source_Dir>..\..\..\Public\Server\</Source_Dir>
<Program_Dir>c:\Program Files (x86)\Program\</Program_Dir>

Task

<Message Importance="low" Text="Copying '$(Source_Dir.FullPath)' to '$(Program_Dir)'" />

Выход

Копирование '' в 'c:\Program Files (x86)\Program \'

4b9b3361

Ответ 1

В MSBuild 4.0 самый простой способ:

$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)\your\path'))

Этот метод работает, даже если script <Import> ed в другой script; путь относится к файлу, содержащему указанный выше код.

(консолидировано из ответа Аарона, а также последняя часть Sayed answer)


В MSBuild 3.5 вы можете использовать задачу ConvertToAbsolutePath:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         DefaultTargets="Test"
         ToolsVersion="3.5">
  <PropertyGroup>
    <Source_Dir>..\..\..\Public\Server\</Source_Dir>
    <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir>
  </PropertyGroup>

  <Target Name="Test">
    <ConvertToAbsolutePath Paths="$(Source_Dir)">
      <Output TaskParameter="AbsolutePaths" PropertyName="Source_Dir_Abs"/>
    </ConvertToAbsolutePath>
    <Message Text='Copying "$(Source_Dir_Abs)" to "$(Program_Dir)".' />
  </Target>
</Project>

Соответствующий вывод:

Project "P:\software\perforce1\main\XxxxxxXxxx\Xxxxx.proj" on node 0 (default targets).
  Copying "P:\software\Public\Server\" to "c:\Program Files (x86)\Program\".

Немного длинный, если вы спросите меня, но он работает. Это будет относиться к "оригинальному" файлу проекта, поэтому, если он помещен внутри файла, который получает <Import> ed, это не относится к этому файлу.


В MSBuild 2.0 существует подход, который не разрешает "..". Однако он ведет себя как абсолютный путь:

<PropertyGroup>
    <Source_Dir_Abs>$(MSBuildProjectDirectory)\$(Source_Dir)</Source_Dir_Abs>
</PropertyGroup>

$(MSBuildProjectDirectory) зарезервированное свойство всегда является каталогом script, который содержит эту ссылку.

Это также будет относиться к "оригинальному" файлу проекта, поэтому, если он помещен внутри файла, который получает <Import> ed, это не относится к этому файлу.

Ответ 2

MSBuild 4.0 добавила Функции свойств, которые позволяют вам вызывать статические функции в некоторых системных dll.net. Очень хорошая вещь о свойствах функций заключается в том, что они будут оценивать сторону цели.

Чтобы определить полный путь, вы можете использовать System.IO.Path.GetFullPath при определении такого свойства:

<PropertyGroup>
  <Source_Dir>$([System.IO.Path]::GetFullPath('..\..\..\Public\Server\'))</Source_Dir>
</PropertyGroup>

Синтаксис немного уродливый, но очень мощный.

Ответ 3

Уэйн прав, что известные метаданные не относятся к свойствам - только к элементам. Использование таких свойств, как "MSBuildProjectDirectory", будет работать, но я не знаю встроенного способа разрешения полного пути.

Другой вариант - написать простую, настраиваемую задачу, которая займет относительный путь и выплюнет полностью разрешенный путь. Он будет выглядеть примерно так:

public class ResolveRelativePath : Task
{
    [Required]
    public string RelativePath { get; set; }

    [Output]
    public string FullPath { get; private set; }

    public override bool Execute()
    {
        try
        {
            DirectoryInfo dirInfo = new DirectoryInfo(RelativePath);
            FullPath = dirInfo.FullName;
        }
        catch (Exception ex)
        {
            Log.LogErrorFromException(ex);
        }
        return !Log.HasLoggedErrors;
    }
}

И ваши строки MSBuild выглядят примерно так:

<PropertyGroup>
    <TaskAssembly>D:\BuildTasks\Build.Tasks.dll</TaskAssembly>
    <Source_Dir>..\..\..\Public\Server\</Source_Dir>
    <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir>
</PropertyGroup>
<UsingTask AssemblyFile="$(TaskAssembly)" TaskName="ResolveRelativePath" />

<Target Name="Default">
    <ResolveRelativePath RelativePath="$(Source_Dir)">
    <Output TaskParameter="FullPath" PropertyName="_FullPath" />
    </ResolveRelativePath>
    <Message Importance="low" Text="Copying '$(_FullPath)' to '$(Program_Dir)'" />
</Target>

Ответ 4

Вы пытаетесь получить доступ к свойству метаданных элемента через свойство, что невозможно. То, что вы хотите сделать, выглядит примерно так:

<PropertyGroup>
  <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir>
</PropertyGroup>
<ItemGroup>
   <Source_Dir Include="..\Desktop"/>
</ItemGroup>     
<Target Name="BuildAll">
   <Message Text="Copying '%(Source_Dir.FullPath)' to '$(Program_Dir)'" />
</Target>

Что будет генерировать вывод как:

 Copying 'C:\Users\sdorman\Desktop' to 'c:\Program Files (x86)\Program\'

(script был запущен из моей папки "Документы", поэтому..\Рабочий стол - это правильный относительный путь для доступа к моему рабочему столу.)

В вашем случае замените "..\Desktop" на "......\Public\Server" в элементе Source_Dir, и все должно быть установлено.

Ответ 5

Если вам нужно преобразовать свойства в элементы, у вас есть два варианта. С помощью msbuild 2 вы можете использовать задачу CreateItem

  <Target Name='Build'>
    <CreateItem Include='$(Source_Dir)'>
      <Output ItemName='SRCDIR' TaskParameter='Include' />
    </CreateItem>

а с помощью MSBuild 3.5 вы можете иметь ItemGroups внутри задачи

  <Target Name='Build'>
    <ItemGroup>
      <SRCDIR2 Include='$(Source_Dir)' />
    </ItemGroup>
    <Message Text="%(SRCDIR2.FullPath)" />
    <Message Text="%(SRCDIR.FullPath)" />
  </Target>