This is basically a follow up question to:
Using Visual Studio project properties effectively for multiple projects and configurations
Our library's target name is currently in this format:
$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)
We'd like to add information about the runtime library used by the project to the target name, I tried adding $(RuntimeLibrary), but that doesn't seem to be set. Is there any other way to get the runtime library at the time the target name is resolved?
Thanks,
John.
With this property sheet you can do this. Import it in your property sheet and you will be able to access the RuntimeLibrary this way: $(RuntimeLibrary)
Yes!!! This will work in your propertie sheet =^.~=
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_IsDebug>$([System.Convert]::ToString($([System.Text.RegularExpressions.Regex]::IsMatch($(Configuration),'[Dd]ebug'))))</_IsDebug>
<_ItemDefinitionGroupRegex><![CDATA[<ItemDefinitionGroup Condition=".*']]>$(Configuration)\|$(Platform)<![CDATA['">((?:.*\n)*?.*)</ItemDefinitionGroup>]]></_ItemDefinitionGroupRegex>
<_RuntimeLibraryRegex><![CDATA[(?:.*\n)*?.*<RuntimeLibrary>(.*)</RuntimeLibrary>(?:.*\n)*?.*]]></_RuntimeLibraryRegex>
<_HasRuntimeLibrary>$([System.Text.RegularExpressions.Regex]::IsMatch($([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText($(ProjectPath))), $(_ItemDefinitionGroupRegex)).Result('$1')), $(_RuntimeLibraryRegex)))</_HasRuntimeLibrary>
<!--
Fix incremental build (Different results when running msbuild within Visual Studio or from console).
http://connect.microsoft.com/VisualStudio/feedback/details/677499/different-results-when-running-msbuild-within-visual-studio-or-from-console
-->
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
<Choose>
<When Condition="$([System.Convert]::ToBoolean($(_HasRuntimeLibrary)))">
<!-- Extract runtime library from project file. -->
<PropertyGroup Label="UserMacros">
<_RuntimeLibrary>$([System.Text.RegularExpressions.Regex]::Match($([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText($(ProjectPath))), $(_ItemDefinitionGroupRegex)).Result('$1')), $(_RuntimeLibraryRegex)).Result('$1'))</_RuntimeLibrary>
</PropertyGroup>
</When>
<Otherwise>
<!-- Set default runtime library -->
<PropertyGroup Label="UserMacros">
<_RuntimeLibrary Condition=" '$(_IsDebug)' == 'True' ">MultiThreadedDebugDLL</_RuntimeLibrary>
<_RuntimeLibrary Condition=" '$(_IsDebug)' == 'False' ">MultiThreadedDLL</_RuntimeLibrary>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup Label="UserMacros">
<IsDebug>$(_IsDebug)</IsDebug>
<ConfigType Condition=" '$(IsDebug)' == 'True' ">Debug</ConfigType>
<ConfigType Condition=" '$(IsDebug)' == 'False' ">Release</ConfigType>
<Architecture Condition=" '$(Platform)' == 'Win32' ">x86</Architecture>
<Architecture Condition=" '$(Platform)' == 'x64' ">x64</Architecture>
<Toolset Condition=" '$(PlatformToolset)' == 'v110' ">msvc.110</Toolset>
<RuntimeLibrary>$(_RuntimeLibrary)</RuntimeLibrary>
</PropertyGroup>
<ItemGroup>
<BuildMacro Include="IsDebug">
<Value>$(IsDebug)</Value>
</BuildMacro>
<BuildMacro Include="Toolset">
<Value>$(Toolset)</Value>
</BuildMacro>
<BuildMacro Include="Architecture">
<Value>$(Architecture)</Value>
</BuildMacro>
<BuildMacro Include="RuntimeLibrary">
<Value>$(RuntimeLibrary)</Value>
</BuildMacro>
<BuildMacro Include="ConfigType">
<Value>$(ConfigType)</Value>
</BuildMacro>
</ItemGroup>
</Project>
Related
I created a custom MSBuild project that I can "build" from Visual Studio 2019, as described in https://stackoverflow.com/a/64917535/1536933. That is, I can select the Build menu item in VS and it runs my custom MSBuild task. Is there a way to do the same with "Run" - get VS to run my custom MSBuild task when I "Start" (or "Start without debugging") that project? I worked out that for the Build menu item to appear VS needs to see MSBuild targets named "Build" and "CoreCompile" - there is probably some equivalent for Start, but what?
The custom project file looks like this:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>(some guid)</ProjectGuid>
<ProjectHome>.</ProjectHome>
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
</PropertyGroup>
<!-- These property groups can be empty, but need to be defined for VS -->
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
</PropertyGroup>
<Import Project="My.Build.targets" />
<!-- Define empty standard MSBuild targets, since this project doesn't have them. Doing it this way allows My.Build.targets to also be used in a project that does define them. -->
<Target Name="Build" />
<Target Name="ReBuild" />
<Target Name="Clean" />
<!-- NOTE: a target named "CoreCompile" is needed for VS to display the Build menu item. -->
<Target Name="CoreCompile" />
<!-- Files shown in Visual Studio - adding and removing these in the UI works as expected -->
<ItemGroup>
<Content Include="myfile..." />
</ItemGroup>
</Project>
Note that it's not a C# project or C++ project or any other common type of project - VS treats its as a Node.js project due to the ProjectTypeGuids, but if I can get it working some other way, I'd be happy to.
SSAS projects can't be built using MSBuild. However, SSAS projects can reportedly be built using Visual Studio or SSAS Helper (description).
Using the Visual Studio GUI (devenv.exe), the build of my SSAS 2016 Tabular project does indeed build fine:
Visual Studio also provides a CLI for non-interactive use: devenv.com . However, although my project builds fine using the GUI, it throws an error when trying to build using the CLI:
How do I build my SSAS 2016 Tabular projects using the CLI? Does devenv.com use another library for building than devenv.exe?
Background / more information / tries:
The SSAS Helper Sample CLI yields the same error.
The internet doesn't seem to know about this problem..
My smproj file looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Development</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8CE414BB-95B2-4C99-9E03-51BA72086E22}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>MyRootNamespace</RootNamespace>
<AssemblyName>MyAssemblyName</AssemblyName>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<OutputPath>bin\</OutputPath>
<Name>ProjectName_Tabular</Name>
<DeploymentServerName>devserver</DeploymentServerName>
<DeploymentServerEdition>Developer</DeploymentServerEdition>
<DeploymentServerVersion>Version_11_0</DeploymentServerVersion>
<DeploymentServerDatabase>ProjectName_Tabular</DeploymentServerDatabase>
<DeploymentServerCubeName>Model</DeploymentServerCubeName>
<DeploymentOptionProcessing>Default</DeploymentOptionProcessing>
<DeploymentOptionTransactionalDeployment>False</DeploymentOptionTransactionalDeployment>
<DeploymentOptionDirectQueryMode>InMemory</DeploymentOptionDirectQueryMode>
<DeploymentOptionQueryImpersonation>Default</DeploymentOptionQueryImpersonation>
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Development' ">
<OutputPath>bin\Development\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DeploymentServerEdition>Enterprise</DeploymentServerEdition>
<DeploymentOptionProcessing>Full</DeploymentOptionProcessing>
</PropertyGroup>
<ItemGroup>
<Compile Include="ProjectName_Tabular.bim">
<SubType>Code</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Business Intelligence Semantic Model\1.0\Microsoft.AnalysisServices.VSHostBuilder.targets" />
</Project>
With tabular, you can run msbuild. For example,
msbuild TabularProject8.smproj /verbosity:m /target:Rebuild /property:Configuration=Release
I'm trying to pass a dynamically determined version of a product to a WiX project via a call to an MSBuild project from Jenkins.
For starters, I don't think the problem is actually in Jenkins, since I can't get what I'm trying to do to work when running MSBuild from the VS2013 command prompt with a version hardcoded into our MSBuild project file.
The MSBuild project file is set to run from Jenkins with the following parameters: /p:Configuration=Release /p:Platform="x86" /p:AllowUnsafeBlocks=true
The MSBuild project looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildCommunityTasksPath>$(MSBuildProjectDirectory)\.build</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.targets"/>
<!-- Version Number -->
<PropertyGroup>
<Major>0</Major>
<Minor>9</Minor>
<Build>1</Build>
<!--Jenkins sets BUILD_NUMBER -->
<Revision>$(BUILD_NUMBER)</Revision>
</PropertyGroup>
<PropertyGroup>
<OutputPath>$(MSBuildProjectDirectory)\_LatestBuild\</OutputPath>
</PropertyGroup>
<Target Name="Version">
<Message Text="Version: $(Version)"/>
<AssemblyInfo CodeLanguage="CS"
OutputFile="$(MSBuildProjectDirectory)\GlobalAssemblyInfo.cs"
AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)"
AssemblyConfiguration="$(Configuration)"
Condition="$(Revision) != '' " />
<AssemblyInfo CodeLanguage="CS"
OutputFile="$(MSBuildProjectDirectory)\GlobalAssemblyInfo.cs"
AssemblyVersion="$(Major).$(Minor).*"
AssemblyConfiguration="$(Configuration)"
Condition="$(Revision) == '' " />
</Target>
<Target Name="AfterBuild">
<ItemGroup>
<ZipSourceFiles Include="$(OutputPath)\Installer\**\*.*" Exclude="$(OutputPath)\Installer\**\*.zip;$(OutputPath)\Installer\**\*.wixpdb" />
<ZipFile Include="ProductName v$(Major).$(Minor).$(Build).$(Revision).zip"/>
</ItemGroup>
<Message Text="Zip: $(OutputPath)\*.*"/>
<Zip Files="#(ZipSourceFiles)" WorkingDirectory="$(OutputPath)\Installer\" ZipFileName="#(ZipFile)" ParallelCompression="false" />
<Message Text="Copying archive..."/>
<Copy SourceFiles="#(ZipFile)" DestinationFolder="\\serverName\Projects\Active\ProductName\Builds" />
</Target>
<!-- Projects to Build -->
<ItemGroup>
<ProjectFiles Include="$(MSBuildProjectDirectory)\**\*.sln">
<Properties>Configuration=$(Configuration)</Properties>
</ProjectFiles>
</ItemGroup>
<Target Name="Compile" DependsOnTargets="Version">
<MSBuild Projects="#(ProjectFiles)" />
</Target>
<Target Name="BuildInstaller">
<MSBuild Projects="$(MSBuildProjectDirectory)\ProductName.Installation\ProductName.Installation.wixproj" Properties="ProductVersion=$(Major).$(Minor).$(Build).$(Revision)" />
</Target>
<Target Name="Build">
<CallTarget Targets="Compile;BuildInstaller;AfterBuild" />
</Target>
</Project>
The WiX project file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>e5232ce4-4412-4e41-9157-8ab1a36960b0</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>DicksonWare.Installation</OutputName>
<OutputType>Package</OutputType>
<ProductVersion Condition=" '$(ProductVersion)' == '' ">2.0.0.0</ProductVersion>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>..\_LatestBuild\Installer\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug;BuildVersion=$(ProductVersion)</DefineConstants>
<SuppressIces>ICE69</SuppressIces>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>..\_LatestBuild\Installer\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>BuildVersion=$(ProductVersion)</DefineConstants>
<SuppressIces>ICE69;ICE61</SuppressIces>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixUIExtension">
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
<Name>WixUIExtension</Name>
</WixExtension>
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
-->
<!--
<Target Name="AfterBuild">
</Target>
-->
</Project>
Then in the .wxs file to set the version I simply do Version="$(var.BuildVersion)"
However, when Jenkins calls MSBuild on the build project or I manually type msbuild build.proj /p:Configuration=Release /p:Platform="x86" /p:AllowUnsafeBlocks=true /p:BUILD_NUMBER=23 and then run the .msi file created, the version given in the .msi file is always the 2.0.0.0 default I've set in the .wixproj file.
I'm pretty sure it's not the actual call to MSBuild that's the problem, since replacing the BuildInstaller task with <MSBuild Projects="$(MSBuildProjectDirectory)\ProductName.Installation\ProductName.Installation.wixproj" Properties="ProductVersion=1.2.3.4" /> still has the same problem.
From what I've been able to find by searching around, what I'm doing should be fine. But it's obviously not. Any ideas on what I'm missing or doing wrong?
Thanks.
Take a look at:
http://iswix.codeplex.com/SourceControl/latest#main/Source/Installer/IsWiX/IsWiX.wixproj
<PropertyGroup>
<!-- If MSIProductVersion not passed in, try to get it fom TFBuild Environments-->
<MSIProductVersion Condition=" '$(MSIProductVersion)' == '' ">$([System.Text.RegularExpressions.Regex]::Match($(TF_BUILD_BUILDNUMBER), "\d+.\d+.\d+.\d+"))</MSIProductVersion>
<!-- If we still don't have a value, default to 1.0.0 for developer builds -->
<MSIProductVersion Condition=" '$(MSIProductVersion)' == '' ">1.0.0</MSIProductVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DefineConstants>WiXProductVersion=$(MSIProductVersion)</DefineConstants>
</PropertyGroup>
http://iswix.codeplex.com/SourceControl/latest#main/Source/Installer/IsWiX/IsWiX.wxs
<Product Id="*" Name="IsWiX" Language="1033" Version="$(var.WiXProductVersion)"
Manufacturer="ISWIX LLC" UpgradeCode="$(var.UpgradeCode)">
Pass /p:MSIProductVerison=1.2.3.4 when you call MSBuild. Alternatively you can set the environment variable TF_BUILD_NUMBER as this is how TFS does it these days.
New F# projects comes with
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
msbuild just fails with it so I even can't write an build script based on this project file.
My solution:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0\FSharp\Microsoft.FSharp.Targets" />
I set v12.0 instead of $(VisualStudioVersion) because VisualStudioVersion is 11 for my msbuild. So but this breaks compatibility with other Visual Studio versions.
I guess I need to make something alike
<FSharpTargetsPath Condition="'$(VisualStudioVersion)' == '11.0'">$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
and
<FSharpTargetsPath Condition="'$(VisualStudioVersion)' == '12.0'">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
But that even doesn't look alike good solution. Is there proper way?
Also I have problems with running 3.0 F# compiler fsc.exe and software alike FAKE :
Could not load file or assembly FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies
So how to not break compatibility between 3.0 / msbuild and 3.1 and newer VS2013-preview stuff ?
The more specific answer that I guess Danny should have given is:
<PropertyGroup Condition="'$(FSharpTargetsPath)' == '' OR (!(Exists('$(FSharpTargetsPath)')))">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(FSharpTargetsPath)' == '' OR (!(Exists('$(FSharpTargetsPath)')))">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(FSharpTargetsPath)' == '' OR (!(Exists('$(FSharpTargetsPath)')))">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\4.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(FSharpTargetsPath)' == '' OR (!(Exists('$(FSharpTargetsPath)')))">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(FSharpTargetsPath)' == '' OR (!(Exists('$(FSharpTargetsPath)')))">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<Import Project="$(FSharpTargetsPath)" />
This should work with all versions.
I would start by creating projects in both versions and diffing the project files. If you build a project file that contains the superset of both files, with appropriate Condition attributes so that each version of VS reads the correct parts, in theory it should work.
Is it possible to change the assembly name based on the project configuration?
I have tried conditional pragmas on the assemblyinfo.cs file, but that only changes the assembly attributes, not the name itself.
If you right click on your project and choose "Edit Project File" (I'm in 2008 here and it may be a new option, if it is then just open the project file in any old text editor) you should see something similar to the following:
<PropertyGroup>
...
<AssemblyName>ClassLibrary1</AssemblyName>
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
...
</PropertyGroup>
Basically any properties that aren't overriden in a more specific property group are inherited from the more general, first group. So to achieve what you want just edit the file so that the AssemblyName tag is defined in each of the specific groups:
<PropertyGroup>
...
<AssemblyName>ClassLibrary1</AssemblyName>
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
<AssemblyName>ClassLibrary1Debug</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
...
<AssemblyName>ClassLibrary1Release</AssemblyName>
</PropertyGroup>
This will change the assembly name on a per config basis.