Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

Показаны сообщения с ярлыком MSBuild. Показать все сообщения
Показаны сообщения с ярлыком MSBuild. Показать все сообщения

How to properly add custom library dependencies to VC++ project

Adding libraries to your Visual Studio C++ projects might be cumbersome if you aint doing "Hello World" applications. You need to specify include paths, library paths, resource paths etc. For each individual configuration BTW. Then you start the application and realize you must copy dll/pdb/whatever files to your output directory. Sure you google the solution and end up having Custom Build Tools or Steps for each item in your library. That sucks, believe me. But there is much simpler solution! As always on thig blog...

Let's say you have reusable library in your (D)VCS repository. Codejock Xtreme Toolkit Pro is a good example of such a library. Lets make it reusable in seconds.

The answer is a property sheet file for you library:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros">
    <CodejockDir Condition="'$(CodejockDir)' == ''">$(MSBuildThisFileDirectory)</CodejockDir>
    <IsDebug>$([System.Text.RegularExpressions.Regex]::IsMatch($(Configuration), '[Dd]ebug'))</IsDebug>
    <CodejockArchSuffix Condition="'$(PlatformArchitecture)' == '64'">x64</CodejockArchSuffix>
    <UnicodeSuffix Condition="'$(CharacterSet)' == 'Unicode'">U</UnicodeSuffix>
    <DebugSuffix Condition="$(IsDebug)">D</DebugSuffix>
    <CodejockBinDir>$(CodejockDir)\Bin\vc$(PlatformToolsetVersion)$(CodejockArchSuffix)</CodejockBinDir>
    <CodejockItemName>ToolkitPro1531vc$(PlatformToolsetVersion)$(CodejockArchSuffix)$(UnicodeSuffix)$(DebugSuffix)</CodejockItemName>
  </PropertyGroup>
  <PropertyGroup>
    <IncludePath>$(CodejockDir)\Source;$(IncludePath)</IncludePath>
    <LibraryPath>$(CodejockDir)\Lib\vc$(PlatformToolsetVersion)$(CodejockArchSuffix);$(LibraryPath)</LibraryPath>
    <SourcePath>$(CodejockDir)\Source;$(SourcePath)</SourcePath>
    <LocalDebuggerEnvironment>$(CodejockBinDir);%(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
  </PropertyGroup>
  <ItemGroup>
    <CustomBuild Include="$(CodejockBinDir)\$(CodejockItemName).dll">
      <Filter>Libraries\Codejock</Filter>
      <Command>xcopy /Y "%(FullPath)" "$(OutDir)"</Command>
      <Outputs>$(OutDir)\$(CodejockItemName).dll</Outputs>
    </CustomBuild>
    <CustomBuild Include="$(CodejockBinDir)\$(CodejockItemName).pdb" Condition="$(IsDebug)">
      <Filter>Libraries\Codejock</Filter>
      <Command>xcopy /Y "%(FullPath)" "$(OutDir)"</Command>
      <Outputs>$(OutDir)\$(CodejockItemName).pdb</Outputs>
    </CustomBuild>
  </ItemGroup>
  <ItemDefinitionGroup>
    <ResourceCompile>
      <AdditionalIncludeDirectories>$(CodejockDir)\Source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ResourceCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <BuildMacro Include="CodejockDir">
      <Value>$(CodejockDir)</Value>
    </BuildMacro>
  </ItemGroup>
</Project>

Let it have Codejock.props name and reside in you library root folder. This is just an ordinary MSBuild file which can act as a property sheet page for you C++ projects. Now you can just open Property Manager and Add Existing Property Sheet to your project. This automaticaly adds necessary environment and build process changes to make the library work for you. Thats it. And it doesnt fucking overwrite your unchanged dll files every time you hit Build command!

You probably want to understand how does this work? Well, go and RTFM for MSBuild system.

The only unpleasant thing about this -  Solution Explorer displays all those referenced files as childrens of your Visual Studio project (filter element is ignored).

StyleCop 4.3 SDK released

The SDK documentation for StyleCop 4.3 is now available for download, here.

This documentation explains how to create and install custom StyleCop rules, how to integrate custom settings into the StyleCop settings dialog, and how to create a wrapper for hosting StyleCop in a custom build environment.

StyleCop 4.3 released

Download StyleCop 4.3 here.

Проблема с MSBuild CallTarget - созданные properties & items не существуют

Если пользоваться инструкцией <CallTarget Targets="..."/> то внутри ее не будут видны properties и items, которые были созданы с помощью <CreateProperty...> и <CreateItem...>

MSBuild properties & items

Долго мучался, пока до меня не дошло: Property и Item - не взаимозаменяемые!!!

Например, если Task имеет
[Output]
String XXX {
get { ... }
}
То конструкция <Output TaskParameter="XXX" ItemName="MyItem"/> тихонько запихнет в MyItem пустое значение! Правильно: <Output TaskParameter="XXX" PropertyName="MyProperty"/>

Анологично с
[Output]
ITaskItem XXX {
get { ... }
}
<Output TaskParameter="XXX" ItemName="MyItem"/>

Кстати, для того, чтобы создать property или item динамически, можно воспользоваться CreateItem или CreateProperty

<CreateItem Include="$(MSBuildProjectDirectory)\**\*.*">
<Output TaskParameter="Include" ItemName="AllFilesUnderProjectFolder"/>
</CreateItem>

<CreateProperty Value="$(XXX).$(YYY)">
<Output TaskParameter="Value" PropertyName="XXX_YYY"/>
</CreateProperty>

Как создать Task в MSBuild

  • Создать Class Library проект, к примеру MyMSBuildTasks;
  • Добавить Assembly Reference на Microsoft.Build.Framework;
  • Создать public class MyTask, который наследует и реализует интерфейс Microsoft.Build.Framework.ITask;
  • Реализовать метод public override bool Execute(), вернуть true в случае успеха;
  • Подключить его в проект MSBuild следующим образом: <UsingTask TaskName="MyMSBuildTasks.MyTask" AssemblyFile="...\MyMSBuildTasks.dll"/>
  • Пользоваться: <MyTask MyParameter="Something here">...</MyTask>
Для того, чтобы передать в Task параметр, необходимо создать public property: public String MyParameter { get { ... } set { ... } } <MyTask MyParameter="Something here">...</MyTask> Для указания, что параметр является обязательным, - можно пометить атрибутом [Required]: [Required] public String MyParameter { get { ... } set { ... } } Результат работы Task-а можно "отдать" в виде Output-переменных, пометив нужные свойства атрибутом [Output]: [Output] public String MyOutParameter { get { ... } set { ... } }
<MyTask MyParameter="Something here"> <Output TaskParameter="MyOutParameter" ItemName="MyItem"/> </MyTask> <Message Text="MyTask returned $(MyItem) to me!"/> Для упрощения жизни с MSBuild существует сборка Microsoft.Build.Utilities, в которой существуют простейшие реализации классов Task, TaskItem и пр.
Copyright 2007-2011 Chabster