summaryrefslogtreecommitdiff
path: root/Tools/Java/Source/GenBuild/org/tianocore/build/FileProcess.java
blob: 59a2e587bde413b522331038631ac416662f5a2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/** @file
  File is FileProcess class which is used to generate ANT script to build 
  source files. 
  
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
package org.tianocore.build;

import java.io.File;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
  <p><code>FileProcess</code> is class to generate ANT script to build source
  files.</p>
  
  <p>If file does not specify file type, <code>FileProcess</code> will judge 
  by its extension. Following is the current supported extensions. </p>
  
  <pre>   
 Source File Suffix     File Type       Description
    .h                   CHeader      C header file
    .c                   CCode        C source file
    .inc                 ASMHeader    Assembly header file
    .asm                 ASM          Assembly source file, usually for IA32 and X64 Arch and MSFT tool chain
    .S                   ASM          Assembly source file, usually for IPF Arch
    .s                   ASM          Assembly source file, usually for IA32 and X64 Arch and GCC tool chain
    .uni                 UNI          Unicode file
    .vfr                 VFR          Visual Forms Representation File
    .fv                  FV           Firmware Volume
    .SEC                 FFS          Firmware File System file
    .PEI                 FFS          Firmware File System file
    .DXE                 FFS          Firmware File System file
    .APP                 FFS          Firmware File System file
    .FVI                 FFS          Firmware File System file
    .FFS                 FFS          Firmware File System file
    .bmp                 BMP          Graphic File
    .i                   PPCode       IPF PreProcessor Code
  </pre>
  
  @since GenBuild 1.0
**/
public class FileProcess {
    ///
    ///  The mapping information about source suffix, tool code, file type.
    ///
    public final String[][] fileTypes = { {".h", "", "CHeader" }, 
                                          {".c", "CC", "CCode" },
                                          {".inc", "", "ASMHeader" },
                                          {".asm", "ASM", "ASM" }, 
                                          {".S", "ASM", "ASM" },
                                          {".s", "ASM", "ASM" },
                                          {".uni", "", "UNI" },
                                          {".vfr", "", "VFR" },
                                          {".Vfr", "", "VFR" },
                                          {".dxs", "", "DPX"},
                                          {".fv", "", "FV" },
                                          {".efi", "", "EFI" },
                                          {".SEC", "", "FFS" },
                                          {".PEI", "", "FFS" },
                                          {".DXE", "", "FFS" },
                                          {".APP", "", "FFS" },
                                          {".FYI", "", "FFS" },
                                          {".FFS", "", "FFS" },
                                          {".bmp", "", "BMP" },
                                          {".i", "PP", "PPCode"}};
    ///
    /// Current ANT context. 
    ///
    private Project project;

    ///
    /// Current module's include pathes
    ///
    private String[] includes;
    
    ///
    /// Xml Document.
    ///
    private Document document;
    
    ///
    /// The flag to ensure all unicode files build before others. 
    ///
    private boolean unicodeFirst = true;
    
    ///
    /// The flag present whether current module contains Unicode files or not.
    ///
    private boolean unicodeExist = false;

    /**
      Initialize the project, includes, sourceFiles, document members.
      
      @param project ANT project
      @param includes Module include pathes
      @param sourceFiles Modules source files
      @param document XML document
    **/
    public void init(Project project, String[] includes, Document document) {
        this.document = document;
        this.includes = includes;
        this.project = project;
    }

    /**
      Parse file without file type. 
      
      @param filename Source file name
      @param root Root node
      @param unicodeFirst whether build Unicode file firstly or not
    **/
    public synchronized void parseFile(String filename, String family, Node root, boolean unicodeFirst) {
        this.unicodeFirst = unicodeFirst;
        parseFile(filename, family, root);
    }
    
    /**
      Get whether current module contains Unicode files or not.
      
      @return Whether current module contains Unicode files or not
    **/
    public boolean isUnicodeExist() {
        return unicodeExist;
    }

    /**
      Parse file.
      
      @param filename Source file name
      @param filetype Source file type
      @param root Root node
      @param unicodeFirst whether build Unicode file firstly or not
    **/
    public synchronized void parseFile(String filename, String filetype, String family, Node root, boolean unicodeFirst) {
        this.unicodeFirst = unicodeFirst;
        parseFile(filename, filetype, family, root);
    }
    
    /**
      Find out source file's type. 
      
      @param filename Source file name
      @param root Root node
    **/
    public synchronized void parseFile(String filename, String family, Node root) throws BuildException {
        for (int i = 0; i < fileTypes.length; i++) {
            if (filename.endsWith(fileTypes[i][0])) {
                parseFile(filename, fileTypes[i][2], family, root);
                return ;
            }
        }
    }

    /**
      Parse file. If flag <code>unicodeFirst</code> is true, then build all
      unicode files firstly. 
      
      <p>Note that AutoGen.c is processed specially. It's output path is always
      <code>${DEST_DIR_OUTPUT}</code>, others are <code>${DEST_DIR_OUTPUT}</code>
      and relative to module path. </p>
      
      @param filename Source file name
      @param filetype Source file type
      @param root Root node
    **/
    public synchronized void parseFile(String filename, String filetype, String family, Node root) {
        //
        // Filter file with family. Only family is specified in source file and
        // not include current family will skip the file. 
        //
        String toolCode = getToolCodeByFileType(filetype);
        if (family != null && !family.trim().equalsIgnoreCase("")) {
            String toolChainFamily = project.getProperty(toolCode + "_FAMILY");
            if (toolChainFamily != null) {
                if(!toolChainFamily.equalsIgnoreCase(family)) {
                    return ;
                }
            }
        }
        
        if (unicodeFirst) {
            if ( ! filetype.equalsIgnoreCase("UNI")){
                return ;
            }
            unicodeExist= true;
        } else {
            if (filetype.equalsIgnoreCase("UNI")){
                return ;
            }
        }
        
        //
        // If file is C or ASM header file, skip it
        //
        if (filetype.equalsIgnoreCase("CHeader") || filetype.equalsIgnoreCase("ASMHeader")) {
            return;
        }
        
        //
        // If file is pre-processor file, skip it
        // 
        if (filetype.equalsIgnoreCase("PPCode")) {
            return;
        }
        
        //
        // If define CC_EXT in tools_def.txt file, the source file with 
        // different suffix is skipped
        //
        String toolsDefExtName = project.getProperty(toolCode + "_EXT");
        if (toolsDefExtName != null) {
            String[] exts = toolsDefExtName.split(" ");
            for (int i = 0; i < exts.length; i++) {
                if ( ! filename.endsWith(exts[i])) {
                    return ;
                }
            }
        }
        
        String module_path = project.getProperty("MODULE_DIR");
        File moduleFile = new File(module_path);
        File sourceFile = new File(filename);
        
        //
        // If source file is AutoGen.c, then Filepath is .
        //
        String sourceFilepath = "";
        String sourceFilename = "";
        String sourceFileext = "";
        if (sourceFile.getPath().endsWith("AutoGen.c")) {
            sourceFilepath = ".";
            sourceFilename = "AutoGen";
            sourceFileext = ".c";
            filetype = "AUTOGEN";
        } else {
            // sourceFile.
            String str = sourceFile.getPath().substring(moduleFile.getPath().length() + 1);
            int index = str.lastIndexOf(File.separatorChar);
            sourceFilepath = ".";
            if (index > 0) {
                sourceFilepath = str.substring(0, index);
                str = str.substring(index + 1);
            }
            sourceFilename = str;
            index = str.lastIndexOf('.');
            if (index > 0) {
                sourceFilename = str.substring(0, index);
                sourceFileext = str.substring(index);
            }
        }
        // <Build_filetype FILEPATH="" FILENAME="" />
        Element ele = document.createElement("Build_" + filetype);
        ele.setAttribute("FILEPATH", sourceFilepath);
        ele.setAttribute("FILENAME", sourceFilename);
        ele.setAttribute("FILEEXT", sourceFileext.substring(1));
        Element includesEle = document.createElement("EXTRA.INC");
        for (int i = 0; i < includes.length; i++) {
            Element includeEle = document.createElement("includepath");
            includeEle.setAttribute("path", project.replaceProperties(includes[i]));
            includesEle.appendChild(includeEle);
        }
        ele.appendChild(includesEle);
        root.appendChild(ele);
    }
    
    private String getToolCodeByFileType(String fileType) {
        for (int i = 0; i < fileTypes.length; i++) {
            if (fileTypes[i][2].equalsIgnoreCase(fileType)) {
                return fileTypes[i][1];
            }
        }
        return null;
    }
}