Cannot get the nuget package to work properly.

This commit is contained in:
H. Utku Maden 2023-07-09 16:33:09 +03:00
parent 5f859adab9
commit 03c477e98f
14 changed files with 269 additions and 56 deletions

4
.gitignore vendored

@ -6,5 +6,5 @@ riderModule.iml
.idea
.vscode
nuget_repo
*.redist/out
*.redist/runtimes
**/out
**/runtimes

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Quik.StbImage.redist</id>
<version>1.0.0</version>
<authors>STBI Authors, H. Utku Maden</authors>
<owners>utkumaden</owners>
<description>
This is a redistribution of STBI for use with the QUIK project.
Compiled with `STBI_NO_STDIO` and a custom assert function. Call
`quik_stbi_failed_assert_store` to replace.
</description>
<tags>native</tags>
</metadata>
<files>
<file src="runtimes/**" target=""/>
</files>
</package>

@ -5,10 +5,26 @@
<Nullable>disable</Nullable>
<LangVersion>7.3</LangVersion>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<RuntimeIdentifiers>linux-arm;linux-arm64;linux-x64;win-x86;win-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup>
<!-- Nuget Properties. -->
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>Quik.StbImage</PackageId>
<Version>1.0.0</Version>
<Authors>STBI Authors, H. Utku Maden</Authors>
<Description>
A C# wrapper for the ubiquitous Stb Image library.
</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Quik.StbImage.redist" Version="1.0" />
<Content Include="runtimes/**">
<PackagePath>runtimes</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

@ -0,0 +1,67 @@
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;
namespace Quik.Stb
{
public unsafe static partial class Stbi
{
private delegate void FailedAssertProc(byte *expression, byte *file, int line, byte *function);
private static readonly string[] LibraryNames = new string[]
{
"runtimes/libstbi.dll",
"runtimes/libstbi.so",
"runtimes/libstbi.dylib",
"libstbi.dll",
"libstbi.so",
"libstbi.dylib",
};
static Stbi()
{
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), Resolver);
quik_stbi_failed_assert_store(Marshal.GetFunctionPointerForDelegate<FailedAssertProc>(FailedAssert));
}
private const DllImportSearchPath SearchPath =
DllImportSearchPath.ApplicationDirectory |
DllImportSearchPath.UserDirectories |
DllImportSearchPath.AssemblyDirectory |
DllImportSearchPath.UseDllDirectoryForDependencies;
private static IntPtr Resolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
Debugger.Break();
if (libraryName != "stbi")
return IntPtr.Zero;
foreach (string name in LibraryNames)
{
if (NativeLibrary.TryLoad(name, assembly, SearchPath, out IntPtr handle))
{
return handle;
}
}
return NativeLibrary.Load(libraryName);
}
private static void FailedAssert(byte *expression, byte *file, int line, byte *function)
{
string expr = expression == null ? string.Empty : Marshal.PtrToStringUTF8((IntPtr)expression);
string f = file == null ? string.Empty : Marshal.PtrToStringUTF8((IntPtr)file);
string func = function == null ? string.Empty : Marshal.PtrToStringUTF8((IntPtr)function);
Exception ex = new Exception("Assert failed in native stbi code.");
ex.Data.Add("Expression", expr);
ex.Data.Add("File", f);
ex.Data.Add("Line", line);
ex.Data.Add("Function", func);
throw ex;
}
}
}

@ -0,0 +1,60 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Quik.Stb
{
public unsafe class StbiStreamWrapper : IDisposable
{
private Stream _stream;
private bool _keepOpen;
private bool _isDisposed;
private delegate int ReadProc(void *userdata, byte* buffer, int count);
private delegate void SkipProc(void *userdata, int count);
private delegate int Eof(void *userdata);
public StbiStreamWrapper(Stream stream, bool keepOpen = false)
{
if (stream == null) throw new ArgumentNullException(nameof(stream));
_stream = stream;
_keepOpen = keepOpen;
}
public void CreateCallbacks(out stbi_io_callbacks cb)
{
cb = default;
cb.read = Marshal.GetFunctionPointerForDelegate<ReadProc>(ReadCb);
cb.skip = Marshal.GetFunctionPointerForDelegate<SkipProc>(SkipCb);
cb.eof = Marshal.GetFunctionPointerForDelegate<Eof>(EofCb);
}
private int ReadCb(void *userdata, byte* buffer, int count)
{
Span<byte> bytes = new Span<byte>(buffer, count);
return _stream.Read(bytes);
}
private void SkipCb(void *userdata, int count)
{
_stream.Seek(count, SeekOrigin.Current);
}
private int EofCb(void *userdata)
{
if (!_stream.CanRead || _stream.Position == _stream.Length)
return 1;
return 0;
}
public void Dispose()
{
if (_isDisposed) return;
if (!_keepOpen) _stream.Dispose();
_isDisposed = true;
}
}
}

@ -14,6 +14,6 @@
<tags>native</tags>
</metadata>
<files>
<file src="runtimes/**" target=""/>
<file src="runtimes/" target="runtimes"/>
</files>
</package>

@ -9,6 +9,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik.StbImage", "Quik.StbIm
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik.StbTrueType", "Quik.StbTrueType\Quik.StbTrueType.csproj", "{AD5B02B0-F957-4816-8CE9-5F278B856C70}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{5E87AF9C-AC12-4E48-99B1-CBEC0C97B624}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik.StbImage.Tests", "tests\Quik.StbImage.Tests\Quik.StbImage.Tests.csproj", "{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -67,5 +71,20 @@ Global
{AD5B02B0-F957-4816-8CE9-5F278B856C70}.Release|x64.Build.0 = Release|Any CPU
{AD5B02B0-F957-4816-8CE9-5F278B856C70}.Release|x86.ActiveCfg = Release|Any CPU
{AD5B02B0-F957-4816-8CE9-5F278B856C70}.Release|x86.Build.0 = Release|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Debug|x64.ActiveCfg = Debug|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Debug|x64.Build.0 = Debug|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Debug|x86.ActiveCfg = Debug|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Debug|x86.Build.0 = Debug|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Release|Any CPU.Build.0 = Release|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Release|x64.ActiveCfg = Release|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Release|x64.Build.0 = Release|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Release|x86.ActiveCfg = Release|Any CPU
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{AFF181CF-D51E-4E16-B3C6-38ED1E1FF615} = {5E87AF9C-AC12-4E48-99B1-CBEC0C97B624}
EndGlobalSection
EndGlobal

@ -1,7 +1,5 @@
#!/bin/bash
source $(dirname "$0")/quik_build_native.sh
ARCHS="linux-arm linux-arm64 linux-x64 linux-x86 win-x64 win-x86"
quik_build_native "Quik.StbImage.redist" "$ARCHS"
cd ..
quik_build_native "Quik.StbTrueType.redist" "$ARCHS"
sh/quik_build_native.sh "Quik.StbImage" "$ARCHS"
./quik_build_native.sh "Quik.StbTrueType.redist" "$ARCHS"

@ -3,36 +3,29 @@
# $1 Source path of the project.
# $2 Target architecture list.
quik_build_native () {
SRC=$1
NAME=$(dirname $SRC)
ARCHS=$2
SRC=$1
NAME=$(dirname $SRC)
ARCHS=$2
cd $SRC
cd $SRC
for ARCH in $ARCHS; do
# Output directory.
PREFIX=runtimes/$ARCH/native
# Build directory.
BUILD=out/$ARCH
# Cmake toolchain file.
TOOLCHAIN=../cmake/$ARCH.cmake
for ARCH in $ARCHS; do
# Output directory.
PREFIX=runtimes/$ARCH/native
# Build directory.
BUILD=out/$ARCH
# Cmake toolchain file.
TOOLCHAIN=../cmake/$ARCH.cmake
# Create directories.
mkdir -p $PREFIX $BUILD
# Configure CMAKE.
cmake -B $BUILD -S . \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN
# Build and install.
make -C $BUILD all
make -C $BUILD install
done
mkdir bin
nuget pack -OutputDirectory bin
nuget push $(find bin/*.nupkg) -Source $QNUGET_LOCAL -NonInteractive
}
# Create directories.
mkdir -p $PREFIX $BUILD
# Configure CMAKE.
cmake -B $BUILD -S . \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN
# Build and install.
make -C $BUILD all
make -C $BUILD install
done

@ -0,0 +1,55 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Runtime.InteropServices;
using Quik.Stb;
namespace Quik.StbImage.Tests
{
[TestClass]
public class LoadImage
{
[TestMethod("Set Global Options")]
public void SetGlobals()
{
Stbi.set_flip_vertically_on_load(1);
Stbi.set_unpremultiply_on_load(1);
}
private StbiStreamWrapper PrepareImage(string path, out stbi_io_callbacks cb)
{
Stream? str = GetType().Assembly.GetManifestResourceStream(path);
Assert.IsNotNull(str, $"Could not find test image resource {path}.");
StbiStreamWrapper wrapper = new StbiStreamWrapper(str);
wrapper.CreateCallbacks(out cb);
return wrapper;
}
[TestMethod("Load a PNG")]
public unsafe void LoadPng()
{
// TODO: Fill these up!
const int TEST_CHANNELS = 0;
const int TEST_WIDTH = 0;
const int TEST_HEIGHT = 0;
int x, y, numChannels;
using StbiStreamWrapper str = PrepareImage("Quik.StbImage.Tests.res.test.png", out stbi_io_callbacks cb);
byte *image = Stbi.load_from_callbacks(&cb, null, &x, &y, &numChannels, (int)StbiEnum.STBI_default);
if (image == null)
{
IntPtr reasonPtr = (IntPtr)Stbi.failure_reason();
string? reason = Marshal.PtrToStringUTF8((IntPtr)reasonPtr);
Assert.Fail("Could not load image: {0}.", reason ?? "None specified. (stbi_failure_reason() is null)");
}
Assert.AreEqual(TEST_CHANNELS, numChannels, "Channel count does not match.");
Assert.AreEqual(TEST_WIDTH, x, "Width does not match.");
Assert.AreEqual(TEST_HEIGHT, y, "Height does not match.");
Stbi.image_free(image);
}
}
}

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Quik.StbImage\Quik.StbImage.csproj" />
</ItemGroup>
</Project>