[rbuild]
[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 * 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 struct SortFilesAscending
49 {
50 bool operator()(const string& rhs, const string& lhs)
51 {
52 return rhs < lhs;
53 }
54 };
55
56
57 VCProjMaker::VCProjMaker ( )
58 {
59 vcproj_file = "";
60 }
61
62 VCProjMaker::VCProjMaker ( Configuration& buildConfig,
63 const std::vector<MSVCConfiguration*>& msvc_configs,
64 std::string filename )
65 {
66 configuration = buildConfig;
67 m_configurations = msvc_configs;
68 vcproj_file = filename;
69
70 OUT = fopen ( vcproj_file.c_str(), "wb" );
71
72 if ( !OUT )
73 {
74 printf ( "Could not create file '%s'.\n", vcproj_file.c_str() );
75 }
76 }
77
78 VCProjMaker::~VCProjMaker()
79 {
80 fclose ( OUT );
81 }
82
83 std::string
84 VCProjMaker::_get_file_path( FileLocation* file, std::string relative_path)
85 {
86 if (file->directory == SourceDirectory)
87 {
88 // We want the full path here for directory support later on
89 return Path::RelativeFromDirectory (file->relative_path, relative_path );
90 }
91 else if(file->directory == IntermediateDirectory)
92 {
93 return std::string("$(RootIntDir)\\") + file->relative_path;
94 }
95 else if(file->directory == OutputDirectory)
96 {
97 return std::string("$(RootOutDir)\\") + file->relative_path;
98 }
99
100 return std::string("");
101 }
102
103
104
105 void
106 VCProjMaker::_generate_proj_file ( const Module& module )
107 {
108 size_t i;
109
110 // make sure the containers are empty
111 header_files.clear();
112 includes.clear();
113 libraries.clear();
114 common_defines.clear();
115
116 printf ( "Creating MSVC project: '%s'\n", vcproj_file.c_str() );
117
118 string path_basedir = module.GetPathToBaseDir ();
119
120 bool include_idl = false;
121
122 vector<string> source_files, resource_files, generated_files;
123
124 const IfableData& data = module.non_if_data;
125 const vector<File*>& files = data.files;
126 for ( i = 0; i < files.size(); i++ )
127 {
128 string path = _get_file_path(&files[i]->file, module.output->relative_path);
129 string file = path + std::string("\\") + files[i]->file.name;
130
131 if (files[i]->file.directory != SourceDirectory)
132 generated_files.push_back ( file );
133 else if ( !stricmp ( Right(file,3).c_str(), ".rc" ) )
134 resource_files.push_back ( file );
135 else if ( !stricmp ( Right(file,2).c_str(), ".h" ) )
136 header_files.push_back ( file );
137 else
138 source_files.push_back ( file );
139 }
140 const vector<Include*>& incs = data.includes;
141 for ( i = 0; i < incs.size(); i++ )
142 {
143 string path = _get_file_path(incs[i]->directory, module.output->relative_path);
144
145 if ( module.type != RpcServer && module.type != RpcClient )
146 {
147 if ( path.find ("/include/reactos/idl") != string::npos)
148 {
149 include_idl = true;
150 continue;
151 }
152 }
153 includes.push_back ( path );
154 }
155 const vector<Library*>& libs = data.libraries;
156 for ( i = 0; i < libs.size(); i++ )
157 {
158 string libpath = "$(RootOutDir)\\" + libs[i]->importedModule->output->relative_path + "\\" + _get_vc_dir() + "\\$(ConfigurationName)\\" + libs[i]->name + ".lib";
159 libraries.push_back ( libpath );
160 }
161 const vector<Define*>& defs = data.defines;
162 for ( i = 0; i < defs.size(); i++ )
163 {
164 if ( defs[i]->backend != "" && defs[i]->backend != "msvc" )
165 continue;
166
167 if ( defs[i]->value[0] )
168 common_defines.insert( defs[i]->name + "=" + defs[i]->value );
169 else
170 common_defines.insert( defs[i]->name );
171 }
172 for ( std::map<std::string, Property*>::const_iterator p = data.properties.begin(); p != data.properties.end(); ++ p )
173 {
174 Property& prop = *p->second;
175 if ( strstr ( module.baseaddress.c_str(), prop.name.c_str() ) )
176 baseaddr = prop.value;
177 }
178
179 if(module.importLibrary)
180 {
181 std::string ImportLibraryPath = _get_file_path(module.importLibrary->source, module.output->relative_path);
182
183 switch (module.IsSpecDefinitionFile())
184 {
185 case PSpec:
186 generated_files.push_back("$(IntDir)\\" + ReplaceExtension(module.importLibrary->source->name,".spec"));
187 case Spec:
188 generated_files.push_back("$(IntDir)\\" + ReplaceExtension(module.importLibrary->source->name,".stubs.c"));
189 generated_files.push_back("$(IntDir)\\" + ReplaceExtension(module.importLibrary->source->name,".def"));
190 default:
191 source_files.push_back(ImportLibraryPath + std::string("\\") + module.importLibrary->source->name);
192 }
193 }
194
195 fprintf ( OUT, "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\r\n" );
196 fprintf ( OUT, "<VisualStudioProject\r\n" );
197 fprintf ( OUT, "\tProjectType=\"Visual C++\"\r\n" );
198
199 if (configuration.VSProjectVersion.empty())
200 configuration.VSProjectVersion = MS_VS_DEF_VERSION;
201
202 fprintf ( OUT, "\tVersion=\"%s\"\r\n", configuration.VSProjectVersion.c_str() );
203 fprintf ( OUT, "\tName=\"%s\"\r\n", module.name.c_str() );
204 fprintf ( OUT, "\tProjectGUID=\"%s\"\r\n", module.guid.c_str() );
205 fprintf ( OUT, "\tKeyword=\"Win32Proj\">\r\n" );
206
207 fprintf ( OUT, "\t<Platforms>\r\n" );
208 fprintf ( OUT, "\t\t<Platform\r\n" );
209 fprintf ( OUT, "\t\t\tName=\"Win32\"/>\r\n" );
210 fprintf ( OUT, "\t</Platforms>\r\n" );
211
212 fprintf ( OUT, "\t<ToolFiles>\r\n" );
213 fprintf ( OUT, "\t\t<ToolFile\r\n" );
214 fprintf ( OUT, "\t\t\tRelativePath=\"%s%s\"\r\n", path_basedir.c_str(), "tools\\rbuild\\backend\\msvc\\s_as_mscpp.rules" );
215 fprintf ( OUT, "\t\t/>\r\n" );
216 fprintf ( OUT, "\t\t<ToolFile\r\n" );
217 fprintf ( OUT, "\t\t\tRelativePath=\"%s%s\"\r\n", path_basedir.c_str(), "tools\\rbuild\\backend\\msvc\\spec.rules" );
218 fprintf ( OUT, "\t\t/>\r\n" );
219 fprintf ( OUT, "\t</ToolFiles>\r\n" );
220
221 // Set the binary type
222 string module_type = GetExtension(*module.output);
223 BinaryType binaryType;
224 if ((module.type == ObjectLibrary) || (module.type == RpcClient) ||(module.type == RpcServer) || (module_type == ".lib") || (module_type == ".a"))
225 binaryType = Lib;
226 else if ((module_type == ".dll") || (module_type == ".cpl"))
227 binaryType = Dll;
228 else if ((module_type == ".exe") || (module_type == ".scr"))
229 binaryType = Exe;
230 else if (module_type == ".sys")
231 binaryType = Sys;
232 else
233 binaryType = BinUnknown;
234
235 // Write out all the configurations
236 fprintf ( OUT, "\t<Configurations>\r\n" );
237 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
238 {
239 const MSVCConfiguration& cfg = *m_configurations[icfg];
240
241 if ( cfg.optimization == RosBuild )
242 {
243 _generate_makefile_configuration( module, cfg );
244 }
245 else
246 {
247 _generate_standard_configuration( module, cfg, binaryType );
248 }
249 }
250 fprintf ( OUT, "\t</Configurations>\r\n" );
251
252 // Write out the project files
253 fprintf ( OUT, "\t<Files>\r\n" );
254
255 // Generated files
256 fprintf ( OUT, "\t\t<Filter\r\n" );
257 fprintf ( OUT, "\t\t\tName=\"Generated Files\">\r\n" );
258 for( i = 0; i < generated_files.size(); i++)
259 {
260 string source_file = DosSeparator(generated_files[i]);
261
262 fprintf ( OUT, "\t\t\t<File\r\n");
263 fprintf ( OUT, "\t\t\t\tRelativePath=\"%s\">\r\n", source_file.c_str() );
264 fprintf ( OUT, "\t\t\t</File>\r\n");
265 }
266 fprintf ( OUT, "\t\t</Filter>\r\n" );
267
268 // Source files
269 fprintf ( OUT, "\t\t<Filter\r\n" );
270 fprintf ( OUT, "\t\t\tName=\"Source Files\"\r\n" );
271 fprintf ( OUT, "\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;S\">\r\n" );
272
273 std::sort(source_files.begin(), source_files.end(), SortFilesAscending());
274 vector<string> last_folder;
275 vector<string> split_path;
276 string indent_tab("\t\t\t");
277
278 for ( size_t isrcfile = 0; isrcfile < source_files.size(); isrcfile++ )
279 {
280 string source_file = DosSeparator(source_files[isrcfile]);
281
282 Path::Split(split_path, source_file, false);
283 size_t same_folder_index = 0;
284 for ( size_t ifolder = 0; ifolder < last_folder.size(); ifolder++ )
285 {
286 if ( ifolder < split_path.size() && last_folder[ifolder] == split_path[ifolder] )
287 ++same_folder_index;
288 else
289 break;
290 }
291
292 if ( same_folder_index < split_path.size() || last_folder.size() > split_path.size() )
293 {
294 int tabStart = 1;
295 if ( split_path.size() > last_folder.size() )
296 {
297 for ( size_t ifolder = last_folder.size(); ifolder < split_path.size(); ifolder++ )
298 indent_tab.push_back('\t');
299 tabStart = split_path.size() - last_folder.size() + 1;
300 }
301 else if ( split_path.size() < last_folder.size() )
302 {
303 indent_tab.resize( split_path.size() + 3 );
304 tabStart = split_path.size() - last_folder.size() + 1;
305 }
306
307 for ( size_t ifolder = last_folder.size(), itab = tabStart; ifolder > same_folder_index; ifolder--, itab++ )
308 {
309 fprintf ( OUT, "%s</Filter>\r\n", indent_tab.substr(0, indent_tab.size() - itab).c_str() );
310 }
311
312 for ( size_t ifolder = same_folder_index, itab = split_path.size() - same_folder_index; ifolder < split_path.size(); ifolder++, itab-- )
313 {
314 const string tab = indent_tab.substr(0, indent_tab.size() - itab);
315 fprintf ( OUT, "%s<Filter\r\n", tab.c_str() );
316 fprintf ( OUT, "%s\tName=\"%s\">\r\n", tab.c_str(), split_path[ifolder].c_str() );
317 }
318
319 last_folder = split_path;
320 }
321
322 fprintf ( OUT, "%s<File\r\n", indent_tab.c_str() );
323 fprintf ( OUT, "%s\tRelativePath=\"%s\">\r\n", indent_tab.c_str(), source_file.c_str() );
324
325 for ( size_t iconfig = 0; iconfig < m_configurations.size(); iconfig++ )
326 {
327 const MSVCConfiguration& config = *m_configurations[iconfig];
328
329 //if (configuration.VSProjectVersion < "8.00") {
330 if ((source_file.find(".idl") != string::npos) || ((source_file.find(".asm") != string::npos)))
331 {
332 fprintf ( OUT, "%s\t<FileConfiguration\r\n", indent_tab.c_str() );
333 fprintf ( OUT, "%s\t\tName=\"%s|Win32\"\r\n", indent_tab.c_str(),config.name.c_str() );
334 fprintf ( OUT, "%s\t\tExcludedFromBuild=\"true\"\r\n",indent_tab.c_str());
335 fprintf ( OUT, ">\r\n" );
336 #if 0
337 fprintf ( OUT, "%s\t\t<Tool\r\n", indent_tab.c_str() );
338 if (source_file.find(".idl") != string::npos)
339 {
340 string src = source_file.substr (0, source_file.find(".idl"));
341
342 if ( src.find (".\\") != string::npos )
343 src.erase (0, 2);
344
345 fprintf ( OUT, "%s\t\t\tName=\"VCCustomBuildTool\"\r\n", indent_tab.c_str() );
346
347 if ( module.type == RpcClient )
348 {
349 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 () );
350 fprintf ( OUT, "&#x0D;&#x0A;");
351 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 () );
352 }
353 else
354 {
355 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 () );
356 fprintf ( OUT, "&#x0D;&#x0A;");
357 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 () );
358
359 }
360 fprintf ( OUT, "&#x0D;&#x0A;");
361 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 () );
362 fprintf ( OUT, "%s\t\t\tOutputs=\"$(IntDir)\\$(InputName).obj\"/>\r\n", indent_tab.c_str() );
363 }
364 else if ((source_file.find(".asm") != string::npos))
365 {
366 fprintf ( OUT, "%s\t\t\tName=\"VCCustomBuildTool\"\r\n", indent_tab.c_str() );
367 fprintf ( OUT, "%s\t\t\tCommandLine=\"nasmw $(InputPath) -f coff -o &quot;$(OutDir)\\$(InputName).obj&quot;\"\r\n", indent_tab.c_str() );
368 fprintf ( OUT, "%s\t\t\tOutputs=\"$(OutDir)\\$(InputName).obj\"/>\r\n", indent_tab.c_str() );
369 }
370 #endif
371 fprintf ( OUT, "%s\t</FileConfiguration>\r\n", indent_tab.c_str() );
372 }
373 //}
374 }
375 fprintf ( OUT, "%s</File>\r\n", indent_tab.c_str() );
376 }
377
378 for ( size_t ifolder = last_folder.size(); ifolder > 0; ifolder-- )
379 {
380 indent_tab.resize( ifolder + 2 );
381 fprintf ( OUT, "%s</Filter>\r\n", indent_tab.c_str() );
382 }
383
384 fprintf ( OUT, "\t\t</Filter>\r\n" );
385
386 // Header files
387 fprintf ( OUT, "\t\t<Filter\r\n" );
388 fprintf ( OUT, "\t\t\tName=\"Header Files\"\r\n" );
389 fprintf ( OUT, "\t\t\tFilter=\"h;hpp;hxx;hm;inl\">\r\n" );
390 for ( i = 0; i < header_files.size(); i++ )
391 {
392 const string& header_file = header_files[i];
393 fprintf ( OUT, "\t\t\t<File\r\n" );
394 fprintf ( OUT, "\t\t\t\tRelativePath=\"%s\">\r\n", header_file.c_str() );
395 fprintf ( OUT, "\t\t\t</File>\r\n" );
396 }
397 fprintf ( OUT, "\t\t</Filter>\r\n" );
398
399 // Resource files
400 fprintf ( OUT, "\t\t<Filter\r\n" );
401 fprintf ( OUT, "\t\t\tName=\"Resource Files\"\r\n" );
402 fprintf ( OUT, "\t\t\tFilter=\"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\">\r\n" );
403 for ( i = 0; i < resource_files.size(); i++ )
404 {
405 const string& resource_file = resource_files[i];
406 fprintf ( OUT, "\t\t\t<File\r\n" );
407 fprintf ( OUT, "\t\t\t\tRelativePath=\"%s\">\r\n", resource_file.c_str() );
408 fprintf ( OUT, "\t\t\t</File>\r\n" );
409 }
410 fprintf ( OUT, "\t\t</Filter>\r\n" );
411
412 fprintf ( OUT, "\t</Files>\r\n" );
413 fprintf ( OUT, "\t<Globals>\r\n" );
414 fprintf ( OUT, "\t</Globals>\r\n" );
415 fprintf ( OUT, "</VisualStudioProject>\r\n" );
416 }
417
418 void VCProjMaker::_generate_user_configuration ()
419 {
420 // Call base implementation
421 ProjMaker::_generate_user_configuration ();
422 }
423
424 void VCProjMaker::_generate_standard_configuration( const Module& module,
425 const MSVCConfiguration& cfg,
426 BinaryType binaryType )
427 {
428 string path_basedir = module.GetPathToBaseDir ();
429 string vcdir;
430
431 bool include_idl = false;
432
433 size_t i;
434 string intermediatedir = "";
435 string importLib;
436
437 if ( configuration.UseVSVersionInPath )
438 {
439 vcdir = DEF_SSEP + _get_vc_dir();
440 }
441
442 if(module.IsSpecDefinitionFile())
443 {
444 importLib = "$(IntDir)\\$(ProjectName).def";
445 }
446 else if (module.importLibrary != NULL)
447 {
448 intermediatedir = module.output->relative_path + vcdir;
449 importLib = _strip_gcc_deffile(module.importLibrary->source->name, module.importLibrary->source->relative_path, intermediatedir);
450 importLib = Path::RelativeFromDirectory (
451 importLib,
452 module.output->relative_path );
453 }
454
455 string module_type = GetExtension(*module.output);
456
457 // Set the configuration type for this config
458 ConfigurationType CfgType;
459 if ( binaryType == Exe )
460 CfgType = ConfigApp;
461 else if ( binaryType == Lib )
462 CfgType = ConfigLib;
463 else if ( binaryType == Dll || binaryType == Sys )
464 CfgType = ConfigDll;
465 else
466 CfgType = ConfigUnknown;
467
468 fprintf ( OUT, "\t\t<Configuration\r\n" );
469 fprintf ( OUT, "\t\t\tName=\"%s|Win32\"\r\n", cfg.name.c_str() );
470
471 if ( configuration.UseConfigurationInPath )
472 {
473 fprintf ( OUT, "\t\t\tOutputDirectory=\"$(RootOutDir)\\%s%s\\$(ConfigurationName)\"\r\n", module.output->relative_path.c_str (), vcdir.c_str () );
474 fprintf ( OUT, "\t\t\tIntermediateDirectory=\"$(RootIntDir)\\%s%s\\$(ConfigurationName)\"\r\n", module.output->relative_path.c_str (), vcdir.c_str () );
475 }
476 else
477 {
478 fprintf ( OUT, "\t\t\tOutputDirectory=\"$(RootOutDir)\\%s%s\"\r\n", module.output->relative_path.c_str (), vcdir.c_str () );
479 fprintf ( OUT, "\t\t\tIntermediateDirectory=\"$(RootIntDir)\\%s%s\"\r\n", module.output->relative_path.c_str (), vcdir.c_str () );
480 }
481
482 fprintf ( OUT, "\t\t\tConfigurationType=\"%d\"\r\n", CfgType );
483
484 fprintf ( OUT, "\t\t\tInheritedPropertySheets=\"%s%s.vsprops\"\r\n", path_basedir.c_str (), cfg.name.c_str ());
485 fprintf ( OUT, "\t\t\tCharacterSet=\"2\"\r\n" );
486 fprintf ( OUT, "\t\t\t>\r\n" );
487
488 fprintf ( OUT, "\t\t\t<Tool\r\n" );
489 fprintf ( OUT, "\t\t\t\tName=\"s_as_mscpp\"\r\n" );
490 fprintf ( OUT, "\t\t\t\tsIncPaths=\"" );
491 fprintf ( OUT, "./;" );
492 for ( i = 0; i < includes.size(); i++ )
493 {
494 const std::string& include = includes[i];
495 if ( strcmp ( include.c_str(), "." ) )
496 {
497 fprintf ( OUT, "%s", include.c_str() );
498 fprintf ( OUT, ";" );
499 }
500 }
501 fprintf ( OUT, "$(globalIncludes);\"\r\n");
502 fprintf ( OUT, "\t\t\t\tsPPDefs=\"__ASM__\"\r\n" );
503 fprintf ( OUT, "\t\t\t/>\r\n" );
504
505 fprintf ( OUT, "\t\t\t<Tool\r\n" );
506 fprintf ( OUT, "\t\t\t\tName=\"Pspec\"\r\n" );
507 fprintf ( OUT, "\t\t\t\tincludes=\"" );
508 fprintf ( OUT, "./;" );
509 for ( i = 0; i < includes.size(); i++ )
510 {
511 const std::string& include = includes[i];
512 if ( strcmp ( include.c_str(), "." ) )
513 {
514 fprintf ( OUT, "%s", include.c_str() );
515 fprintf ( OUT, ";" );
516 }
517 }
518 fprintf ( OUT, "$(globalIncludes);\"\r\n");
519 fprintf ( OUT, "\t\t\t\tsPPDefs=\"__ASM__\"\r\n" );
520 fprintf ( OUT, "\t\t\t/>\r\n" );
521
522
523 fprintf ( OUT, "\t\t\t<Tool\r\n" );
524 fprintf ( OUT, "\t\t\t\tName=\"VCCLCompilerTool\"\r\n" );
525
526 fprintf ( OUT, "\t\t\t\tAdditionalIncludeDirectories=\"" );
527 bool multiple_includes = false;
528 fprintf ( OUT, "./;" );
529 for ( i = 0; i < includes.size(); i++ )
530 {
531 const std::string& include = includes[i];
532 if ( strcmp ( include.c_str(), "." ) )
533 {
534 if ( multiple_includes )
535 fprintf ( OUT, ";" );
536 fprintf ( OUT, "%s", include.c_str() );
537 multiple_includes = true;
538 }
539 }
540 if ( include_idl )
541 {
542 if ( multiple_includes )
543 fprintf ( OUT, ";" );
544
545 if ( configuration.UseConfigurationInPath )
546 {
547 fprintf ( OUT, "$(int)\\include\\reactos\\idl%s\\$(ConfigurationName)\r\n", vcdir.c_str ());
548 }
549 else
550 {
551 fprintf ( OUT, "$(int)\\include\\reactos\\idl\r\n" );
552 }
553 }
554
555 fprintf ( OUT, "\"\r\n" );
556
557 StringSet defines = common_defines;
558
559 if ( binaryType == Lib || binaryType == Exe )
560 {
561 defines.insert ( "_LIB" );
562 }
563 else
564 {
565 defines.insert ( "_WINDOWS" );
566 defines.insert ( "_USRDLL" );
567 }
568
569 fprintf ( OUT, "\t\t\t\tPreprocessorDefinitions=\"" );
570 for ( StringSet::iterator it1=defines.begin(); it1!=defines.end(); it1++ )
571 {
572 string unescaped = *it1;
573 fprintf ( OUT, "%s ; ", _replace_str(unescaped, "\"","").c_str() );
574 }
575 fprintf ( OUT, "\"\r\n" );
576
577 //disable precompiled headers for now
578 #if 0
579 if ( module.pch != NULL )
580 {
581 fprintf ( OUT, "\t\t\t\tUsePrecompiledHeader=\"2\"\r\n" );
582 string pch_path = Path::RelativeFromDirectory (
583 module.pch->file->name,
584 module.output->relative_path );
585 string::size_type pos = pch_path.find_last_of ("/");
586 if ( pos != string::npos )
587 pch_path.erase(0, pos+1);
588 fprintf ( OUT, "\t\t\t\tPrecompiledHeaderThrough=\"%s\"\r\n", pch_path.c_str() );
589
590 // Only include from the same module
591 pos = pch_path.find("../");
592 if (pos == string::npos && std::find(header_files.begin(), header_files.end(), pch_path) == header_files.end())
593 header_files.push_back(pch_path);
594 }
595 #endif
596
597 if ( module.cplusplus )
598 fprintf ( OUT, "\t\t\t\tCompileAs=\"2\"\r\n" );
599
600 fprintf ( OUT, "\t\t\t/>\r\n");
601
602 fprintf ( OUT, "\t\t\t<Tool\r\n" );
603 fprintf ( OUT, "\t\t\t\tName=\"VCCustomBuildTool\"/>\r\n" );
604
605 if ( binaryType != Lib )
606 {
607 fprintf ( OUT, "\t\t\t<Tool\r\n" );
608 fprintf ( OUT, "\t\t\t\tName=\"VCLinkerTool\"\r\n" );
609 if (module.GetEntryPoint() == "0" && binaryType != Sys )
610 fprintf ( OUT, "AdditionalOptions=\"/noentry\"" );
611
612 if (configuration.VSProjectVersion == "9.00")
613 {
614 fprintf ( OUT, "\t\t\t\tRandomizedBaseAddress=\"0\"\r\n" );
615 fprintf ( OUT, "\t\t\t\tDataExecutionPrevention=\"0\"\r\n" );
616 }
617
618 if (module.importLibrary != NULL)
619 fprintf ( OUT, "\t\t\t\tModuleDefinitionFile=\"%s\"\r\n", importLib.c_str());
620
621 fprintf ( OUT, "\t\t\t\tAdditionalDependencies=\"" );
622 bool use_msvcrt_lib = false;
623 for ( i = 0; i < libraries.size(); i++ )
624 {
625 if ( i > 0 )
626 fprintf ( OUT, " " );
627 string libpath = libraries[i].c_str();
628 libpath = libpath.erase (0, libpath.find_last_of ("\\") + 1 );
629 if ( libpath == "msvcrt.lib" )
630 {
631 use_msvcrt_lib = true;
632 }
633 fprintf ( OUT, "%s", libpath.c_str() );
634 }
635 fprintf ( OUT, "\"\r\n" );
636
637 fprintf ( OUT, "\t\t\t\tAdditionalLibraryDirectories=\"" );
638
639 // Add conventional libraries dirs
640 for (i = 0; i < libraries.size (); i++)
641 {
642 if ( i > 0 )
643 fprintf ( OUT, ";" );
644
645 string libpath = libraries[i].c_str();
646 libpath = libpath.substr (0, libpath.find_last_of ("\\") );
647 fprintf ( OUT, "%s", libpath.c_str() );
648 }
649
650 fprintf ( OUT, "\"\r\n" );
651
652 fprintf ( OUT, "\t\t\t\tOutputFile=\"$(OutDir)/%s%s\"\r\n", module.name.c_str(), module_type.c_str() );
653 if ( binaryType == Sys )
654 {
655 if (module.GetEntryPoint() == "0")
656 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /noentry /ALIGN:0x20 /SECTION:INIT,D /IGNORE:4001,4037,4039,4065,4070,4078,4087,4089,4096\"\r\n" );
657 else
658 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /ALIGN:0x20 /SECTION:INIT,D /IGNORE:4001,4037,4039,4065,4070,4078,4087,4089,4096\"\r\n" );
659 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
660 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
661 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 3 );
662 fprintf ( OUT, "\t\t\t\tDriver=\"%d\"\r\n", 1 );
663 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"%s\"\r\n", module.GetEntryPoint() == "" ? "DriverEntry" : module.GetEntryPoint().c_str ());
664 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr == "" ? "0x10000" : baseaddr.c_str ());
665 }
666 else if ( binaryType == Exe )
667 {
668 if ( module.type == Kernel )
669 {
670 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /SECTION:INIT,D /ALIGN:0x80\"\r\n" );
671 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
672 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
673 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 3 );
674 fprintf ( OUT, "\t\t\t\tDriver=\"%d\"\r\n", 1 );
675 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"KiSystemStartup\"\r\n" );
676 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr.c_str ());
677 }
678 else if ( module.type == NativeCUI )
679 {
680 fprintf ( OUT, "\t\t\t\tAdditionalOptions=\" /ALIGN:0x20\"\r\n" );
681 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 1 );
682 fprintf ( OUT, "\t\t\t\tGenerateManifest=\"FALSE\"\r\n" );
683 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
684 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"NtProcessStartup\"\r\n" );
685 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr.c_str ());
686 }
687 else if ( module.type == Win32CUI || module.type == Win32GUI || module.type == Win32SCR)
688 {
689 if ( use_msvcrt_lib )
690 {
691 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
692 }
693 fprintf ( OUT, "\t\t\t\tSubSystem=\"%d\"\r\n", 2 );
694 }
695 }
696 else if ( binaryType == Dll )
697 {
698 if (module.GetEntryPoint() == "0")
699 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"\"\r\n" );
700 else
701 {
702 // get rid of DllMain@12 because MSVC needs to link to _DllMainCRTStartup@12
703 // when using CRT
704 if (module.GetEntryPoint() == "DllMain@12")
705 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"\"\r\n" );
706 else
707 fprintf ( OUT, "\t\t\t\tEntryPointSymbol=\"%s\"\r\n", module.GetEntryPoint().c_str ());
708 }
709 fprintf ( OUT, "\t\t\t\tBaseAddress=\"%s\"\r\n", baseaddr == "" ? "0x40000" : baseaddr.c_str ());
710 if ( use_msvcrt_lib )
711 {
712 fprintf ( OUT, "\t\t\t\tIgnoreAllDefaultLibraries=\"TRUE\"\r\n" );
713 }
714 }
715 fprintf ( OUT, "\t\t\t/>\r\n" );
716 }
717
718 fprintf ( OUT, "\t\t\t<Tool\r\n" );
719 fprintf ( OUT, "\t\t\t\tName=\"VCResourceCompilerTool\"\r\n" );
720 fprintf ( OUT, "\t\t\t\tAdditionalIncludeDirectories=\"" );
721 multiple_includes = false;
722 fprintf ( OUT, "./;" );
723 for ( i = 0; i < includes.size(); i++ )
724 {
725 const std::string& include = includes[i];
726 if ( strcmp ( include.c_str(), "." ) )
727 {
728 if ( multiple_includes )
729 fprintf ( OUT, ";" );
730 fprintf ( OUT, "%s", include.c_str() );
731 multiple_includes = true;
732 }
733 }
734
735 fprintf ( OUT, "\"/>\r\n " );
736
737 fprintf ( OUT, "\t\t\t<Tool\r\n" );
738 fprintf ( OUT, "\t\t\t\tName=\"VCMIDLTool\"/>\r\n" );
739 if (configuration.VSProjectVersion == "8.00")
740 {
741 fprintf ( OUT, "\t\t\t<Tool\r\n" );
742 fprintf ( OUT, "\t\t\t\tName=\"VCManifestTool\"\r\n" );
743 fprintf ( OUT, "\t\t\t\tEmbedManifest=\"false\"/>\r\n" );
744 }
745 fprintf ( OUT, "\t\t</Configuration>\r\n" );
746 }
747
748
749 void
750 VCProjMaker::_generate_makefile_configuration( const Module& module, const MSVCConfiguration& cfg )
751 {
752 string path_basedir = module.GetPathToBaseDir ();
753 string intenv = Environment::GetIntermediatePath ();
754 string outenv = Environment::GetOutputPath ();
755
756 string outdir;
757 string intdir;
758
759 if ( intenv == "obj-i386" )
760 intdir = path_basedir + "obj-i386"; /* append relative dir from project dir */
761 else
762 intdir = intenv;
763
764 if ( outenv == "output-i386" )
765 outdir = path_basedir + "output-i386";
766 else
767 outdir = outenv;
768
769 fprintf ( OUT, "\t\t<Configuration\r\n" );
770 fprintf ( OUT, "\t\t\tName=\"%s|Win32\"\r\n", cfg.name.c_str() );
771
772 if ( configuration.UseConfigurationInPath )
773 {
774 fprintf ( OUT, "\t\t\tOutputDirectory=\"%s\\%s\\%s\"\r\n", outdir.c_str (), module.output->relative_path.c_str (), cfg.name.c_str() );
775 fprintf ( OUT, "\t\t\tIntermediateDirectory=\"%s\\%s\\%s\"\r\n", intdir.c_str (), module.output->relative_path.c_str (), cfg.name.c_str() );
776 }
777 else
778 {
779 fprintf ( OUT, "\t\t\tOutputDirectory=\"%s\\%s\"\r\n", outdir.c_str (), module.output->relative_path.c_str () );
780 fprintf ( OUT, "\t\t\tIntermediateDirectory=\"%s\\%s\"\r\n", intdir.c_str (), module.output->relative_path.c_str () );
781 }
782
783 fprintf ( OUT, "\t\t\tConfigurationType=\"0\"\r\n");
784 fprintf ( OUT, "\t\t\t>\r\n" );
785
786 fprintf ( OUT, "\t\t\t<Tool\r\n" );
787
788 fprintf ( OUT, "\t\t\t\tName=\"VCNMakeTool\"\r\n" );
789 fprintf ( OUT, "\t\t\t\tBuildCommandLine=\"%srosbuild.bat build %s\"\r\n", path_basedir.c_str (), module.name.c_str ());
790 fprintf ( OUT, "\t\t\t\tReBuildCommandLine=\"%srosbuild.bat rebuild %s\"\r\n", path_basedir.c_str (), module.name.c_str ());
791 fprintf ( OUT, "\t\t\t\tCleanCommandLine=\"%srosbuild.bat clean %s\"\r\n", path_basedir.c_str (), module.name.c_str ());
792 fprintf ( OUT, "\t\t\t\tOutput=\"\"\r\n");
793 fprintf ( OUT, "\t\t\t\tPreprocessorDefinitions=\"\"\r\n");
794 fprintf ( OUT, "\t\t\t\tIncludeSearchPath=\"\"\r\n");
795 fprintf ( OUT, "\t\t\t\tForcedIncludes=\"\"\r\n");
796 fprintf ( OUT, "\t\t\t\tAssemblySearchPath=\"\"\r\n");
797 fprintf ( OUT, "\t\t\t\tForcedUsingAssemblies=\"\"\r\n");
798 fprintf ( OUT, "\t\t\t\tCompileAsManaged=\"\"\r\n");
799
800 fprintf ( OUT, "\t\t\t/>\r\n" );
801 fprintf ( OUT, "\t\t</Configuration>\r\n" );
802 }