0260c892e99b74494f18250b4979bf3c20fbff4c
[mono.git] / mcs / tools / linker / Mono.Linker.Steps / OutputStep.cs
1 //
2 // OutputStep.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2006 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.IO;
31
32 using Mono.Cecil;
33 using Mono.Cecil.Cil;
34
35 namespace Mono.Linker.Steps {
36
37         public class OutputStep : BaseStep {
38
39                 protected override void Process ()
40                 {
41                         CheckOutputDirectory ();
42                         Annotations.SaveDependencies ();
43                 }
44
45                 void CheckOutputDirectory ()
46                 {
47                         if (Directory.Exists (Context.OutputDirectory))
48                                 return;
49
50                         Directory.CreateDirectory (Context.OutputDirectory);
51                 }
52
53                 protected override void ProcessAssembly (AssemblyDefinition assembly)
54                 {
55                         OutputAssembly (assembly);
56                 }
57
58                 void OutputAssembly (AssemblyDefinition assembly)
59                 {
60                         string directory = Context.OutputDirectory;
61
62                         CopyConfigFileIfNeeded (assembly, directory);
63
64                         switch (Annotations.GetAction (assembly)) {
65                         case AssemblyAction.Save:
66                         case AssemblyAction.Link:
67                                 Context.Annotations.AddDependency (assembly);
68                                 assembly.Write (GetAssemblyFileName (assembly, directory), SaveSymbols (assembly));
69                                 break;
70                         case AssemblyAction.Copy:
71                                 Context.Annotations.AddDependency (assembly);
72                                 CloseSymbols (assembly);
73                                 CopyAssembly (GetOriginalAssemblyFileInfo (assembly), directory, Context.LinkSymbols);
74                                 break;
75                         case AssemblyAction.Delete:
76                                 CloseSymbols (assembly);
77                                 var target = GetAssemblyFileName (assembly, directory);
78                                 if (File.Exists (target)) {
79                                         File.Delete (target);
80                                         File.Delete (target + ".mdb");
81                                         File.Delete (GetConfigFile (target));
82                                 }
83                                 break;
84                         default:
85                                 CloseSymbols (assembly);
86                                 break;
87                         }
88                 }
89
90                 void CloseSymbols (AssemblyDefinition assembly)
91                 {
92                         Annotations.CloseSymbolReader (assembly);
93                 }
94
95                 WriterParameters SaveSymbols (AssemblyDefinition assembly)
96                 {
97                         var parameters = new WriterParameters ();
98                         if (!Context.LinkSymbols)
99                                 return parameters;
100
101                         if (!assembly.MainModule.HasSymbols)
102                                 return parameters;
103
104                         if (Context.SymbolWriterProvider != null)
105                                 parameters.SymbolWriterProvider = Context.SymbolWriterProvider;
106                         else
107                                 parameters.WriteSymbols = true;
108                         return parameters;
109                 }
110
111                 static void CopyConfigFileIfNeeded (AssemblyDefinition assembly, string directory)
112                 {
113                         string config = GetConfigFile (GetOriginalAssemblyFileInfo (assembly).FullName);
114                         if (!File.Exists (config))
115                                 return;
116
117                         string target = Path.GetFullPath (GetConfigFile (GetAssemblyFileName (assembly, directory)));
118
119                         if (config == target)
120                                 return;
121
122                         File.Copy (config, GetConfigFile (GetAssemblyFileName (assembly, directory)), true);
123                 }
124
125                 static string GetConfigFile (string assembly)
126                 {
127                         return assembly + ".config";
128                 }
129
130                 static FileInfo GetOriginalAssemblyFileInfo (AssemblyDefinition assembly)
131                 {
132                         return new FileInfo (assembly.MainModule.FullyQualifiedName);
133                 }
134
135                 static void CopyAssembly (FileInfo fi, string directory, bool symbols)
136                 {
137                         string target = Path.GetFullPath (Path.Combine (directory, fi.Name));
138                         string source = fi.FullName;
139                         if (source == target)
140                                 return;
141
142                         File.Copy (source, target, true);
143
144                         if (!symbols)
145                                 return;
146
147                         source += ".mdb";
148                         if (!File.Exists (source))
149                                 return;
150                         File.Copy (source, target + ".mdb", true);
151                 }
152
153                 static string GetAssemblyFileName (AssemblyDefinition assembly, string directory)
154                 {
155                         string file = assembly.Name.Name + (assembly.MainModule.Kind == ModuleKind.Dll ? ".dll" : ".exe");
156                         return Path.Combine (directory, file);
157                 }
158         }
159 }