虽然C#可以直接编译成AnyCPU
,可以直接在x86
,x64
,ARM
平台运行。
但是实际项目中,我们可能避免不了会引用一些外部的依赖库,而这些外部依赖库又不能编译成 AnyCPU
!
通常解决这种问题可以通过进程隔离来解决,也可以通过动态加载程序集来解决。
所以采用动态程序集加载的方式的话,我们的nuget包就需要同时把 x86,x64,arm
相关的运行库同时打包进去了。
之前我们已经讲过,如何手动构建nuget包
,如果还不太清楚的小伙伴,可以回顾下手动构建nuget包。
构建多平台nuget
包之前,需要先了解一些基础知识:
- 手动创建nuget包的基本方法
- nuget的目录结构
- csproj的结构的基础
- 编译过程
这里不做详细描述~
Nuget包的基础结构
├─ Build
│ ├─net462
│ │ └─*.props
│ │ └─*.targets
│ └─netstandard1.3
├─lib
│ ├─net462
│ └─netstandard1.3
└─runtimes
├─win-arm64
│ └─native
├─win-x64
│ └─native
└─win-x86
└─native
说明:
-
Build 文件夹,存放用于参与编译的配置文件。包含
*.props
和*.targets
格式文件。*.props
通常用于设置csproj
文件中特定的属性,可以理解为一个普通类的属性,这个属性值可以先设置,用不用就不关它事情
。*.targets
通常用于执行某个操作,可以理解为一个普通类里面的方法,可以使用其它属性执行某个操作
。需要注意的是:上述描述主要是为了方便理解,普通属性的设置也可以存放在*.targets
文件中。 -
lib 文件夹,存放参与编译的相关(动态/静态)链接库,可同时存放多个。编译时,默认情况下,该文件夹的文件会自动拷贝到输出目录下。
-
runtimes 文件夹,存放运行时所依赖的相关(动态/静态)链接库。该文件夹的结构请参考上述结构来存放。虽然该结构并不是nuget包里面的强制要求,但是按照这种结构会比较规范。尤其是在
.NET CORE
的应用中,运行时将会自动再该结构中查找对应的依赖库。
细心的朋友会发现,这个结构和上一次的结构会有什么区别?
是的,多了Build目录!所以这次构建多平台nuget
包,就需要用到它。
要想同时支持多平台,就需要在AnyCPU
的条件编译下,将Nuget
包内部的文件,动态输出到指定的目录。程序运行的时候,再动态加载该文件即可。
Nuget包内部文件组织步骤
这里以.net framework net45为例,命名为nuget.test
其它框架下修改对应的框架名称即可:
- 分别创建
build->net45
,lib->net45
,runtimes->win-x86
,runtimes->win-x64
等文件夹 - 将需要打包的文件分别拖动到对应的文件夹中。
- 创建
nuget.test.targets
文件
编辑该文件,输入以下内容:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Condition="'$(Platform)' == 'AnyCPU' Or '$(Platform)' == 'Any CPU'">
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x86\native\CefSharp.Wpf.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>runtimes\win-x86\native\CefSharp.Wpf.dll</Link>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\CefSharp.Wpf.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>runtimes\win-x64\native\CefSharp.Wpf.dll</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
</Project>
上面这段配置的主要目的,是根据编译器的条件编译,把nuget包中不同平台下的文件,复制到输出目录。
上述配置简要说明:
$(Platform) 表示编译平台:x86,x64,Any CPU,ARM64
$(MSBuildThisFileDirectory) 表示当前文件所在的目录,这里是指 nuget.test.targets 文件所在的目录绝对路径。
Content 表示项目内容
CopyToOutputDirectory 复制到输出目录
PreserveNewest 较新才复制
Always 总是复制
Never 从不
Link 需要输出的文件目录位置,以输出目录作为根目录。
有这段配置文件后,编译的时候就会根据条件编译配置,自动把文件添加到输出目录中。x86,x64的条件编译的方法也是一样的,大家可以自行补充。
注意事项:
- 一个nuget包的
*.targets
和*.props
文件只能创建一个 *.targets
和*.props
前缀文件名需要和包名一致- 配置文件中的格式不能有无故的换行,空格。参见:诡异的编译错误
根据上述方法,可以尝试打一个多平台的nuget包了。
微信公众号:
欢迎转载分享,如若转载,请标注署名。
本文会经常更新,请阅读原文: https://huchengv5.gitee.io//post/NET-%E5%A6%82%E4%BD%95%E6%9E%84%E5%BB%BA%E5%A4%9A%E5%B9%B3%E5%8F%B0nuget%E5%8C%85.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名胡承(包含链接: https://huchengv5.gitee.io/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。