我创建了一个C ++ / CLI(混合)程序集,它有一个围绕某些非托管C ++代码的托管包装类。托管部分以.NET 4.6.1为目标,我得到了一个文件entry.cpp
只有这一行来做到这一点:
[assembly:System::Runtime::Versioning::TargetFrameworkAttribute(L".NETFramework,Version=v4.6.1", FrameworkDisplayName = L".NET Framework 4.6.1")];
当我现在在.NET 4.6.1项目中手动包含已编译的程序集时,我可以按预期使用托管类。
此项目可以通过以下四种方式构建: x86 或 x64 ,作为 debug 或 release 构建。它没有托管依赖项。
现在我想要一个(或者如果需要多个)NuGet包,我可以上传到我的feed并在我希望的每个.NET 4.6.1兼容项目中轻松使用包装器组件。 我如何实现这一目标?
到目前为止,我尝试了两种方法:
首先,我创建了一个.autopkg
文件,该文件符合this blog post提供本机DLL的方式。该文件的files
部分如下所示:
files {
// include: { *.h };
[x86,v120,release] {
symbols: { ..\Release\*.pdb; }
bin: { ..\Release\*.dll; }
};
[x86,v120,debug] {
symbols: { ..\Debug\*.pdb; }
bin: { ..\Debug\*.dll; }
};
};
此过程会生成三个.nupkg
个文件,我可以将其上传到我的Feed中。但是当我尝试将该软件包安装到.NET 4.6.1项目时,我收到此错误消息:
无法安装软件包' MyCppCliWrapper.redist 1.0.0.2'。您正在尝试将此软件包安装到针对.NETFramework,Version = v4.6.1'的项目中,但该软件包不包含任何与该框架兼容的程序集引用或内容文件。有关更多信息,请与软件包作者联系。
所以我重新考虑是否应该使用托管程序集的方式来创建.nupkg
,因为程序集有一个我想从托管代码中使用的托管类。我创建了.nuspec
(使用nuget spec
)并提供了元数据。然后我尝试像这样创建我的包:
nuget pack MyCppCliWrapper.nuspec -Prop Configuration=Release -Prop Platform=x86 -Build
但是这会产生一个包含整个项目的包,包含所有源文件和临时文件,就像该文件夹的zip文件一样。
显然,也缺少有关目标框架的元信息。
当我尝试使用项目文件来创建包时(就像使用C#程序集一样),这也失败了:
请指定要使用的nuspec,project.json或项目文件
NuGet似乎不支持C ++项目文件.vcxproj
(我正在使用NuGet 3.5.0.1938命令行实用程序)。
我是否需要手动构建并在files
的{{1}}部分中提供所有文件?如果是的话,他怎么会从这一行知道哪个DLL是针对哪个.NET框架加平台的呢?
.nuspec
我相信Hans Passant是对的,这只是一个常规托管的nuget包,但是包装程序不处理<file src="bin\**\*.dll" target="lib" />
文件,所以我编写了自己的.vcxproj
:
.nuspec
以这种方式生成的包有效。
还有一个问题:这样,我是否必须做两个包,一个用于32位,一个用于64位 - 或者是否可以将它们包含在一个包中(我更喜欢)并使用消耗项目一个或另一个取决于目标架构(any-cpu大多是32位)?
答案 0 :(得分:5)
我不知道这是否仍然可以帮到你,但我已经成功地打包了x64和x86 C ++代码,以及在AnyCPU上编译的C#包装器。
在我的C#项目中,我有两个平台:“x86”和“x64”。
在我的Nuget文件夹中,我有以下结构:
\Project
\Project.1.0.nuspec
\build
\x64
\*.dll
\*.pdb
\x86
\*.dll
\*.pdb
\Project.targets
\lib
\net452
\Wrapper.dll
\Wrapper.pdb
Project.nuspec:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Project</id>
<version>1.0</version>
<authors>nilsonneto</authors>
<owners>nilsonneto</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Example.</description>
<references>
<reference file="Wrapper.dll" />
</references>
</metadata>
<files>
<file src="build\Project.targets" target="build\Project.targets" />
<file src="build\x64\**" target="build\x64" />
<file src="build\x86\**" target="build\x86" />
<file src="lib\net452\Wrapper.dll" target="lib\net452\Wrapper.dll" />
<file src="lib\net452\Wrapper.pdb" target="lib\net452\Wrapper.pdb" />
</files>
</package>
Project.targets:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)\$(Platform)\*.*" />
<Content Include="@(NativeLibs)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
注意$(Platform),这是在Visual Studio上构建的Platform的名称,这就是为什么我将文件夹中的C ++ DLL与Visual Studio中的平台同名。
根据文档(https://docs.microsoft.com/en-us/nuget/create-packages/native-packages),所有本机DLL都必须放在\ build目录中。
以native为目标的Native NuGet包然后在\ build,\ content和\ tools文件夹中提供文件;在这种情况下不使用\ lib(NuGet不能直接添加对C ++项目的引用)。包中还可能包含\ build中的目标和props文件,NuGet会自动导入到使用该包的项目中。这些文件的名称必须与包含.targets和/或.props扩展名的包ID相同。
因此,只需根据您在.NET项目和设置上支持的平台调整文件夹名称。