Merge pull request #799 from kebby/master
[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                 }
43
44                 void CheckOutputDirectory ()
45                 {
46                         if (Directory.Exists (Context.OutputDirectory))
47                                 return;
48
49                         Directory.CreateDirectory (Context.OutputDirectory);
50                 }
51
52                 protected override void ProcessAssembly (AssemblyDefinition assembly)
53                 {
54                         OutputAssembly (assembly);
55                 }
56
57                 void OutputAssembly (AssemblyDefinition assembly)
58                 {
59                         string directory = Context.OutputDirectory;
60
61                         CopyConfigFileIfNeeded (assembly, directory);
62
63                         switch (Annotations.GetAction (assembly)) {
64                         case AssemblyAction.Save:
65                         case AssemblyAction.Link:
66                                 assembly.Write (GetAssemblyFileName (assembly, directory), SaveSymbols (assembly));
67                                 break;
68                         case AssemblyAction.Copy:
69                                 CloseSymbols (assembly);
70                                 CopyAssembly (GetOriginalAssemblyFileInfo (assembly), directory, Context.LinkSymbols);
71                                 break;
72                         case AssemblyAction.Delete:
73                                 CloseSymbols (assembly);
74                                 var target = GetAssemblyFileName (assembly, directory);
75                                 if (File.Exists (target)) {
76                                         File.Delete (target);
77                                         File.Delete (target + ".mdb");
78                                         File.Delete (GetConfigFile (target));
79                                 }
80                                 break;
81                         default:
82                                 CloseSymbols (assembly);
83                                 break;
84                         }
85                 }
86
87                 void CloseSymbols (AssemblyDefinition assembly)
88                 {
89                         Annotations.CloseSymbolReader (assembly);
90                 }
91
92                 WriterParameters SaveSymbols (AssemblyDefinition assembly)
93                 {
94                         var parameters = new WriterParameters ();
95                         if (!Context.LinkSymbols)
96                                 return parameters;
97
98                         if (!assembly.MainModule.HasSymbols)
99                                 return parameters;
100
101                         if (Context.SymbolWriterProvider != null)
102                                 parameters.SymbolWriterProvider = Context.SymbolWriterProvider;
103                         else
104                                 parameters.WriteSymbols = true;
105                         return parameters;
106                 }
107
108                 static void CopyConfigFileIfNeeded (AssemblyDefinition assembly, string directory)
109                 {
110                         string config = GetConfigFile (GetOriginalAssemblyFileInfo (assembly).FullName);
111                         if (!File.Exists (config))
112                                 return;
113
114                         string target = Path.GetFullPath (GetConfigFile (GetAssemblyFileName (assembly, directory)));
115
116                         if (config == target)
117                                 return;
118
119                         File.Copy (config, GetConfigFile (GetAssemblyFileName (assembly, directory)), true);
120                 }
121
122                 static string GetConfigFile (string assembly)
123                 {
124                         return assembly + ".config";
125                 }
126
127                 static FileInfo GetOriginalAssemblyFileInfo (AssemblyDefinition assembly)
128                 {
129                         return new FileInfo (assembly.MainModule.FullyQualifiedName);
130                 }
131
132                 static void CopyAssembly (FileInfo fi, string directory, bool symbols)
133                 {
134                         string target = Path.GetFullPath (Path.Combine (directory, fi.Name));
135                         string source = fi.FullName;
136                         if (source == target)
137                                 return;
138
139                         File.Copy (source, target, true);
140
141                         if (!symbols)
142                                 return;
143
144                         source += ".mdb";
145                         if (!File.Exists (source))
146                                 return;
147                         File.Copy (source, target + ".mdb", true);
148                 }
149
150                 static string GetAssemblyFileName (AssemblyDefinition assembly, string directory)
151                 {
152                         string file = assembly.Name.Name + (assembly.MainModule.Kind == ModuleKind.Dll ? ".dll" : ".exe");
153                         return Path.Combine (directory, file);
154                 }
155         }
156 }