Skip to content

Commit

Permalink
Pack external dependencies to redistribution
Browse files Browse the repository at this point in the history
  • Loading branch information
mayuki committed Jul 28, 2023
1 parent a229910 commit 507a672
Show file tree
Hide file tree
Showing 89 changed files with 1,044 additions and 60 deletions.
12 changes: 12 additions & 0 deletions YetAnotherHttpHandler.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
THIRD-PARTY-NOTICES = THIRD-PARTY-NOTICES
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YetAnotherHttpHandler.Unity.Dependencies", "src\YetAnotherHttpHandler.Unity.Dependencies\YetAnotherHttpHandler.Unity.Dependencies.csproj", "{9F9F6B43-8CBF-4025-8B8B-A4465C04740E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YetAnotherHttpHandler.Unity.Dependencies.Sync", "src\YetAnotherHttpHandler.Unity.Dependencies.Sync\YetAnotherHttpHandler.Unity.Dependencies.Sync.csproj", "{7038AD7C-6767-4427-8B89-473BC27E9C9A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -31,6 +35,14 @@ Global
{22CFEF14-D36A-4E21-B51F-F31053C0E870}.Debug|Any CPU.Build.0 = Debug|Any CPU
{22CFEF14-D36A-4E21-B51F-F31053C0E870}.Release|Any CPU.ActiveCfg = Release|Any CPU
{22CFEF14-D36A-4E21-B51F-F31053C0E870}.Release|Any CPU.Build.0 = Release|Any CPU
{9F9F6B43-8CBF-4025-8B8B-A4465C04740E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F9F6B43-8CBF-4025-8B8B-A4465C04740E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F9F6B43-8CBF-4025-8B8B-A4465C04740E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F9F6B43-8CBF-4025-8B8B-A4465C04740E}.Release|Any CPU.Build.0 = Release|Any CPU
{7038AD7C-6767-4427-8B89-473BC27E9C9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7038AD7C-6767-4427-8B89-473BC27E9C9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7038AD7C-6767-4427-8B89-473BC27E9C9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7038AD7C-6767-4427-8B89-473BC27E9C9A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
120 changes: 120 additions & 0 deletions src/YetAnotherHttpHandler.Unity.Dependencies.Sync/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// See https://aka.ms/new-console-template for more information

using System.Text.Json;

var projectAssetJsonPath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"..\YetAnotherHttpHandler.Unity.Dependencies\obj\project.assets.json"));
Console.WriteLine($"projectAssetJsonPath: {projectAssetJsonPath}");
if (!File.Exists(projectAssetJsonPath))
{
Console.Error.WriteLine("Error: project.assets.json is not found. Please execute `dotnet build ../YetAnotherHttpHandler.Dependencies` before run this.");
return -1;
}

var pluginBaseDir = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"..\YetAnotherHttpHandler.Unity\Assets\Plugins"));
Console.WriteLine($"pluginBaseDir: {pluginBaseDir}");
if (!Directory.Exists(pluginBaseDir))
{
Console.Error.WriteLine($"Error: Cannot load project.assets.json.");
return -1;
}

// Load project.assets.json
var jsonSerializerOptions = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
};
var projectAssets = JsonSerializer.Deserialize<PackageAssetsJson>(File.ReadAllText(projectAssetJsonPath), jsonSerializerOptions);
if (projectAssets == null)
{
Console.Error.WriteLine($"Error: Plugins directory is not found in YetAnotherHttpHandler.Unity project.");
return -1;
}

Console.WriteLine($"PackageFolders: {string.Join(";", projectAssets.PackageFolders.Keys)}");

// Determine the files that need to be copied
var copyItems = new List<CopyToPlugins>();
var targetNetStandard2_1 = projectAssets.Targets[".NETStandard,Version=v2.1"];
foreach (var dep in targetNetStandard2_1)
{
var licenseFiles = projectAssets.Libraries[dep.Key].Files.Where(x => x.StartsWith("LICENSE", StringComparison.OrdinalIgnoreCase));
copyItems.Add(new CopyToPlugins(dep.Key, dep.Value.Runtime.Keys.Concat(licenseFiles).ToArray()));
}

// List the files that will be copy.
foreach (var item in copyItems)
{
var srcDir = projectAssets.PackageFolders.Select(x => Path.Combine(x.Key, item.BaseName.ToLower())).FirstOrDefault(x => Directory.Exists(x));
if (srcDir is null)
{
Console.Error.WriteLine($"Error: NuGet package '{item.BaseName}' not found in any package directories.");
return -1;
}
var destDir = Path.Combine(pluginBaseDir, item.BaseName);
foreach (var file in item.Files)
{
var src = Path.Combine(srcDir, file);
var dest = Path.Combine(destDir, file);

var destFileDir = Path.GetDirectoryName(dest);
if (!Directory.Exists(destFileDir))
{
Console.WriteLine($"Create directory: {destFileDir}");
Directory.CreateDirectory(destFileDir);
}

Console.WriteLine($"Copy: {src} -> {dest}");
File.Copy(src, dest, overwrite: true);
}
}

// Create the dependencies lists to build .unitypackage.
HashSet<string> depsForYaha;
{
var depsListFileName = "YetAnotherHttpHandler.deps.txt";
var depsRootPackage = "System.IO.Pipelines";
var outputDepsListPath = Path.Combine(pluginBaseDir, depsListFileName);
var deps = ResolveDependencies(depsRootPackage, targetNetStandard2_1);
Console.WriteLine($"Write dependencies list: {outputDepsListPath}");
File.WriteAllText(outputDepsListPath, string.Join("\r\n", deps.OrderBy(x => x)));
depsForYaha = deps;
}
{
var depsListFileName = "Grpc.Net.Client.deps.txt";
var depsRootPackage = "Grpc.Net.Client";
var outputDepsListPath = Path.Combine(pluginBaseDir, depsListFileName);
var deps = ResolveDependencies(depsRootPackage, targetNetStandard2_1, depsForYaha); // No need to include System.IO.Pipelines and other packages.
Console.WriteLine($"Write dependencies list: {outputDepsListPath}");
File.WriteAllText(outputDepsListPath, string.Join("\r\n", deps.OrderBy(x => x)));
}

return 0;

static HashSet<string> ResolveDependencies(string library, IReadOnlyDictionary<string, Dependency> installedDeps, HashSet<string>? excludes = null)
{
var hashSet = new HashSet<string>();
hashSet.Add(library);
var targetLib = installedDeps.FirstOrDefault(x => x.Key.StartsWith(library + "/"));
foreach (var dep in targetLib.Value.Dependencies?.Keys ?? Array.Empty<string>())
{
if (excludes is not null && excludes.Contains(dep)) continue;

hashSet.Add(dep);
foreach (var depdep in ResolveDependencies(dep, installedDeps, excludes))
{
hashSet.Add(depdep);
}
}
return hashSet;
}
record CopyToPlugins(string BaseName, IReadOnlyList<string> Files);

public record AssetDetails(string Related);
public record Dependency(string Type, IDictionary<string, string>? Dependencies, IReadOnlyDictionary<string, AssetDetails> Compile, IReadOnlyDictionary<string, AssetDetails> Runtime);
public record Library(string Sha512, string Type, string Path, IReadOnlyList<string> Files);
public record PackageAssetsJson(
int Version,
IReadOnlyDictionary<string, IReadOnlyDictionary<string, Dependency>> Targets,
IReadOnlyDictionary<string, Library> Libraries,
IReadOnlyDictionary<string, object> PackageFolders
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
8 changes: 8 additions & 0 deletions src/YetAnotherHttpHandler.Unity.Dependencies/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# YetAnotherHttpHandler.Unity.Dependencies
A project for managing NuGet references for Unity.

To update the library in Unity, please follow the steps below:

- Build this project
- Run `YetAnotherHttpHandler.Unity.Dependencies.Sync` project
- Open `YetAnotherHttpHandler.Unity` in Unity (to update the `.meta` files)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Grpc.Net.Client" Version="2.55.0" />
<PackageReference Include="System.IO.Pipelines" Version="7.0.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -11,72 +11,25 @@ public static class PackageExporter
[MenuItem("Tools/Export Unitypackage")]
public static void Export()
{
const string PackageName = "Cysharp.Net.Http.YetAnotherHttpHandler.Native";

var root = $"Plugins/{PackageName}";
var version = GetVersion(root);

var fileName = string.IsNullOrEmpty(version) ? $"{PackageName}.unitypackage" : $"{PackageName}.{version}.unitypackage";
var exportPath = "./" + fileName;

var additionalAssets = new string[]
{
"Assets/Plugins/System.IO.Pipelines",
"Assets/Plugins/System.Runtime.CompilerServices.Unsafe",
};

var path = Path.Combine(Application.dataPath, root);
var assets = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories)
.Where(x => Path.GetExtension(x) is ".cs" or ".asmdef" or ".json" or ".meta" or ".jslib" or ".so" or ".dll" or ".a" or ".dylib")
.Select(x => "Assets" + x.Replace(Application.dataPath, "").Replace(@"\", "/"))
.Concat(additionalAssets.SelectMany(x => Directory.EnumerateFiles(x, "*", SearchOption.AllDirectories)))
.ToArray();
PackDependencies("Cysharp.Net.Http.YetAnotherHttpHandler.Dependencies", "YetAnotherHttpHandler.deps.txt");
PackDependencies("Grpc.Net.Client.Dependencies", "Grpc.Net.Client.deps.txt");
}

UnityEngine.Debug.Log("Export below files" + Environment.NewLine + string.Join(Environment.NewLine, assets));
static void PackDependencies(string unityPackageName, string dependenciesListFileName)
{
Debug.Log($"Creating package '{unityPackageName}'...");
var pluginsDir = Path.Combine(Application.dataPath, "Plugins");
var libraryNames = File.ReadAllLines(Path.Combine(pluginsDir, dependenciesListFileName));
Debug.Log($"Includes library: {string.Join(';', libraryNames)}");

var exportPath = $"./{unityPackageName}.unitypackage";
AssetDatabase.ExportPackage(
assets,
libraryNames.Select(x => $"Assets/Plugins/{x}").ToArray(),
exportPath,
ExportPackageOptions.Default);
ExportPackageOptions.Recurse);

UnityEngine.Debug.Log("Export complete: " + Path.GetFullPath(exportPath));
}

static string GetVersion(string root)
{
var version = Environment.GetEnvironmentVariable("UNITY_PACKAGE_VERSION");
var versionJson = Path.Combine(Application.dataPath, root, "package.json");

if (File.Exists(versionJson))
{
var v = JsonUtility.FromJson<Version>(File.ReadAllText(versionJson));

if (!string.IsNullOrEmpty(version))
{
if (v.version != version)
{
var msg = $"package.json and env version are mismatched. UNITY_PACKAGE_VERSION:{version}, package.json:{v.version}";

if (Application.isBatchMode)
{
Console.WriteLine(msg);
Application.Quit(1);
}

throw new Exception("package.json and env version are mismatched.");
}
}

version = v.version;
}

return version;
}

public class Version
{
public string version;
}
}

#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Grpc.Core.Api
Grpc.Net.Client
Grpc.Net.Common
Microsoft.Extensions.Logging.Abstractions
System.Diagnostics.DiagnosticSource

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Loading

0 comments on commit 507a672

Please sign in to comment.