1 // Copyright (c) Microsoft. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 
4 using System;
5 using System.IO;
6 using Microsoft.Build.Framework;
7 using Microsoft.Build.Utilities;
8 using Microsoft.Build.Shared;
9 using Microsoft.Build.Tasks.Deployment.ManifestUtilities;
10 
11 namespace Microsoft.Build.Tasks
12 {
13     /// <summary>
14     /// The License Compiler task
15     /// </summary>
16     public class LC : ToolTaskExtension
17     {
18         #region Constructors
19 
20         /// <summary>
21         /// public constructor
22         /// </summary>
LC()23         public LC()
24         {
25             // do nothing
26         }
27 
28         #endregion
29 
30         #region Input/output properties
31 
32         /// <summary>
33         /// Specifies the items that contain licensed components that need to be included in the .licenses file
34         /// </summary>
35         [Required]
36         public ITaskItem[] Sources
37         {
38             set { Bag["Sources"] = value; }
39             get { return (ITaskItem[])Bag["Sources"]; }
40         }
41 
42         /// <summary>
43         /// The name of the .licenses file, output only. It's inferred from LicenseTarget and OutputDirectory.
44         /// </summary>
45         [Output]
46         public ITaskItem OutputLicense
47         {
48             set { Bag["OutputLicense"] = value; }
49             get { return (ITaskItem)Bag["OutputLicense"]; }
50         }
51 
52         /// <summary>
53         /// Specifies the executable for which the .licenses files are being generated
54         /// </summary>
55         [Required]
56         public ITaskItem LicenseTarget
57         {
58             set { Bag["LicenseTarget"] = value; }
59             get { return (ITaskItem)Bag["LicenseTarget"]; }
60         }
61 
62         /// <summary>
63         /// Output directory for the generated .licenses file
64         /// </summary>
65         /// <value></value>
66         public string OutputDirectory
67         {
68             set { Bag["OutputDirectory"] = value; }
69             get { return (string)Bag["OutputDirectory"]; }
70         }
71 
72         /// <summary>
73         /// Specifies the referenced components (licensed controls and possibly their dependent assemblies)
74         /// to load when generating the .license file.
75         /// </summary>
76         public ITaskItem[] ReferencedAssemblies
77         {
78             set { Bag["ReferencedAssemblies"] = value; }
79             get { return (ITaskItem[])Bag["ReferencedAssemblies"]; }
80         }
81 
82         /// <summary>
83         /// Suppresses the display of the startup banner
84         /// </summary>
85         public bool NoLogo
86         {
87             set { Bag["NoLogo"] = value; }
88             get { return GetBoolParameterWithDefault("NoLogo", false); }
89         }
90 
91         public string SdkToolsPath
92         {
93             set { Bag["SdkToolsPath"] = value; }
94             get { return (string)Bag["SdkToolsPath"]; }
95         }
96 
97         /// <summary>
98         /// Targeted version of the framework (i.e. 4.5 or 2.0, etc.)
99         /// </summary>
100         [Required]
101         public string TargetFrameworkVersion
102         {
103             get; set;
104         }
105         #endregion
106 
107         #region Class properties
108 
109         /// <summary>
110         /// The name of the tool to execute
111         /// </summary>
112         protected override string ToolName
113         {
114             get
115             {
116                 return "lc.exe";
117             }
118         }
119 
120         #endregion
121 
122         #region Methods
123 
124         /// <summary>
125         /// Validate the task arguments, log any warnings/errors
126         /// </summary>
127         /// <returns>true if arguments are corrent enough to continue processing, false otherwise</returns>
ValidateParameters()128         protected override bool ValidateParameters()
129         {
130             // if all the Required attributes are set, we're good to go.
131             return true;
132         }
133 
134         /// <summary>
135         /// Determing the path to lc.exe
136         /// </summary>
137         /// <returns>path to lc.exe, null if not found</returns>
GenerateFullPathToTool()138         protected override string GenerateFullPathToTool()
139         {
140             string pathToTool = SdkToolsPathUtility.GeneratePathToTool(SdkToolsPathUtility.FileInfoExists, Microsoft.Build.Utilities.ProcessorArchitecture.CurrentProcessArchitecture, SdkToolsPath, ToolExe, Log, true);
141             return pathToTool;
142         }
143 
144         /// <summary>
145         /// Generates arguments to be passed to lc.exe
146         /// </summary>
147         /// <param name="commandLine">command line builder class to add arguments to</param>
AddCommands(CommandLineBuilderExtension commandLine)148         private void AddCommands(CommandLineBuilderExtension commandLine)
149         {
150             commandLine.AppendSwitchIfNotNull("/target:", LicenseTarget.ItemSpec);
151 
152             foreach (ITaskItem item in Sources)
153             {
154                 commandLine.AppendSwitchIfNotNull("/complist:", item.ItemSpec);
155             }
156 
157             commandLine.AppendSwitchIfNotNull("/outdir:", OutputDirectory);
158 
159             if (ReferencedAssemblies != null)
160             {
161                 foreach (ITaskItem item in ReferencedAssemblies)
162                 {
163                     commandLine.AppendSwitchIfNotNull("/i:", item.ItemSpec);
164                 }
165             }
166 
167             commandLine.AppendWhenTrue("/nologo", Bag, "NoLogo");
168 
169             // generate the output file name
170             string outputPath = LicenseTarget.ItemSpec + ".licenses";
171 
172             if (OutputDirectory != null)
173                 outputPath = Path.Combine(OutputDirectory, outputPath);
174 
175             OutputLicense = new TaskItem(outputPath);
176         }
177 
178 
179         /// <summary>
180         /// Generates response file with arguments for lc.exe
181         /// Used when targeting framework version is 4.6 or later
182         /// </summary>
183         /// <param name="commandLine">command line builder class to add arguments to the response file</param>
AddResponseFileCommands(CommandLineBuilderExtension commandLine)184         protected internal override void AddResponseFileCommands(CommandLineBuilderExtension commandLine)
185         {
186             Version targetFramework = Util.GetTargetFrameworkVersion(TargetFrameworkVersion);
187             // Don't generate response file on versions of the framework < 4.6
188             // They will use an older lc.exe which does not understand response files
189             if (targetFramework.CompareTo(new Version("4.6")) < 0)
190             {
191                 return;
192             }
193 
194             AddCommands(commandLine);
195         }
196 
197         /// <summary>
198         /// Generates command line arguments for lc.exe
199         /// Used when targeting framework version is less than 4.6
200         /// </summary>
201         /// <param name="commandLine">command line builder class to add arguments to the command line</param>
AddCommandLineCommands(CommandLineBuilderExtension commandLine)202         protected internal override void AddCommandLineCommands(CommandLineBuilderExtension commandLine)
203         {
204             Version targetFramework = Util.GetTargetFrameworkVersion(TargetFrameworkVersion);
205             // If the target framework version is < 4.6, we will be using lc.exe from an older SDK
206             // In this case, we want to use command line parameters instead of a response file
207             if (targetFramework.CompareTo(new Version("4.6")) >= 0)
208             {
209                 return;
210             }
211 
212             AddCommands(commandLine);
213         }
214 
215         #endregion
216     }
217 }
218