Skip to content

Commit 621ca4c

Browse files
committed
improve build process
1 parent ee7c6ce commit 621ca4c

File tree

3 files changed

+76
-144
lines changed

3 files changed

+76
-144
lines changed

Editor/LLMBuildProcessor.cs

+25-117
Original file line numberDiff line numberDiff line change
@@ -2,150 +2,58 @@
22
using UnityEditor.Build;
33
using UnityEditor.Build.Reporting;
44
using UnityEngine;
5-
using System.IO;
6-
using System.Collections.Generic;
7-
using System;
85

96
namespace LLMUnity
107
{
11-
public class LLMBuildProcessor : MonoBehaviour, IPreprocessBuildWithReport, IPostprocessBuildWithReport
8+
public class LLMBuildProcessor : IPreprocessBuildWithReport, IPostprocessBuildWithReport
129
{
1310
public int callbackOrder => 0;
14-
static string tempDir = Path.Combine(Application.temporaryCachePath, "LLMBuildProcessor", Path.GetFileName(LLMUnitySetup.libraryPath));
15-
static List<MovedPair> movedPairs = new List<MovedPair>();
16-
static string movedCache = Path.Combine(tempDir, "moved.json");
1711

18-
[InitializeOnLoadMethod]
19-
private static void InitializeOnLoad()
20-
{
21-
if (!Directory.Exists(tempDir)) Directory.CreateDirectory(tempDir);
22-
else ResetMoves();
23-
}
24-
25-
// CALLED BEFORE THE BUILD
12+
// called before the build
2613
public void OnPreprocessBuild(BuildReport report)
2714
{
28-
// Start listening for errors when build starts
2915
Application.logMessageReceived += OnBuildError;
30-
HideLibraryPlatforms(report.summary.platform);
31-
HideModels();
32-
if (movedPairs.Count > 0) AssetDatabase.Refresh();
33-
}
34-
35-
// CALLED DURING BUILD TO CHECK FOR ERRORS
36-
private void OnBuildError(string condition, string stacktrace, LogType type)
37-
{
38-
if (type == LogType.Error)
39-
{
40-
// FAILED TO BUILD, STOP LISTENING FOR ERRORS
41-
BuildCompleted();
42-
}
43-
}
44-
45-
// CALLED AFTER THE BUILD
46-
public void OnPostprocessBuild(BuildReport report)
47-
{
48-
BuildCompleted();
49-
}
50-
51-
public void BuildCompleted()
52-
{
53-
Application.logMessageReceived -= OnBuildError;
54-
ResetMoves();
55-
}
56-
57-
static bool MovePath(string source, string target)
58-
{
59-
bool moved = false;
60-
if (File.Exists(source))
61-
{
62-
File.Move(source, target);
63-
moved = true;
64-
}
65-
else if (Directory.Exists(source))
66-
{
67-
Directory.Move(source, target);
68-
moved = true;
69-
}
70-
if (moved)
71-
{
72-
movedPairs.Add(new MovedPair {source = source, target = target});
73-
File.WriteAllText(movedCache, JsonUtility.ToJson(new FoldersMovedWrapper { movedPairs = movedPairs }));
74-
}
75-
return moved;
76-
}
77-
78-
static void MoveAssetAndMeta(string source, string target)
79-
{
80-
MovePath(source + ".meta", target + ".meta");
81-
MovePath(source, target);
82-
}
83-
84-
static void HideLibraryPlatforms(BuildTarget buildPlatform)
85-
{
86-
List<string> platforms = new List<string>(){ "windows", "macos", "linux", "android" };
87-
switch (buildPlatform)
16+
string platform = null;
17+
switch (report.summary.platform)
8818
{
8919
case BuildTarget.StandaloneWindows:
9020
case BuildTarget.StandaloneWindows64:
91-
platforms.Remove("windows");
21+
platform = "windows";
9222
break;
9323
case BuildTarget.StandaloneLinux64:
94-
platforms.Remove("linux");
24+
platform = "linux";
9525
break;
9626
case BuildTarget.StandaloneOSX:
97-
platforms.Remove("macos");
27+
platform = "macos";
9828
break;
9929
case BuildTarget.Android:
100-
platforms.Remove("android");
30+
platform = "android";
31+
break;
32+
case BuildTarget.iOS:
33+
platform = "ios";
10134
break;
10235
}
103-
104-
foreach (string dirname in Directory.GetDirectories(LLMUnitySetup.libraryPath))
105-
{
106-
foreach (string platform in platforms)
107-
{
108-
if (Path.GetFileName(dirname).StartsWith(platform))
109-
{
110-
MoveAssetAndMeta(dirname, Path.Combine(tempDir, Path.GetFileName(dirname)));
111-
}
112-
}
113-
}
36+
LLMBuilder.HideLibraryPlatforms(platform);
37+
LLMBuilder.CopyModels();
38+
AssetDatabase.Refresh();
11439
}
11540

116-
static void HideModels()
41+
// called during build to check for errors
42+
private void OnBuildError(string condition, string stacktrace, LogType type)
11743
{
118-
foreach (LLM llm in FindObjectsOfType<LLM>())
119-
{
120-
// if (!llm.downloadOnBuild) continue;
121-
// if (llm.modelURL != "") MoveAssetAndMeta(LLMUnitySetup.GetAssetPath(llm.model), Path.Combine(tempDir, Path.GetFileName(llm.model)));
122-
if (llm.loraURL != "") MoveAssetAndMeta(LLMUnitySetup.GetAssetPath(llm.lora), Path.Combine(tempDir, Path.GetFileName(llm.lora)));
123-
}
44+
if (type == LogType.Error) BuildCompleted();
12445
}
12546

126-
static void ResetMoves()
47+
// called after the build
48+
public void OnPostprocessBuild(BuildReport report)
12749
{
128-
if (!File.Exists(movedCache)) return;
129-
List<MovedPair> movedPairs = JsonUtility.FromJson<FoldersMovedWrapper>(File.ReadAllText(movedCache)).movedPairs;
130-
if (movedPairs == null) return;
131-
132-
bool refresh = false;
133-
foreach (var pair in movedPairs) refresh |= MovePath(pair.target, pair.source);
134-
if (refresh) AssetDatabase.Refresh();
135-
File.Delete(movedCache);
50+
BuildCompleted();
13651
}
137-
}
13852

139-
[Serializable]
140-
public struct MovedPair
141-
{
142-
public string source;
143-
public string target;
144-
}
145-
146-
[Serializable]
147-
public class FoldersMovedWrapper
148-
{
149-
public List<MovedPair> movedPairs;
53+
public void BuildCompleted()
54+
{
55+
Application.logMessageReceived -= OnBuildError;
56+
LLMBuilder.Reset();
57+
}
15058
}
15159
}

Editor/LLMEditor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void AddModelLoaders(SerializedObject llmScriptSO, LLM llmScript)
6363
}
6464
EditorGUILayout.EndHorizontal();
6565
}
66-
AddLoadButtons();
66+
_ = AddLoadButtons();
6767
bool downloadOnStart = EditorGUILayout.Toggle("Download on Start", LLMManager.downloadOnStart);
6868
if (downloadOnStart != LLMManager.downloadOnStart)
6969
{

Runtime/LLMUnitySetup.cs

+50-26
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,14 @@ public class LLMUnitySetup
7878
public static string LlamaLibURL = $"https://github.com/undreamai/LlamaLib/releases/download/{LlamaLibVersion}/undreamai-{LlamaLibVersion}-llamacpp.zip";
7979
/// <summary> LlamaLib path </summary>
8080
public static string libraryPath = GetAssetPath(Path.GetFileName(LlamaLibURL).Replace(".zip", ""));
81+
/// <summary> LLMnity store path </summary>
82+
public static string LLMUnityStore = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "LLMUnity");
8183
/// <summary> Model download path </summary>
82-
public static string modelDownloadPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "LLMUnity");
84+
public static string modelDownloadPath = Path.Combine(LLMUnityStore, "models");
8385
/// <summary> Model list for project </summary>
8486
public static string modelListPath = Path.Combine(Application.temporaryCachePath, "modelCache.json");
87+
/// <summary> Temporary dir for build </summary>
88+
public static string buildTempDir = Path.Combine(Application.temporaryCachePath, "LLMUnityBuild");
8589

8690
/// <summary> Default models for download </summary>
8791
[HideInInspector] public static readonly (string, string)[] modelOptions = new(string, string)[]
@@ -228,11 +232,11 @@ public static async Task AndroidExtractFile(string assetName, bool overwrite = f
228232
string target = GetAssetPath(assetName);
229233
if (!overwrite && File.Exists(target))
230234
{
231-
Debug.Log($"File {target} already exists");
235+
Log($"File {target} already exists");
232236
return;
233237
}
234238

235-
Debug.Log($"Extracting {source} to {target}");
239+
Log($"Extracting {source} to {target}");
236240

237241
// UnityWebRequest to read the file from StreamingAssets
238242
UnityWebRequest www = UnityWebRequest.Get(source);
@@ -242,7 +246,7 @@ public static async Task AndroidExtractFile(string assetName, bool overwrite = f
242246
while (!operation.isDone) await Task.Delay(1);
243247
if (www.result != UnityWebRequest.Result.Success)
244248
{
245-
Debug.LogError("Failed to load file from StreamingAssets: " + www.error);
249+
LogError("Failed to load file from StreamingAssets: " + www.error);
246250
}
247251
else
248252
{
@@ -267,6 +271,44 @@ public static bool IsSubPath(string childPath, string parentPath)
267271
}
268272

269273
#if UNITY_EDITOR
274+
275+
public static void CopyPath(string source, string target)
276+
{
277+
if (File.Exists(source))
278+
{
279+
File.Copy(source, target);
280+
}
281+
else if (Directory.Exists(source))
282+
{
283+
Directory.CreateDirectory(target);
284+
List<string> filesAndDirs = new List<string>();
285+
filesAndDirs.AddRange(Directory.GetFiles(source));
286+
filesAndDirs.AddRange(Directory.GetDirectories(source));
287+
foreach (string path in filesAndDirs)
288+
{
289+
CopyPath(path, Path.Combine(target, Path.GetFileName(path)));
290+
}
291+
}
292+
}
293+
294+
public static void MovePath(string source, string target)
295+
{
296+
CopyPath(source, target);
297+
DeletePath(source);
298+
}
299+
300+
public static bool DeletePath(string path)
301+
{
302+
if (!IsSubPath(path, GetAssetPath()) && !IsSubPath(path, buildTempDir))
303+
{
304+
LogError($"Safeguard: {path} will not be deleted because it may not be safe");
305+
return false;
306+
}
307+
if (File.Exists(path)) File.Delete(path);
308+
else if (Directory.Exists(path)) Directory.Delete(path, true);
309+
return true;
310+
}
311+
270312
[HideInInspector] public static float libraryProgress = 1;
271313

272314
private static async Task DownloadLibrary()
@@ -277,7 +319,9 @@ private static async Task DownloadLibrary()
277319
if (!Directory.Exists(libraryPath))
278320
{
279321
await DownloadFile(LlamaLibURL, libZip, true, null, SetLibraryProgress);
322+
AssetDatabase.StartAssetEditing();
280323
ZipFile.ExtractToDirectory(libZip, libraryPath);
324+
AssetDatabase.StopAssetEditing();
281325
File.Delete(libZip);
282326
}
283327
libraryProgress = 1;
@@ -307,26 +351,6 @@ public static string AddAsset(string assetPath)
307351
return filename;
308352
}
309353

310-
public static void CreateSymlink(string sourcePath, string targetPath)
311-
{
312-
bool isDirectory = Directory.Exists(sourcePath);
313-
if (!isDirectory && !File.Exists(sourcePath)) throw new FileNotFoundException($"Source path does not exist: {sourcePath}");
314-
315-
bool success;
316-
#if UNITY_STANDALONE_WIN
317-
success = CreateSymbolicLink(targetPath, sourcePath, (int)isDirectory);
318-
#else
319-
success = symlink(sourcePath, targetPath) == 0;
320-
#endif
321-
if (!success) throw new IOException($"Failed to create symbolic link: {targetPath}");
322-
}
323-
324-
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
325-
private static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags);
326-
327-
[DllImport("libc", SetLastError = true)]
328-
private static extern int symlink(string oldpath, string newpath);
329-
330354
#endif
331355
/// \endcond
332356
public static int GetMaxFreqKHz(int cpuId)
@@ -422,7 +446,7 @@ public static int AndroidGetNumBigCores()
422446
}
423447
catch (Exception e)
424448
{
425-
Debug.LogError(e.Message);
449+
LogError(e.Message);
426450
}
427451

428452
int numBigCores = 0;
@@ -474,7 +498,7 @@ public static int AndroidGetNumBigCoresCapacity()
474498
}
475499
catch (Exception e)
476500
{
477-
Debug.LogError(e.Message);
501+
LogError(e.Message);
478502
}
479503

480504
int numBigCores = 0;

0 commit comments

Comments
 (0)