- Add specific module type for keyboard layouts
[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 module.type == KeyboardLayout))
361 {
362 string WdkBase, SdkPath, CrtPath, DdkPath;
363 WdkBase = getenv ( "BASEDIR" );
364 SdkPath = WdkBase + "\\inc\\api";
365 CrtPath = WdkBase + "\\inc\\crt";
366 DdkPath = WdkBase + "\\inc\\ddk";
367
368 if ( multiple_includes )
369 fprintf ( OUT, ";" );
370
371 fprintf ( OUT, "%s;", SdkPath.c_str() );
372 fprintf ( OUT, "%s;", CrtPath.c_str() );
373 fprintf ( OUT, "%s", DdkPath.c_str() );
374 multiple_includes = true;
375 }
376 }
377 fprintf ( OUT, "\"\r\n" );
378
379 StringSet defines = common_defines;
380
381 // Always add _CRT_SECURE_NO_WARNINGS to disable warnings about not
382 // using the safe functions introduced in MSVC8.
383 defines.insert ( "_CRT_SECURE_NO_WARNINGS" );
384
385 if ( debug )
386 {
387 defines.insert ( "_DEBUG" );
388 }
389
390 if ( cfg.headers == MSVCHeaders )
391 {
392 // this is a define in MinGW w32api, but not Microsoft's headers
393 defines.insert ( "STDCALL=__stdcall" );
394 }
395
396 if ( lib || exe )
397 {
398 defines.insert ( "_LIB" );
399 }
400 else
401 {
402 defines.insert ( "_WINDOWS" );
403 defines.insert ( "_USRDLL" );
404 }
405
406 fprintf ( OUT, "\t\t\t\tPreprocessorDefinitions=\"" );
407 for ( StringSet::iterator it1=defines.begin(); it1!=defines.end(); it1++ )
408 {
409 if ( i > 0 )
410 fprintf ( OUT, ";" );
411
412 string unescaped = *it1;
413 defines.erase(unescaped);
414 const string& escaped = _replace_str(unescaped, "\"","");
415
416 defines.insert(escaped);
417 fprintf ( OUT, "%s", escaped.c_str() );
418 }
419 fprintf ( OUT, "\"\r\n" );
420 fprintf ( OUT, "\t\t\t\tForcedIncludeFiles=\"%s\"\r\n", "warning.h");
421 fprintf ( OUT, "\t\t\t\tMinimalRebuild=\"%s\"\r\n", speed ? "TRUE" : "FALSE" );
422 fprintf ( OUT, "\t\t\t\tBasicRuntimeChecks=\"0\"\r\n" );
423 fprintf ( OUT, "\t\t\t\tRuntimeLibrary=\"%d\"\r\n", debug ? 1 : 5 ); // 1=/MTd 5=/MT
424 fprintf ( OUT, "\t\t\t\tBufferSecurityCheck=\"FALSE\"\r\n" );
425 fprintf ( OUT, "\t\t\t\tEnableFunctionLevelLinking=\"FALSE\"\r\n" );
426
427 if ( module.pch != NULL )
428 {
429 fprintf ( OUT, "\t\t\t\tUsePrecompiledHeader=\"2\"\r\n" );
430 string pch_path = Path::RelativeFromDirectory (
431 module.pch->file->name,
432 module.output->relative_path );
433 string::size_type pos = pch_path.find_last_of ("/");
434 if ( pos != string::npos )
435 pch_path.erase(0, pos+1);
436 fprintf ( OUT, "\t\t\t\tPrecompiledHeaderThrough=\"%s\"\r\n", pch_path.c_str() );
437
438 // Only include from the same module
439 pos = pch_path.find("../");
440 if (pos == string::npos && std::find(header_files.begin(), header_files.end(), pch_path) == header_files.end())
441 header_files.push_back(pch_path);
442 }
443 else
444 {
445 fprintf ( OUT, "\t\t\t\tUsePrecompiledHeader=\"0\"\r\n" );
446 }
447
448 fprintf ( OUT, "\t\t\t\tWholeProgramOptimization=\"%s\"\r\n", release ? "FALSE" : "FALSE");
449 if ( release )
450 {
451 fprintf ( OUT, "\t\t\t\tFavorSizeOrSpeed=\"1\"\r\n" );
452 fprintf ( OUT, "\t\t\t\tStringPooling=\"true\"\r\n" );
453 }
454
455 fprintf ( OUT, "\t\t\t\tWarningLevel=\"%s\"\r\n", speed ? "0" : "3" );
456 fprintf ( OUT, "\t\t\t\tDetect64BitPortabilityProblems=\"%s\"\r\n", "FALSE");
457 if ( !module.cplusplus )
458 fprintf ( OUT, "\t\t\t\tCompileAs=\"1\"\r\n" );
459
460 if ( module.type == Win32CUI || module.type == Win32GUI )
461 {
462 fprintf ( OUT, "\t\t\t\tCallingConvention=\"%d\"\r\n", 0 ); // 0=__cdecl
463 }
464 else
465 {
466 fprintf ( OUT, "\t\t\t\tCallingConvention=\"%d\"\r\n", 2 ); // 2=__stdcall
467 }
468
469 fprintf ( OUT, "\t\t\t\tDebugInformationFormat=\"%s\"/>\r\n", speed ? "0" : release ? "3": "4"); // 3=/Zi 4=ZI
470
471 fprintf ( OUT, "\t\t\t<Tool\r\n" );
472 fprintf ( OUT, "\t\t\t\tName=\"VCCustomBuildTool\"/>\r\n" );
473
474 if ( lib )
475 {
476 fprintf ( OUT, "\t\t\t<Tool\r\n" );
477 fprintf ( OUT, "\t\t\t\tName=\"VCLibrarianTool\"\r\n" );
478 fprintf ( OUT, "\t\t\t\tOutputFile=\"$(OutDir)/%s.lib\"/>\r\n", module.name.c_str() );
479 }
480 else
481 {
482 fprintf ( OUT, "\t\t\t<Tool\r\n" );
483 fprintf ( OUT, "\t\t\t\tName=\"VCLinkerTool\"\r\n" );
484 if (module.GetEntryPoint(false) == "0")
485 fprintf ( OUT, "AdditionalOptions=\"/noentry\"" );
486
487 if (configuration.VSProjectVersion == "9.00")
488 {
489 fprintf ( OUT, "\t\t\t\tRandomizedBaseAddress=\"0\"\r\n" );
490 fprintf ( OUT, "\t\t\t\tDataExecutionPrevention=\"0\"\r\n" );
491 }
492
493 if (module.importLibrary != NULL)
494 fprintf ( OUT, "\t\t\t\tModuleDefinitionFile=\"%s\"\r\n", importLib.c_str());
495
496 fprintf ( OUT, "\t\t\t\tAdditionalDependencies=\"" );
497 bool use_msvcrt_lib = false;
498 for ( i = 0; i < libraries.size(); i++ )
499 {
500 if ( i > 0 )
501 fprintf ( OUT, " " );
502 string libpath = libraries[i].c_str();
503 libpath = libpath.erase (0, libpath.find_last_of ("\\") + 1 );
504 if ( libpath == "msvcrt.lib" )
505 {
506 use_msvcrt_lib = true;
507 }
508 fprintf ( OUT, "%s", libpath.c_str() );
509 }
510 fprintf ( OUT, "\"\r\n" );
511
512 fprintf ( OUT, "\t\t\t\tAdditionalLibraryDirectories=\"" );
513
514 // Add WDK libs paths, if needed
515 if (getenv ( "BASEDIR" ) != NULL &&
516 (module.type == Kernel ||
517 module.type == KernelModeDLL ||
518 module.type == KernelModeDriver ||
519 module.type == KeyboardLayout))
520 {
521 string WdkBase, CrtPath, DdkPath;
522 WdkBase = getenv ( "BASEDIR" );
523 CrtPath = WdkBase + "\\lib\\crt\\i386";
524 DdkPath = WdkBase + "\\lib\\wnet\\i386";
525
526 fprintf ( OUT, "%s;", CrtPath.c_str() );
527 fprintf ( OUT, "%s", DdkPath.c_str() );
528
529 if (libraries.size () > 0)
530 fprintf ( OUT, ";" );
531 }
532
533 // Add conventional libraries dirs
534 for (i = 0; i < libraries.size (); i++)
535 {
536 if ( i > 0 )
537 fprintf ( OUT, ";" );
538
539 string libpath = libraries[i].c_str();
540 libpath.replace (libpath.find("---"), 3, cfg.name);
541 libpath = libpath.substr (0, libpath.find_last_of ("\\") );
542 fprintf ( OUT, "%s", libpath.c_str() );
543 }
544
545 fprintf ( OUT, "\"\r\n" );
546
547 fprintf ( OUT, "\t\t\t\tOutputFile=\"$(OutDir)/%s%s\"\r\n", module.name.c_str(), module_type.c_str() );
548 fprintf ( OUT, "\t\t\t\tLinkIncremental=\"%d\"\r\n", debug ? 2 : 1 );
549 fprintf ( OUT, "\t\t\t\tGenerateDebugInformation=\"%s\"\r\n", speed ? "FALSE" : "TRUE" );
550 fprintf ( OUT, "\t\t\t\tLinkTimeCodeGeneration=\"%d\"\r\n", release? 0 : 0); // whole program optimization
551
552 if ( debug )
553 fprintf ( OUT, "\t\t\t\tProgramDatabaseFile=\"$(OutDir)/%s.pdb\"\r\n", module.name.c_str() );
554
555 if ( sys )
556 {
557 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /ALIGN:0x20 /SECTION:INIT,D /IGNORE:4001,4037,4039,4065,4070,4078,4087,4089,4096\"\r\n" );
558 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
559 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
560 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 3 );
561 fprintf ( OUT, "\t\t\t\tDriver=\"%d\"\r\n", 1 );
562 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"%s\"\r\n", module.GetEntryPoint(false) == "" ? "DriverEntry" : module.GetEntryPoint(false).c_str ());
563 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr == "" ? "0x10000" : baseaddr.c_str ());
564 }
565 else if ( exe )
566 {
567 if ( module.type == Kernel )
568 {
569 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /SECTION:INIT,D /ALIGN:0x80\"\r\n" );
570 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
571 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
572 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 3 );
573 fprintf ( OUT, "\t\t\t\tDriver=\"%d\"\r\n", 1 );
574 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"KiSystemStartup\"\r\n" );
575 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr.c_str ());
576 }
577 else if ( module.type == NativeCUI )
578 {
579 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /ALIGN:0x20\"\r\n" );
580 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 1 );
581 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
582 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
583 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"NtProcessStartup\"\r\n" );
584 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr.c_str ());
585 }
586 else if ( module.type == Win32CUI || module.type == Win32GUI || module.type == Win32SCR)
587 {
588 if ( use_msvcrt_lib )
589 {
590 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
591 }
592 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", console ? 1 : 2 );
593 }
594 }
595 else if ( dll )
596 {
597 if (module.GetEntryPoint(false) == "0")
598 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"\"\r\n" );
599 else
600 {
601 // get rid of DllMain@12 because MSVC needs to link to _DllMainCRTStartup@12
602 // when using CRT
603 if (module.GetEntryPoint(false) == "DllMain@12")
604 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"\"\r\n" );
605 else
606 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"%s\"\r\n", module.GetEntryPoint(false).c_str ());
607 }
608 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr == "" ? "0x40000" : baseaddr.c_str ());
609 if ( use_msvcrt_lib )
610 {
611 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
612 }
613 }
614 fprintf ( OUT, "\t\t\t\tTargetMachine=\"%d\"/>\r\n", 1 );
615 }
616
617 fprintf ( OUT, "\t\t\t<Tool\r\n" );
618 fprintf ( OUT, "\t\t\t\tName=\"VCResourceCompilerTool\"\r\n" );
619 fprintf ( OUT, "\t\t\t\tAdditionalIncludeDirectories=\"" );
620 multiple_includes = false;
621 fprintf ( OUT, "./;" );
622 for ( i = 0; i < includes.size(); i++ )
623 {
624 const std::string& include = includes[i];
625 if ( strcmp ( include.c_str(), "." ) )
626 {
627 if ( multiple_includes )
628 fprintf ( OUT, ";" );
629 fprintf ( OUT, "%s", include.c_str() );
630 multiple_includes = true;
631 }
632 }
633 if ( cfg.headers == ReactOSHeaders )
634 {
635 for ( i = 0; i < includes_ros.size(); i++ )
636 {
637 const std::string& include = includes_ros[i];
638 if ( multiple_includes )
639 fprintf ( OUT, ";" );
640 fprintf ( OUT, "%s", include.c_str() );
641 multiple_includes = true;
642 }
643 }
644 fprintf ( OUT, "\"/>\r\n " );
645
646 fprintf ( OUT, "\t\t\t<Tool\r\n" );
647 fprintf ( OUT, "\t\t\t\tName=\"VCMIDLTool\"/>\r\n" );
648 if (configuration.VSProjectVersion == "8.00")
649 {
650 fprintf ( OUT, "\t\t\t<Tool\r\n" );
651 fprintf ( OUT, "\t\t\t\tName=\"VCManifestTool\"\r\n" );
652 fprintf ( OUT, "\t\t\t\tEmbedManifest=\"false\"/>\r\n" );
653 }
654 fprintf ( OUT, "\t\t\t<Tool\r\n" );
655 fprintf ( OUT, "\t\t\t\tName=\"VCPostBuildEventTool\"/>\r\n" );
656 fprintf ( OUT, "\t\t\t<Tool\r\n" );
657 fprintf ( OUT, "\t\t\t\tName=\"VCPreBuildEventTool\"/>\r\n" );
658 fprintf ( OUT, "\t\t\t<Tool\r\n" );
659 fprintf ( OUT, "\t\t\t\tName=\"VCPreLinkEventTool\"/>\r\n" );
660 fprintf ( OUT, "\t\t\t<Tool\r\n" );
661 fprintf ( OUT, "\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"/>\r\n" );
662 fprintf ( OUT, "\t\t\t<Tool\r\n" );
663 fprintf ( OUT, "\t\t\t\tName=\"VCWebDeploymentTool\"/>\r\n" );
664 fprintf ( OUT, "\t\t</Configuration>\r\n" );
665
666 n++;
667 }
668 fprintf ( OUT, "\t</Configurations>\r\n" );
669
670 fprintf ( OUT, "\t<Files>\r\n" );
671
672 // Source files
673 fprintf ( OUT, "\t\t<Filter\r\n" );
674 fprintf ( OUT, "\t\t\tName=\"Source Files\"\r\n" );
675 fprintf ( OUT, "\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;S\">\r\n" );
676
677 std::sort(source_files.begin(), source_files.end(), SortFilesAscending());
678 vector<string> last_folder;
679 vector<string> split_path;
680 string indent_tab("\t\t\t");
681
682 for ( size_t isrcfile = 0; isrcfile < source_files.size(); isrcfile++ )
683 {
684 string source_file = DosSeparator(source_files[isrcfile]);
685
686 Path::Split(split_path, source_file, false);
687 size_t same_folder_index = 0;
688 for ( size_t ifolder = 0; ifolder < last_folder.size(); ifolder++ )
689 {
690 if ( ifolder < split_path.size() && last_folder[ifolder] == split_path[ifolder] )
691 ++same_folder_index;
692 else
693 break;
694 }
695
696 if ( same_folder_index < split_path.size() || last_folder.size() > split_path.size() )
697 {
698 int tabStart = 1;
699 if ( split_path.size() > last_folder.size() )
700 {
701 for ( size_t ifolder = last_folder.size(); ifolder < split_path.size(); ifolder++ )
702 indent_tab.push_back('\t');
703 tabStart = split_path.size() - last_folder.size() + 1;
704 }
705 else if ( split_path.size() < last_folder.size() )
706 {
707 indent_tab.resize( split_path.size() + 3 );
708 tabStart = split_path.size() - last_folder.size() + 1;
709 }
710
711 for ( size_t ifolder = last_folder.size(), itab = tabStart; ifolder > same_folder_index; ifolder--, itab++ )
712 {
713 fprintf ( OUT, "%s</Filter>\r\n", indent_tab.substr(0, indent_tab.size() - itab).c_str() );
714 }
715
716 for ( size_t ifolder = same_folder_index, itab = split_path.size() - same_folder_index; ifolder < split_path.size(); ifolder++, itab-- )
717 {
718 const string tab = indent_tab.substr(0, indent_tab.size() - itab);
719 fprintf ( OUT, "%s<Filter\r\n", tab.c_str() );
720 fprintf ( OUT, "%s\tName=\"%s\">\r\n", tab.c_str(), split_path[ifolder].c_str() );
721 }
722
723 last_folder = split_path;
724 }
725
726 fprintf ( OUT, "%s<File\r\n", indent_tab.c_str() );
727 fprintf ( OUT, "%s\tRelativePath=\"%s\">\r\n", indent_tab.c_str(), source_file.c_str() );
728
729 for ( size_t iconfig = 0; iconfig < m_configurations.size(); iconfig++ )
730 {
731 const MSVCConfiguration& config = *m_configurations[iconfig];
732
733 if (( isrcfile == 0 ) && ( module.pch != NULL ))
734 {
735 /* little hack to speed up PCH */
736 fprintf ( OUT, "%s\t<FileConfiguration\r\n", indent_tab.c_str() );
737 fprintf ( OUT, "%s\t\tName=\"", indent_tab.c_str() );
738 fprintf ( OUT, config.name.c_str() );
739 fprintf ( OUT, "|Win32\">\r\n" );
740 fprintf ( OUT, "%s\t\t<Tool\r\n", indent_tab.c_str() );
741 fprintf ( OUT, "%s\t\t\tName=\"VCCLCompilerTool\"\r\n", indent_tab.c_str() );
742 fprintf ( OUT, "%s\t\t\tUsePrecompiledHeader=\"1\"/>\r\n", indent_tab.c_str() );
743 fprintf ( OUT, "%s\t</FileConfiguration>\r\n", indent_tab.c_str() );
744 }
745
746 //if (configuration.VSProjectVersion < "8.00") {
747 if ((source_file.find(".idl") != string::npos) || ((source_file.find(".asm") != string::npos || tolower(source_file.at(source_file.size() - 1)) == 's')))
748 {
749 fprintf ( OUT, "%s\t<FileConfiguration\r\n", indent_tab.c_str() );
750 fprintf ( OUT, "%s\t\tName=\"", indent_tab.c_str() );
751 fprintf ( OUT, config.name.c_str() );
752 fprintf ( OUT, "|Win32\">\r\n" );
753 fprintf ( OUT, "%s\t\t<Tool\r\n", indent_tab.c_str() );
754 if (source_file.find(".idl") != string::npos)
755 {
756 string src = source_file.substr (0, source_file.find(".idl"));
757
758 if ( src.find (".\\") != string::npos )
759 src.erase (0, 2);
760
761 fprintf ( OUT, "%s\t\t\tName=\"VCCustomBuildTool\"\r\n", indent_tab.c_str() );
762
763 if ( module.type == RpcClient )
764 {
765 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 () );
766 fprintf ( OUT, "&#x0D;&#x0A;");
767 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 () );
768 }
769 else
770 {
771 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 () );
772 fprintf ( OUT, "&#x0D;&#x0A;");
773 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 () );
774
775 }
776 fprintf ( OUT, "&#x0D;&#x0A;");
777 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 () );
778 fprintf ( OUT, "%s\t\t\tOutputs=\"$(IntDir)\\$(InputName).obj\"/>\r\n", indent_tab.c_str() );
779 }
780 else if ((source_file.find(".asm") != string::npos))
781 {
782 fprintf ( OUT, "%s\t\t\tName=\"VCCustomBuildTool\"\r\n", indent_tab.c_str() );
783 fprintf ( OUT, "%s\t\t\tCommandLine=\"nasmw $(InputPath) -f coff -o &quot;$(OutDir)\\$(InputName).obj&quot;\"\r\n", indent_tab.c_str() );
784 fprintf ( OUT, "%s\t\t\tOutputs=\"$(OutDir)\\$(InputName).obj\"/>\r\n", indent_tab.c_str() );
785 }
786 else if ((tolower(source_file.at(source_file.size() - 1)) == 's'))
787 {
788 fprintf ( OUT, "%s\t\t\tName=\"VCCustomBuildTool\"\r\n", indent_tab.c_str() );
789 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() );
790 fprintf ( OUT, "%s\t\t\tOutputs=\"$(OutDir)\\$(InputName).obj\"/>\r\n", indent_tab.c_str() );
791 }
792 fprintf ( OUT, "%s\t</FileConfiguration>\r\n", indent_tab.c_str() );
793 }
794 //}
795 }
796 fprintf ( OUT, "%s</File>\r\n", indent_tab.c_str() );
797 }
798
799 for ( size_t ifolder = last_folder.size(); ifolder > 0; ifolder-- )
800 {
801 indent_tab.resize( ifolder + 2 );
802 fprintf ( OUT, "%s</Filter>\r\n", indent_tab.c_str() );
803 }
804
805 fprintf ( OUT, "\t\t</Filter>\r\n" );
806
807 // Header files
808 fprintf ( OUT, "\t\t<Filter\r\n" );
809 fprintf ( OUT, "\t\t\tName=\"Header Files\"\r\n" );
810 fprintf ( OUT, "\t\t\tFilter=\"h;hpp;hxx;hm;inl\">\r\n" );
811 for ( i = 0; i < header_files.size(); i++ )
812 {
813 const string& header_file = header_files[i];
814 fprintf ( OUT, "\t\t\t<File\r\n" );
815 fprintf ( OUT, "\t\t\t\tRelativePath=\"%s\">\r\n", header_file.c_str() );
816 fprintf ( OUT, "\t\t\t</File>\r\n" );
817 }
818 fprintf ( OUT, "\t\t</Filter>\r\n" );
819
820 // Resource files
821 fprintf ( OUT, "\t\t<Filter\r\n" );
822 fprintf ( OUT, "\t\t\tName=\"Resource Files\"\r\n" );
823 fprintf ( OUT, "\t\t\tFilter=\"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\">\r\n" );
824 for ( i = 0; i < resource_files.size(); i++ )
825 {
826 const string& resource_file = resource_files[i];
827 fprintf ( OUT, "\t\t\t<File\r\n" );
828 fprintf ( OUT, "\t\t\t\tRelativePath=\"%s\">\r\n", resource_file.c_str() );
829 fprintf ( OUT, "\t\t\t</File>\r\n" );
830 }
831 fprintf ( OUT, "\t\t</Filter>\r\n" );
832
833 fprintf ( OUT, "\t</Files>\r\n" );
834 fprintf ( OUT, "\t<Globals>\r\n" );
835 fprintf ( OUT, "\t</Globals>\r\n" );
836 fprintf ( OUT, "</VisualStudioProject>\r\n" );
837 fclose ( OUT );
838
839 /* User configuration file */
840 if (vcproj_file_user != "")
841 {
842 OUT = fopen ( vcproj_file_user.c_str(), "wb" );
843 fprintf ( OUT, "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\r\n" );
844 fprintf ( OUT, "<VisualStudioUserFile\r\n" );
845 fprintf ( OUT, "\tProjectType=\"Visual C++\"\r\n" );
846 fprintf ( OUT, "\tVersion=\"%s\"\r\n", configuration.VSProjectVersion.c_str() );
847 fprintf ( OUT, "\tShowAllFiles=\"false\"\r\n" );
848 fprintf ( OUT, "\t>\r\n" );
849
850 fprintf ( OUT, "\t<Configurations>\r\n" );
851 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
852 {
853 const MSVCConfiguration& cfg = *m_configurations[icfg];
854 fprintf ( OUT, "\t\t<Configuration\r\n" );
855 fprintf ( OUT, "\t\t\tName=\"%s|Win32\"\r\n", cfg.name.c_str() );
856 fprintf ( OUT, "\t\t\t>\r\n" );
857 fprintf ( OUT, "\t\t\t<DebugSettings\r\n" );
858 if ( module_type == ".cpl" )
859 {
860 fprintf ( OUT, "\t\t\t\tCommand=\"rundll32.exe\"\r\n" );
861 fprintf ( OUT, "\t\t\t\tCommandArguments=\" shell32,Control_RunDLL &quot;$(TargetPath)&quot;,@\"\r\n" );
862 }
863 else
864 {
865 fprintf ( OUT, "\t\t\t\tCommand=\"$(TargetPath)\"\r\n" );
866 fprintf ( OUT, "\t\t\t\tCommandArguments=\"\"\r\n" );
867 }
868 fprintf ( OUT, "\t\t\t\tAttach=\"false\"\r\n" );
869 fprintf ( OUT, "\t\t\t\tDebuggerType=\"3\"\r\n" );
870 fprintf ( OUT, "\t\t\t\tRemote=\"1\"\r\n" );
871 string remote_machine = "\t\t\t\tRemoteMachine=\"" + computername + "\"\r\n";
872 fprintf ( OUT, remote_machine.c_str() );
873 fprintf ( OUT, "\t\t\t\tRemoteCommand=\"\"\r\n" );
874 fprintf ( OUT, "\t\t\t\tHttpUrl=\"\"\r\n" );
875 fprintf ( OUT, "\t\t\t\tPDBPath=\"\"\r\n" );
876 fprintf ( OUT, "\t\t\t\tSQLDebugging=\"\"\r\n" );
877 fprintf ( OUT, "\t\t\t\tEnvironment=\"\"\r\n" );
878 fprintf ( OUT, "\t\t\t\tEnvironmentMerge=\"true\"\r\n" );
879 fprintf ( OUT, "\t\t\t\tDebuggerFlavor=\"\"\r\n" );
880 fprintf ( OUT, "\t\t\t\tMPIRunCommand=\"\"\r\n" );
881 fprintf ( OUT, "\t\t\t\tMPIRunArguments=\"\"\r\n" );
882 fprintf ( OUT, "\t\t\t\tMPIRunWorkingDirectory=\"\"\r\n" );
883 fprintf ( OUT, "\t\t\t\tApplicationCommand=\"\"\r\n" );
884 fprintf ( OUT, "\t\t\t\tApplicationArguments=\"\"\r\n" );
885 fprintf ( OUT, "\t\t\t\tShimCommand=\"\"\r\n" );
886 fprintf ( OUT, "\t\t\t\tMPIAcceptMode=\"\"\r\n" );
887 fprintf ( OUT, "\t\t\t\tMPIAcceptFilter=\"\"\r\n" );
888 fprintf ( OUT, "\t\t\t/>\r\n" );
889 fprintf ( OUT, "\t\t</Configuration>\r\n" );
890 }
891 fprintf ( OUT, "\t</Configurations>\r\n" );
892 fprintf ( OUT, "</VisualStudioUserFile>\r\n" );
893 fclose ( OUT );
894 }
895
896 }
897
898 std::string
899 MSVCBackend::_strip_gcc_deffile(std::string Filename, std::string sourcedir, std::string objdir)
900 {
901 std::string NewFilename = Environment::GetIntermediatePath () + "\\" + objdir + "\\" + Filename;
902 // we don't like infinite loops - so replace it in two steps
903 NewFilename = _replace_str(NewFilename, ".def", "_msvc.de");
904 NewFilename = _replace_str(NewFilename, "_msvc.de", "_msvc.def");
905 Filename = sourcedir + "\\" + Filename;
906
907 Directory dir(objdir);
908 dir.GenerateTree(IntermediateDirectory, false);
909
910 std::fstream in_file(Filename.c_str(), std::ios::in);
911 std::fstream out_file(NewFilename.c_str(), std::ios::out);
912 std::string::size_type pos;
913 DWORD i = 0;
914
915 std::string line;
916 while (std::getline(in_file, line))
917 {
918 pos = line.find("@", 0);
919 while (std::string::npos != pos)
920 {
921 if (pos > 1)
922 {
923 // make sure it is stdcall and no ordinal
924 if (line[pos -1] != ' ')
925 {
926 i = 0;
927 while (true)
928 {
929 i++;
930 if ((line[pos + i] < '0') || (line[pos + i] > '9'))
931 break;
932 }
933 line.replace(pos, i, "");
934 }
935 }
936 pos = line.find("@", pos + 1);
937 }
938
939 line += "\n";
940 out_file << line;
941 }
942 in_file.close();
943 out_file.close();
944
945 return NewFilename;
946 }
947
948 std::string
949 MSVCBackend::_replace_str(std::string string1, const std::string &find_str, const std::string &replace_str)
950 {
951 std::string::size_type pos = string1.find(find_str, 0);
952 int intLen = find_str.length();
953
954 while(std::string::npos != pos)
955 {
956 string1.replace(pos, intLen, replace_str);
957 pos = string1.find(find_str, intLen + pos);
958 }
959
960 return string1;
961 }
962
963 std::string
964 MSVCBackend::_get_solution_version ( void )
965 {
966 string version;
967
968 if (configuration.VSProjectVersion.empty())
969 configuration.VSProjectVersion = MS_VS_DEF_VERSION;
970
971 else if (configuration.VSProjectVersion == "7.00")
972 version = "7.00";
973
974 else if (configuration.VSProjectVersion == "7.10")
975 version = "8.00";
976
977 else if (configuration.VSProjectVersion == "8.00")
978 version = "9.00";
979
980 else if (configuration.VSProjectVersion == "9.00")
981 version = "10.00";
982
983 return version;
984 }
985
986 std::string
987 MSVCBackend::_get_studio_version ( void )
988 {
989 string version;
990
991 if (configuration.VSProjectVersion.empty())
992 configuration.VSProjectVersion = MS_VS_DEF_VERSION;
993
994 else if (configuration.VSProjectVersion == "7.00")
995 version = "2002";
996
997 else if (configuration.VSProjectVersion == "7.10")
998 version = "2003";
999
1000 else if (configuration.VSProjectVersion == "8.00")
1001 version = "2005";
1002
1003 else if (configuration.VSProjectVersion == "9.00")
1004 version = "2008";
1005
1006 return version;
1007 }
1008
1009 void
1010 MSVCBackend::_generate_sln_header ( FILE* OUT )
1011 {
1012 fprintf ( OUT, "Microsoft Visual Studio Solution File, Format Version %s\r\n", _get_solution_version().c_str() );
1013 fprintf ( OUT, "# Visual Studio %s\r\n", _get_studio_version().c_str() );
1014 fprintf ( OUT, "\r\n" );
1015 }
1016
1017
1018 void
1019 MSVCBackend::_generate_sln_project (
1020 FILE* OUT,
1021 const Module& module,
1022 std::string vcproj_file,
1023 std::string sln_guid,
1024 std::string vcproj_guid,
1025 const std::vector<Library*>& libraries )
1026 {
1027 vcproj_file = DosSeparator ( std::string(".\\") + vcproj_file );
1028
1029 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() );
1030
1031 //FIXME: only omit ProjectDependencies in VS 2005 when there are no dependencies
1032 //NOTE: VS 2002 do not use ProjectSection; it uses GlobalSection instead
1033 if ((configuration.VSProjectVersion == "7.10") || (libraries.size() > 0)) {
1034 fprintf ( OUT, "\tProjectSection(ProjectDependencies) = postProject\r\n" );
1035 for ( size_t i = 0; i < libraries.size(); i++ )
1036 {
1037 const Module& module = *libraries[i]->importedModule;
1038 fprintf ( OUT, "\t\t%s = %s\r\n", module.guid.c_str(), module.guid.c_str() );
1039 }
1040 fprintf ( OUT, "\tEndProjectSection\r\n" );
1041 }
1042
1043 fprintf ( OUT, "EndProject\r\n" );
1044 }
1045
1046
1047 void
1048 MSVCBackend::_generate_sln_footer ( FILE* OUT )
1049 {
1050 fprintf ( OUT, "Global\r\n" );
1051 fprintf ( OUT, "\tGlobalSection(SolutionConfiguration) = preSolution\r\n" );
1052 for ( size_t i = 0; i < m_configurations.size(); i++ )
1053 fprintf ( OUT, "\t\t%s = %s\r\n", m_configurations[i]->name.c_str(), m_configurations[i]->name.c_str() );
1054 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1055 fprintf ( OUT, "\tGlobalSection(ProjectConfiguration) = postSolution\r\n" );
1056 for ( size_t i = 0; i < ProjectNode.modules.size(); i++ )
1057 {
1058 Module& module = *ProjectNode.modules[i];
1059 std::string guid = module.guid;
1060 _generate_sln_configurations ( OUT, guid.c_str() );
1061 }
1062 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1063 fprintf ( OUT, "\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n" );
1064 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1065 fprintf ( OUT, "\tGlobalSection(ExtensibilityAddIns) = postSolution\r\n" );
1066 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1067
1068 if (configuration.VSProjectVersion == "7.00") {
1069 fprintf ( OUT, "\tGlobalSection(ProjectDependencies) = postSolution\r\n" );
1070 //FIXME: Add dependencies for VS 2002
1071 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1072 }
1073
1074 if (configuration.VSProjectVersion == "8.00") {
1075 fprintf ( OUT, "\tGlobalSection(SolutionProperties) = preSolution\r\n" );
1076 fprintf ( OUT, "\t\tHideSolutionNode = FALSE\r\n" );
1077 fprintf ( OUT, "\tEndGlobalSection\r\n" );
1078 }
1079
1080 fprintf ( OUT, "EndGlobal\r\n" );
1081 fprintf ( OUT, "\r\n" );
1082 }
1083
1084
1085 void
1086 MSVCBackend::_generate_sln_configurations ( FILE* OUT, std::string vcproj_guid )
1087 {
1088 for ( size_t i = 0; i < m_configurations.size (); i++)
1089 {
1090 const MSVCConfiguration& cfg = *m_configurations[i];
1091 fprintf ( OUT, "\t\t%s.%s|Win32.ActiveCfg = %s|Win32\r\n", vcproj_guid.c_str(), cfg.name.c_str(), cfg.name.c_str() );
1092 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() );
1093 }
1094 }
1095
1096 void
1097 MSVCBackend::_generate_sln ( FILE* OUT )
1098 {
1099 string sln_guid = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}";
1100 vector<string> guids;
1101
1102 _generate_sln_header(OUT);
1103 // TODO FIXME - is it necessary to sort them?
1104 for ( size_t i = 0; i < ProjectNode.modules.size(); i++ )
1105 {
1106 Module& module = *ProjectNode.modules[i];
1107
1108 std::string vcproj_file = VcprojFileName ( module );
1109 _generate_sln_project ( OUT, module, vcproj_file, sln_guid, module.guid, module.non_if_data.libraries );
1110 }
1111 _generate_sln_footer ( OUT );
1112 }
1113
1114 const Property*
1115 MSVCBackend::_lookup_property ( const Module& module, const std::string& name ) const
1116 {
1117 /* Check local values */
1118 for ( size_t i = 0; i < module.non_if_data.properties.size(); i++ )
1119 {
1120 const Property& property = *module.non_if_data.properties[i];
1121 if ( property.name == name )
1122 return &property;
1123 }
1124 // TODO FIXME - should we check local if-ed properties?
1125 for ( size_t i = 0; i < module.project.non_if_data.properties.size(); i++ )
1126 {
1127 const Property& property = *module.project.non_if_data.properties[i];
1128 if ( property.name == name )
1129 return &property;
1130 }
1131 // TODO FIXME - should we check global if-ed properties?
1132 return NULL;
1133 }