8fed100ce1b66c334891dccd538a18df8dc7acfe
[reactos.git] / reactos / tools / rbuild / backend / msvc / vcprojmaker.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 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifdef _MSC_VER
23 #pragma warning ( disable : 4786 )
24 #endif//_MSC_VER
25
26 #include <string>
27 #include <vector>
28 #include <set>
29 #include <algorithm>
30 #include <fstream>
31 #include <iostream>
32
33 #include <stdio.h>
34
35 #include "msvc.h"
36
37 using std::string;
38 using std::vector;
39 using std::set;
40
41 typedef set<string> StringSet;
42
43 #ifdef OUT
44 #undef OUT
45 #endif//OUT
46
47 struct SortFilesAscending
48 {
49 bool operator()(const string& rhs, const string& lhs)
50 {
51 return rhs < lhs;
52 }
53 };
54
55 MSVCConfiguration::MSVCConfiguration ( const OptimizationType optimization, const HeadersType headers, const std::string &name )
56 {
57 this->optimization = optimization;
58 this->headers = headers;
59 if ( name != "" )
60 this->name = name;
61 else
62 {
63 std::string headers_name;
64 if ( headers == MSVCHeaders )
65 headers_name = "";
66 else
67 headers_name = " - ReactOS headers";
68 if ( optimization == Debug )
69 this->name = "Debug" + headers_name;
70 else if ( optimization == Release )
71 this->name = "Release" + headers_name;
72 else if ( optimization == Speed )
73 this->name = "Speed" + headers_name;
74 else
75 this->name = "Unknown" + headers_name;
76 }
77 }
78
79 void
80 MSVCBackend::_generate_vcproj ( const Module& module )
81 {
82 size_t i;
83
84 string vcproj_file = VcprojFileName(module);
85 string computername;
86 string username;
87 string intermediatedir = "";
88
89 if (getenv ( "USERNAME" ) != NULL)
90 username = getenv ( "USERNAME" );
91 if (getenv ( "COMPUTERNAME" ) != NULL)
92 computername = getenv ( "COMPUTERNAME" );
93 else if (getenv ( "HOSTNAME" ) != NULL)
94 computername = getenv ( "HOSTNAME" );
95
96 string vcproj_file_user = "";
97
98 if ((computername != "") && (username != ""))
99 vcproj_file_user = vcproj_file + "." + computername + "." + username + ".user";
100
101 printf ( "Creating MSVC.NET project: '%s'\n", vcproj_file.c_str() );
102 FILE* OUT = fopen ( vcproj_file.c_str(), "wb" );
103
104 vector<string> imports;
105 string module_type = GetExtension(*module.output);
106 bool lib = (module.type == ObjectLibrary) || (module.type == RpcClient) ||(module.type == RpcServer) || (module_type == ".lib") || (module_type == ".a");
107 bool dll = (module_type == ".dll") || (module_type == ".cpl");
108 bool exe = (module_type == ".exe") || (module_type == ".scr");
109 bool sys = (module_type == ".sys");
110
111 string path_basedir = module.GetPathToBaseDir ();
112 string intenv = Environment::GetIntermediatePath ();
113 string outenv = Environment::GetOutputPath ();
114 string outdir;
115 string intdir;
116 string vcdir;
117
118
119 if ( intenv == "obj-i386" )
120 intdir = path_basedir + "obj-i386"; /* append relative dir from project dir */
121 else
122 intdir = intenv;
123
124 if ( outenv == "output-i386" )
125 outdir = path_basedir + "output-i386";
126 else
127 outdir = outenv;
128
129 if ( configuration.UseVSVersionInPath )
130 {
131 vcdir = DEF_SSEP + _get_vc_dir();
132 }
133 // TODO FIXME - need more checks here for 'sys' and possibly 'drv'?
134
135 bool console = exe && (module.type == Win32CUI);
136 bool include_idl = false;
137
138 vector<string> source_files, resource_files, header_files, includes, includes_ros, libraries;
139 StringSet common_defines;
140 vector<const IfableData*> ifs_list;
141 ifs_list.push_back ( &module.project.non_if_data );
142 ifs_list.push_back ( &module.non_if_data );
143
144 string baseaddr;
145
146 while ( ifs_list.size() )
147 {
148 const IfableData& data = *ifs_list.back();
149 ifs_list.pop_back();
150 for ( i = 0; i < data.ifs.size(); i++ )
151 {
152 const Property* property = _lookup_property( module, data.ifs[i]->property );
153 if ( property != NULL )
154 {
155 if ( data.ifs[i]->value == property->value && data.ifs[i]->negated == false ||
156 data.ifs[i]->value != property->value && data.ifs[i]->negated)
157 ifs_list.push_back ( &data.ifs[i]->data );
158 }
159 }
160 const vector<File*>& files = data.files;
161 for ( i = 0; i < files.size(); i++ )
162 {
163 if (files[i]->file.directory != SourceDirectory)
164 continue;
165
166 // We want the full path here for directory support later on
167 string path = Path::RelativeFromDirectory (
168 files[i]->file.relative_path,
169 module.output->relative_path );
170 string file = path + std::string("\\") + files[i]->file.name;
171
172 if ( !stricmp ( Right(file,3).c_str(), ".rc" ) )
173 resource_files.push_back ( file );
174 else if ( !stricmp ( Right(file,2).c_str(), ".h" ) )
175 header_files.push_back ( file );
176 else
177 source_files.push_back ( file );
178 }
179 const vector<Include*>& incs = data.includes;
180 for ( i = 0; i < incs.size(); i++ )
181 {
182 string path = Path::RelativeFromDirectory (
183 incs[i]->directory->relative_path,
184 module.output->relative_path );
185 if ( module.type != RpcServer && module.type != RpcClient )
186 {
187 if ( path.find ("/include/reactos/idl") != string::npos)
188 {
189 include_idl = true;
190 continue;
191 }
192 }
193 // switch between general headers and ros headers
194 if ( !strncmp(incs[i]->directory->relative_path.c_str(), "include\\crt", 11 ) ||
195 !strncmp(incs[i]->directory->relative_path.c_str(), "include\\ddk", 11 ) ||
196 !strncmp(incs[i]->directory->relative_path.c_str(), "include\\GL", 10 ) ||
197 !strncmp(incs[i]->directory->relative_path.c_str(), "include\\psdk", 12 ) ||
198 !strncmp(incs[i]->directory->relative_path.c_str(), "include\\reactos\\wine", 20 ) )
199 {
200 if (strncmp(incs[i]->directory->relative_path.c_str(), "include\\crt", 11 ))
201 // not crt include
202 includes_ros.push_back ( path );
203 }
204 else
205 {
206 includes.push_back ( path );
207 }
208 }
209 const vector<Library*>& libs = data.libraries;
210 for ( i = 0; i < libs.size(); i++ )
211 {
212 string libpath = outdir + "\\" + libs[i]->importedModule->output->relative_path + "\\" + _get_vc_dir() + "\\---\\" + libs[i]->name + ".lib";
213 libraries.push_back ( libpath );
214 }
215 const vector<Define*>& defs = data.defines;
216 for ( i = 0; i < defs.size(); i++ )
217 {
218 if ( defs[i]->backend != "" && defs[i]->backend != "msvc" )
219 continue;
220
221 if ( defs[i]->value[0] )
222 common_defines.insert( defs[i]->name + "=" + defs[i]->value );
223 else
224 common_defines.insert( defs[i]->name );
225 }
226 for ( i = 0; i < data.properties.size(); i++ )
227 {
228 Property& prop = *data.properties[i];
229 if ( strstr ( module.baseaddress.c_str(), prop.name.c_str() ) )
230 baseaddr = prop.value;
231 }
232 }
233 /* include intermediate path for reactos.rc */
234 string version = intdir + "\\include";
235 includes.push_back (version);
236 version += "\\reactos";
237 includes.push_back (version);
238
239 string include_string;
240
241 fprintf ( OUT, "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\r\n" );
242 fprintf ( OUT, "<VisualStudioProject\r\n" );
243 fprintf ( OUT, "\tProjectType=\"Visual C++\"\r\n" );
244
245 if (configuration.VSProjectVersion.empty())
246 configuration.VSProjectVersion = MS_VS_DEF_VERSION;
247
248 fprintf ( OUT, "\tVersion=\"%s\"\r\n", configuration.VSProjectVersion.c_str() );
249 fprintf ( OUT, "\tName=\"%s\"\r\n", module.name.c_str() );
250 fprintf ( OUT, "\tProjectGUID=\"%s\"\r\n", module.guid.c_str() );
251 fprintf ( OUT, "\tKeyword=\"Win32Proj\">\r\n" );
252
253 fprintf ( OUT, "\t<Platforms>\r\n" );
254 fprintf ( OUT, "\t\t<Platform\r\n" );
255 fprintf ( OUT, "\t\t\tName=\"Win32\"/>\r\n" );
256 fprintf ( OUT, "\t</Platforms>\r\n" );
257
258 //fprintf ( OUT, "\t<ToolFiles>\r\n" );
259 //fprintf ( OUT, "\t\t<ToolFile\r\n" );
260
261 //string path = Path::RelativeFromDirectory ( ProjectNode.name, module.GetBasePath() );
262 //path.erase(path.find(ProjectNode.name, 0), ProjectNode.name.size() + 1);
263
264 //fprintf ( OUT, "\t\t\tRelativePath=\"%sgccasm.rules\"/>\r\n", path.c_str() );
265 //fprintf ( OUT, "\t</ToolFiles>\r\n" );
266
267 int n = 0;
268
269 std::string output_dir;
270 string importLib;
271
272 // don't do the work m_configurations.size() times
273 if (module.importLibrary != NULL)
274 {
275 intermediatedir = module.output->relative_path + vcdir;
276 importLib = _strip_gcc_deffile(module.importLibrary->source->name, module.importLibrary->source->relative_path, intermediatedir);
277 importLib = Path::RelativeFromDirectory (
278 importLib,
279 module.output->relative_path );
280 }
281
282 fprintf ( OUT, "\t<Configurations>\r\n" );
283 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
284 {
285 const MSVCConfiguration& cfg = *m_configurations[icfg];
286
287 bool debug = ( cfg.optimization == Debug );
288 bool release = ( cfg.optimization == Release );
289 bool speed = ( cfg.optimization == Speed );
290
291 fprintf ( OUT, "\t\t<Configuration\r\n" );
292 fprintf ( OUT, "\t\t\tName=\"%s|Win32\"\r\n", cfg.name.c_str() );
293
294 if ( configuration.UseConfigurationInPath )
295 {
296 fprintf ( OUT, "\t\t\tOutputDirectory=\"%s\\%s%s\\%s\"\r\n", outdir.c_str (), module.output->relative_path.c_str (), vcdir.c_str (), cfg.name.c_str() );
297 fprintf ( OUT, "\t\t\tIntermediateDirectory=\"%s\\%s%s\\%s\"\r\n", intdir.c_str (), module.output->relative_path.c_str (), vcdir.c_str (), cfg.name.c_str() );
298 }
299 else
300 {
301 fprintf ( OUT, "\t\t\tOutputDirectory=\"%s\\%s%s\"\r\n", outdir.c_str (), module.output->relative_path.c_str (), vcdir.c_str () );
302 fprintf ( OUT, "\t\t\tIntermediateDirectory=\"%s\\%s%s\"\r\n", intdir.c_str (), module.output->relative_path.c_str (), vcdir.c_str () );
303 }
304
305 fprintf ( OUT, "\t\t\tConfigurationType=\"%d\"\r\n", exe ? 1 : dll ? 2 : lib ? 4 : -1 );
306 fprintf ( OUT, "\t\t\tCharacterSet=\"2\">\r\n" );
307
308 fprintf ( OUT, "\t\t\t<Tool\r\n" );
309 fprintf ( OUT, "\t\t\t\tName=\"VCCLCompilerTool\"\r\n" );
310 fprintf ( OUT, "\t\t\t\tOptimization=\"%d\"\r\n", release ? 2 : 0 );
311
312 fprintf ( OUT, "\t\t\t\tAdditionalIncludeDirectories=\"" );
313 bool multiple_includes = false;
314 fprintf ( OUT, "./;" );
315 for ( i = 0; i < includes.size(); i++ )
316 {
317 const std::string& include = includes[i];
318 if ( strcmp ( include.c_str(), "." ) )
319 {
320 if ( multiple_includes )
321 fprintf ( OUT, ";" );
322 fprintf ( OUT, "%s", include.c_str() );
323 include_string += " /I " + include;
324 multiple_includes = true;
325 }
326 }
327 if ( include_idl )
328 {
329 if ( multiple_includes )
330 fprintf ( OUT, ";" );
331
332 if ( configuration.UseConfigurationInPath )
333 {
334 fprintf ( OUT, "%s\\include\\reactos\\idl%s\\%s\r\n", intdir.c_str (), vcdir.c_str (), cfg.name.c_str() );
335 }
336 else
337 {
338 fprintf ( OUT, "%s\\include\\reactos\\idl\r\n", intdir.c_str () );
339 }
340 }
341 if ( cfg.headers == ReactOSHeaders )
342 {
343 for ( i = 0; i < includes_ros.size(); i++ )
344 {
345 const std::string& include = includes_ros[i];
346 if ( multiple_includes )
347 fprintf ( OUT, ";" );
348 fprintf ( OUT, "%s", include.c_str() );
349 //include_string += " /I " + include;
350 multiple_includes = true;
351 }
352 }
353 else
354 {
355 // Add WDK or PSDK paths, if user provides them
356 if (getenv ( "BASEDIR" ) != NULL &&
357 (module.type == Kernel ||
358 module.type == KernelModeDLL ||
359 module.type == KernelModeDriver))
360 {
361 string WdkBase, SdkPath, CrtPath, DdkPath;
362 WdkBase = getenv ( "BASEDIR" );
363 SdkPath = WdkBase + "\\inc\\api";
364 CrtPath = WdkBase + "\\inc\\crt";
365 DdkPath = WdkBase + "\\inc\\ddk";
366
367 if ( multiple_includes )
368 fprintf ( OUT, ";" );
369
370 fprintf ( OUT, "%s;", SdkPath.c_str() );
371 fprintf ( OUT, "%s;", CrtPath.c_str() );
372 fprintf ( OUT, "%s", DdkPath.c_str() );
373 multiple_includes = true;
374 }
375 }
376 fprintf ( OUT, "\"\r\n" );
377
378 StringSet defines = common_defines;
379
380 // Always add _CRT_SECURE_NO_WARNINGS to disable warnings about not
381 // using the safe functions introduced in MSVC8.
382 defines.insert ( "_CRT_SECURE_NO_WARNINGS" );
383
384 if ( debug )
385 {
386 defines.insert ( "_DEBUG" );
387 }
388
389 if ( cfg.headers == MSVCHeaders )
390 {
391 // this is a define in MinGW w32api, but not Microsoft's headers
392 defines.insert ( "STDCALL=__stdcall" );
393 }
394
395 if ( lib || exe )
396 {
397 defines.insert ( "_LIB" );
398 }
399 else
400 {
401 defines.insert ( "_WINDOWS" );
402 defines.insert ( "_USRDLL" );
403 }
404
405 fprintf ( OUT, "\t\t\t\tPreprocessorDefinitions=\"" );
406 for ( StringSet::iterator it1=defines.begin(); it1!=defines.end(); it1++ )
407 {
408 if ( i > 0 )
409 fprintf ( OUT, ";" );
410
411 string unescaped = *it1;
412 defines.erase(unescaped);
413 const string& escaped = _replace_str(unescaped, "\"","");
414
415 defines.insert(escaped);
416 fprintf ( OUT, "%s", escaped.c_str() );
417 }
418 fprintf ( OUT, "\"\r\n" );
419 fprintf ( OUT, "\t\t\t\tForcedIncludeFiles=\"%s\"\r\n", "warning.h");
420 fprintf ( OUT, "\t\t\t\tMinimalRebuild=\"%s\"\r\n", speed ? "TRUE" : "FALSE" );
421 fprintf ( OUT, "\t\t\t\tBasicRuntimeChecks=\"0\"\r\n" );
422 fprintf ( OUT, "\t\t\t\tRuntimeLibrary=\"%d\"\r\n", debug ? 1 : 5 ); // 1=/MTd 5=/MT
423 fprintf ( OUT, "\t\t\t\tBufferSecurityCheck=\"FALSE\"\r\n" );
424 fprintf ( OUT, "\t\t\t\tEnableFunctionLevelLinking=\"FALSE\"\r\n" );
425
426 if ( module.pch != NULL )
427 {
428 fprintf ( OUT, "\t\t\t\tUsePrecompiledHeader=\"2\"\r\n" );
429 string pch_path = Path::RelativeFromDirectory (
430 module.pch->file->name,
431 module.output->relative_path );
432 string::size_type pos = pch_path.find_last_of ("/");
433 if ( pos != string::npos )
434 pch_path.erase(0, pos+1);
435 fprintf ( OUT, "\t\t\t\tPrecompiledHeaderThrough=\"%s\"\r\n", pch_path.c_str() );
436
437 // Only include from the same module
438 pos = pch_path.find("../");
439 if (pos == string::npos && std::find(header_files.begin(), header_files.end(), pch_path) == header_files.end())
440 header_files.push_back(pch_path);
441 }
442 else
443 {
444 fprintf ( OUT, "\t\t\t\tUsePrecompiledHeader=\"0\"\r\n" );
445 }
446
447 fprintf ( OUT, "\t\t\t\tWholeProgramOptimization=\"%s\"\r\n", release ? "FALSE" : "FALSE");
448 if ( release )
449 {
450 fprintf ( OUT, "\t\t\t\tFavorSizeOrSpeed=\"1\"\r\n" );
451 fprintf ( OUT, "\t\t\t\tStringPooling=\"true\"\r\n" );
452 }
453
454 fprintf ( OUT, "\t\t\t\tWarningLevel=\"%s\"\r\n", speed ? "0" : "3" );
455 fprintf ( OUT, "\t\t\t\tDetect64BitPortabilityProblems=\"%s\"\r\n", "FALSE");
456 if ( !module.cplusplus )
457 fprintf ( OUT, "\t\t\t\tCompileAs=\"1\"\r\n" );
458
459 if ( module.type == Win32CUI || module.type == Win32GUI )
460 {
461 fprintf ( OUT, "\t\t\t\tCallingConvention=\"%d\"\r\n", 0 ); // 0=__cdecl
462 }
463 else
464 {
465 fprintf ( OUT, "\t\t\t\tCallingConvention=\"%d\"\r\n", 2 ); // 2=__stdcall
466 }
467
468 fprintf ( OUT, "\t\t\t\tDebugInformationFormat=\"%s\"/>\r\n", speed ? "0" : release ? "3": "4"); // 3=/Zi 4=ZI
469
470 fprintf ( OUT, "\t\t\t<Tool\r\n" );
471 fprintf ( OUT, "\t\t\t\tName=\"VCCustomBuildTool\"/>\r\n" );
472
473 if ( lib )
474 {
475 fprintf ( OUT, "\t\t\t<Tool\r\n" );
476 fprintf ( OUT, "\t\t\t\tName=\"VCLibrarianTool\"\r\n" );
477 fprintf ( OUT, "\t\t\t\tOutputFile=\"$(OutDir)/%s.lib\"/>\r\n", module.name.c_str() );
478 }
479 else
480 {
481 fprintf ( OUT, "\t\t\t<Tool\r\n" );
482 fprintf ( OUT, "\t\t\t\tName=\"VCLinkerTool\"\r\n" );
483 if (module.GetEntryPoint(false) == "0")
484 fprintf ( OUT, "AdditionalOptions=\"/noentry\"" );
485
486 if (configuration.VSProjectVersion == "9.00")
487 {
488 fprintf ( OUT, "\t\t\t\tRandomizedBaseAddress=\"0\"\r\n" );
489 fprintf ( OUT, "\t\t\t\tDataExecutionPrevention=\"0\"\r\n" );
490 }
491
492 if (module.importLibrary != NULL)
493 fprintf ( OUT, "\t\t\t\tModuleDefinitionFile=\"%s\"\r\n", importLib.c_str());
494
495 fprintf ( OUT, "\t\t\t\tAdditionalDependencies=\"" );
496 bool use_msvcrt_lib = false;
497 for ( i = 0; i < libraries.size(); i++ )
498 {
499 if ( i > 0 )
500 fprintf ( OUT, " " );
501 string libpath = libraries[i].c_str();
502 libpath = libpath.erase (0, libpath.find_last_of ("\\") + 1 );
503 if ( libpath == "msvcrt.lib" )
504 {
505 use_msvcrt_lib = true;
506 }
507 fprintf ( OUT, "%s", libpath.c_str() );
508 }
509 fprintf ( OUT, "\"\r\n" );
510
511 fprintf ( OUT, "\t\t\t\tAdditionalLibraryDirectories=\"" );
512
513 // Add WDK libs paths, if needed
514 if (getenv ( "BASEDIR" ) != NULL &&
515 (module.type == Kernel ||
516 module.type == KernelModeDLL ||
517 module.type == KernelModeDriver))
518 {
519 string WdkBase, CrtPath, DdkPath;
520 WdkBase = getenv ( "BASEDIR" );
521 CrtPath = WdkBase + "\\lib\\crt\\i386";
522 DdkPath = WdkBase + "\\lib\\wnet\\i386";
523
524 fprintf ( OUT, "%s;", CrtPath.c_str() );
525 fprintf ( OUT, "%s", DdkPath.c_str() );
526
527 if (libraries.size () > 0)
528 fprintf ( OUT, ";" );
529 }
530
531 // Add conventional libraries dirs
532 for (i = 0; i < libraries.size (); i++)
533 {
534 if ( i > 0 )
535 fprintf ( OUT, ";" );
536
537 string libpath = libraries[i].c_str();
538 libpath.replace (libpath.find("---"), 3, cfg.name);
539 libpath = libpath.substr (0, libpath.find_last_of ("\\") );
540 fprintf ( OUT, "%s", libpath.c_str() );
541 }
542
543 fprintf ( OUT, "\"\r\n" );
544
545 fprintf ( OUT, "\t\t\t\tOutputFile=\"$(OutDir)/%s%s\"\r\n", module.name.c_str(), module_type.c_str() );
546 fprintf ( OUT, "\t\t\t\tLinkIncremental=\"%d\"\r\n", debug ? 2 : 1 );
547 fprintf ( OUT, "\t\t\t\tGenerateDebugInformation=\"%s\"\r\n", speed ? "FALSE" : "TRUE" );
548 fprintf ( OUT, "\t\t\t\tLinkTimeCodeGeneration=\"%d\"\r\n", release? 0 : 0); // whole program optimization
549
550 if ( debug )
551 fprintf ( OUT, "\t\t\t\tProgramDatabaseFile=\"$(OutDir)/%s.pdb\"\r\n", module.name.c_str() );
552
553 if ( sys )
554 {
555 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /ALIGN:0x20 /SECTION:INIT,D /IGNORE:4001,4037,4039,4065,4070,4078,4087,4089,4096\"\r\n" );
556 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
557 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
558 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 3 );
559 fprintf ( OUT, "\t\t\t\tDriver=\"%d\"\r\n", 1 );
560 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"%s\"\r\n", module.GetEntryPoint(false) == "" ? "DriverEntry" : module.GetEntryPoint(false).c_str ());
561 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr == "" ? "0x10000" : baseaddr.c_str ());
562 }
563 else if ( exe )
564 {
565 if ( module.type == Kernel )
566 {
567 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /SECTION:INIT,D /ALIGN:0x80\"\r\n" );
568 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
569 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
570 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 3 );
571 fprintf ( OUT, "\t\t\t\tDriver=\"%d\"\r\n", 1 );
572 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"KiSystemStartup\"\r\n" );
573 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr.c_str ());
574 }
575 else if ( module.type == NativeCUI )
576 {
577 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /ALIGN:0x20\"\r\n" );
578 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 1 );
579 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
580 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
581 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"NtProcessStartup\"\r\n" );
582 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr.c_str ());
583 }
584 else if ( module.type == Win32CUI || module.type == Win32GUI || module.type == Win32SCR)
585 {
586 if ( use_msvcrt_lib )
587 {
588 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
589 }
590 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", console ? 1 : 2 );
591 }
592 }
593 else if ( dll )
594 {
595 if (module.GetEntryPoint(false) == "0")
596 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"\"\r\n" );
597 else
598 {
599 // get rid of DllMain@12 because MSVC needs to link to _DllMainCRTStartup@12
600 // when using CRT
601 if (module.GetEntryPoint(false) == "DllMain@12")
602 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"\"\r\n" );
603 else
604 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"%s\"\r\n", module.GetEntryPoint(false).c_str ());
605 }
606 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr == "" ? "0x40000" : baseaddr.c_str ());
607 if ( use_msvcrt_lib )
608 {
609 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
610 }
611 }
612 fprintf ( OUT, "\t\t\t\tTargetMachine=\"%d\"/>\r\n", 1 );
613 }
614
615 fprintf ( OUT, "\t\t\t<Tool\r\n" );
616 fprintf ( OUT, "\t\t\t\tName=\"VCResourceCompilerTool\"\r\n" );
617 fprintf ( OUT, "\t\t\t\tAdditionalIncludeDirectories=\"" );
618 multiple_includes = false;
619 fprintf ( OUT, "./;" );
620 for ( i = 0; i < includes.size(); i++ )
621 {
622 const std::string& include = includes[i];
623 if ( strcmp ( include.c_str(), "." ) )
624 {
625 if ( multiple_includes )
626 fprintf ( OUT, ";" );
627 fprintf ( OUT, "%s", include.c_str() );
628 multiple_includes = true;
629 }
630 }
631 if ( cfg.headers == ReactOSHeaders )
632 {
633 for ( i = 0; i < includes_ros.size(); i++ )
634 {
635 const std::string& include = includes_ros[i];
636 if ( multiple_includes )
637 fprintf ( OUT, ";" );
638 fprintf ( OUT, "%s", include.c_str() );
639 multiple_includes = true;
640 }
641 }
642 fprintf ( OUT, "\"/>\r\n " );
643
644 fprintf ( OUT, "\t\t\t<Tool\r\n" );
645 fprintf ( OUT, "\t\t\t\tName=\"VCMIDLTool\"/>\r\n" );
646 if (configuration.VSProjectVersion == "8.00")
647 {
648 fprintf ( OUT, "\t\t\t<Tool\r\n" );
649 fprintf ( OUT, "\t\t\t\tName=\"VCManifestTool\"\r\n" );
650 fprintf ( OUT, "\t\t\t\tEmbedManifest=\"false\"/>\r\n" );
651 }
652 fprintf ( OUT, "\t\t\t<Tool\r\n" );
653 fprintf ( OUT, "\t\t\t\tName=\"VCPostBuildEventTool\"/>\r\n" );
654 fprintf ( OUT, "\t\t\t<Tool\r\n" );
655 fprintf ( OUT, "\t\t\t\tName=\"VCPreBuildEventTool\"/>\r\n" );
656 fprintf ( OUT, "\t\t\t<Tool\r\n" );
657 fprintf ( OUT, "\t\t\t\tName=\"VCPreLinkEventTool\"/>\r\n" );
658 fprintf ( OUT, "\t\t\t<Tool\r\n" );
659 fprintf ( OUT, "\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"/>\r\n" );
660 fprintf ( OUT, "\t\t\t<Tool\r\n" );
661 fprintf ( OUT, "\t\t\t\tName=\"VCWebDeploymentTool\"/>\r\n" );
662 fprintf ( OUT, "\t\t</Configuration>\r\n" );
663
664 n++;
665 }
666 fprintf ( OUT, "\t</Configurations>\r\n" );
667
668 fprintf ( OUT, "\t<Files>\r\n" );
669
670 // Source files
671 fprintf ( OUT, "\t\t<Filter\r\n" );
672 fprintf ( OUT, "\t\t\tName=\"Source Files\"\r\n" );
673 fprintf ( OUT, "\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;S\">\r\n" );
674
675 std::sort(source_files.begin(), source_files.end(), SortFilesAscending());
676 vector<string> last_folder;
677 vector<string> split_path;
678 string indent_tab("\t\t\t");
679
680 for ( size_t isrcfile = 0; isrcfile < source_files.size(); isrcfile++ )
681 {
682 string source_file = DosSeparator(source_files[isrcfile]);
683
684 Path::Split(split_path, source_file, false);
685 size_t same_folder_index = 0;
686 for ( size_t ifolder = 0; ifolder < last_folder.size(); ifolder++ )
687 {
688 if ( ifolder < split_path.size() && last_folder[ifolder] == split_path[ifolder] )
689 ++same_folder_index;
690 else
691 break;
692 }
693
694 if ( same_folder_index < split_path.size() || last_folder.size() > split_path.size() )
695 {
696 int tabStart = 1;
697 if ( split_path.size() > last_folder.size() )
698 {
699 for ( size_t ifolder = last_folder.size(); ifolder < split_path.size(); ifolder++ )
700 indent_tab.push_back('\t');
701 tabStart = split_path.size() - last_folder.size() + 1;
702 }
703 else if ( split_path.size() < last_folder.size() )
704 {
705 indent_tab.resize( split_path.size() + 3 );
706 tabStart = split_path.size() - last_folder.size() + 1;
707 }
708
709 for ( size_t ifolder = last_folder.size(), itab = tabStart; ifolder > same_folder_index; ifolder--, itab++ )
710 {
711 fprintf ( OUT, "%s</Filter>\r\n", indent_tab.substr(0, indent_tab.size() - itab).c_str() );
712 }
713
714 for ( size_t ifolder = same_folder_index, itab = split_path.size() - same_folder_index; ifolder < split_path.size(); ifolder++, itab-- )
715 {
716 const string tab = indent_tab.substr(0, indent_tab.size() - itab);
717 fprintf ( OUT, "%s<Filter\r\n", tab.c_str() );
718 fprintf ( OUT, "%s\tName=\"%s\">\r\n", tab.c_str(), split_path[ifolder].c_str() );
719 }
720
721 last_folder = split_path;
722 }
723
724 fprintf ( OUT, "%s<File\r\n", indent_tab.c_str() );
725 fprintf ( OUT, "%s\tRelativePath=\"%s\">\r\n", indent_tab.c_str(), source_file.c_str() );
726
727 for ( size_t iconfig = 0; iconfig < m_configurations.size(); iconfig++ )
728 {
729 const MSVCConfiguration& config = *m_configurations[iconfig];
730
731 if (( isrcfile == 0 ) && ( module.pch != NULL ))
732 {
733 /* little hack to speed up PCH */
734 fprintf ( OUT, "%s\t<FileConfiguration\r\n", indent_tab.c_str() );
735 fprintf ( OUT, "%s\t\tName=\"", indent_tab.c_str() );
736 fprintf ( OUT, config.name.c_str() );
737 fprintf ( OUT, "|Win32\">\r\n" );
738 fprintf ( OUT, "%s\t\t<Tool\r\n", indent_tab.c_str() );
739 fprintf ( OUT, "%s\t\t\tName=\"VCCLCompilerTool\"\r\n", indent_tab.c_str() );
740 fprintf ( OUT, "%s\t\t\tUsePrecompiledHeader=\"1\"/>\r\n", indent_tab.c_str() );
741 fprintf ( OUT, "%s\t</FileConfiguration>\r\n", indent_tab.c_str() );
742 }
743
744 //if (configuration.VSProjectVersion < "8.00") {
745 if ((source_file.find(".idl") != string::npos) || ((source_file.find(".asm") != string::npos || tolower(source_file.at(source_file.size() - 1)) == 's')))
746 {
747 fprintf ( OUT, "%s\t<FileConfiguration\r\n", indent_tab.c_str() );
748 fprintf ( OUT, "%s\t\tName=\"", indent_tab.c_str() );
749 fprintf ( OUT, config.name.c_str() );
750 fprintf ( OUT, "|Win32\">\r\n" );
751 fprintf ( OUT, "%s\t\t<Tool\r\n", indent_tab.c_str() );
752 if (source_file.find(".idl") != string::npos)
753 {
754 string src = source_file.substr (0, source_file.find(".idl"));
755
756 if ( src.find (".\\") != string::npos )
757 src.erase (0, 2);
758
759 fprintf ( OUT, "%s\t\t\tName=\"VCCustomBuildTool\"\r\n", indent_tab.c_str() );
760
761 if ( module.type == RpcClient )
762 {
763 fprintf ( OUT, "%s\t\t\tCommandLine=\"midl.exe /cstub %s_c.c /header %s_c.h /server none &quot;$(InputPath)&quot; /out &quot;$(IntDir)&quot;", indent_tab.c_str(), src.c_str (), src.c_str () );
764 fprintf ( OUT, "&#x0D;&#x0A;");
765 fprintf ( OUT, "cl.exe /Od /D &quot;WIN32&quot; /D &quot;_DEBUG&quot; /D &quot;_WINDOWS&quot; /D &quot;_WIN32_WINNT=0x502&quot; /D &quot;_UNICODE&quot; /D &quot;UNICODE&quot; /Gm /EHsc /RTC1 /MDd /Fo&quot;$(IntDir)\\%s.obj&quot; /W3 /c /Wp64 /ZI /TC &quot;$(IntDir)\\%s_c.c&quot; /nologo /errorReport:prompt", src.c_str (), src.c_str () );
766 }
767 else
768 {
769 fprintf ( OUT, "%s\t\t\tCommandLine=\"midl.exe /sstub %s_s.c /header %s_s.h /client none &quot;$(InputPath)&quot; /out &quot;$(IntDir)&quot;", indent_tab.c_str(), src.c_str (), src.c_str () );
770 fprintf ( OUT, "&#x0D;&#x0A;");
771 fprintf ( OUT, "cl.exe /Od /D &quot;WIN32&quot; /D &quot;_DEBUG&quot; /D &quot;_WINDOWS&quot; /D &quot;_WIN32_WINNT=0x502&quot; /D &quot;_UNICODE&quot; /D &quot;UNICODE&quot; /Gm /EHsc /RTC1 /MDd /Fo&quot;$(IntDir)\\%s.obj&quot; /W3 /c /Wp64 /ZI /TC &quot;$(IntDir)\\%s_s.c&quot; /nologo /errorReport:prompt", src.c_str (), src.c_str () );
772
773 }
774 fprintf ( OUT, "&#x0D;&#x0A;");
775 fprintf ( OUT, "lib.exe /OUT:&quot;$(OutDir)\\%s.lib&quot; &quot;$(IntDir)\\%s.obj&quot;&#x0D;&#x0A;\"\r\n", module.name.c_str (), src.c_str () );
776 fprintf ( OUT, "%s\t\t\tOutputs=\"$(IntDir)\\$(InputName).obj\"/>\r\n", indent_tab.c_str() );
777 }
778 else if ((source_file.find(".asm") != string::npos))
779 {
780 fprintf ( OUT, "%s\t\t\tName=\"VCCustomBuildTool\"\r\n", indent_tab.c_str() );
781 fprintf ( OUT, "%s\t\t\tCommandLine=\"nasmw $(InputPath) -f coff -o &quot;$(OutDir)\\$(InputName).obj&quot;\"\r\n", indent_tab.c_str() );
782 fprintf ( OUT, "%s\t\t\tOutputs=\"$(OutDir)\\$(InputName).obj\"/>\r\n", indent_tab.c_str() );
783 }
784 else if ((tolower(source_file.at(source_file.size() - 1)) == 's'))
785 {
786 fprintf ( OUT, "%s\t\t\tName=\"VCCustomBuildTool\"\r\n", indent_tab.c_str() );
787 fprintf ( OUT, "%s\t\t\tCommandLine=\"cl /E &quot;$(InputPath)&quot; %s /D__ASM__ | as -o &quot;$(OutDir)\\$(InputName).obj&quot;\"\r\n", indent_tab.c_str(), include_string.c_str() );
788 fprintf ( OUT, "%s\t\t\tOutputs=\"$(OutDir)\\$(InputName).obj\"/>\r\n", indent_tab.c_str() );
789 }
790 fprintf ( OUT, "%s\t</FileConfiguration>\r\n", indent_tab.c_str() );
791 }
792 //}
793 }
794 fprintf ( OUT, "%s</File>\r\n", indent_tab.c_str() );
795 }
796
797 for ( size_t ifolder = last_folder.size(); ifolder > 0; ifolder-- )
798 {
799 indent_tab.resize( ifolder + 2 );
800 fprintf ( OUT, "%s</Filter>\r\n", indent_tab.c_str() );
801 }
802
803 fprintf ( OUT, "\t\t</Filter>\r\n" );
804
805 // Header files
806 fprintf ( OUT, "\t\t<Filter\r\n" );
807 fprintf ( OUT, "\t\t\tName=\"Header Files\"\r\n" );
808 fprintf ( OUT, "\t\t\tFilter=\"h;hpp;hxx;hm;inl\">\r\n" );
809 for ( i = 0; i < header_files.size(); i++ )
810 {
811 const string& header_file = header_files[i];
812 fprintf ( OUT, "\t\t\t<File\r\n" );
813 fprintf ( OUT, "\t\t\t\tRelativePath=\"%s\">\r\n", header_file.c_str() );
814 fprintf ( OUT, "\t\t\t</File>\r\n" );
815 }
816 fprintf ( OUT, "\t\t</Filter>\r\n" );
817
818 // Resource files
819 fprintf ( OUT, "\t\t<Filter\r\n" );
820 fprintf ( OUT, "\t\t\tName=\"Resource Files\"\r\n" );
821 fprintf ( OUT, "\t\t\tFilter=\"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\">\r\n" );
822 for ( i = 0; i < resource_files.size(); i++ )
823 {
824 const string& resource_file = resource_files[i];
825 fprintf ( OUT, "\t\t\t<File\r\n" );
826 fprintf ( OUT, "\t\t\t\tRelativePath=\"%s\">\r\n", resource_file.c_str() );
827 fprintf ( OUT, "\t\t\t</File>\r\n" );
828 }
829 fprintf ( OUT, "\t\t</Filter>\r\n" );
830
831 fprintf ( OUT, "\t</Files>\r\n" );
832 fprintf ( OUT, "\t<Globals>\r\n" );
833 fprintf ( OUT, "\t</Globals>\r\n" );
834 fprintf ( OUT, "</VisualStudioProject>\r\n" );
835 fclose ( OUT );
836
837 /* User configuration file */
838 if (vcproj_file_user != "")
839 {
840 OUT = fopen ( vcproj_file_user.c_str(), "wb" );
841 fprintf ( OUT, "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\r\n" );
842 fprintf ( OUT, "<VisualStudioUserFile\r\n" );
843 fprintf ( OUT, "\tProjectType=\"Visual C++\"\r\n" );
844 fprintf ( OUT, "\tVersion=\"%s\"\r\n", configuration.VSProjectVersion.c_str() );
845 fprintf ( OUT, "\tShowAllFiles=\"false\"\r\n" );
846 fprintf ( OUT, "\t>\r\n" );
847
848 fprintf ( OUT, "\t<Configurations>\r\n" );
849 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
850 {
851 const MSVCConfiguration& cfg = *m_configurations[icfg];
852 fprintf ( OUT, "\t\t<Configuration\r\n" );
853 fprintf ( OUT, "\t\t\tName=\"%s|Win32\"\r\n", cfg.name.c_str() );
854 fprintf ( OUT, "\t\t\t>\r\n" );
855 fprintf ( OUT, "\t\t\t<DebugSettings\r\n" );
856 if ( module_type == ".cpl" )
857 {
858 fprintf ( OUT, "\t\t\t\tCommand=\"rundll32.exe\"\r\n" );
859 fprintf ( OUT, "\t\t\t\tCommandArguments=\" shell32,Control_RunDLL &quot;$(TargetPath)&quot;,@\"\r\n" );
860 }
861 else
862 {
863 fprintf ( OUT, "\t\t\t\tCommand=\"$(TargetPath)\"\r\n" );
864 fprintf ( OUT, "\t\t\t\tCommandArguments=\"\"\r\n" );
865 }
866 fprintf ( OUT, "\t\t\t\tAttach=\"false\"\r\n" );
867 fprintf ( OUT, "\t\t\t\tDebuggerType=\"3\"\r\n" );
868 fprintf ( OUT, "\t\t\t\tRemote=\"1\"\r\n" );
869 string remote_machine = "\t\t\t\tRemoteMachine=\"" + computername + "\"\r\n";
870 fprintf ( OUT, remote_machine.c_str() );
871 fprintf ( OUT, "\t\t\t\tRemoteCommand=\"\"\r\n" );
872 fprintf ( OUT, "\t\t\t\tHttpUrl=\"\"\r\n" );
873 fprintf ( OUT, "\t\t\t\tPDBPath=\"\"\r\n" );
874 fprintf ( OUT, "\t\t\t\tSQLDebugging=\"\"\r\n" );
875 fprintf ( OUT, "\t\t\t\tEnvironment=\"\"\r\n" );
876 fprintf ( OUT, "\t\t\t\tEnvironmentMerge=\"true\"\r\n" );
877 fprintf ( OUT, "\t\t\t\tDebuggerFlavor=\"\"\r\n" );
878 fprintf ( OUT, "\t\t\t\tMPIRunCommand=\"\"\r\n" );
879 fprintf ( OUT, "\t\t\t\tMPIRunArguments=\"\"\r\n" );
880 fprintf ( OUT, "\t\t\t\tMPIRunWorkingDirectory=\"\"\r\n" );
881 fprintf ( OUT, "\t\t\t\tApplicationCommand=\"\"\r\n" );
882 fprintf ( OUT, "\t\t\t\tApplicationArguments=\"\"\r\n" );
883 fprintf ( OUT, "\t\t\t\tShimCommand=\"\"\r\n" );
884 fprintf ( OUT, "\t\t\t\tMPIAcceptMode=\"\"\r\n" );
885 fprintf ( OUT, "\t\t\t\tMPIAcceptFilter=\"\"\r\n" );
886 fprintf ( OUT, "\t\t\t/>\r\n" );
887 fprintf ( OUT, "\t\t</Configuration>\r\n" );
888 }
889 fprintf ( OUT, "\t</Configurations>\r\n" );
890 fprintf ( OUT, "</VisualStudioUserFile>\r\n" );
891 fclose ( OUT );
892 }
893
894 }
895
896 std::string
897 MSVCBackend::_strip_gcc_deffile(std::string Filename, std::string sourcedir, std::string objdir)
898 {
899 std::string NewFilename = Environment::GetIntermediatePath () + "\\" + objdir + "\\" + Filename;
900 // we don't like infinite loops - so replace it in two steps
901 NewFilename = _replace_str(NewFilename, ".def", "_msvc.de");
902 NewFilename = _replace_str(NewFilename, "_msvc.de", "_msvc.def");
903 Filename = sourcedir + "\\" + Filename;
904
905 Directory dir(objdir);
906 dir.GenerateTree(IntermediateDirectory, false);
907
908 std::fstream in_file(Filename.c_str(), std::ios::in);
909 std::fstream out_file(NewFilename.c_str(), std::ios::out);
910 std::string::size_type pos;
911 DWORD i = 0;
912
913 std::string line;
914 while (std::getline(in_file, line))
915 {
916 pos = line.find("@", 0);
917 while (std::string::npos != pos)
918 {
919 if (pos > 1)
920 {
921 // make sure it is stdcall and no ordinal
922 if (line[pos -1] != ' ')
923 {
924 i = 0;
925 while (true)
926 {
927 i++;
928 if ((line[pos + i] < '0') || (line[pos + i] > '9'))
929 break;
930 }
931 line.replace(pos, i, "");
932 }
933 }
934 pos = line.find("@", pos + 1);
935 }
936
937 line += "\n";
938 out_file << line;
939 }
940 in_file.close();
941 out_file.close();
942
943 return NewFilename;
944 }
945
946 std::string
947 MSVCBackend::_replace_str(std::string string1, const std::string &find_str, const std::string &replace_str)
948 {
949 std::string::size_type pos = string1.find(find_str, 0);
950 int intLen = find_str.length();
951
952 while(std::string::npos != pos)
953 {
954 string1.replace(pos, intLen, replace_str);
955 pos = string1.find(find_str, intLen + pos);
956 }
957
958 return string1;
959 }
960
961 std::string
962 MSVCBackend::_get_solution_version ( void )
963 {
964 string version;
965
966 if (configuration.VSProjectVersion.empty())
967 configuration.VSProjectVersion = MS_VS_DEF_VERSION;
968
969 else if (configuration.VSProjectVersion == "7.00")
970 version = "7.00";
971
972 else if (configuration.VSProjectVersion == "7.10")
973 version = "8.00";
974
975 else if (configuration.VSProjectVersion == "8.00")
976 version = "9.00";
977
978 else if (configuration.VSProjectVersion == "9.00")
979 version = "10.00";
980
981 return version;
982 }
983
984 std::string
985 MSVCBackend::_get_studio_version ( void )
986 {
987 string version;
988
989 if (configuration.VSProjectVersion.empty())
990 configuration.VSProjectVersion = MS_VS_DEF_VERSION;
991
992 else if (configuration.VSProjectVersion == "7.00")
993 version = "2002";
994
995 else if (configuration.VSProjectVersion == "7.10")
996 version = "2003";
997
998 else if (configuration.VSProjectVersion == "8.00")
999 version = "2005";
1000
1001 else if (configuration.VSProjectVersion == "9.00")
1002 version = "2008";
1003
1004 return version;
1005 }
1006
1007 void
1008 MSVCBackend::_generate_sln_header ( FILE* OUT )
1009 {
1010 fprintf ( OUT, "Microsoft Visual Studio Solution File, Format Version %s\r\n", _get_solution_version().c_str() );
1011 fprintf ( OUT, "# Visual Studio %s\r\n", _get_studio_version().c_str() );
1012 fprintf ( OUT, "\r\n" );
1013 }
1014
1015
1016 void
1017 MSVCBackend::_generate_sln_project (
1018 FILE* OUT,
1019 const Module& module,
1020 std::string vcproj_file,
1021 std::string sln_guid,
1022 std::string vcproj_guid,
1023 const std::vector<Library*>& libraries )
1024 {
1025 vcproj_file = DosSeparator ( std::string(".\\") + vcproj_file );
1026
1027 fprintf ( OUT, "Project(\"%s\") = \"%s\", \"%s\", \"%s\"\r\n", sln_guid.c_str() , module.name.c_str(), vcproj_file.c_str(), vcproj_guid.c_str() );
1028
1029 //FIXME: only omit ProjectDependencies in VS 2005 when there are no dependencies
1030 //NOTE: VS 2002 do not use ProjectSection; it uses GlobalSection instead
1031 if ((configuration.VSProjectVersion == "7.10") || (libraries.size() > 0)) {
1032 fprintf ( OUT, "\tProjectSection(ProjectDependencies) = postProject\r\n" );
1033 for ( size_t i = 0; i < libraries.size(); i++ )
1034 {
1035 const Module& module = *libraries[i]->importedModule;
1036 fprintf ( OUT, "\t\t%s = %s\r\n", module.guid.c_str(), module.guid.c_str() );
1037 }
1038 fprintf ( OUT, "\tEndProjectSection\r\n" );
1039 }
1040
1041 fprintf ( OUT, "EndProject\r\n" );
1042 }
1043
1044
1045 void
1046 MSVCBackend::_generate_sln_footer ( FILE* OUT )
1047 {
1048 fprintf ( OUT, "Global\r\n" );
1049 fprintf ( OUT, "\tGlobalSection(SolutionConfiguration) = preSolution\r\n" );
1050 for ( size_t i = 0; i < m_configurations.size(); i++ )
1051 fprintf ( OUT, "\t\t%s = %s\r\n", m_configurations[i]->name.c_str(), m_configurations[i]->name.c_str() );
1052 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1053 fprintf ( OUT, "\tGlobalSection(ProjectConfiguration) = postSolution\r\n" );
1054 for ( size_t i = 0; i < ProjectNode.modules.size(); i++ )
1055 {
1056 Module& module = *ProjectNode.modules[i];
1057 std::string guid = module.guid;
1058 _generate_sln_configurations ( OUT, guid.c_str() );
1059 }
1060 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1061 fprintf ( OUT, "\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n" );
1062 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1063 fprintf ( OUT, "\tGlobalSection(ExtensibilityAddIns) = postSolution\r\n" );
1064 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1065
1066 if (configuration.VSProjectVersion == "7.00") {
1067 fprintf ( OUT, "\tGlobalSection(ProjectDependencies) = postSolution\r\n" );
1068 //FIXME: Add dependencies for VS 2002
1069 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1070 }
1071
1072 if (configuration.VSProjectVersion == "8.00") {
1073 fprintf ( OUT, "\tGlobalSection(SolutionProperties) = preSolution\r\n" );
1074 fprintf ( OUT, "\t\tHideSolutionNode = FALSE\r\n" );
1075 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1076 }
1077
1078 fprintf ( OUT, "EndGlobal\r\n" );
1079 fprintf ( OUT, "\r\n" );
1080 }
1081
1082
1083 void
1084 MSVCBackend::_generate_sln_configurations ( FILE* OUT, std::string vcproj_guid )
1085 {
1086 for ( size_t i = 0; i < m_configurations.size (); i++)
1087 {
1088 const MSVCConfiguration& cfg = *m_configurations[i];
1089 fprintf ( OUT, "\t\t%s.%s|Win32.ActiveCfg = %s|Win32\r\n", vcproj_guid.c_str(), cfg.name.c_str(), cfg.name.c_str() );
1090 fprintf ( OUT, "\t\t%s.%s|Win32.Build.0 = %s|Win32\r\n", vcproj_guid.c_str(), cfg.name.c_str(), cfg.name.c_str() );
1091 }
1092 }
1093
1094 void
1095 MSVCBackend::_generate_sln ( FILE* OUT )
1096 {
1097 string sln_guid = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}";
1098 vector<string> guids;
1099
1100 _generate_sln_header(OUT);
1101 // TODO FIXME - is it necessary to sort them?
1102 for ( size_t i = 0; i < ProjectNode.modules.size(); i++ )
1103 {
1104 Module& module = *ProjectNode.modules[i];
1105
1106 std::string vcproj_file = VcprojFileName ( module );
1107 _generate_sln_project ( OUT, module, vcproj_file, sln_guid, module.guid, module.non_if_data.libraries );
1108 }
1109 _generate_sln_footer ( OUT );
1110 }
1111
1112 const Property*
1113 MSVCBackend::_lookup_property ( const Module& module, const std::string& name ) const
1114 {
1115 /* Check local values */
1116 for ( size_t i = 0; i < module.non_if_data.properties.size(); i++ )
1117 {
1118 const Property& property = *module.non_if_data.properties[i];
1119 if ( property.name == name )
1120 return &property;
1121 }
1122 // TODO FIXME - should we check local if-ed properties?
1123 for ( size_t i = 0; i < module.project.non_if_data.properties.size(); i++ )
1124 {
1125 const Property& property = *module.project.non_if_data.properties[i];
1126 if ( property.name == name )
1127 return &property;
1128 }
1129 // TODO FIXME - should we check global if-ed properties?
1130 return NULL;
1131 }