Clean-as-you-go mode to remove generated files as soon as possible to minimize disk...
[reactos.git] / reactos / tools / rbuild / backend / devcpp / devcpp.cpp
1 /*
2 * Dev-C++ Backend
3 * Copyright (C) 2005 Trevor McCort
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifdef _MSC_VER
21 #pragma warning ( disable : 4786 )
22 #endif//_MSC_VER
23
24 #include <iostream>
25 #include <fstream>
26 #include <string>
27
28 #include "devcpp.h"
29
30 using namespace std;
31
32 static class DevCppFactory : public Backend::Factory
33 {
34 public:
35
36 DevCppFactory() : Factory("devcpp") {}
37 Backend *operator() (Project &project,
38 bool verbose,
39 bool cleanAsYouGo)
40 {
41 return new DevCppBackend(project, verbose, cleanAsYouGo);
42 }
43
44 } factory;
45
46
47 DevCppBackend::DevCppBackend(Project &project,
48 bool verbose,
49 bool cleanAsYouGo) : Backend(project, verbose, cleanAsYouGo)
50 {
51 m_unitCount = 0;
52 }
53
54 void DevCppBackend::Process()
55 {
56 string filename = ProjectNode.name + ".dev";
57
58 cout << "Creating Dev-C++ project: " << filename << endl;
59
60 ProcessModules();
61
62 m_devFile.open(filename.c_str());
63
64 if(!m_devFile.is_open())
65 {
66 cout << "Could not open file." << endl;
67 return;
68 }
69
70 m_devFile << "[Project]" << endl;
71
72 m_devFile << "FileName=" << filename << endl
73 << "Name=" << ProjectNode.name << endl
74 << "UnitCount=" << m_unitCount << endl
75 << "Type=1" << endl
76 << "Ver=1" << endl
77 << "ObjFiles=" << endl
78 << "Includes=" << endl
79 << "Libs=" << endl
80 << "PrivateResource=" << endl
81 << "ResourceIncludes=" << endl
82 << "MakeIncludes=" << endl
83 << "Compiler=" << endl
84 << "CppCompiler=" << endl
85 << "Linker=" << endl
86 << "IsCpp=1" << endl
87 << "Icon=" << endl
88 << "ExeOutput=" << endl
89 << "ObjectOutput=" << endl
90 << "OverrideOutput=0" << endl
91 << "OverrideOutputName=" << endl
92 << "HostApplication=" << endl
93 << "CommandLine=" << endl
94 << "UseCustomMakefile=1" << endl
95 << "CustomMakefile=" << ProjectNode.makefile << endl
96 << "IncludeVersionInto=0" << endl
97 << "SupportXPThemes=0" << endl
98 << "CompilerSet=0" << endl
99
100 << "CompilerSettings=0000000000000000000000" << endl;
101
102 OutputFolders();
103
104 m_devFile << endl << endl;
105
106 OutputFileUnits();
107
108 m_devFile.close();
109
110 // Dev-C++ needs a makefile, so use the MinGW backend to create one.
111
112 cout << "Creating Makefile: " << ProjectNode.makefile << endl;
113
114 Backend *backend = Backend::Factory::Create("mingw",
115 ProjectNode,
116 verbose,
117 cleanAsYouGo );
118 backend->Process();
119 delete backend;
120
121 cout << "Done." << endl << endl;
122
123 cout << "You may want to disable Class browsing (see below) before you open this project in Dev-C++, as the "
124 << "parsing required for large projects can take quite awhile."
125 << endl << endl
126 << "(Tools->Editor Options->Class browsing->Enable class browsing check box)"
127 << endl << endl;
128 }
129
130 void DevCppBackend::ProcessModules()
131 {
132 for(size_t i = 0; i < ProjectNode.modules.size(); i++)
133 {
134 Module &module = *ProjectNode.modules[i];
135
136 for(size_t k = 0; k < module.non_if_data.files.size(); k++)
137 {
138 File &file = *module.non_if_data.files[k];
139
140 ProcessFile(file.name);
141 }
142 }
143 }
144
145 bool FileExists(string &filename)
146 {
147 ifstream file(filename.c_str());
148
149 if(!file.is_open())
150 return false;
151
152 file.close();
153 return true;
154 }
155
156 void DevCppBackend::ProcessFile(string &filepath)
157 {
158 // Remove the .\ at the start of the filenames
159 filepath.erase(0, 2);
160
161 if(!FileExists(filepath))
162 return;
163
164 // Change the \ to /
165 for(size_t i = 0; i < filepath.length(); i++)
166 {
167 if(filepath[i] == '\\')
168 filepath[i] = '/';
169 }
170
171 // Remove the filename from the path
172 string folder = "";
173
174 size_t pos = filepath.rfind(string("/"), filepath.length() - 1);
175
176 if(pos != string::npos)
177 {
178 folder = filepath;
179 folder.erase(pos, folder.length() - pos);
180 }
181
182 FileUnit fileUnit;
183 fileUnit.filename = filepath;
184 fileUnit.folder = folder;
185
186 m_fileUnits.push_back(fileUnit);
187
188 if(folder != "")
189 AddFolders(folder);
190
191 m_unitCount++;
192 }
193
194 bool DevCppBackend::CheckFolderAdded(string &folder)
195 {
196 for(size_t i = 0; i < m_folders.size(); i++)
197 {
198 if(m_folders[i] == folder)
199 return true;
200 }
201
202 return false;
203 }
204
205 void DevCppBackend::AddFolders(string &folder)
206 {
207 // Check if this folder was already added. true if it was, false otherwise.
208 if(CheckFolderAdded(folder))
209 return;
210
211 m_folders.push_back(folder);
212
213 size_t pos = folder.rfind(string("/"), folder.length() - 1);
214
215 if(pos == string::npos)
216 return;
217
218 folder.erase(pos, folder.length() - pos);
219 AddFolders(folder);
220 }
221
222 void DevCppBackend::OutputFolders()
223 {
224 m_devFile << "Folders=";
225
226 for(size_t i = 0; i < m_folders.size(); i++)
227 {
228 if(i > 0)
229 m_devFile << ",";
230
231 m_devFile << m_folders[i];
232 }
233 }
234
235 void DevCppBackend::OutputFileUnits()
236 {
237 for(size_t i = 0; i < m_fileUnits.size(); i++)
238 {
239 m_devFile << "[Unit" << i + 1 << "]" << endl;
240
241
242 m_devFile << "FileName=" << m_fileUnits[i].filename << endl;
243 m_devFile << "CompileCpp=1" << endl;
244 m_devFile << "Folder=" << m_fileUnits[i].folder << endl;
245 m_devFile << "Compile=1" << endl;
246 m_devFile << "Link=1" << endl;
247 m_devFile << "Priority=1000" << endl;
248 m_devFile << "OverrideBuildCmd=0" << endl;
249 m_devFile << "BuildCmd=" << endl << endl;;
250 }
251 }