I am having a problem with nuget (version 4.3.0.4406) and msbuild (version 15.3.409.57025). I am using VS2017 to create class library. Using the pack capability of VS2017 i can successfully create a nuget package (that i can install in another solution). Now i want to add an install.ps1 script to the package in the tools folder that runs when the nuget is installed.
In the csproj file i am specifying multiple target frameworks:
<TargetFrameworks>net45;net452</TargetFrameworks>
I cannot figure out how to do this. I've created a nuspec file using the nuget -spec command which generates a simple nuspec file. When i use the msbuild command with the /t:pack and /p:Nuspecfile=path.to.nuspec I get the following errors:
NuGet.Build.Tasks.Pack.targets(141,5): error : Value cannot be null or an empty string.
I have nuspec files from other projects (from VS2015 solutions) that work without problem, and the structure of the one i am using now is basically the same. Can anyone let me know whether i am trying something that cannot be done?
You can pack any item by updating its metadata in the csproj file:
<ItemGroup>
<None Update="install.ps1" CopyToOutputDirectory="PreserveNewest" Pack="true" PackagePath="\tools" />
</ItemGroup>
Note that the ps1 file is only run for projects using packages.config to reference the NuGet package and you should investigate alternative ways to accomplish what you are trying to do with the script as PackageReference is now more likely to be used instead.
Related
I've read these instructions for creating NuGet packages for C++/CLI .vcxproj projects using a .nuspec file. However, I'd like to use MSBuild to create my package instead of using a .nuspec file. I've seen these instructions for packaging .NET Framework projects using MSBuild, but I haven't been able to find anything for doing the same with .vcxproj files.
MSBuild can pack a Visual Studio project into a NuGet package, but only if that project uses PackageReference instead of packages.config.
As of this writing, the Visual Studio UI doesn't allow you to choose PackageReference instead of packages.config as the NuGet package configuration mechanic for VCXPROJ files. However, you can manually edit the .vcxproj file and convert it to PackageReference format.
Edit .vcxproj
By default, .vcxproj files are not SDK-style projects (I don't know if they can even be converted to SDK-style projects). To build NuGet packages from non-SDK-style projects, you'll need to reference NuGet.Build.Tasks.Pack:
Add the following to your .vcxproj (inside the Project element):
<ItemGroup>
<PackageReference Include="NuGet.Build.Tasks.Pack">
<Version>5.11.0</Version>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
Add any other packages your project depends on. Notice the <PrivateAssets>all</PrivateAssets> element. You need NuGet.Build.Tasks.Pack to pack your project, but you don't want it as a dependency when others try and install your NuGet package. Adjust the version for NuGet.Build.Tasks.Pack as appropriate.
If your project references static libraries, you don't want those included as NuGet package dependencies. Use the PrivateAssets element to exclude them. I.e:
<ItemGroup>
<ProjectReference Include="..\vendor\static-lib-build\static-lib\static-lib.vcxproj">
<Project>{8aa99891-3ff7-3fa7-b1b5-131664298a26}</Project>
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
</ItemGroup>
Also add the following inside the Project element"
<PropertyGroup>
<PackageId>Your.Package.Id</PackageId>
<Authors>Your Name</Authors>
<BuildOutputTargetFolder>lib</BuildOutputTargetFolder>
<PackageDescription>A description of this package.</PackageDescription>
<TargetFramework>net461</TargetFramework>
</PropertyGroup>
What's in the TargetFramework element should correspond to what's in the TargetFrameworkVersion element elsewere in your project.
Note that I haven't covered building a cross-platform NuGet package. By its very nature, C++/CLI projects are targeted to a specific processor / architecture. You can include native libraries for multiple architectures in the runtime directory of your NuGet package, but I don't cover that here.
Restore, Build, and Pack Using MSBuild
This line will restore your NuGet packages, build the project, and then pack it:
"c:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" path\to\the_project.vcxproj /p:Platform="Any CPU" /p:ProductVersion=1.0.0.69 /t:Restore;Build /t:pack
Change the command line options to suit your needs. You may need to run this command twice if NuGet.Build.Tasks.Pack hasn't already been restored.
I know Since the release of msbuild 15 (vs 2017) that NuGet is now fully integrated into MSBuild.
I have a nuspec file with defining variables of package properties like:
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$authors$</authors>
...
</metadata>
The nuspec file is located in the same folder of the project.
When using nuget tool to create the package , it works fine.
nuget pack
When using msbuild v15, it raise an exception.
run the command:
msbuild -version
Microsoft (R) Build Engine version 15.8.168+ga8fba1ebd7 for .NET Framework
15.8.168.64424
msbuild /t:pack /p:configuration=release /p:NuspecFile=mylib.nuspec
raise exception:
C:\Program Files\dotnet\sdk\2.1.402\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets(199,5): error : Value cannot be null or an empty string.
The strange is that dotnet sdk version 2.1.402 raises the exception.
I tried msbuild installed with vs2017 with its path and also it raises the same exception.
When i substitute the variables with its values, msbuild is working fine.
The question
Is this a bug in msbuild version 15.8.168.64424 or i missed something ?
In other words, Can msbuild support using the metadata variables of the package?.
As has been mentioned in the comments, you no longer need a Nuspec file as most aspects can be controlled via properties in the csproj file or additional metadata on items (e.g. if you need additional content).
If you do need a nuspec file for some reason, you need to provide the variables for substitution yourself. You can do this in a target inside the csproj file like this:
<Target Name="SetNuspecProperties" BeforeTargets="GenerateNuspec">
<PropertyGroup>
<NuspecProperties>$(NuspecProperties);id=$(AssemblyName)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);config=$(Configuration)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);version=$(PackageVersion)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);description=$(Description)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);authors=$(Authors)</NuspecProperties>
</PropertyGroup>
</Target>
I'm trying to create a .netstandard nuget package following these instructions, using VS2017 RC. It builds fine, but when I try to create the package using
msbuild /t:pack /p:Configuration=Release
I get an error, that the target pack is not available in my solution:
error MSB4057: The target "pack" does not exist in the project.
I'm not really sure what to do with this message or where I should be looking to fix it. Any suggestions?
Thanks to an answer on the MSDN forums I was able to get it working.
You'll have to specify your .csproj in the build command so it won't try to use the solution file (.sln).
msbuild "C:\Users\Administrator\Documents\visual studio 2017\Projects\AppLogger\AppLogger\AppLogger.csproj" /t:pack /p:Configuration=Release
Additionally I had to install the NuGet.Build.Tasks.Pack" package from NuGet.
The command msbuild /t:pack /p:Configuration=Release is specifying that MSBuild should run the pack target within the build script. The error indicates that MSBuild isn't able to find that target within the build script (or one of it's imports). Have you double checked your prerequisites? You're either using the wrong build script or it's missing an <import> tag.
You must import targets before using them. In project file before using targets write:
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
We use MSBuild on our CI server to compile our WebApp, however the build omits the JavaScript files built by TypeScript from the output of the build.
I would expect the output to contain the JavaScript and not the Typescript, however neither are in the output at the expected locations.
How can I include the JavaScript files without having to have them all in my solution? The TypeScript team seems to think this is bad, but I would rather not have duplicates of all the files in my solution either.
The problem was due to using MSBuild instead of the "Publish" on the build server it seems. I added an AfterBuild target to content include all of the JS files to the build output.
<Target Name="AfterBuild">
<ItemGroup>
<Content Include="**\*.js" />
</ItemGroup>
</Target>
Although this is not ideal, it allows the js files not to show in the solution when using visual studio and the files end up in the build output.
I tried many solutions from the web including the <Content Include="**\*.js" />, but nothing worked. I'm using MSBuild on my local dev box and typescript is installed and targets available in C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\TypeScript.
It turns out my "old" MSBuild runner for web app csproj files is obsolete. I was doing this:
MSBuild.exe my.csproj /Target:ResolveReferences;_CopyWebApplication /property:WebProjectOutputDir=myfolder;OutDir=myfolder\bin;Configuration=Debug
but thanks to this post I need to use UseWPP_CopyWebApplication instead of the legacy _CopyWebApplication:
MSBuild.exe /t:Rebuild "/p:WebProjectOutputDir=myfolder;OutDir=myfolder\bin;Configuration=Debug;UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False" my.csproj
Now without any editing of the csproj file, all my TypeScript is included!
TypeScript is probably not installed on your build server. To install it, copy your TypeScript folder from c:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\ to the same folder on your build server (where v12 is the version of your Visual Studio).
The Visual Studio version on your build server can be different however. In my situation, the version on my development machine is v12, while the build server uses v11. I found that out by adding the following to the [WebProjectName].csproj file:
<Target Name="PrintVisualStudioInfo">
<Message Text="VisualStudioVersion: '$(VisualStudioVersion)'" Importance="High" />
</Target>
<PropertyGroup>
<CompileDependsOn>
PrintVisualStudioInfo;
$(CompileDependsOn)
</CompileDependsOn>
</PropertyGroup>
Be sure you put it after the last <Import /> element. Now when you look at the output of your build on the build server, you should see 'VisualStudioVersion: xx' somewhere.
Copy the TypeScript folder to the correct version folder on the build server.
Just adding in case it helps people.
We had this issue recently and it was fixed by adding
/p:VisualStudioVersion=12.0 to the BAT file :
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe FullBuild.proj /p:VisualStudioVersion=12.0 /t:createRelease /p:ReleaseNumber=5.22.0
Does anyone know how to add a an MSBuild .proj file to my solution?
I was just given existing code from a vendor with a solution that references an MSBuild .proj file as one of its projects. When I open the solution, the project shows as (unavailable). It appears that I need to install some sort of project template to get this project to open correctly. I installed the Codeplex MSBuild Template, but this doesn't appear to be it.
Any ideas?
If you don't need IDE support, it's possible to do this using MSBuild solution extension targets.
Create a file named "before.SolutionName.sln.targets" with the following code:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectReference Include="CustomProject\CustomProject.proj">
<AdditionalProperties>Configuration=$(Configuration); Platform=AnyCPU</AdditionalProperties>
<Configuration>$(Configuration)</Configuration>
<Platform>AnyCPU</Platform>
</ProjectReference>
</ItemGroup>
</Project>
When your solution is built at command line by MSBuild (ie/ build server) the custom MSBuild project will be pulled into the temporary in-memory project file that MSBuild converts the solution into.
I actually got it to work! I re-started Visual Studio and still saw that the projects were unavailable after installing the MSBuild Template mentioned above. I had to manually reload the projects. That fixed the issue.