* Bring back rbuild build to be used until bug 6372 is fixed.
[reactos.git] / tools / rbuild / backend / msvc / projmaker.cpp
1 /*
2 * Copyright (C) 2002 Patrik Stridvall
3 * Copyright (C) 2005 Royce Mitchell III
4 * Copyright (C) 2006 Hervé Poussineau
5 * Copyright (C) 2006 Christoph von Wittich
6 * Copyright (C) 2009 Ged Murphy
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #ifdef _MSC_VER
24 #pragma warning ( disable : 4786 )
25 #endif//_MSC_VER
26
27 #include <string>
28 #include <vector>
29 #include <set>
30 #include <algorithm>
31 #include <fstream>
32 #include <iostream>
33
34 #include <stdio.h>
35
36 #include "msvc.h"
37
38 using std::string;
39 using std::vector;
40 using std::set;
41
42 typedef set<string> StringSet;
43
44 #ifdef OUT
45 #undef OUT
46 #endif//OUT
47
48 ProjMaker::ProjMaker ( )
49 {
50 vcproj_file = "";
51 }
52
53 ProjMaker::ProjMaker ( Configuration& buildConfig,
54 const std::vector<MSVCConfiguration*>& msvc_configs,
55 std::string filename )
56 {
57 configuration = buildConfig;
58 m_configurations = msvc_configs;
59 vcproj_file = filename;
60 }
61
62 void
63 ProjMaker::_generate_proj_file ( const Module& module )
64 {
65 printf("_generate_proj_file not implemented for the base class\n");
66 }
67
68 void
69 ProjMaker::_generate_user_configuration()
70 {
71 #if 0
72 string computername;
73 string username;
74 string vcproj_file_user = "";
75
76 if (getenv ( "USERNAME" ) != NULL)
77 username = getenv ( "USERNAME" );
78 if (getenv ( "COMPUTERNAME" ) != NULL)
79 computername = getenv ( "COMPUTERNAME" );
80 else if (getenv ( "HOSTNAME" ) != NULL)
81 computername = getenv ( "HOSTNAME" );
82
83 if ((computername != "") && (username != ""))
84 vcproj_file_user = vcproj_file + "." + computername + "." + username + ".user";
85
86 /* User configuration file */
87 if (vcproj_file_user != "")
88 {
89 OUT = fopen ( vcproj_file_user.c_str(), "wb" );
90 fprintf ( OUT, "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\r\n" );
91 fprintf ( OUT, "<VisualStudioUserFile\r\n" );
92 fprintf ( OUT, "\tProjectType=\"Visual C++\"\r\n" );
93 fprintf ( OUT, "\tVersion=\"%s\"\r\n", configuration.VSProjectVersion.c_str() );
94 fprintf ( OUT, "\tShowAllFiles=\"false\"\r\n" );
95 fprintf ( OUT, "\t>\r\n" );
96
97 fprintf ( OUT, "\t<Configurations>\r\n" );
98 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
99 {
100 const MSVCConfiguration& cfg = *m_configurations[icfg];
101 fprintf ( OUT, "\t\t<Configuration\r\n" );
102 fprintf ( OUT, "\t\t\tName=\"%s|Win32\"\r\n", cfg.name.c_str() );
103 fprintf ( OUT, "\t\t\t>\r\n" );
104 fprintf ( OUT, "\t\t\t<DebugSettings\r\n" );
105 if ( module_type == ".cpl" )
106 {
107 fprintf ( OUT, "\t\t\t\tCommand=\"rundll32.exe\"\r\n" );
108 fprintf ( OUT, "\t\t\t\tCommandArguments=\" shell32,Control_RunDLL &quot;$(TargetPath)&quot;,@\"\r\n" );
109 }
110 else
111 {
112 fprintf ( OUT, "\t\t\t\tCommand=\"$(TargetPath)\"\r\n" );
113 fprintf ( OUT, "\t\t\t\tCommandArguments=\"\"\r\n" );
114 }
115 fprintf ( OUT, "\t\t\t\tAttach=\"false\"\r\n" );
116 fprintf ( OUT, "\t\t\t\tDebuggerType=\"3\"\r\n" );
117 fprintf ( OUT, "\t\t\t\tRemote=\"1\"\r\n" );
118 string remote_machine = "\t\t\t\tRemoteMachine=\"" + computername + "\"\r\n";
119 fprintf ( OUT, remote_machine.c_str() );
120 fprintf ( OUT, "\t\t\t\tRemoteCommand=\"\"\r\n" );
121 fprintf ( OUT, "\t\t\t\tHttpUrl=\"\"\r\n" );
122 fprintf ( OUT, "\t\t\t\tPDBPath=\"\"\r\n" );
123 fprintf ( OUT, "\t\t\t\tSQLDebugging=\"\"\r\n" );
124 fprintf ( OUT, "\t\t\t\tEnvironment=\"\"\r\n" );
125 fprintf ( OUT, "\t\t\t\tEnvironmentMerge=\"true\"\r\n" );
126 fprintf ( OUT, "\t\t\t\tDebuggerFlavor=\"\"\r\n" );
127 fprintf ( OUT, "\t\t\t\tMPIRunCommand=\"\"\r\n" );
128 fprintf ( OUT, "\t\t\t\tMPIRunArguments=\"\"\r\n" );
129 fprintf ( OUT, "\t\t\t\tMPIRunWorkingDirectory=\"\"\r\n" );
130 fprintf ( OUT, "\t\t\t\tApplicationCommand=\"\"\r\n" );
131 fprintf ( OUT, "\t\t\t\tApplicationArguments=\"\"\r\n" );
132 fprintf ( OUT, "\t\t\t\tShimCommand=\"\"\r\n" );
133 fprintf ( OUT, "\t\t\t\tMPIAcceptMode=\"\"\r\n" );
134 fprintf ( OUT, "\t\t\t\tMPIAcceptFilter=\"\"\r\n" );
135 fprintf ( OUT, "\t\t\t/>\r\n" );
136 fprintf ( OUT, "\t\t</Configuration>\r\n" );
137 }
138 fprintf ( OUT, "\t</Configurations>\r\n" );
139 fprintf ( OUT, "</VisualStudioUserFile>\r\n" );
140 fclose ( OUT );
141 }
142 #endif
143 }
144
145
146 void
147 ProjMaker::_generate_standard_configuration( const Module& module, const MSVCConfiguration& cfg, BinaryType binaryType )
148 {
149 printf("_generate_standard_configuration not implemented for the base class\n");
150 }
151
152 void
153 ProjMaker::_generate_makefile_configuration( const Module& module, const MSVCConfiguration& cfg )
154 {
155 printf("_generate_makefile_configuration not implemented for the base class\n");
156 }
157
158 std::string
159 ProjMaker::_get_vc_dir ( void ) const
160 {
161 if ( configuration.VSProjectVersion == "8.00" )
162 return "vc8";
163 else if ( configuration.VSProjectVersion == "10.00" )
164 return "vc10";
165 else /* default to VS2008 */
166 return "vc9";
167 }
168
169 std::string
170 ProjMaker::VcprojFileName ( const Module& module ) const
171 {
172 return FixSeparatorForSystemCommand(
173 ReplaceExtension ( module.output->relative_path + "\\" + module.name, "_" + _get_vc_dir() + "_auto.vcproj" )
174 );
175 }
176
177 std::string
178 ProjMaker::_strip_gcc_deffile(std::string Filename, std::string sourcedir, std::string objdir)
179 {
180 std::string NewFilename = Environment::GetIntermediatePath () + "\\" + objdir + "\\" + Filename;
181 // we don't like infinite loops - so replace it in two steps
182 NewFilename = _replace_str(NewFilename, ".def", "_msvc.de");
183 NewFilename = _replace_str(NewFilename, "_msvc.de", "_msvc.def");
184 Filename = sourcedir + "\\" + Filename;
185
186 Directory dir(objdir);
187 dir.GenerateTree(IntermediateDirectory, false);
188
189 std::fstream in_file(Filename.c_str(), std::ios::in);
190 std::fstream out_file(NewFilename.c_str(), std::ios::out);
191 std::string::size_type pos;
192 DWORD i = 0;
193
194 std::string line;
195 while (std::getline(in_file, line))
196 {
197 pos = line.find("@", 0);
198 while (std::string::npos != pos)
199 {
200 if (pos > 1)
201 {
202 // make sure it is stdcall and no ordinal
203 if (line[pos -1] != ' ')
204 {
205 i = 0;
206 while (true)
207 {
208 i++;
209 if ((line[pos + i] < '0') || (line[pos + i] > '9'))
210 break;
211 }
212 line.replace(pos, i, "");
213 }
214 }
215 pos = line.find("@", pos + 1);
216 }
217
218 line += "\n";
219 out_file << line;
220 }
221 in_file.close();
222 out_file.close();
223
224 return NewFilename;
225 }
226
227 std::string
228 ProjMaker::_replace_str(std::string string1, const std::string &find_str, const std::string &replace_str)
229 {
230 std::string::size_type pos = string1.find(find_str, 0);
231 int intLen = find_str.length();
232
233 while(std::string::npos != pos)
234 {
235 string1.replace(pos, intLen, replace_str);
236 pos = string1.find(find_str, intLen + pos);
237 }
238
239 return string1;
240 }
241
242
243 std::string
244 ProjMaker::_get_file_path( FileLocation* file, std::string relative_path)
245 {
246 if (file->directory == SourceDirectory)
247 {
248 // We want the full path here for directory support later on
249 return Path::RelativeFromDirectory (file->relative_path, relative_path );
250 }
251 else if(file->directory == IntermediateDirectory)
252 {
253 return std::string("$(RootIntDir)\\") + file->relative_path;
254 }
255 else if(file->directory == OutputDirectory)
256 {
257 return std::string("$(RootOutDir)\\") + file->relative_path;
258 }
259
260 return std::string("");
261 }
262
263 void
264 ProjMaker::_collect_files(const Module& module)
265 {
266 size_t i;
267 const IfableData& data = module.non_if_data;
268 const vector<File*>& files = data.files;
269 for ( i = 0; i < files.size(); i++ )
270 {
271 string path = _get_file_path(&files[i]->file, module.output->relative_path);
272 string file = path + std::string("\\") + files[i]->file.name;
273
274 if (files[i]->file.directory != SourceDirectory)
275 generated_files.push_back ( file );
276 else if ( !stricmp ( Right(file,3).c_str(), ".rc" ) )
277 resource_files.push_back ( file );
278 else if ( !stricmp ( Right(file,2).c_str(), ".h" ) )
279 header_files.push_back ( file );
280 else
281 source_files.push_back ( file );
282 }
283 const vector<Include*>& incs = data.includes;
284 for ( i = 0; i < incs.size(); i++ )
285 {
286 includes.push_back ( _get_file_path(incs[i]->directory, module.output->relative_path) );
287 }
288 const vector<Library*>& libs = data.libraries;
289 for ( i = 0; i < libs.size(); i++ )
290 {
291 string libpath = "$(RootOutDir)\\" + libs[i]->importedModule->output->relative_path + "\\" + _get_vc_dir() + "\\$(ConfigurationName)\\" + libs[i]->name + ".lib";
292 libraries.push_back ( libpath );
293 }
294 const vector<Define*>& defs = data.defines;
295 for ( i = 0; i < defs.size(); i++ )
296 {
297 if ( defs[i]->backend != "" && defs[i]->backend != "msvc" )
298 continue;
299
300 if( module.isUnicode && (defs[i]->name == "UNICODE" || defs[i]->name == "_UNICODE"))
301 continue;
302
303 if ( defs[i]->value != "" )
304 defines.push_back( defs[i]->name + "=" + defs[i]->value );
305 else
306 defines.push_back( defs[i]->name );
307 }
308 for ( std::map<std::string, Property*>::const_iterator p = data.properties.begin(); p != data.properties.end(); ++ p )
309 {
310 Property& prop = *p->second;
311 if ( strstr ( module.baseaddress.c_str(), prop.name.c_str() ) )
312 baseaddr = prop.value;
313 }
314
315 if(module.importLibrary)
316 {
317 std::string ImportLibraryPath = _get_file_path(module.importLibrary->source, module.output->relative_path);
318
319 switch (module.IsSpecDefinitionFile())
320 {
321 case PSpec:
322 generated_files.push_back("$(IntDir)\\" + ReplaceExtension(module.importLibrary->source->name,".spec"));
323 case Spec:
324 generated_files.push_back("$(IntDir)\\" + ReplaceExtension(module.importLibrary->source->name,".stubs.c"));
325 generated_files.push_back("$(IntDir)\\" + ReplaceExtension(module.importLibrary->source->name,".def"));
326 default:
327 source_files.push_back(ImportLibraryPath + std::string("\\") + module.importLibrary->source->name);
328 }
329 }
330 }