Skip to content

Commit de8daa5

Browse files
committed
feat: Supporting a no-platform build
1 parent 9800cdb commit de8daa5

7 files changed

Lines changed: 167 additions & 12 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ $RECYCLE.BIN/
107107

108108
# Test output directories
109109
TestOutput/
110+
test.*
110111

111112
# Package manager files
112113
*.nupkg

AssetBundleBuilder.Tests/ArgumentParserTests.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ private static string GetTestPath(string relativePath) {
1616
public void Parse_MinimalArgs_ShouldParseCorrectly() {
1717
var assetPath = GetTestPath("Assets");
1818
var outputPath = GetTestPath("Output");
19-
var args = new[] { "2022.3.35f1", assetPath, "test.bundle", outputPath };
19+
var args = new[] { "2022.3.35f1", assetPath, "testmod", outputPath };
2020
var config = ArgumentParser.Parse(args);
2121

2222
Assert.NotNull(config);
2323
Assert.Equal("2022.3.35f1", config.UnityVersion);
2424
Assert.Equal(Path.GetFullPath(assetPath), config.AssetDirectory);
2525
Assert.Equal(Path.GetFullPath(outputPath), config.OutputDirectory);
26-
Assert.Equal("test.bundle", config.BundleName);
27-
Assert.Equal("windows", config.BuildTarget);
26+
Assert.Equal("testmod", config.BundleName);
27+
Assert.Equal("", config.BuildTarget); // Default is empty - auto-detected current OS without platform suffix
2828
Assert.Equal("copy", config.LinkMethod);
2929
}
3030

@@ -33,21 +33,21 @@ public void Parse_WithUnityPath_ShouldParseCorrectly() {
3333
using var tempUnity = new TempUnityFile("Unity");
3434
var assetPath = GetTestPath("Assets");
3535
var outputPath = GetTestPath("Output");
36-
var args = new[] { tempUnity.Path, assetPath, "test.bundle", outputPath };
36+
var args = new[] { tempUnity.Path, assetPath, "testmod", outputPath };
3737
var config = ArgumentParser.Parse(args);
3838

3939
Assert.NotNull(config);
4040
Assert.Equal(tempUnity.Path, config.UnityPath);
4141
Assert.Equal(Path.GetFullPath(assetPath), config.AssetDirectory);
4242
Assert.Equal(Path.GetFullPath(outputPath), config.OutputDirectory);
43-
Assert.Equal("test.bundle", config.BundleName);
43+
Assert.Equal("testmod", config.BundleName);
4444
}
4545

4646
[Fact]
4747
public void Parse_WithBuildTarget_ShouldParseCorrectly() {
4848
var assetPath = GetTestPath("Assets");
4949
var outputPath = GetTestPath("Output");
50-
var args = new[] { "2022.3.35f1", assetPath, "test.bundle", outputPath, "--target", "windows" };
50+
var args = new[] { "2022.3.35f1", assetPath, "testmod", outputPath, "--target", "windows" };
5151
var config = ArgumentParser.Parse(args);
5252

5353
Assert.NotNull(config);
@@ -113,6 +113,21 @@ public void Parse_TooFewArgs_ShouldReturnNull() {
113113
Assert.Null(config);
114114
}
115115

116+
[Theory]
117+
[InlineData("test.framework")]
118+
[InlineData("my.bundle")]
119+
[InlineData("Test.Framework")]
120+
[InlineData("My.Bundle")]
121+
public void Parse_BundleNameWithForbiddenExtension_ShouldThrowException(string bundleName) {
122+
var assetPath = GetTestPath("Assets");
123+
var outputPath = GetTestPath("Output");
124+
var args = new[] { "2022.3.35f1", assetPath, bundleName, outputPath };
125+
126+
var exception = Assert.Throws<ArgumentException>(() => ArgumentParser.Parse(args));
127+
Assert.Contains("cannot end with .framework or .bundle", exception.Message);
128+
Assert.Contains(bundleName.ToLower(), exception.Message);
129+
}
130+
116131
[Fact]
117132
public void Parse_WithRelativePaths_ShouldConvertToAbsolute() {
118133
var currentDir = Directory.GetCurrentDirectory();

AssetBundleBuilder.Tests/AssetBundleNamingTests.cs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Runtime.InteropServices;
12
using Xunit;
23
using Xunit.Abstractions;
34

@@ -144,6 +145,28 @@ public void GenerateAssetBundleName_LogicTest() {
144145
}
145146
}
146147

148+
[Fact]
149+
public void GenerateAssetBundleName_NoTargetLogicTest() {
150+
// Test the naming logic for no platform suffix without requiring Unity
151+
var testCases = new[]
152+
{
153+
new { BundleName = "author.modname", Expected = "resource_author_modname" },
154+
new { BundleName = "mymod", Expected = "resource_mymod" },
155+
new { BundleName = "test.bundle", Expected = "resource_test_bundle" },
156+
new { BundleName = "complex.name.with.dots", Expected = "resource_complex_name_with_dots" },
157+
new { BundleName = "simple", Expected = "resource_simple" }
158+
};
159+
160+
foreach (var testCase in testCases) {
161+
// Simulate the naming logic from ModAssetBundleBuilder.cs when noPlatformSuffix = true
162+
var normalizedBundleName = testCase.BundleName.Replace(".", "_");
163+
var actualResult = $"resource_{normalizedBundleName}"; // No platform suffix
164+
165+
_output.WriteLine($"Input: '{testCase.BundleName}' (no target) -> '{actualResult}'");
166+
Assert.Equal(testCase.Expected, actualResult);
167+
}
168+
}
169+
147170
[Theory]
148171
[InlineData("windows")]
149172
[InlineData("linux")]
@@ -200,6 +223,86 @@ public async Task CreateAssetBundle_DifferentTargets_ShouldIncludeTargetInName(s
200223
if (File.Exists(manifestFile)) File.Delete(manifestFile);
201224
}
202225

226+
[Fact]
227+
public async Task CreateAssetBundle_NoTargetSpecified_ShouldNotIncludePlatformSuffix() {
228+
// Skip test in CI environments or if Unity is not available
229+
var isCI = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI")) ||
230+
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GITHUB_ACTIONS"));
231+
232+
if (isCI) {
233+
_output.WriteLine("Skipping test: Unity tests are disabled in CI environment");
234+
return;
235+
}
236+
237+
var unityPath = UnityPathFinder.FindUnityExecutable("2022.3.35f1");
238+
if (string.IsNullOrEmpty(unityPath)) {
239+
_output.WriteLine("Skipping test: Unity 2022.3.35f1 not found");
240+
return;
241+
}
242+
243+
// Verify test assets exist
244+
if (!Directory.Exists(_testAssetsPath)) {
245+
_output.WriteLine($"Skipping test: TestAssets directory not found at {_testAssetsPath}");
246+
return;
247+
}
248+
249+
const string bundleName = "no.target.test";
250+
var expectedFileName = "resource_no_target_test"; // No platform suffix expected
251+
252+
var config = new BuildConfiguration
253+
{
254+
UnityPath = unityPath,
255+
UnityVersion = "2022.3.35f1",
256+
AssetDirectory = _testAssetsPath,
257+
OutputDirectory = _testOutputPath,
258+
BundleName = bundleName,
259+
BuildTarget = "", // Empty string means auto-detect current OS without platform suffix
260+
KeepTempProject = false,
261+
CleanTempProject = true,
262+
LinkMethod = "copy"
263+
};
264+
265+
_output.WriteLine($"Testing default behavior: '{bundleName}' -> '{expectedFileName}' (no platform suffix)");
266+
267+
var success = await BuildAssetBundleAsync(config);
268+
Assert.True(success, "Asset bundle creation failed for default (no target) case");
269+
270+
// Verify the platform suffix is NOT included in the filename
271+
var expectedBundleFile = Path.Combine(_testOutputPath, expectedFileName);
272+
var expectedManifestFile = Path.Combine(_testOutputPath, expectedFileName + ".manifest");
273+
274+
_output.WriteLine($"Looking for bundle file at: {expectedBundleFile}");
275+
_output.WriteLine($"Looking for manifest file at: {expectedManifestFile}");
276+
277+
// List all files in output directory for debugging
278+
var outputFiles = Directory.GetFiles(_testOutputPath, "*", SearchOption.AllDirectories);
279+
_output.WriteLine("Files in output directory:");
280+
foreach (var file in outputFiles)
281+
_output.WriteLine($" {Path.GetRelativePath(_testOutputPath, file)} ({new FileInfo(file).Length} bytes)");
282+
283+
Assert.True(File.Exists(expectedBundleFile),
284+
$"Bundle file should NOT include platform suffix when no target specified: {expectedFileName}");
285+
Assert.True(File.Exists(expectedManifestFile),
286+
$"Manifest file should NOT include platform suffix when no target specified: {expectedFileName}.manifest");
287+
288+
// Verify no platform-suffixed files exist (verify that we don't accidentally get the old behavior)
289+
var currentOS = DetectCurrentOSForTest();
290+
var withSuffixFile = Path.Combine(_testOutputPath, $"resource_no_target_test_{currentOS}");
291+
Assert.False(File.Exists(withSuffixFile),
292+
$"Bundle file with platform suffix should NOT exist when no target specified: {withSuffixFile}");
293+
294+
// Clean up
295+
if (File.Exists(expectedBundleFile)) File.Delete(expectedBundleFile);
296+
if (File.Exists(expectedManifestFile)) File.Delete(expectedManifestFile);
297+
}
298+
299+
private static string DetectCurrentOSForTest() {
300+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return "windows";
301+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return "mac";
302+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return "linux";
303+
return "unknown";
304+
}
305+
203306
private Task<bool> BuildAssetBundleAsync(BuildConfiguration config) {
204307
return Task.Run(() =>
205308
{

AssetBundleBuilder/ArgumentParser.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ public static class ArgumentParser {
108108
if (string.IsNullOrEmpty(config.BundleName)) return null;
109109

110110
config.BundleName = config.BundleName.ToLower().Replace(" ", "");
111+
112+
// Validate bundle name doesn't end with forbidden extensions
113+
if (config.BundleName.EndsWith(".framework") || config.BundleName.EndsWith(".bundle")) {
114+
throw new ArgumentException($"Bundle name '{config.BundleName}' cannot end with .framework or .bundle");
115+
}
111116
config.AssetDirectory = Path.GetFullPath(config.AssetDirectory);
112117
config.OutputDirectory = Path.GetFullPath(config.OutputDirectory);
113118

AssetBundleBuilder/AssetBundleBuilder.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,27 @@ public static int BuildAssetBundle(BuildConfiguration config) {
7070

7171
GlobalConfig.Logger.Information("Using bundle name: {BundleName}", config.BundleName);
7272

73+
// Determine if we're using auto-detected target (no platform suffix) or explicit target
74+
var isAutoTarget = string.IsNullOrEmpty(config.BuildTarget);
75+
76+
// If no build target specified, detect current OS and don't append platform suffix
77+
if (isAutoTarget) {
78+
config.BuildTarget = DetectCurrentOS();
79+
GlobalConfig.Logger.Information("No target specified, using current OS: {BuildTarget} (no platform suffix)", config.BuildTarget);
80+
} else {
81+
GlobalConfig.Logger.Information("Using specified build target: {BuildTarget}", config.BuildTarget);
82+
}
83+
7384
// Convert user-friendly build target to Unity command line format
7485
var unityBuildTarget = ConvertBuildTarget(config.BuildTarget);
7586
GlobalConfig.Logger.Information("Unity build target: {BuildTarget}", unityBuildTarget);
7687

7788
// Create temporary Unity project if not specified
7889
if (string.IsNullOrEmpty(config.TempProjectPath)) {
7990
// Create hash from input parameters for consistent temp directory naming
80-
var hashInput = $"{config.AssetDirectory}|{config.BundleName}|{config.BuildTarget}";
91+
// Include a flag to distinguish between explicit and auto-detected targets
92+
var targetForHash = isAutoTarget ? "auto" : config.BuildTarget;
93+
var hashInput = $"{config.AssetDirectory}|{config.BundleName}|{targetForHash}";
8194
var hash = HashUtility.ComputeHash(hashInput);
8295
config.TempProjectPath = Path.Combine(Path.GetTempPath(), $"AssetBundleBuilder_{hash}");
8396
}
@@ -149,7 +162,9 @@ public static int BuildAssetBundle(BuildConfiguration config) {
149162
"-output",
150163
config.OutputDirectory,
151164
"-assetDirectory",
152-
config.AssetDirectory
165+
config.AssetDirectory,
166+
"-noPlatformSuffix",
167+
isAutoTarget ? "true" : "false"
153168
]);
154169

155170
var unityArgs = unityArgsList.ToArray();
@@ -448,6 +463,13 @@ private static int RunCommand(string command, string arguments) {
448463
return process.ExitCode;
449464
}
450465

466+
private static string DetectCurrentOS() {
467+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return "windows";
468+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return "mac";
469+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return "linux";
470+
throw new PlatformNotSupportedException("Unsupported operating system");
471+
}
472+
451473
private static string ConvertBuildTarget(string userBuildTarget) {
452474
return userBuildTarget.ToLower() switch
453475
{

AssetBundleBuilder/BuildConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public class BuildConfiguration {
66
public string AssetDirectory { get; set; } = string.Empty;
77
public string OutputDirectory { get; set; } = string.Empty;
88
public string BundleName { get; set; } = string.Empty;
9-
public string BuildTarget { get; set; } = "windows";
9+
public string BuildTarget { get; set; } = ""; // Empty means current OS without platform suffix
1010
public string TempProjectPath { get; set; } = string.Empty;
1111
public bool KeepTempProject { get; set; } = false;
1212
public bool CleanTempProject { get; set; } = false;

AssetBundleBuilder/UnityScripts/ModAssetBundleBuilder.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public static void BuildBundles()
2525
var outputDirectory = "";
2626
var assetDirectory = "";
2727
var buildTarget = "all";
28+
var noPlatformSuffix = false;
2829
for (int i = 0; i < arguments.Length; i++)
2930
{
3031
var arg = arguments[i];
@@ -70,6 +71,12 @@ public static void BuildBundles()
7071
Debug.Log($"Using asset directory: {assetDirectory}");
7172
i++; // Skip the next argument since we've consumed it
7273
}
74+
else if (arg == "-noPlatformSuffix" && i + 1 < arguments.Length)
75+
{
76+
noPlatformSuffix = arguments[i + 1].ToLower() == "true";
77+
Debug.Log($"No platform suffix: {noPlatformSuffix}");
78+
i++; // Skip the next argument since we've consumed it
79+
}
7380
}
7481

7582
if (string.IsNullOrEmpty(bundleName))
@@ -148,12 +155,14 @@ public static void BuildBundles()
148155
if (File.Exists(unityManifestFile)) File.Delete(unityManifestFile);
149156
if (File.Exists(unityManifestMetaFile)) File.Delete(unityManifestMetaFile);
150157

151-
// Generate the new naming format: resource_<bundlename>_<target>
158+
// Generate the new naming format: resource_<bundlename>_<target> or resource_<bundlename> if no platform suffix
152159
// Convert periods to underscores in bundle name
153160
var normalizedBundleName = assetBundleName.Replace(".", "_");
154-
var finalFileName = $"resource_{normalizedBundleName}_{buildTarget}";
161+
var finalFileName = noPlatformSuffix
162+
? $"resource_{normalizedBundleName}"
163+
: $"resource_{normalizedBundleName}_{buildTarget}";
155164

156-
Debug.Log($"Bundle naming: '{assetBundleName}' -> '{finalFileName}'");
165+
Debug.Log($"Bundle naming: '{assetBundleName}' -> '{finalFileName}' (no platform suffix: {noPlatformSuffix})");
157166

158167
var originalBundleFile = Path.Combine(tempOutputLocation, assetBundleName);
159168
var originalManifestFile = Path.Combine(tempOutputLocation, assetBundleName + ".manifest");

0 commit comments

Comments
 (0)