aboutsummaryrefslogtreecommitdiff
path: root/src/wix/WixToolset.Core/Librarian.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/wix/WixToolset.Core/Librarian.cs')
-rw-r--r--src/wix/WixToolset.Core/Librarian.cs135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/wix/WixToolset.Core/Librarian.cs b/src/wix/WixToolset.Core/Librarian.cs
new file mode 100644
index 00000000..1dd1b44d
--- /dev/null
+++ b/src/wix/WixToolset.Core/Librarian.cs
@@ -0,0 +1,135 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Core
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using WixToolset.Core.Bind;
9 using WixToolset.Core.Link;
10 using WixToolset.Data;
11 using WixToolset.Extensibility.Data;
12 using WixToolset.Extensibility.Services;
13
14 /// <summary>
15 /// Core librarian tool.
16 /// </summary>
17 internal class Librarian : ILibrarian
18 {
19 internal Librarian(IServiceProvider serviceProvider)
20 {
21 this.ServiceProvider = serviceProvider;
22
23 this.Messaging = this.ServiceProvider.GetService<IMessaging>();
24 }
25
26 private IServiceProvider ServiceProvider { get; }
27
28 private IMessaging Messaging { get; }
29
30 /// <summary>
31 /// Create a library by combining several intermediates (objects).
32 /// </summary>
33 /// <returns>Returns the new library.</returns>
34 public Intermediate Combine(ILibraryContext context)
35 {
36 if (String.IsNullOrEmpty(context.LibraryId))
37 {
38 context.LibraryId = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).TrimEnd('=').Replace('+', '.').Replace('/', '_');
39 }
40
41 foreach (var extension in context.Extensions)
42 {
43 extension.PreCombine(context);
44 }
45
46 Intermediate library = null;
47 try
48 {
49 var sections = context.Intermediates.SelectMany(i => i.Sections).ToList();
50
51 var collate = new CollateLocalizationsCommand(this.Messaging, context.Localizations);
52 var localizationsByCulture = collate.Execute();
53
54 if (this.Messaging.EncounteredError)
55 {
56 return null;
57 }
58
59 this.ResolveFilePathsToEmbed(context, sections);
60
61 foreach (var section in sections)
62 {
63 section.AssignToLibrary(context.LibraryId);
64 }
65
66 library = new Intermediate(context.LibraryId, IntermediateLevels.Compiled, sections, localizationsByCulture);
67
68 library.UpdateLevel(IntermediateLevels.Combined);
69
70 this.Validate(library);
71 }
72 finally
73 {
74 foreach (var extension in context.Extensions)
75 {
76 extension.PostCombine(library);
77 }
78 }
79
80 return this.Messaging.EncounteredError ? null : library;
81 }
82
83 private void ResolveFilePathsToEmbed(ILibraryContext context, IEnumerable<IntermediateSection> sections)
84 {
85 // Resolve paths to files that are to be embedded in the library.
86 if (context.BindFiles)
87 {
88 var variableResolver = this.ServiceProvider.GetService<IVariableResolver>();
89
90 var fileResolver = new FileResolver(context.BindPaths, context.Extensions);
91
92 foreach (var symbol in sections.SelectMany(s => s.Symbols))
93 {
94 foreach (var field in symbol.Fields.Where(f => f?.Type == IntermediateFieldType.Path))
95 {
96 var pathField = field.AsPath();
97
98 if (pathField != null && !String.IsNullOrEmpty(pathField.Path))
99 {
100 var resolution = variableResolver.ResolveVariables(symbol.SourceLineNumbers, pathField.Path);
101
102 var file = fileResolver.Resolve(symbol.SourceLineNumbers, symbol.Definition, resolution.Value);
103
104 if (!String.IsNullOrEmpty(file))
105 {
106 // File was successfully resolved so track the embedded index as the embedded file index.
107 field.Set(new IntermediateFieldPathValue { Embed = true, Path = file });
108 }
109 else
110 {
111 this.Messaging.Write(ErrorMessages.FileNotFound(symbol.SourceLineNumbers, pathField.Path, symbol.Definition.Name));
112 }
113 }
114 }
115 }
116 }
117 }
118
119 private void Validate(Intermediate library)
120 {
121 var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, library.Sections, OutputType.Library);
122 find.Execute();
123
124 // TODO: Consider bringing this sort of verification back.
125 // foreach (Section section in library.Sections)
126 // {
127 // ResolveReferencesCommand resolve = new ResolveReferencesCommand(find.EntrySection, find.Symbols);
128 // resolve.Execute();
129 //
130 // ReportDuplicateResolvedSymbolErrorsCommand reportDupes = new ReportDuplicateResolvedSymbolErrorsCommand(find.SymbolsWithDuplicates, resolve.ResolvedSections);
131 // reportDupes.Execute();
132 // }
133 }
134 }
135}