将 x86 和 x64 库添加到 NuGet 包
Adding x86 and x64 libraries to NuGet package
我制作了一个依赖于 CefSharp 的库,它需要为特定平台构建库。所以没有 AnyCPU 支持。
现在我想将其打包到 NuGet 中。据我所知,您必须将这些文件放入构建文件夹中,并有一个 .targets
文件来选择要引用的正确 dll。所以我最终得到了一个看起来像这样的 NuGet 包:
lib
monodroid
MyLib.dll
xamarin.ios10
MyLib.dll
net45
MyLib.dll (x86)
build
net45
x86
MyLib.dll (x86)
x64
MyLib.dll (x64)
MyLib.targets
我将以下内容放入 .targets
文件中:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="InjectReference"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
<Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences">
<ItemGroup Condition="'$(Platform)' == 'x86' or '$(Platform)' == 'x64'">
<Reference Include="MyLib">
<HintPath>$(MSBuildThisFileDirectory)$(Platform)\MyLib.dll</HintPath>
</Reference>
</ItemGroup>
</Target>
</Project>
到目前为止一切顺利。现在问题来了。将此 NuGet 添加到新的 WPF 项目时,我看到对库的引用出现在 .csproj
文件中,如:
<Reference Include="MyLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d64412599724c860, processorArchitecture=x86">
<HintPath>..\packages\MyLib.0.0.1\lib\net45\MyLib.dll</HintPath>
<Private>True</Private>
</Reference>
尽管我没有看到任何关于 .targets
文件的内容。这仍然是使用 NuGet 3 的方法吗?我做错什么了吗?目前,由于引用了 x86 lib.运行 x64,这在运行时失败。
在摆弄这个太久之后,我想通了。
显然,build.prop 和 build.target 文件的名称必须与 NuGet 包的名称完全相同,否则将不会添加到 csproj 文件中。
编辑:
我创建了一个 small GitHub repository 展示如何将其用于您自己的项目。
它演示了一个包含 3 个项目的解决方案 - 一个用于 iOS,一个用于 Android,以及一个同时针对 x86 和 x64 的 Net45。
请注意,在 .props 文件中,路径指向解压后的 NuGet 的文件夹结构。所以这些路径映射到您在 nuspec 文件中放置的内容。
因此,就像在回购协议中一样,您定义了一个 nuspec,例如:
<?xml version="1.0"?>
<package>
<metadata>
<id>My.Awesome.Library</id>
<version>1.0.0</version>
<title>My Awesome Library</title>
<description>Herpa Derpa</description>
</metadata>
<files>
<file src="My.Awesome.Library.Droid\bin\Release\My.Awesome.Library.*"
target="lib\monodroid70" />
<file src="My.Awesome.Library.iOS\bin\Release\My.Awesome.Library.*"
target="lib\xamarin.ios10" />
<file src="My.Awesome.Library.Net45\bin\x64\Release\My.Awesome.Library.*"
target="build\x64" />
<file src="My.Awesome.Library.Net45\bin\x86\Release\My.Awesome.Library.*"
target="build\x86" />
<file src="My.Awesome.Library.Net45\bin\x86\Release\My.Awesome.Library.*"
target="lib\net45" />
<file src="My.Awesome.Library.props" target="build\net45" />
</files>
</package>
我将 x86 文件放入 build\x86
,将 x64 文件放入 build\x64
。在这种情况下,对于这些文件,文件夹 build 的名称基本上可以是任何名称。这里重要的是 props 文件,下面指向各个平台的这些文件夹。
我不确定将 x86 库放入 lib\net45
是否重要。你可以试验一下。无论如何,道具文件应该为您选择正确的。
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="My.Awesome.Library" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)..\x86\My.Awesome.Library.dll</HintPath>
</Reference>
<Reference Include="My.Awesome.Library" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)..\x64\My.Awesome.Library.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
在这种情况下,$(MSBuildThisFileDirectory)
将是 build\net45\
文件夹,确保您的路径正确指向 dll。 build\net45
文件夹在这里很重要。这就是 NuGet 自动导入目标和道具文件的方式。
另请注意,My.Awesome.Library
这个名字在各个方面都非常一致。此处重要的是您的 props 文件的名称与 NuGet 包 ID 相匹配。否则,NuGet 似乎不会导入它。
上面的解决方案有几点我不同意。
如果您通过将文件添加到 nuget 文件夹来使用默认文件结构,则 nuspec 文件不必包含任何 <Files>
信息。但是如果你想从你的解决方案文件夹中 运行 nuget 文件,那么它是必需的
更好的 nuspec 内容:
<?xml version="1.0"?>
<package>
<metadata>
<id>YourProjectName</id>
<version>1.0.0</version>
<authors>John Doe</authors>
<title>Your Project Name</title>
<description>Herpa Derpa</description>
</metadata>
</package>
我也不同意他在 build
文件夹中有 .dll,这些应该放在你的 lib
文件夹中,build
文件夹中应该包含你的 .targets
和 .props
个文件。
nuget here 的文档提到了这一点。
lib
文件夹也用于您的参考资料中的 .dll。其次,添加到您的 build
文件夹的 .dll 是一些 cases-similar 可能需要的补充 dll,以了解 SQlite 如何为它的 interop
dll 做这件事。所以在这种情况下,最好将它们保存在 lib 文件夹中。
更好的文件夹结构:
- nuget
-- project.nuspec
-- build
---- YourProjectName.props
---- YourProjectName.targets
-- lib
--- <x64>
---- YourProjectName.dll
--- <x86>
---- YourProjectName.dll
.props 文件内容:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)x86\YourProjectName.dll</HintPath>
</Reference>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)x64\YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
.目标文件内容:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="InjectReference"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
<Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences">
<ItemGroup Condition="('$(Platform)' == 'x86' or '$(Platform)' == 'x64') and '$(TargetFrameworkVersion)'=='v4.6'">
<Reference Include=" YourProjectName ">
<HintPath>$(MSBuildThisFileDirectory)..\..\lib\net46$(Platform)\ YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Target>
</Project>
您可以通过使用 Nuget 包管理器应用程序打开您的 nuspec 文件并检查您添加的所有文件是否已被拾取来检查上述是否有效。现在,当您将这些添加到项目时,它将根据为引用它的项目选择的体系结构加载 dll。还要注意在目标文件中,如果选择“Any CPU”,它将引发错误,并且通知用户他们必须在 x86 和 x64
之间选择
编辑:
有一点没有说清楚,就是 .target 和 .props 的命名需要与 nuget 包文件名相同(也意味着版本)。 如果没有这个,双重引用会出现 当 re-opening Visual Studio.
为了阐明整个解决方案,这就是它对我来说完美工作的方式
.nuspec 文件
<?xml version="1.0"?>
<package>
<metadata>
<id>YourProjectName</id>
<version>1.0.0</version>
<authors>John Doe</authors>
<title>Your Project Name</title>
<description>Herpa Derpa</description>
</metadata>
</package>
文件夹结构
-- project.nuspec
-- build
---- YourProjectName.props
---- YourProjectName.targets
-- tools
--- <x64>
---- YourProjectName.dll
--- <x86>
---- YourProjectName.dll
.props 文件
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)..\tools\x86\YourProjectName.dll</HintPath>
</Reference>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)..\tools\x64\YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
.目标文件
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="BuildOnlySettings"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
</Project>
这是 100% 有效的解决方案。
我制作了一个依赖于 CefSharp 的库,它需要为特定平台构建库。所以没有 AnyCPU 支持。
现在我想将其打包到 NuGet 中。据我所知,您必须将这些文件放入构建文件夹中,并有一个 .targets
文件来选择要引用的正确 dll。所以我最终得到了一个看起来像这样的 NuGet 包:
lib
monodroid
MyLib.dll
xamarin.ios10
MyLib.dll
net45
MyLib.dll (x86)
build
net45
x86
MyLib.dll (x86)
x64
MyLib.dll (x64)
MyLib.targets
我将以下内容放入 .targets
文件中:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="InjectReference"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
<Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences">
<ItemGroup Condition="'$(Platform)' == 'x86' or '$(Platform)' == 'x64'">
<Reference Include="MyLib">
<HintPath>$(MSBuildThisFileDirectory)$(Platform)\MyLib.dll</HintPath>
</Reference>
</ItemGroup>
</Target>
</Project>
到目前为止一切顺利。现在问题来了。将此 NuGet 添加到新的 WPF 项目时,我看到对库的引用出现在 .csproj
文件中,如:
<Reference Include="MyLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d64412599724c860, processorArchitecture=x86">
<HintPath>..\packages\MyLib.0.0.1\lib\net45\MyLib.dll</HintPath>
<Private>True</Private>
</Reference>
尽管我没有看到任何关于 .targets
文件的内容。这仍然是使用 NuGet 3 的方法吗?我做错什么了吗?目前,由于引用了 x86 lib.运行 x64,这在运行时失败。
在摆弄这个太久之后,我想通了。
显然,build.prop 和 build.target 文件的名称必须与 NuGet 包的名称完全相同,否则将不会添加到 csproj 文件中。
编辑:
我创建了一个 small GitHub repository 展示如何将其用于您自己的项目。
它演示了一个包含 3 个项目的解决方案 - 一个用于 iOS,一个用于 Android,以及一个同时针对 x86 和 x64 的 Net45。
请注意,在 .props 文件中,路径指向解压后的 NuGet 的文件夹结构。所以这些路径映射到您在 nuspec 文件中放置的内容。
因此,就像在回购协议中一样,您定义了一个 nuspec,例如:
<?xml version="1.0"?>
<package>
<metadata>
<id>My.Awesome.Library</id>
<version>1.0.0</version>
<title>My Awesome Library</title>
<description>Herpa Derpa</description>
</metadata>
<files>
<file src="My.Awesome.Library.Droid\bin\Release\My.Awesome.Library.*"
target="lib\monodroid70" />
<file src="My.Awesome.Library.iOS\bin\Release\My.Awesome.Library.*"
target="lib\xamarin.ios10" />
<file src="My.Awesome.Library.Net45\bin\x64\Release\My.Awesome.Library.*"
target="build\x64" />
<file src="My.Awesome.Library.Net45\bin\x86\Release\My.Awesome.Library.*"
target="build\x86" />
<file src="My.Awesome.Library.Net45\bin\x86\Release\My.Awesome.Library.*"
target="lib\net45" />
<file src="My.Awesome.Library.props" target="build\net45" />
</files>
</package>
我将 x86 文件放入 build\x86
,将 x64 文件放入 build\x64
。在这种情况下,对于这些文件,文件夹 build 的名称基本上可以是任何名称。这里重要的是 props 文件,下面指向各个平台的这些文件夹。
我不确定将 x86 库放入 lib\net45
是否重要。你可以试验一下。无论如何,道具文件应该为您选择正确的。
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="My.Awesome.Library" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)..\x86\My.Awesome.Library.dll</HintPath>
</Reference>
<Reference Include="My.Awesome.Library" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)..\x64\My.Awesome.Library.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
在这种情况下,$(MSBuildThisFileDirectory)
将是 build\net45\
文件夹,确保您的路径正确指向 dll。 build\net45
文件夹在这里很重要。这就是 NuGet 自动导入目标和道具文件的方式。
另请注意,My.Awesome.Library
这个名字在各个方面都非常一致。此处重要的是您的 props 文件的名称与 NuGet 包 ID 相匹配。否则,NuGet 似乎不会导入它。
上面的解决方案有几点我不同意。
如果您通过将文件添加到 nuget 文件夹来使用默认文件结构,则 nuspec 文件不必包含任何 <Files>
信息。但是如果你想从你的解决方案文件夹中 运行 nuget 文件,那么它是必需的
更好的 nuspec 内容:
<?xml version="1.0"?>
<package>
<metadata>
<id>YourProjectName</id>
<version>1.0.0</version>
<authors>John Doe</authors>
<title>Your Project Name</title>
<description>Herpa Derpa</description>
</metadata>
</package>
我也不同意他在 build
文件夹中有 .dll,这些应该放在你的 lib
文件夹中,build
文件夹中应该包含你的 .targets
和 .props
个文件。
nuget here 的文档提到了这一点。
lib
文件夹也用于您的参考资料中的 .dll。其次,添加到您的 build
文件夹的 .dll 是一些 cases-similar 可能需要的补充 dll,以了解 SQlite 如何为它的 interop
dll 做这件事。所以在这种情况下,最好将它们保存在 lib 文件夹中。
更好的文件夹结构:
- nuget
-- project.nuspec
-- build
---- YourProjectName.props
---- YourProjectName.targets
-- lib
--- <x64>
---- YourProjectName.dll
--- <x86>
---- YourProjectName.dll
.props 文件内容:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)x86\YourProjectName.dll</HintPath>
</Reference>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)x64\YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
.目标文件内容:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="InjectReference"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
<Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences">
<ItemGroup Condition="('$(Platform)' == 'x86' or '$(Platform)' == 'x64') and '$(TargetFrameworkVersion)'=='v4.6'">
<Reference Include=" YourProjectName ">
<HintPath>$(MSBuildThisFileDirectory)..\..\lib\net46$(Platform)\ YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Target>
</Project>
您可以通过使用 Nuget 包管理器应用程序打开您的 nuspec 文件并检查您添加的所有文件是否已被拾取来检查上述是否有效。现在,当您将这些添加到项目时,它将根据为引用它的项目选择的体系结构加载 dll。还要注意在目标文件中,如果选择“Any CPU”,它将引发错误,并且通知用户他们必须在 x86 和 x64
之间选择编辑:
有一点没有说清楚,就是 .target 和 .props 的命名需要与 nuget 包文件名相同(也意味着版本)。 如果没有这个,双重引用会出现 当 re-opening Visual Studio.
为了阐明整个解决方案,这就是它对我来说完美工作的方式
.nuspec 文件
<?xml version="1.0"?>
<package>
<metadata>
<id>YourProjectName</id>
<version>1.0.0</version>
<authors>John Doe</authors>
<title>Your Project Name</title>
<description>Herpa Derpa</description>
</metadata>
</package>
文件夹结构
-- project.nuspec
-- build
---- YourProjectName.props
---- YourProjectName.targets
-- tools
--- <x64>
---- YourProjectName.dll
--- <x86>
---- YourProjectName.dll
.props 文件
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)..\tools\x86\YourProjectName.dll</HintPath>
</Reference>
<Reference Include="YourProjectName" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)..\tools\x64\YourProjectName.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
.目标文件
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PlatformCheck" BeforeTargets="BuildOnlySettings"
Condition="(('$(Platform)' != 'x86') AND ('$(Platform)' != 'x64'))">
<Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)' platform. You need to specify platform (x86 or x64)." />
</Target>
</Project>
这是 100% 有效的解决方案。