Kernel FP的MakeFile可以指定输出文件、报告文件以及代码文件,并且可以继承其他的MakeFile。首先我们来看一下MakeFile的例子:
这是一个叫Project.txt的MakeFile,继承自Default.txt和Default2.txt
1 <kfpProject>
2 <inherit path="Default.txt"/>
3 <inherit path="Default2.txt"/>
4 <code>
5 <base path="CodeBase\"/>
6 <include path="CodeA.txt"/>
7 <include path="CodeB.txt"/>
8 </code>
9 <code>
10 <include path="CodeC.txt"/>
11 <include path="CodeD.txt"/>
12 </code>
13 <output path="Output.txt"/>
14 <report path="Report.txt"/>
15 </kfpProject>
如果一部分代码放在一个文件夹下面的话,可以使用code/base来节省书写MakeFile的时间。让我们看一下剩下的三个MakeFile,最后一个MakeFile被Default.txt和Default2.txt共同继承:
Default.txt
1 <kfpProject>
2 <inherit path="Library\Library.txt"/>
3 <code>
4 <base path="DefBase\"/>
5 <include path="DefA.txt"/>
6 <include path="DefB.txt"/>
7 </code>
8 <code>
9 <include path="DefC.txt"/>
10 <include path="DefD.txt"/>
11 </code>
12 <output path="Output.txt"/>
13 <report path="Report.txt"/>
14 </kfpProject>
Default2.txt
1 <kfpProject>
2 <inherit path="Library\Library.txt"/>
3 <code>
4 <base path="Def2Base\"/>
5 <include path="Def2A.txt"/>
6 <include path="Def2B.txt"/>
7 </code>
8 <code>
9 <include path="Def2C.txt"/>
10 <include path="Def2D.txt"/>
11 </code>
12 <output path="Output.txt"/>
13 <report path="Report.txt"/>
14 </kfpProject>
他们共同继承的Library\Library.txt
1 <kfpProject>
2 <code>
3 <base path="LibBase\"/>
4 <include path="LibA.txt"/>
5 <include path="LibB.txt"/>
6 </code>
7 <code>
8 <include path="LibC.txt"/>
9 <include path="LibD.txt"/>
10 </code>
11 <output path="LibOutput.txt"/>
12 <report path="LibReport.txt"/>
13 </kfpProject>
MakeFile分析器的第一个作用是解析MakeFile,第二个作用是生成合并的MakeFile,也就是说,要将继承下来的所有东西进行合并,并且为所有路径制定直接路径而不是相对路径。让我们看看Project.txt合并后的结果:
1 <?xml version="1.0" encoding="gb2312" standalone="no" ?>
2 <kfpProject>
3 <output path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Output.txt" />
4 <report path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Report.txt" />
5 <code>
6 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Library\LibBase\LibA.txt" />
7 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Library\LibBase\LibB.txt" />
8 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Library\LibC.txt" />
9 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Library\LibD.txt" />
10 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Def2Base\Def2A.txt" />
11 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Def2Base\Def2B.txt" />
12 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Def2C.txt" />
13 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\Def2D.txt" />
14 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\DefBase\DefA.txt" />
15 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\DefBase\DefB.txt" />
16 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\DefC.txt" />
17 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\DefD.txt" />
18 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\CodeBase\CodeA.txt" />
19 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\CodeBase\CodeB.txt" />
20 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\CodeC.txt" />
21 <include path="E:\Coding\VL++\Tools\KfpCompiler\TestData\CodeD.txt" />
22 </code>
23 </kfpProject>
MakeFile分析器的代码如下。
头文件:
1 #ifndef KERNEL_COMPILER_PROJECTFILE
2 #define KERNEL_COMPILER_PROJECTFILE
3
4 #include "..\..\..\Library\Data\Data\VL_Data_String.h"
5 #include "..\..\..\Library\Data\Data\VL_Data_List.h"
6
7 using namespace vl;
8 using namespace vl::collection;
9
10 class ProjectError : public VL_Base
11 {
12 public:
13 VUnicodeString Path;
14 VUnicodeString Message;
15 };
16
17 class ProjectFile : public VL_Base
18 {
19 public:
20 typedef VL_AutoPtr<ProjectFile> Ptr;
21
22 class CodeBlock : public VL_Base
23 {
24 public:
25 typedef VL_AutoPtr<CodeBlock> Ptr;
26 typedef VL_List<Ptr , false , CodeBlock*> List;
27
28 VUnicodeString CodeBase;
29 VL_List<VUnicodeString , false> CodePaths;
30 };
31
32 VL_List<VUnicodeString , false> InheritPaths;
33 VUnicodeString OutputPath;
34 VUnicodeString ReportPath;
35 CodeBlock::List Codes;
36
37 void Load(VUnicodeString Path);
38 void LoadCombined(VUnicodeString Path);
39 void Save(VUnicodeString Path);
40 };
41
42 #endif
实现文件:
1 #include "ProjectFile.h"
2 #include "..\..\..\Library\Data\VL_Stream.h"
3 #include "..\..\..\Library\Data\VL_System.h"
4 #include "..\..\..\Library\XML\VL_XML.h"
5
6 using namespace vl::stream;
7 using namespace vl::system;
8 using namespace vl::xml;
9
10 /*********************************************************************************************************
11 事件
12 *********************************************************************************************************/
13
14 #define THROW_ERROR(MESSAGE) \
15 do{ \
16 ProjectError Error; \
17 Error.Path=Path; \
18 Error.Message=MESSAGE; \
19 throw Error; \
20 }while(0)
21
22 void ProjectFile::Load(VUnicodeString Path)
23 {
24 try
25 {
26 VL_XMLDocument Document;
27 VL_FileStream Stream(Path,VL_FileStream::vfomRead);
28 if(!Stream.IsAvailable())
29 {
30 THROW_ERROR(L"工程文件\""+Path+L"\"不存在。");
31 }
32 Document.Load(&Stream);
33
34 OutputPath=L"";
35 ReportPath=L"";
36 InheritPaths.Clear();
37 Codes.Clear();
38
39 if(Document.GetRootElement()->GetName()!=L"kfpProject")
40 {
41 THROW_ERROR(L"工程文件根节点必须是kfpProject。");
42 }
43
44 for(VInt i=0;i<Document.GetRootElement()->GetChildren().GetCount();i++)
45 {
46 VL_XMLElement* Element=Document.GetRootElement()->GetChildren()[i]->GetElement();
47 if(Element)
48 {
49 if(Element->GetName()==L"inherit")
50 {
51 InheritPaths.Add(Element->GetAttributeByName(L"path")->GetText());
52 }
53 else if(Element->GetName()==L"output")
54 {
55 if(OutputPath!=L"")
56 {
57 THROW_ERROR(L"output节点只能有一个。");
58 }
59 OutputPath=Element->GetAttributeByName(L"path")->GetText();
60 }
61 else if(Element->GetName()==L"report")
62 {
63 if(ReportPath!=L"")
64 {
65 THROW_ERROR(L"report节点只能有一个。");
66 }
67 ReportPath=Element->GetAttributeByName(L"path")->GetText();
68 }
69 else if(Element->GetName()==L"code")
70 {
71 CodeBlock::Ptr CurrentCode=new CodeBlock;
72 for(VInt j=0;j<Element->GetChildren().GetCount();j++)
73 {
74 VL_XMLElement* SubElement=Element->GetChildren()[j]->GetElement();
75 if(SubElement)
76 {
77 if(SubElement->GetName()==L"base")
78 {
79 if(CurrentCode->CodeBase!=L"")
80 {
81 THROW_ERROR(L"base节点只能有一个。");
82 }
83 CurrentCode->CodeBase=SubElement->GetAttributeByName(L"path")->GetText();
84 }
85 else if(SubElement->GetName()==L"include")
86 {
87 CurrentCode->CodePaths.Add(SubElement->GetAttributeByName(L"path")->GetText());
88 }
89 else
90 {
91 THROW_ERROR(L"节点"+SubElement->GetName()+L"没有定义。");
92 }
93 }
94 }
95 Codes.Add(CurrentCode);
96 }
97 else
98 {
99 THROW_ERROR(L"节点"+Element->GetName()+L"没有定义。");
100 }
101 }
102 }
103 }
104 catch(const VL_XMLError& XMLError)
105 {
106 THROW_ERROR(L"XML格式错误:"+XMLError.Message);
107 }
108 }
109
110 void ProjectFile::LoadCombined(VUnicodeString Path)
111 {
112 VL_List<ProjectFile::Ptr , false , ProjectFile*> Projects;
113 VL_List<VUnicodeString , false> ProjectPaths;
114 VL_List<VUnicodeString , false> ToLoadPaths;
115 ToLoadPaths.Add(Path);
116
117 while(ToLoadPaths.GetCount())
118 {
119 VUnicodeString CurrentPath=ToLoadPaths.Fetch(0);
120 ProjectPaths.Insert(0,CurrentPath);
121 ProjectFile::Ptr Project=new ProjectFile;
122 Project->Load(CurrentPath);
123 Projects.Insert(0,Project);
124 for(VInt i=0;i<Project->InheritPaths.GetCount();i++)
125 {
126 VUnicodeString InheritPath=VFileName(CurrentPath).GetPath().MakeAbsolute(Project->InheritPaths[i]).GetStrW();
127 if(!ToLoadPaths.Exists(InheritPath) && !ProjectPaths.Exists(InheritPath))
128 {
129 ToLoadPaths.Add(InheritPath);
130 }
131 }
132 }
133
134 OutputPath=L"";
135 ReportPath=L"";
136 InheritPaths.Clear();
137 Codes.Clear();
138
139 VUnicodeString CodeBase;
140 CodeBlock::Ptr UniqueCode=new CodeBlock;
141 Codes.Add(UniqueCode);
142
143 for(VInt i=0;i<Projects.GetCount();i++)
144 {
145 ProjectFile::Ptr Project=Projects[i];
146 if(Project->OutputPath!=L"")
147 {
148 OutputPath=VFileName(ProjectPaths[i]).GetPath().MakeAbsolute(Project->OutputPath).GetStrW();
149 }
150 if(Project->ReportPath!=L"")
151 {
152 ReportPath=VFileName(ProjectPaths[i]).GetPath().MakeAbsolute(Project->ReportPath).GetStrW();
153 }
154 for(VInt j=0;j<Project->Codes.GetCount();j++)
155 {
156 CodeBlock::Ptr CurrentCode=Project->Codes[j];
157 if(CurrentCode->CodeBase!=L"")
158 {
159 CodeBase=VFileName(ProjectPaths[i]).GetPath().MakeAbsolute(CurrentCode->CodeBase).GetStrW();
160 }
161 else
162 {
163 CodeBase=ProjectPaths[i];
164 }
165
166 for(VInt k=0;k<CurrentCode->CodePaths.GetCount();k++)
167 {
168 VUnicodeString CodePath=VFileName(CodeBase).GetPath().MakeAbsolute(CurrentCode->CodePaths[k]).GetStrW();
169 UniqueCode->CodePaths.Add(CodePath);
170 }
171 }
172 }
173 }
174
175 void ProjectFile::Save(VUnicodeString Path)
176 {
177 try
178 {
179 VL_XMLDocument Document;
180 Document.GetRootElement()->SetName(L"kfpProject");
181 for(VInt i=0;i<InheritPaths.GetCount();i++)
182 {
183 Document.GetRootElement()->CreateElement(L"inherit")->GetElement()->CreateAttribute(L"path",InheritPaths[i]);
184 }
185 if(OutputPath!=L"")
186 {
187 Document.GetRootElement()->CreateElement(L"output")->GetElement()->CreateAttribute(L"path",OutputPath);
188 }
189 if(ReportPath!=L"")
190 {
191 Document.GetRootElement()->CreateElement(L"report")->GetElement()->CreateAttribute(L"path",ReportPath);
192 }
193 for(VInt i=0;i<Codes.GetCount();i++)
194 {
195 CodeBlock::Ptr CurrentCode=Codes[i];
196 VL_XMLElement* CodeElement=Document.GetRootElement()->CreateElement(L"code")->GetElement();
197 if(CurrentCode->CodeBase!=L"")
198 {
199 CodeElement->CreateElement(L"base")->GetElement()->CreateAttribute(L"path",CurrentCode->CodeBase);
200 }
201 for(VInt j=0;j<CurrentCode->CodePaths.GetCount();j++)
202 {
203 CodeElement->CreateElement(L"include")->GetElement()->CreateAttribute(L"path",CurrentCode->CodePaths[j]);
204 }
205 }
206 VL_FileStream Stream(Path,VL_FileStream::vfomWrite);
207 Document.Save(&Stream,true);
208 }
209 catch(const VL_XMLError& XMLError)
210 {
211 THROW_ERROR(L"XML格式错误:"+XMLError.Message);
212 }
213 }
posted on 2008-12-24 05:20
陈梓瀚(vczh) 阅读(1785)
评论(1) 编辑 收藏 引用 所属分类:
脚本技术