Probably every programmer who was familiar with the MsBuild project building system had the idea not to expand the existing build process, but to invent it from scratch. In other words, add to the existing project types .csproj (a project in C #) and .vbproj (a project in VB.NET) another type (for example, .myproj or simply .proj). And someone, maybe, even tried to realize this idea.
On this topic, it would seem, full of information, there is even a
step-by-step tutorial on MSDN . But, after creating a project file for any such leadership, it becomes clear that we were cruelly deceived - projects created in this way live “by themselves” and can neither be included in the solution nor opened in Visual Studio.
In this article, I present to you my own research on this topic.
Formulation of the problem
In order to determine the minimum requirements imposed on "normal" in the understanding of Visual Studio 2008 projects, create a project that:
- does not perform any actions in the build process;
- correctly opened and displayed in Visual Studio 2008;
- can be added to the list of dependencies for other projects;
- contains several files;
- All project files are considered holidays, i.e. must be copied to the output directories of dependent projects.
Decision process
The process of solving this problem is quite complicated, and therefore is beyond the scope of this article. Let me just say that in the decision process the following tools were used:
- MsBuild Reference on MSDN ;
- text editor;
- the contents of the file% windir% \ Microsoft .NET \ Framework \ v3.5 \ Microsoft.Common.targets;
- the / v: d and / v: diag options of the msbuild.exe program;
- The program grep.exe from the cygwin kit.
Decision
The following project file satisfies all requirements (and is suitable for further expansion):
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <ProjectGuid>{F4279D30-8B96-4217-B811-D2912FAD2C71}</ProjectGuid> </PropertyGroup> <ItemGroup> <BuiltProjectOutputGroupKeyOutput Include="SuperLibrary.dll" /> </ItemGroup> <ItemGroup> <Content Include="logo.bmp" /> <Content Include="help.html" /> </ItemGroup> <Target Name="Build" Outputs="" /> <Target Name="Rebuild" /> <Target Name="Clean" /> <Target Name="GetTargetPath" Outputs="" /> <Target Name="GetNativeManifest" Outputs="" /> <Target Name="GetCopyToOutputDirectoryItems" Outputs="@(_Content)"> <ItemGroup> <Content Include="@(BuiltProjectOutputGroupKeyOutput)" /> <_Content Include="@(Content->'%(FullPath)')"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>%(Filename)%(Extension)</TargetPath> </_Content> </ItemGroup> </Target> </Project>
')
findings
In the process of working on the above project file, the following requirements emerged that were imposed by Visual Studio 2008 on all project files:
- The project file must have an extension associated with languages ​​using MsBuild, that is, .csproj or .vbproj, but not .myproj;
- ProjectGuid property must be present in the project file;
- the project must have an element BuiltProjectOutputGroupKeyOutput with the extension .dll or .exe (this element can be imported);
- all elements specified in the project file (but not imported from other files!) are displayed in Solution Explorer and must be present on the disk (elements imported from other files are not displayed in the GUI);
- The project must have Build, Rebuild and Clean goals, as well as GetTargetPath, GetNativeManifest and GetCopyToOutputDirectoryItem goal-functions;
- The Build and GetTargetPath targets must specify the output of the project’s primary output file (but may not return anything if there is no primary file);
- the goal of GetNativeManifest is to return the project manifest in the case when the project has this same manifest;
- The GetCopyToOutputDirectoryItems target should return a list of files that are output for the project;
- for all elements returned by goal-functions (including Build), only full paths should be used (since these elements are transferred between projects);
- for all items returned by the GetCopyToOutputDirectoryItems target, the CopyToOutputDirectory metadata with the value Always or PreserveNewest must be specified;
- For all items returned by the GetCopyToOutputDirectoryItems target, TargetPath metadata must be specified, meaning the relative file name when copying it to the output directory of another project (% (Filename)% (Extension), that is, the name and extension of the source element) is a good default).
I argue that any project that meets these requirements can be opened in Visual Studio 2008, added to the solution to other projects, and also added to the dependency list of another project.