为C++/CLI(混合)程序集创建NuGet包

Zoo*_*Way 9 c++-cli nuget

我创建了一个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")];
Run Code Online (Sandbox Code Playgroud)

当我现在在.NET 4.6.1项目中手动包含已编译的程序集时,我可以按预期使用托管类.

该项目可以构建四种方式:x86x64作为调试发布版本.它没有托管依赖项.

现在我想要一个(或者如果需要多个)NuGet包,我可以上传到我的feed并在我想要的每个.NET 4.6.1兼容项目中轻松使用包装器组件.我该如何实现这一目标?


到目前为止我尝试了两种方法:

首先,我创建了一个.autopkg文件,根据这篇博文文章提供本机DLL的方式.该files文件的部分如下所示:

files {
  // include: { *.h }; 
  [x86,v120,release] {
     symbols: { ..\Release\*.pdb; }
     bin:     { ..\Release\*.dll; }
  };
  [x86,v120,debug] {
     symbols: { ..\Debug\*.pdb; }
     bin:     { ..\Debug\*.dll; }
  };
};
Run Code Online (Sandbox Code Playgroud)

此过程会生成三个.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
Run Code Online (Sandbox Code Playgroud)

但是这会产生一个包含整个项目的包,包含所有源文件和临时文件,就像该文件夹的zip文件一样.

显然,也缺少有关目标框架的元信息.

当我尝试使用项目文件来创建包(就像使用C#程序集)时,这也会失败:

请指定要使用的nuspec,project.json或项目文件

.vcxprojNuGet似乎不支持C++项目文件(我使用的是NuGet 3.5.0.1938命令行实用程序).

我是否需要手动构建和提供的所有文件中files的部分.nuspec?如果是的话,他怎么会从这一行知道哪个DLL是针对哪个.NET框架加平台?

<file src="bin\**\*.dll" target="lib" />
Run Code Online (Sandbox Code Playgroud)

我相信Hans Passant是对的,这只是一个常规的管理nuget包,但打包器不处理.vcxproj文件所以我自己编写.nuspec:

<?xml version="1.0"?>
<package >
  <metadata>
  ...
  </metadata>
  <files>
    <file src="readme.txt" target="" />
    <file src="bin\Win32\Release\*.dll" target="lib\net461" />
    <file src="bin\Win32\Release\*.pdb" target="lib\net461" />
  </files>
</package>
Run Code Online (Sandbox Code Playgroud)

这种方式生成的包有效.

还有一个问题:这样,我是否必须做两个包,一个用于32位,一个用于64位 - 或者是否可以将它们包含在一个包中(我更喜欢)并让消费项目使用一个或另一个取决于目标架构(any-cpu大多是32位)?

nil*_*eto 6

我不知道这是否仍然可以帮助你,但我已经设法包装了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
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

注意$(Platform),这是在Visual Studio上构建的Platform的名称,这就是为什么我将文件夹中的C++ DLL与Visual Studio中的平台同名.

根据文档(https://docs.microsoft.com/en-us/nuget/create-packages/native-packages),所有本机DLL都必须放在\ build目录中.

针对native的本机NuGet包然后在\ build,\ content和\ tools文件夹中提供文件; 在这种情况下不使用\ lib(NuGet不能直接添加对C++项目的引用).包中还可能包含\ build中的目标和props文件,NuGet会自动导入到使用该包的项目中.这些文件的名称必须与包含.targets和/或.props扩展名的包ID相同.

因此,只需根据.NET项目和您的集合支持的平台调整文件夹名称.