Skip to content

Commit 55a9b49

Browse files
committed
Refactored/Simplified DLL merging implementation in cake scripts
1 parent 7864444 commit 55a9b49

File tree

2 files changed

+73
-163
lines changed

2 files changed

+73
-163
lines changed

cake-build/helpers/tools.cake

Lines changed: 52 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -11,144 +11,82 @@ public class ILRepackHelper
1111
_context = context;
1212
}
1313

14-
public void MergeJsonNet(DirectoryPath sourcePath, DirectoryPath outputPath)
14+
public void MergeDLLs(FilePath primaryDll, FilePath[] dllsToMerge, FilePath outputDll)
1515
{
16-
var targetDll = sourcePath.CombineWithFilePath("IO.Ably.dll");
17-
var docsFile = sourcePath.CombineWithFilePath("IO.Ably.xml");
18-
var outputDll = outputPath.CombineWithFilePath("IO.Ably.dll");
19-
var jsonNetDll = sourcePath.CombineWithFilePath("Newtonsoft.Json.dll");
20-
21-
_context.EnsureDirectoryExists(outputPath);
22-
23-
_context.Information($"Merging {jsonNetDll.GetFilename()} into {targetDll.GetFilename()}...");
24-
25-
// Get the root directory (parent of cake-build)
26-
var rootDir = _context.MakeAbsolute(_context.Directory("../"));
27-
var ilRepackPath = rootDir.CombineWithFilePath("tools/ilrepack.exe");
28-
29-
// Use ILRepack directly like FAKE does
30-
var exitCode = _context.StartProcess(ilRepackPath.FullPath, new ProcessSettings
31-
{
32-
Arguments = new ProcessArgumentBuilder()
33-
.Append($"/lib:\"{sourcePath.FullPath}\"")
34-
.Append("/targetplatform:v4")
35-
.Append("/internalize")
36-
.Append($"/attr:\"{targetDll.FullPath}\"")
37-
.Append($"/keyfile:\"{rootDir.CombineWithFilePath("IO.Ably.snk").FullPath}\"")
38-
.Append("/parallel")
39-
.Append($"/out:\"{outputDll.FullPath}\"")
40-
.Append($"\"{targetDll.FullPath}\"")
41-
.Append($"\"{jsonNetDll.FullPath}\"")
42-
});
43-
44-
if (exitCode != 0)
45-
{
46-
throw new Exception($"ILRepack failed with exit code {exitCode}");
47-
}
48-
49-
// Copy XML documentation
50-
if (_context.FileExists(docsFile))
51-
{
52-
_context.CopyFile(docsFile, outputPath.CombineWithFilePath("IO.Ably.xml"));
53-
}
54-
55-
_context.Information($"✓ Merged assembly created at {outputDll}");
56-
}
57-
58-
public void MergeDeltaCodec(DirectoryPath sourcePath, DirectoryPath outputPath)
59-
{
60-
var targetDll = outputPath.CombineWithFilePath("IO.Ably.dll");
61-
var docsFile = outputPath.CombineWithFilePath("IO.Ably.xml");
62-
var deltaCodecDll = sourcePath.CombineWithFilePath("IO.Ably.DeltaCodec.dll");
63-
var tempInputDll = outputPath.CombineWithFilePath("IO.Ably.temp.dll");
64-
65-
if (!_context.FileExists(deltaCodecDll))
16+
if (!_context.FileExists(primaryDll))
6617
{
67-
_context.Warning($"DeltaCodec DLL not found at {deltaCodecDll}, skipping merge...");
68-
return;
18+
throw new Exception($"Primary DLL not found: {primaryDll}");
6919
}
7020

71-
if (!_context.FileExists(targetDll))
21+
if (dllsToMerge == null || dllsToMerge.Length == 0)
7222
{
73-
_context.Warning($"Target DLL not found at {targetDll}, skipping merge...");
74-
return;
23+
throw new ArgumentException("At least one DLL must be specified to merge");
7524
}
7625

77-
_context.Information($"Merging {deltaCodecDll.GetFilename()} into {targetDll.GetFilename()}...");
78-
7926
// Get the root directory (parent of cake-build)
8027
var rootDir = _context.MakeAbsolute(_context.Directory("../"));
8128
var ilRepackPath = rootDir.CombineWithFilePath("tools/ilrepack.exe");
8229

83-
// Copy target DLL to temp location to avoid input/output conflict
84-
_context.CopyFile(targetDll, tempInputDll);
85-
86-
// Backup PDB and config files
87-
var targetPdb = outputPath.CombineWithFilePath("IO.Ably.pdb");
88-
var tempInputPdb = outputPath.CombineWithFilePath("IO.Ably.temp.pdb");
89-
if (_context.FileExists(targetPdb))
90-
{
91-
_context.CopyFile(targetPdb, tempInputPdb);
92-
}
93-
94-
var targetConfig = outputPath.CombineWithFilePath("IO.Ably.dll.config");
95-
var tempInputConfig = outputPath.CombineWithFilePath("IO.Ably.temp.dll.config");
96-
if (_context.FileExists(targetConfig))
97-
{
98-
_context.CopyFile(targetConfig, tempInputConfig);
99-
}
30+
// Build list of DLL paths - primary first, then merging DLLs
31+
var dllPaths = new List<string> { $"\"{primaryDll.FullPath}\"" };
32+
var mergingDllNames = new List<string>();
10033

101-
try
34+
foreach (var dllPath in dllsToMerge)
10235
{
103-
// Merge DeltaCodec into IO.Ably.dll (output directly with correct name)
104-
var exitCode = _context.StartProcess(ilRepackPath.FullPath, new ProcessSettings
36+
if (_context.FileExists(dllPath))
10537
{
106-
Arguments = new ProcessArgumentBuilder()
107-
.Append($"/lib:\"{sourcePath.FullPath}\"")
108-
.Append($"/lib:\"{outputPath.FullPath}\"")
109-
.Append("/targetplatform:v4")
110-
.Append("/internalize")
111-
.Append($"/attr:\"{tempInputDll.FullPath}\"")
112-
.Append($"/keyfile:\"{rootDir.CombineWithFilePath("IO.Ably.snk").FullPath}\"")
113-
.Append("/parallel")
114-
.Append($"/out:\"{targetDll.FullPath}\"")
115-
.Append($"\"{tempInputDll.FullPath}\"")
116-
.Append($"\"{deltaCodecDll.FullPath}\"")
117-
});
118-
119-
if (exitCode != 0)
38+
dllPaths.Add($"\"{dllPath.FullPath}\"");
39+
mergingDllNames.Add(dllPath.GetFilename().ToString());
40+
}
41+
else
12042
{
121-
throw new Exception($"ILRepack failed with exit code {exitCode}");
43+
throw new Exception($"Merge dll not found at path \"{dllPath.FullPath}\"");
12244
}
12345
}
124-
finally
46+
47+
_context.Information($"Merging {string.Join(", ", mergingDllNames)} into {primaryDll.GetFilename()}...");
48+
49+
// Ensure output directory exists
50+
var outputDir = outputDll.GetDirectory();
51+
_context.EnsureDirectoryExists(outputDir);
52+
53+
// Get the directory containing the primary DLL for assembly resolution
54+
var binDir = primaryDll.GetDirectory();
55+
56+
// Build ILRepack arguments - explicitly merge only the DLLs we specify
57+
var args = new ProcessArgumentBuilder()
58+
.Append("/targetplatform:v4")
59+
.Append("/internalize")
60+
// /lib: Specifies where ILRepack should search for referenced assemblies when loading the primary DLL.
61+
// This is needed because Mono.Cecil (used by ILRepack) must resolve all type references while reading
62+
// the assembly metadata, even before the merge begins. Without this, it fails to resolve types from
63+
// dependencies like Newtonsoft.Json that are referenced in custom attributes or type signatures.
64+
.Append($"/lib:\"{binDir.FullPath}\"")
65+
.Append($"/attr:\"{primaryDll.FullPath}\"")
66+
.Append($"/keyfile:\"{rootDir.CombineWithFilePath("IO.Ably.snk").FullPath}\"")
67+
.Append("/parallel")
68+
.Append($"/out:\"{outputDll.FullPath}\"");
69+
70+
// Add all DLL paths explicitly (primary + merging DLLs)
71+
foreach (var dllPath in dllPaths)
12572
{
126-
// Clean up temp files
127-
if (_context.FileExists(tempInputDll))
128-
{
129-
_context.DeleteFile(tempInputDll);
130-
}
131-
if (_context.FileExists(tempInputPdb))
132-
{
133-
_context.DeleteFile(tempInputPdb);
134-
}
135-
if (_context.FileExists(tempInputConfig))
136-
{
137-
_context.DeleteFile(tempInputConfig);
138-
}
73+
args.Append(dllPath);
13974
}
14075

141-
// Clean up DeltaCodec files from output path since they're now merged
142-
var deltaCodecFiles = _context.GetFiles(outputPath.Combine("IO.Ably.DeltaCodec.*").FullPath);
143-
144-
foreach (var file in deltaCodecFiles)
76+
// Use ILRepack to merge all DLLs in one go
77+
var exitCode = _context.StartProcess(ilRepackPath.FullPath, new ProcessSettings
78+
{
79+
Arguments = args
80+
});
81+
82+
if (exitCode != 0)
14583
{
146-
_context.DeleteFile(file);
147-
_context.Information($"Cleaned up: {file.GetFilename()}");
84+
throw new Exception($"ILRepack failed with exit code {exitCode}");
14885
}
14986

150-
_context.Information($"✓ DeltaCodec merged into {targetDll}");
87+
_context.Information($"✓ Merged assembly created at {outputDll}");
15188
}
15289
}
15390

15491
var ilRepackHelper = new ILRepackHelper(Context);
92+

cake-build/tasks/package.cake

Lines changed: 21 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ Task("_Package_Build_All")
2727
MSBuild(paths.PackageSolution, settings);
2828
});
2929

30-
Task("_Package_Merge_JsonNet")
30+
Task("_Package_Merge_All")
3131
.IsDependentOn("_Package_Build_All")
3232
.Does(() =>
3333
{
34-
Information("Merging Newtonsoft.Json into Ably assemblies...");
34+
Information("Merging dependencies (Newtonsoft.Json and DeltaCodec) into Ably assemblies...");
3535

36-
var projectsToMerge = new[]
37-
{
38-
"IO.Ably.Android",
39-
"IO.Ably.iOS",
40-
"IO.Ably.NETFramework"
36+
var projectsToMerge = new[]
37+
{
38+
"IO.Ably.Android",
39+
"IO.Ably.iOS",
40+
"IO.Ably.NETFramework"
4141
};
4242

4343
foreach (var project in projectsToMerge)
@@ -51,7 +51,6 @@ Task("_Package_Merge_JsonNet")
5151
}
5252

5353
var binPath = projectPath.Combine("bin/Release");
54-
var packagedPath = binPath.Combine("Packaged");
5554

5655
if (!DirectoryExists(binPath))
5756
{
@@ -61,56 +60,29 @@ Task("_Package_Merge_JsonNet")
6160

6261
Information($"Processing {project}...");
6362

64-
// Copy all IO.Ably* files to Packaged folder
65-
var ablyFiles = GetFiles(binPath.Combine("IO.Ably*").FullPath);
66-
EnsureDirectoryExists(packagedPath);
67-
CopyFiles(ablyFiles, packagedPath);
68-
69-
// Merge Newtonsoft.Json
70-
ilRepackHelper.MergeJsonNet(binPath, packagedPath);
71-
}
72-
});
73-
74-
Task("_Package_Merge_DeltaCodec")
75-
.IsDependentOn("_Package_Merge_JsonNet")
76-
.Does(() =>
77-
{
78-
Information("Merging DeltaCodec into Ably assemblies for all platforms...");
79-
80-
// Legacy platforms (already in packaged folder after JsonNet merge)
81-
var legacyProjects = new[]
82-
{
83-
"IO.Ably.Android",
84-
"IO.Ably.iOS",
85-
"IO.Ably.NETFramework"
86-
};
87-
88-
foreach (var project in legacyProjects)
89-
{
90-
var projectPath = paths.Src.Combine(project);
91-
92-
if (!DirectoryExists(projectPath))
63+
var primaryDll = binPath.CombineWithFilePath("IO.Ably.dll");
64+
var dllsToMerge = new[]
9365
{
94-
Warning($"Project directory not found: {project}, skipping...");
95-
continue;
96-
}
97-
98-
var binPath = projectPath.Combine("bin/Release");
66+
binPath.CombineWithFilePath("Newtonsoft.Json.dll"),
67+
binPath.CombineWithFilePath("IO.Ably.DeltaCodec.dll")
68+
};
9969
var packagedPath = binPath.Combine("Packaged");
70+
var outputDll = packagedPath.CombineWithFilePath("IO.Ably.dll");
10071

101-
if (!DirectoryExists(packagedPath))
72+
// Merge all dependencies into primary DLL in one go
73+
ilRepackHelper.MergeDLLs(primaryDll, dllsToMerge, outputDll);
74+
75+
// Copy XML documentation if it exists
76+
var docsFile = binPath.CombineWithFilePath("IO.Ably.xml");
77+
if (FileExists(docsFile))
10278
{
103-
Warning($"Packaged directory not found for {project}, skipping...");
104-
continue;
79+
CopyFile(docsFile, packagedPath.CombineWithFilePath("IO.Ably.xml"));
10580
}
106-
107-
Information($"Merging DeltaCodec for {project}...");
108-
ilRepackHelper.MergeDeltaCodec(binPath, packagedPath);
10981
}
11082
});
11183

11284
Task("_Package_Create_NuGet")
113-
.IsDependentOn("_Package_Merge_DeltaCodec")
85+
.IsDependentOn("_Package_Merge_All")
11486
.WithCriteria(() => !string.IsNullOrEmpty(version))
11587
.Does(() =>
11688
{

0 commit comments

Comments
 (0)