我正在使用.NET Core构建跨平台类库。根据为使用.csproj文件构建C#.NET Core项目的操作系统,我需要将本机库复制到项目的输出目录。例如,对于OS X,我想复制.dylib文件,对于Windows,我要复制.DLL文件,对于Linux我要复制.so文件。
如何使用.csproj ItemGroup中的Condition子句执行此操作?
<ItemGroup>
<Content Include="libNative.dylib" Condition=" '$(Configuration)|$(Platform)' == 'Debug|OSX' ">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
$(Platform)
似乎不起作用。我可以使用不同的变量吗?
答案 0 :(得分:8)
区分Windows&amp; Mac / Linux您可以使用$(os)
属性:这为Windows提供了Windows_NT
,为Mac / Linux提供了UNIX
。
区分Mac&amp; Linux,至少在最新版本的MSBuild上,您可以使用RuntimeInformation.IsOSPlatform
。
所以,结合起来,你的csproj可以有这样的东西:
<ItemGroup>
<Content Include="libNative.dll" Condition=" '$(OS)' == 'Windows_NT' ">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="libNative.so" Condition=" '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' ">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="libNative.dylib" Condition=" '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' ">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
据我所知,这应该适用于.Net Core,Mono和.Net Framework的所有最新版本。
在旧版本中,您需要诉诸恶意技巧来区分Mac&amp; Linux:
对于Linux - &gt; Condition=" '$(OS)' == 'Unix' and ! $([System.IO.File]::Exists('/usr/lib/libc.dylib')) "
对于Mac - &gt; Condition=" '$(OS)' == 'Unix' and $([System.IO.File]::Exists('/usr/lib/libc.dylib')) "
来源:
答案 1 :(得分:0)
我确实有这样的问题,最后在资源中保存了dll,并在库首次启动时为x86或X64暂停了dll。这对我来说是最干净的方式。
替代当您在nuget中包含dll时,您还必须确保在som删除/清理bin mapp时重新获取相同的dll。
所以你必须将文件添加到nuger并在构建文件上创建目标以在构建时重新复制dll
这就是我所做的。
internal class EmbeddedDllClass
{
public static void LoadAllDll()
{
Assembly assem = Assembly.GetExecutingAssembly();
if (IntPtr.Size == 8)
{
var path = Path.Combine(string.Join("\\", assem.Location.Split('\\').Reverse().Skip(1).Reverse()), "x64");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
path = Path.Combine(path, "SQLite.Interop.dll");
if (!File.Exists(path))
File.WriteAllBytes(path, Properties.Resources.SQLite_Interop_64);
}
else if (IntPtr.Size == 4)
{
var path = Path.Combine(string.Join("\\", assem.Location.Split('\\').Reverse().Skip(1).Reverse()), "x86");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
path = Path.Combine(path, "SQLite.Interop.dll");
if (!File.Exists(path))
File.WriteAllBytes(path, Properties.Resources.SQLite_Interop_86);
}
}
}
然后只需称呼它
EmbeddedDllClass.LoadAllDll();
答案 2 :(得分:0)
还想为我的 Nuget 包创建跨平台。 在 .csproj 中尝试了以下代码。
<Content Include="libNative.win" Condition=" '$(OS)' == 'Windows_NT' ">
<Content Include="libNative.dylib" Condition=" '$(OS)' != 'Windows_NT' ">
因此创建了 .nupkg。
当在 Linux 上引用相同的 .nupkg 时,因为 $(OS) 已经设置为 Windows_NT,添加了 libNative.win 而不是 libNative.dylib(这是预期的)。
所以这个 $(OS) 是在创建 nuget 时设置的,而不是在添加时设置的。
有关更多详细信息:您可以在 <Description>
中使用 $(OS) 或 $(Platform) 并查看值是如何设置的。