7b0a5fe2b60da3b2131d789f152c9f6a69fc98f5
[reactos.git] / reactos / tools / rbuild / backend / msvc / msvc.cpp
1 /*
2 * Copyright (C) 2005 Trevor McCort
3 * Copyright (C) 2005 Casper S. Hornstrup
4 * Copyright (C) 2005 Steven Edwards
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 "msvc.h"
29 #include "../mingw/mingw.h"
30
31 using namespace std;
32
33 char get_key(char *valid,char *prompt); //FIXME
34 bool spawn_new(const string& cmd); //FIXME
35 void gen_guid();
36
37 static class MSVCFactory : public Backend::Factory
38 {
39 public:
40
41 MSVCFactory() : Factory("MSVC") {}
42 Backend *operator() (Project &project,
43 Configuration& configuration)
44 {
45 return new MSVCBackend(project, configuration);
46 }
47
48 } factory;
49
50
51 MSVCBackend::MSVCBackend(Project &project,
52 Configuration& configuration) : Backend(project, configuration)
53 {
54 m_unitCount = 0;
55 }
56
57 void MSVCBackend::Process()
58 {
59 //bool exec = false;
60 //const char rbuild_mingw[] = "output-i386\\tools\\rbuild\\rbuild.exe mingw";
61
62 string filename = ProjectNode.name + ".dsw";
63
64 printf ( "Creating MSVC workspace: %s\n", filename.c_str() );
65
66 ProcessModules();
67
68 m_dswFile = fopen ( filename.c_str(), "wb" );
69
70 if ( !m_dswFile )
71 {
72 printf ( "Could not create file '%s'.\n", filename.c_str() );
73 return;
74 }
75 _generate_wine_dsw ( m_dswFile );
76 #if 0
77 m_devFile << "Microsoft Visual Studio Solution File, Format Version 9.00" << endl;
78 m_devFile << "# Visual C++ Express 2005" << endl;
79
80 m_devFile << "# FIXME Project listings here" << endl;
81 m_devFile << "EndProject" << endl;
82 m_devFile << "Global" << endl;
83 m_devFile << " GlobalSection(SolutionConfigurationPlatforms) = preSolution" << endl;
84 m_devFile << " Debug|Win32 = Debug|Win32" << endl;
85 m_devFile << " Release|Win32 = Release|Win32" << endl;
86 m_devFile << " EndGlobalSection" << endl;
87 m_devFile << " GlobalSection(ProjectConfigurationPlatforms) = postSolution" << endl;
88 m_devFile << " #FIXME Project Listings Here" << endl;
89 m_devFile << " EndGlobalSection" << endl;
90 m_devFile << " GlobalSection(SolutionProperties) = preSolution" << endl;
91 m_devFile << " HideSolutionNode = FALSE" << endl;
92 m_devFile << " EndGlobalSection" << endl;
93 m_devFile << "EndGlobal" << endl;
94
95 m_devFile << endl << endl;
96 #endif
97 fclose ( m_dswFile );
98
99 // The MSVC build still needs the mingw backend.
100 //ProcessModules();
101
102 printf ( "Done.\n" );
103
104 /*cout << "Don't expect the MSVC backend to work yet. "<< endl << endl;
105
106 if(get_key("yn","Would you like to configure for a Mingw build as well? (y/n)") == 'y')
107 {
108 exec = spawn_new(rbuild_mingw);
109 if (!exec)
110 printf("\nError invoking rbuild\n");
111 }*/
112 }
113
114 void MSVCBackend::ProcessModules()
115 {
116 for(size_t i = 0; i < ProjectNode.modules.size(); i++)
117 {
118 Module &module = *ProjectNode.modules[i];
119
120 this->_generate_dsp ( module );
121 gen_guid();
122
123 /*for(size_t k = 0; k < module.non_if_data.files.size(); k++)
124 {
125 File &file = *module.non_if_data.files[k];
126
127 ProcessFile(file.name);
128 }*/
129 }
130 }
131
132 static bool FileExists(string &filename)
133 {
134 ifstream file(filename.c_str());
135
136 if(!file.is_open())
137 return false;
138
139 file.close();
140 return true;
141 }
142
143 void MSVCBackend::ProcessFile(string &filepath)
144 {
145 // Remove the .\ at the start of the filenames
146 if ( filepath[0] == '.' && strchr ( "/\\", filepath[1] ) )
147 filepath.erase(0, 2);
148
149 if(!FileExists(filepath))
150 return;
151
152 // Change the \ to /
153 for(size_t i = 0; i < filepath.length(); i++)
154 {
155 if(filepath[i] == '\\')
156 filepath[i] = '/';
157 }
158
159 // Remove the filename from the path
160 string folder = "";
161
162 size_t pos = filepath.rfind(string("/"), filepath.length() - 1);
163
164 if(pos != string::npos)
165 {
166 folder = filepath;
167 folder.erase(pos, folder.length() - pos);
168 }
169
170 FileUnit fileUnit;
171 fileUnit.filename = filepath;
172 fileUnit.folder = folder;
173
174 m_fileUnits.push_back(fileUnit);
175
176 if(folder != "")
177 AddFolders(folder);
178
179 m_unitCount++;
180 }
181
182 bool MSVCBackend::CheckFolderAdded(string &folder)
183 {
184 for(size_t i = 0; i < m_folders.size(); i++)
185 {
186 if(m_folders[i] == folder)
187 return true;
188 }
189
190 return false;
191 }
192
193 void MSVCBackend::AddFolders(string &folder)
194 {
195 // Check if this folder was already added. true if it was, false otherwise.
196 if(CheckFolderAdded(folder))
197 return;
198
199 m_folders.push_back(folder);
200
201 size_t pos = folder.rfind(string("/"), folder.length() - 1);
202
203 if(pos == string::npos)
204 return;
205
206 folder.erase(pos, folder.length() - pos);
207 AddFolders(folder);
208 }
209
210 void MSVCBackend::OutputFolders()
211 {
212 #if 0
213 m_devFile << "Folders=";
214
215 for(size_t i = 0; i < m_folders.size(); i++)
216 {
217 if(i > 0)
218 m_devFile << ",";
219
220 m_devFile << m_folders[i];
221 }
222 #endif
223 }
224
225
226 char get_key(char *valid,char *prompt)
227 {
228 int ch,okay;
229
230 while (1) {
231 if (prompt) printf("%s ",prompt);
232 fflush(stdout);
233 while (ch = getchar(), ch == ' ' || ch == '\t');
234 if (ch == EOF) exit(1);
235 if (!strchr(valid,okay = ch)) okay = 0;
236 while (ch = getchar(), ch != '\n' && ch != EOF);
237 if (ch == EOF) exit(1);
238 if (okay) return okay;
239 printf("Invalid input.\n");
240 }
241 }
242
243 bool spawn_new( const string& cmd )
244 {
245 string command = ssprintf (
246 "%s",
247 cmd.c_str (),
248 NUL,
249 NUL );
250 int exitcode = system ( command.c_str () );
251 return (exitcode == 0);
252 }
253
254 std::string
255 MSVCBackend::DspFileName ( const Module& module ) const
256 {
257 return DosSeparator(
258 ReplaceExtension ( module.GetPath(), ".dsp" )
259 );
260 }