Improvement: Handle platform specific assemblies (x86, x64 etc) with msbuild conditionals
sipsorcery opened this issue · 7 comments
Lots of us are having issues using nuget to package platform specific assemblies (#8435, #1221 etc). The crux of the problem is that while the platform specific artifacts can be packaged with nuget if the assembly reference(s) is platform specific there is no clean way to set it in the consuming project file.
To illustrate the problem my partial nuspec is:
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
....
<references>
<reference file="SIPSorceryMedia.dll" />
</references>
</metadata>
<files>
<file src="x86\Release\SIPSorceryMedia.dll" target="lib\net47" />
<file src="SIPSorceryMedia.targets" target="build\SIPSorceryMedia.targets" />
<file src="SIPSorceryMedia.props" target="build\SIPSorceryMedia.props" />
<file src="x64\Release\*.dll" target="build\x64" />
<file src="x86\Release\*.dll" target="build\x86" />
</files>
</package>
The subsequent reference that ends up in a consuming project files is:
<Reference Include="SIPSorceryMedia, Version=1.1.7192.37613, Culture=neutral, processorArchitecture=x86">
<HintPath>packages\SIPSorceryMedia.1.7.2\lib\net47\SIPSorceryMedia.dll</HintPath>
</Reference>
I have found no way to be able to override the hint path in that reference with the use of platform specific overrides in a .props
or .targets
file. For example if msbuild accepted an override on the hint path of the original reference it would be possible to use the example SIPSorceryMedia.props
file shown below. Unfortunately it doesn't work.
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="SIPSorceryMedia, Version=1.1.7192.37613, Culture=neutral, processorArchitecture=x64" Condition="'$(Platform)' == 'x64' or '$(Platform)' == 'AnyCPU'">
<HintPath>packages\SIPSorceryMedia.1.7.2\build\x64\SIPSorceryMedia.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
But what does work is if the reference inserted into the project file has a platform specific condition:
<Reference Condition="'$(Platform)' == 'x86' Include="SIPSorceryMedia, Version=1.1.7192.37613, Culture=neutral, processorArchitecture=x86">
<HintPath>packages\SIPSorceryMedia.1.7.2\lib\net47\SIPSorceryMedia.dll</HintPath>
</Reference>
Suggested Improvement
The suggestion is if nuspec file references could be specified as:
<file src="x86\Release\SIPSorceryMedia.dll" target="lib\x86\net47" />
<file src="x64\Release\SIPSorceryMedia.dll" target="lib\x64\net47" />
Then the references could be added to the consuming project as shown below and which builds correctly when the msbuild platform is specified:
<Reference Include="SIPSorceryMedia, Version=1.1.7192.37613, Culture=neutral, processorArchitecture=x86" Condition="'$(Platform)' == 'x86'">
<HintPath>packages\SIPSorceryMedia.1.7.2\build\x86\SIPSorceryMedia.dll</HintPath>
</Reference>
<Reference Include="SIPSorceryMedia, Version=1.1.7192.37613, Culture=neutral, processorArchitecture=x64" Condition="'$(Platform)' == 'x64'">
<HintPath>packages\SIPSorceryMedia.1.7.2\build\x64\SIPSorceryMedia.dll</HintPath>
</Reference>
It is possible to build a package like this, that supports Packages.Config and PackageReference scenarios.
Your SIPSorceryMedia.1.0.0.nupkg would have a structure like this:
ref\netstandard2.0\SIPSorceryMedia.dll
runtimes\win-x64\lib\netstandard2.0\SIPSorceryMedia.dll
runtimes\win-x86\lib\netstandard2.0\SIPSorceryMedia.dll
build\netstandard2.0\SIPSorceryMedia.targets
the targets file would be created to handle packages.config scenarios.
It would need to conditionally include one of the runtimes dlls as appropriate.
Related docs:
https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
https://docs.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks#architecture-specific-folders
Please let us (@rrelyea and @zivkan) know if you have any problems.
Thanks a lot for the pointers.
the targets file would be created to handle packages.config scenarios. It would need to conditionally include one of the runtimes dlls as appropriate.
That's the problem. I cannot find a way to make assembly reference in the targets/props files override the assembly reference that gets set when the nuget package is installed.
For example installing the nuget package in a consuming project results in the reference being added as below and the only way I have found to override it is the suggestion in my first post.
<Reference Include="SIPSorceryMedia, Version=2.0.1.36269, Culture=neutral, processorArchitecture=x86">
<HintPath>packages\SIPSorceryMedia.2.0.1\lib\net47\SIPSorceryMedia.dll</HintPath>
</Reference>
I tried the creating the package as per the architecture specific folders reference but that does not seem to do anything useful.
My .nuget
package ends up as shown below but the runtime dll's are not copied into the build output directory. Even so that wasn't a problem I was having any way. I am able to use a .targets
file to copy the required runtime dll's to the appropriate locations.
The sole problem I'm having is the consuming project compiling against the reference assembly that does not match the build platform. I've not been able to find a way to get the build to use the correct reference assembly at compile time if it does not match the original reference added by the nuget install.
(in the diagram below lib\net47\SIPSorceryMedia.dll is compiled as x86)
Update: This is the build warning:
1>------ Rebuild All started: Project: WebRtcDaemon, Configuration: Release x64 ------
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3270: There was a mismatch between the processor architecture of the project being built "AMD64" and the processor architecture of the reference "SIPSorceryMedia, Version=2.0.0.33779, Culture=neutral, processorArchitecture=x86", "x86". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project.
1> WebRtcDaemon -> C:\Dev\sipsorcery\sipsorcery-public\sipsorcery-media\samples\WebRtcDaemon\x64\Release\WebRTCDaemon.exe
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
At a glance, your attempts in your first post about putting a condition on $(PLATFORM)
looks good. Someone would need to do some MSBuild debugging to understand why it didn't work (I recommend using msbuild -bl
and open the msbuild.binlog
file with https://github.com/KirillOsenkov/MSBuildStructuredLog/releases).
It's unclear to me if the project you're testing with uses packages.config
(PC) or PackageReference
(PR). If it's a PC project, then the runtimes/
files are not used, it's a new feature for PR.
To work correctly in PR projects, your compile-time assembly should be in ref/..
, not lib/..
. You can get useful information looking at obj/project.assets.json
and checking which assets were selected from your package. To avoid the compiler warning about mismatched architecture, the assembly in ref/
should also be targeting AnyCPU. The C# compiler has a command line parameter (also available as an MSBuild property) to write a reference assembly. My understanding is that this is just like compiling your code but without any method bodies. I don't know if using this will always output an AnyCPU assembly, or if you will need a 3rd architecture target for your project (x86, x64 and AnyCPU).
At a glance, your attempts in your first post about putting a condition on $(PLATFORM) looks good.
Do you mean why the condition for the reference in the .props
file didn't take priority over the reference in the main .vcxproj
file? I will follow your instructions and see what the build log reveals.
It's unclear to me if the project you're testing with uses packages.config (PC) or PackageReference (PR). If it's a PC project, then the runtimes/ files are not used, it's a new feature for PR.
I'm using a package reference My mistake I am using the packages.config file (is it the only option for .Net Framework project files?). I'm adding my nuget package to a C# .Net 4.7 Console project using the Visual Studio 2019 Package Manager Console:
Package Manager Console Host Version 5.2.0.6090
PM> Install-Package SIPSorceryMedia -Source ..\..\SIPSorcery.Media\nuspec
The C# compiler has a command line parameter (also available as an MSBuild property) to write a reference assembly.
The source assembly is Managed C++. I guess it would be possible to front it with a reference C# assembly but that seems like a lot of overhead.
I spotted this adding-a-packagereference-condition to do with setting a framework condition on a nuget reference. The equivalent condition for a platform seems to be what's missing.
At a glance, your attempts in your first post about putting a condition on $(PLATFORM) looks good. Someone would need to do some MSBuild debugging to understand why it didn't work (I recommend using msbuild -bl and open the msbuild.binlog file with https://github.com/KirillOsenkov/MSBuildStructuredLog/releases).
A screenshot of the binlog analysis is shown below. The only thing I spotted that looked relevant was the DoubleWrites
.
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild.exe -bl /p:Platform=x64 /t:clean,build WebRtcDaemon.sln
Building the projects in this solution one at a time. To enable parallel build, please add the "-m" switch.
Build started 23/09/2019 3:20:29 PM.
Project "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.sln" on node 1 (clean;build target(s)).
ValidateSolutionConfiguration:
Building solution configuration "Debug|x64".
Project "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.sln" (1) is building "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDa
emon.csproj" (2) on node 1 (Clean target(s)).
CoreClean:
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\Media\max_intro.mp4".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\Media\testpattern.jpeg".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\Media\wizard.jpeg".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\Certs\localhost.pem".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\Certs\localhost.pfx".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\Certs\localhost_key.pem".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\avcodec-58.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\avutil-56.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\LIBEAY32.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\SIPSorceryMedia.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\srtp2.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\SSLEAY32.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\swresample-3.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\swscale-5.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\WebRTCDaemon.exe.config".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\WebRTCDaemon.exe".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\WebRTCDaemon.pdb".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\log4net.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\NAudio.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\SIPSorcery.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\websocket-sharp.dll".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\log4net.xml".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\NAudio.xml".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\obj\x64\Debug\WebRtcDaemon.csprojAssemblyReference.cache".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\obj\x64\Debug\WebRtcDaemon.csproj.CoreCompileInputs.cache".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\obj\x64\Debug\WebRtcDaemon.csproj.CopyComplete".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\obj\x64\Debug\WebRTCDaemon.exe".
Deleting file "C:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\obj\x64\Debug\WebRTCDaemon.pdb".
Done Building Project "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj" (Clean target(s)).
Project "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.sln" (1) is building "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDa
emon.csproj" (2:2) on node 1 (default targets).
_HandlePackageFileConflicts:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\Microsoft.NET.Build.Extensions.ConflictResolution.targe
ts(33,5): message NETSDK1041: Encountered conflict between 'Reference:SIPSorceryMedia' and 'Reference:SIPSorceryMedia, Version=2.0.0.33779, Culture=neutral, processor
Architecture=x86'. NETSDK1033: Choosing 'Reference:SIPSorceryMedia, Version=2.0.0.33779, Culture=neutral, processorArchitecture=x86' because AssemblyVersion '2.0.0.3
3779' is greater than '1.1.7192.14819'. [c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj]
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\Microsoft.NET.Build.Extensions.ConflictResolution.targe
ts(33,5): message NETSDK1041: Encountered conflict between 'Reference:SIPSorceryMedia' and 'Reference:SIPSorceryMedia, Version=2.0.0.33779, Culture=neutral, processor
Architecture=x86'. NETSDK1033: Choosing 'Reference:SIPSorceryMedia, Version=2.0.0.33779, Culture=neutral, processorArchitecture=x86' because AssemblyVersion '2.0.0.3
3779' is greater than '1.1.7192.14819'. [c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj]
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3270: There was a mismat
ch between the processor architecture of the project being built "AMD64" and the processor architecture of the reference "SIPSorceryMedia, Version=2.0.0.33779, Cultur
e=neutral, processorArchitecture=x86", "x86". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project t
hrough the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor a
rchitecture that matches the targeted processor architecture of your project. [c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj]
GenerateBindingRedirects:
No suggested binding redirects from ResolveAssemblyReferences.
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
CoreCompile:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csc.exe /noconfig /unsafe+ /nowarn:1701,1702 /nostdlib+ /platform:x64 /erro
rreport:prompt /define:DEBUG;TRACE /highentropyva+ /reference:c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\log4net.2.0.8\lib\net45-full\log4net
.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\Microsoft.CSharp.dll" /reference:"C:\Program Files (x86)\Refer
ence Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\mscorlib.dll" /reference:c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\NAudio.1.9.0\lib
\net35\NAudio.dll /reference:c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorcery.3.0.1\lib\netstandard2.0\SIPSorcery.dll /reference:c:\Dev\
sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\lib\net47\SIPSorceryMedia.dll /reference:"C:\Program Files (x86)\Reference Assembli
es\Microsoft\Framework\.NETFramework\v4.7.2\System.Configuration.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7
.2\System.Configuration.Install.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Core.dll" /reference:"C
:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Fr
amework\.NETFramework\v4.7.2\System.Drawing.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.ServiceProc
ess.dll" /reference:c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\WebSocketSharpFork.1.0.4.0\lib\net35\websocket-sharp.dll /reference:"C:\Progra
m Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\Facades\netstandard.dll" /debug+ /debug:full /filealign:512 /out:obj\x64\Debug\WebRTCDae
mon.exe /ruleset:"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Team Tools\Static Analysis Tools\\Rule Sets\MinimumRecommendedRules.ruleset" /subsys
temversion:6.00 /target:exe /utf8output AppState.cs WebRTCDaemon.cs Program.cs Properties\AssemblyInfo.cs WebRTCService.cs WebRTCServiceInstaller.cs WebRtcSession.c
s "C:\Users\aaron\AppData\Local\Temp\.NETFramework,Version=v4.7.2.AssemblyAttributes.cs"
Using shared compilation with compiler from directory: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn
_CopyFilesMarkedCopyLocal:
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\WebSocketSharpFork.1.0.4.0\lib\net35\websocket-sharp.dll" to "c:\Dev\sipsorcery
\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\websocket-sharp.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\lib\net47\SIPSorceryMedia.dll" to "c:\Dev\sipsorcery\sips
orcery-media\examples\WebRtcDaemon\x64\Debug\SIPSorceryMedia.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\log4net.2.0.8\lib\net45-full\log4net.dll" to "c:\Dev\sipsorcery\sipsorcery-medi
a\examples\WebRtcDaemon\x64\Debug\log4net.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorcery.3.0.1\lib\netstandard2.0\SIPSorcery.dll" to "c:\Dev\sipsorcery\sipso
rcery-media\examples\WebRtcDaemon\x64\Debug\SIPSorcery.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\log4net.2.0.8\lib\net45-full\log4net.xml" to "c:\Dev\sipsorcery\sipsorcery-medi
a\examples\WebRtcDaemon\x64\Debug\log4net.xml".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\NAudio.1.9.0\lib\net35\NAudio.dll" to "c:\Dev\sipsorcery\sipsorcery-media\examp
les\WebRtcDaemon\x64\Debug\NAudio.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\NAudio.1.9.0\lib\net35\NAudio.xml" to "c:\Dev\sipsorcery\sipsorcery-media\examp
les\WebRtcDaemon\x64\Debug\NAudio.xml".
Creating "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\obj\x64\Debug\WebRtcDaemon.csproj.CopyComplete" because "AlwaysCreate" was specified.
_CopyOutOfDateSourceItemsToOutputDirectory:
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\Media\wizard.jpeg" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debu
g\Media\wizard.jpeg".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\Media\max_intro.mp4" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\De
bug\Media\max_intro.mp4".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\Certs\localhost_key.pem" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x6
4\Debug\Certs\localhost_key.pem".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\Media\testpattern.jpeg" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64
\Debug\Media\testpattern.jpeg".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\Certs\localhost.pfx" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\De
bug\Certs\localhost.pfx".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\Certs\localhost.pem" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\De
bug\Certs\localhost.pem".
_CopyOutOfDateSourceItemsToOutputDirectoryAlways:
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\build\x64\avutil-56.dll" to "c:\Dev\sipsorcery\sipsorcery
-media\examples\WebRtcDaemon\x64\Debug\avutil-56.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\build\x64\SIPSorceryMedia.dll" to "c:\Dev\sipsorcery\sips
orcery-media\examples\WebRtcDaemon\x64\Debug\SIPSorceryMedia.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\build\x64\LIBEAY32.dll" to "c:\Dev\sipsorcery\sipsorcery-
media\examples\WebRtcDaemon\x64\Debug\LIBEAY32.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\build\x64\avcodec-58.dll" to "c:\Dev\sipsorcery\sipsorcer
y-media\examples\WebRtcDaemon\x64\Debug\avcodec-58.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\build\x64\SSLEAY32.dll" to "c:\Dev\sipsorcery\sipsorcery-
media\examples\WebRtcDaemon\x64\Debug\SSLEAY32.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\build\x64\srtp2.dll" to "c:\Dev\sipsorcery\sipsorcery-med
ia\examples\WebRtcDaemon\x64\Debug\srtp2.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\build\x64\swresample-3.dll" to "c:\Dev\sipsorcery\sipsorc
ery-media\examples\WebRtcDaemon\x64\Debug\swresample-3.dll".
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\packages\SIPSorceryMedia.2.0.0\build\x64\swscale-5.dll" to "c:\Dev\sipsorcery\sipsorcery
-media\examples\WebRtcDaemon\x64\Debug\swscale-5.dll".
_CopyAppConfigFile:
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\App.config" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\WebRT
CDaemon.exe.config".
CopyFilesToOutputDirectory:
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\obj\x64\Debug\WebRTCDaemon.exe" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDa
emon\x64\Debug\WebRTCDaemon.exe".
WebRtcDaemon -> c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\x64\Debug\WebRTCDaemon.exe
Copying file from "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\obj\x64\Debug\WebRTCDaemon.pdb" to "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDa
emon\x64\Debug\WebRTCDaemon.pdb".
Done Building Project "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj" (default targets).
Done Building Project "c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.sln" (clean;build target(s)).
Deferred Messages
Detailed Build Summary
======================
============================== Build Hierarchy (IDs represent configurations) =====================================================
Id : Exclusive Time Total Time Path (Targets)
-----------------------------------------------------------------------------------------------------------------------------------
0 : 0.054s 0.688s c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.sln (clean, build)
| 1 : 0.198s 0.198s c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj (Clean)
. 2 : 0.436s 0.436s c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj ()
============================== Node Utilization (IDs represent configurations) ====================================================
Timestamp: 1 Duration Cumulative
-----------------------------------------------------------------------------------------------------------------------------------
637048416292127892: 0 0.048s 0.048s
637048416292607882: 1 0.198s 0.246s ...
637048416294587841: 0 0.002s 0.248s
637048416294608102: 2 0.436s 0.684s ........
637048416298967843: 0 0.004s 0.688s
-----------------------------------------------------------------------------------------------------------------------------------
Utilization: 100.0 Average Utilization: 100.0
Build succeeded.
"c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.sln" (clean;build target) (1) ->
"c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj" (default target) (2:2) ->
(ResolveAssemblyReferences target) ->
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3270: There was a mism
atch between the processor architecture of the project being built "AMD64" and the processor architecture of the reference "SIPSorceryMedia, Version=2.0.0.33779, Cult
ure=neutral, processorArchitecture=x86", "x86". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project
through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor
architecture that matches the targeted processor architecture of your project. [c:\Dev\sipsorcery\sipsorcery-media\examples\WebRtcDaemon\WebRtcDaemon.csproj]
1 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.81
Do you mean why the condition for the reference in the
.props
file didn't take priority over the reference in the main.vcxproj
file? I will follow your instructions and see what the build log reveals.
I just meant that MSBuild supports skipping over XML elements when the condition evaluates to false. So the concept of having two <Reference
elements, one pointing to the x86 dll and the other to the x64 dll, and using only one of them by using conditions, that's a conceptually sound idea. The syntax looked about right, so I wouldn't have been surprised if it worked.
Perhaps the issue is that $(Platform)
isn't defined at MSBuild evaluation time, so both == 'x86'
and == 'x64'
evaluate to false. You can check the evaluation properties to see if that property is defined or not, and if so, what it's value is. If it's not defined, it might only get defined when running a target, in which case you'll need add the reference in a target, rather than a "global" property. The binlog viewer has a search to make it quick to find.
My mistake I am using the packages.config file
Then only option is to include a MSBuild props and/or targets file in your package, and do whatever is needed in there.
edit: I forgot to mention that you should not have any dlls in lib/
in this case. This will avoid the double-writes, and ensure that any reference added by your MSBuild props/targets file will be used.
is it the only option for .Net Framework project files?
For C++ projects, yes, it's the only option. For C#/VB.NET/F# SDK style projects, only PackageReference works, packages.config is not an option. For C#/VB.NET (and possibly F#) projects using non-SDK style projects, it's possible to choose. See the NuGet-General options in Tools-Options for the default and option to prompt on first package install.
@zivkan thanks to all your suggestions I was finally able to construct my nuget package so consuming projects build without warnings and get the correct native dll's copied to the output directory. The main thing was not to put anything in the nuget package's lib directory.
I've pasted the .nuspec
, .props
and .targets
files below for the many others attempting the same thing:
.nuspec
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>SIPSorceryMedia</id>
<version>3.0.0</version>
<title>SIPSorceryMedia</title>
<authors>Aaron Clauson</authors>
<owners>Aaron Clauson</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">BSD-3-Clause</license>
<projectUrl>https://www.sipsorcery.com/</projectUrl>
<iconUrl>http://www.sipsorcery.com/mainsite/favicon.ico</iconUrl>
<description>The SIPSorcery package for audio and video capabiltities.</description>
<releaseNotes>Tweaked nuget package to remove build warnings due to mismatched platform reference.</releaseNotes>
<copyright>Copyright (c) 2019, Aaron Clauson</copyright>
<language>en-US</language>
<tags>WebRtc MediaFoundation</tags>
<repository type="git" url="https://github.com/sipsorcery/sipsorcery-media" branch="master" />
</metadata>
<files>
<file src="SIPSorceryMedia.targets" target="build\SIPSorceryMedia.targets" />
<file src="SIPSorceryMedia.props" target="build\SIPSorceryMedia.props" />
<file src="..\x64\Release\*.dll" target="build\x64" />
<file src="..\x86\Release\*.dll" target="build\x86" />
</files>
</package>
.props
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="SIPSorceryMedia" Condition="'$(Platform)' == 'x64' or '$(Platform)' == 'AnyCPU'">
<HintPath>$(MSBuildThisFileDirectory)\..\build\x64\SIPSorceryMedia.dll</HintPath>
</Reference>
<Reference Include="SIPSorceryMedia" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)\..\build\x86\SIPSorceryMedia.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
.targets
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)\..\build\x86\*.dll" Condition="'$(Platform)' == 'x86'" />
<NativeLibs Include="$(MSBuildThisFileDirectory)\..\build\x64\*.dll" Condition="'$(Platform)' == 'x64' or '$(Platform)' == 'AnyCPU'" />
<ContentWithTargetPath Include="@(NativeLibs)">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
</Project>