随笔-341  评论-2670  文章-0  trackbacks-0
    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) 阅读(1761) 评论(1)  编辑 收藏 引用 所属分类: 脚本技术

评论:
# re: Kernel FP 编译器MakeFile开发完成 2008-12-24 06:06 | 123
哇哇哇。。。更新够快的Y。。。神神。。。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理