sdk/Build System: Added support for cross-compiling the tarball
[sdk] / ide / src / project / vsSupport.ec
1 #ifdef __WIN32__
2 import "Project"
3
4 static char indendation[MAX_F_STRING];
5
6 #define VCPROJ_INDENTATION
7 #define VCPROJ_TAGS_ON_NEW_LINES
8 #define VCPROJ_ATTRIBS_ON_NEW_LINES
9
10 #define VCPROJ_NEW_LINE "\n"
11 //#define VCPROJ_NEW_LINE "\r\n"
12
13 #ifdef VCPROJ_INDENTATION
14 define tagIndent = (char *)indendation;
15 #else
16 define tagIndent = "";
17 #endif
18
19 #ifdef VCPROJ_TAGS_ON_NEW_LINES
20 define tagLine = VCPROJ_NEW_LINE;
21 #else
22 define tagLine = "";
23 #endif
24
25 #ifdef VCPROJ_ATTRIBS_ON_NEW_LINES
26 define attribSep = VCPROJ_NEW_LINE;
27 #ifdef VCPROJ_INDENTATION
28 define attribIndent = (char *)indendation;
29 #else
30 define attribIndent = "";
31 #endif
32 #else
33 define attribSep = " ";
34 define attribIndent = "";
35 #endif
36
37 static void IndentClear()
38 {
39    indendation[0] = '\0';
40 }
41 static void IndentPush()
42 {
43 #ifdef VCPROJ_INDENTATION
44    int len = strlen(indendation);
45    indendation[len] = '\t';
46    indendation[len+1] = '\0';
47 #endif
48 }
49 static void IndentPop()
50 {
51 #ifdef VCPROJ_INDENTATION
52    int len = strlen(indendation);
53    if(len)
54       indendation[len-1] = '\0';
55 #endif
56 }
57
58 void GenerateVSSolutionFile(Project project, CompilerConfig compiler)
59 {
60    char filePath[MAX_LOCATION];
61    char slnFileName[MAX_LOCATION];
62    char * projectName = project.name;
63    File f;
64
65    IndentClear();
66
67    strcpy(filePath, project.topNode.path);
68    //PathCat(filePath, "..\\");
69    sprintf(slnFileName, "%s.sln", projectName);
70    PathCatSlash(filePath, slnFileName);
71
72    f = FileOpen(filePath, write);
73    if(f)
74    {
75       char * slnGUID = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942";
76       char * prjGUID = "3A1E5467-4EE2-4299-8F0C-7D26CC8C24BA";
77       //char * relPathToVCProjFile = "win32ProjectConsoleApp\\win32ProjectConsoleApp";
78
79       f.Print(""); f.Printf("\r\n");
80       f.Print("Microsoft Visual Studio Solution File, Format Version ", compiler.type.solutionFileVersionString); f.Printf("\r\n");
81       f.Print("# Visual Studio ", compiler.type.yearString); f.Printf("\r\n");
82       f.Print("Project(\"{", slnGUID, "}\") = \"", projectName, "\", \"", projectName, ".", 
83             compiler.type.projectFileExtension, "\", \"{", prjGUID, "}\"", attribSep); f.Printf("\r\n");
84       f.Print("EndProject"); f.Printf("\r\n");
85       f.Print("Global"); f.Printf("\r\n");
86       f.Print("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); f.Printf("\r\n");
87       for(config : project.configurations)
88       {
89          f.Print("\t\t", config.name, "|Win32 = ", config.name, "|Win32"); f.Printf("\r\n");
90       }
91       f.Print("\tEndGlobalSection"); f.Printf("\r\n");
92       f.Print("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); f.Printf("\r\n");
93       for(config : project.configurations)
94       {
95          f.Print("\t\t{", prjGUID, "}.", config.name, "|Win32.ActiveCfg = ", config.name, "|Win32"); f.Printf("\r\n");
96          f.Print("\t\t{", prjGUID, "}.", config.name, "|Win32.Build.0 = ", config.name, "|Win32"); f.Printf("\r\n");
97       }
98       f.Print("\tEndGlobalSection"); f.Printf("\r\n");
99       f.Print("\tGlobalSection(SolutionProperties) = preSolution"); f.Printf("\r\n");
100       f.Print("\t\tHideSolutionNode = FALSE"); f.Printf("\r\n");
101       f.Print("\tEndGlobalSection"); f.Printf("\r\n");
102       f.Print("EndGlobal"); f.Printf("\r\n");
103    
104       delete f;
105    }
106 }
107
108 void GenerateVCProjectFile(Project project, CompilerConfig compiler)
109 {
110    char filePath[MAX_LOCATION];
111    char slnFileName[MAX_LOCATION];
112    char * projectName = project.name;
113    bool usePrecompiledHeaders = false;
114    File f;
115
116    IndentClear();
117
118    strcpy(filePath, project.topNode.path);
119    sprintf(slnFileName, "%s.%s", projectName, compiler.type.projectFileExtension);
120    PathCatSlash(filePath, slnFileName);
121
122    f = FileOpen(filePath, write);
123    if(f)
124    {
125       char * targetFrameworkVersion = "196613";
126       char * prjGUID = "3A1E5467-4EE2-4299-8F0C-7D26CC8C24BA";
127       char * rootNamespace = projectName;
128       Map<String, NameCollisionInfo> namesInfo { };
129       // TOFIX: Collision and Config-specific!
130       project.topNode.GenMakefileGetNameCollisionInfo(namesInfo, project.config);
131
132       f.Print(tagIndent, "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>", tagLine);
133       f.Print(tagIndent, "<VisualStudioProject", attribSep);
134          IndentPush();
135          f.Print(attribIndent, "ProjectType=\"Visual C++\"", attribSep);
136          f.Print(attribIndent, "Version=\"", compiler.type.versionString, "\"", attribSep);
137          f.Print(attribIndent, "Name=\"", projectName, "\"", attribSep);
138          f.Print(attribIndent, "ProjectGUID=\"{", prjGUID, "}\"", attribSep);
139          f.Print(attribIndent, "RootNamespace=\"", rootNamespace, "\"", attribSep);
140          f.Print(attribIndent, "Keyword=\"Win32Proj\"", attribSep);
141       if(compiler.type == vs9)
142          f.Print(attribIndent, "TargetFrameworkVersion=\"", targetFrameworkVersion, "\"", attribSep);
143          f.Print(attribIndent, ">", tagLine);
144
145          f.Print(tagIndent, "<Platforms>", tagLine);
146             IndentPush();
147             f.Print(tagIndent, "<Platform", attribSep);
148                IndentPush();
149                f.Print(attribIndent, "Name=\"Win32\"", attribSep);
150             IndentPop();
151             f.Print(attribIndent, "/>", tagLine);
152          IndentPop();
153          f.Print(tagIndent, "</Platforms>", tagLine);
154          
155          f.Print(tagIndent, "<ToolFiles>", tagLine);
156          f.Print(tagIndent, "</ToolFiles>", tagLine);
157
158          f.Print(tagIndent, "<Configurations>", tagLine);
159             IndentPush();
160
161          for(config : project.configurations)
162             PrintConfiguration(f, project, compiler, config, usePrecompiledHeaders);
163
164          IndentPop();
165          f.Print(tagIndent, "</Configurations>", tagLine);
166
167          f.Print(tagIndent, "<References>", tagLine);
168          f.Print(tagIndent, "</References>", tagLine);
169
170          f.Print(tagIndent, "<Files>", tagLine);
171             IndentPush();
172             f.Print(tagIndent, "<Filter", attribSep);
173                IndentPush();
174                f.Print(attribIndent, "Name=\"Source Files\"", attribSep);
175                f.Print(attribIndent, "Filter=\"cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx\"", attribSep);
176                f.Print(attribIndent, "UniqueIdentifier=\"{4FC737F1-C7A5-4376-A066-2A32D752A2FF}\"", attribSep);
177                f.Print(attribIndent, ">", tagLine);
178             
179                PrintNodes(f, project, project.topNode, namesInfo, source, false, usePrecompiledHeaders);
180             IndentPop();
181             f.Print(tagIndent, "</Filter>", tagLine);
182
183             f.Print(tagIndent, "<Filter", attribSep);
184                IndentPush();
185                f.Print(attribIndent, "Name=\"Header Files\"", attribSep);
186                f.Print(attribIndent, "Filter=\"h;hpp;hxx;hm;inl;inc;xsd\"", attribSep);
187                f.Print(attribIndent, "UniqueIdentifier=\"{93995380-89BD-4b04-88EB-625FBE52EBFB}\"", attribSep);
188                f.Print(attribIndent, ">", tagLine);
189             
190                PrintNodes(f, project, project.topNode, namesInfo, header, false, usePrecompiledHeaders);
191             IndentPop();
192             f.Print(tagIndent, "</Filter>", tagLine);
193
194             f.Print(tagIndent, "<Filter", attribSep);
195                IndentPush();
196                f.Print(attribIndent, "Name=\"Resource Files\"", attribSep);
197                f.Print(attribIndent, "Filter=\"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav\"", attribSep);
198                f.Print(attribIndent, "UniqueIdentifier=\"{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}\"", attribSep);
199                f.Print(attribIndent, ">", tagLine);
200             
201                PrintNodes(f, project, project.resNode, namesInfo, resource, false, usePrecompiledHeaders);
202             IndentPop();
203             f.Print(tagIndent, "</Filter>", tagLine);
204             PrintNodes(f, project, project.topNode, namesInfo, other, false, usePrecompiledHeaders);
205          IndentPop();
206          f.Print(tagIndent, "</Files>", tagLine);
207
208          f.Print(tagIndent, "<Globals>", tagLine);
209          f.Print(tagIndent, "</Globals>", tagLine);
210       
211       IndentPop();
212       f.Print("</VisualStudioProject>", tagLine);
213    
214       namesInfo.Free();
215       delete namesInfo;
216       delete f;
217    }
218 }
219
220 void PrintConfiguration(File f, Project project, CompilerConfig compiler, ProjectConfig config, bool usePrecompiledHeaders)
221 {
222    ProjectOptions options = project.options;
223    SetBool consoleSet = localConsole;
224    SetBool debugSet = localDebug;
225    OptimizationStrategy optimizationSet = localOptimization;
226    String targetFileName = localTargetFileName;
227    bool console = consoleSet == true;
228    bool debug = debugSet == true;
229    bool optimize = optimizationSet == speed;
230    char * objDirExpr = localObjectsDirectory;
231    char * targetDirExpr = localTargetDirectory;
232    DirExpression objDir { type = intermediateObjectsDir };
233    DirExpression targetDir { type = DirExpressionType::targetDir };
234    TargetTypes targetType = project.GetTargetType(config);
235
236    if(!objDirExpr)
237       objDirExpr = settingsObjectsDirectory;
238    objDir.Evaluate(objDirExpr, project, compiler, config);
239    if(!targetDirExpr)
240       targetDirExpr = settingsTargetDirectory;
241    targetDir.Evaluate(targetDirExpr, project, compiler, config);
242
243    f.Print(tagIndent, "<Configuration", attribSep);
244       IndentPush();
245       f.Print(attribIndent, "Name=\"", config.name, "|Win32\"", attribSep);
246       f.Print(attribIndent, "OutputDirectory=\"$(SolutionDir)", targetDir.dir/*"$(ConfigurationName)"*/, "\"", attribSep);
247       f.Print(attribIndent, "IntermediateDirectory=\"", objDir.dir/*"$(ConfigurationName)"*/, "\"", attribSep);
248       f.Print(attribIndent, "ConfigurationType=\"", targetType == sharedLibrary ? 2 : targetType == staticLibrary ? 4 : 1, "\"", attribSep);
249       f.Print(attribIndent, "CharacterSet=\"", false/*unicode*/ ? 1 : true/*multibyte*/ ? 2 : 0, "\"", attribSep);
250    if(optimizationSet == speed)
251       f.Print(attribIndent, "WholeProgramOptimization=\"1\"", attribSep);
252       f.Print(attribIndent, ">", tagLine);
253
254       f.Print(tagIndent, "<Tool", attribSep);
255          IndentPush();
256          f.Print(attribIndent, "Name=\"VCPreBuildEventTool\"", attribSep);
257       IndentPop();
258       f.Print(attribIndent, "/>", tagLine);
259       f.Print(tagIndent, "<Tool", attribSep);
260          IndentPush();
261          f.Print(attribIndent, "Name=\"VCCustomBuildTool\"", attribSep);
262       IndentPop();
263       f.Print(attribIndent, "/>", tagLine);
264       f.Print(tagIndent, "<Tool", attribSep);
265          IndentPush();
266          f.Print(attribIndent, "Name=\"VCXMLDataGeneratorTool\"", attribSep);
267       IndentPop();
268       f.Print(attribIndent, "/>", tagLine);
269       f.Print(tagIndent, "<Tool", attribSep);
270          IndentPush();
271          f.Print(attribIndent, "Name=\"VCWebServiceProxyGeneratorTool\"", attribSep);
272       IndentPop();
273       f.Print(attribIndent, "/>", tagLine);
274       f.Print(tagIndent, "<Tool", attribSep);
275          IndentPush();
276          f.Print(attribIndent, "Name=\"VCMIDLTool\"", attribSep);
277       IndentPop();
278       f.Print(attribIndent, "/>", tagLine);
279       f.Print(tagIndent, "<Tool", attribSep);
280          IndentPush();
281          f.Print(attribIndent, "Name=\"VCCLCompilerTool\"", attribSep);
282    if(debug || (optimize && compiler.type == vs9))
283          f.Print(attribIndent, "Optimization=\"", debug ? 0 : 2, "\"", attribSep);
284    if(optimize && compiler.type == vs9)
285          f.Print(attribIndent, "EnableIntrinsicFunctions=\"true\"", attribSep);
286          {
287             Array<DirPath> additionalIncludeDirs { };
288             if(project.options && project.options.includeDirs)
289             {
290                for(dir : project.options.includeDirs)
291                   additionalIncludeDirs.Add(CopySystemPath(dir));
292             }
293             if(config && config.options && config.options.includeDirs)
294             {
295                for(dir : config.options.includeDirs)
296                   additionalIncludeDirs.Add(CopySystemPath(dir));
297             }
298             CollectPlatformSpecificDirs(project, config, null, additionalIncludeDirs, null, null);
299             if(additionalIncludeDirs.count)
300             {
301                f.Print(attribIndent, "AdditionalIncludeDirectories=\"");
302                for(dir : additionalIncludeDirs)
303                   f.Print(dir == additionalIncludeDirs.firstIterator.data ?  "" : ";", dir);
304                f.Print("\"", attribSep);
305                additionalIncludeDirs.Free();
306             }
307             delete additionalIncludeDirs;
308          }
309          f.Print(attribIndent, "PreprocessorDefinitions=\"WIN32");
310          f.Print(";_CRT_SECURE_NO_DEPRECATE");
311          if(console)
312             f.Print(";_CONSOLE");
313          if(targetType == sharedLibrary)
314             f.Print(";_WINDOWS;_USRDLL;WIN32DYNAMICLIB_EXPORTS");
315          else if(targetType == staticLibrary)
316             f.Print(";_LIB");
317          if(project.options && project.options.preprocessorDefinitions)
318          {
319             for(def : project.options.preprocessorDefinitions)
320                f.Print(";", def);
321          }
322          if(config && config.options && config.options.preprocessorDefinitions)
323          {
324             for(def : config.options.preprocessorDefinitions)
325                f.Print(";", def);
326          }
327          f.Print("\"", attribSep);
328    if(debug)
329    {
330          f.Print(attribIndent, "MinimalRebuild=\"true\"", attribSep);
331          f.Print(attribIndent, "BasicRuntimeChecks=\"3\"", attribSep);
332    }
333          f.Print(attribIndent, "RuntimeLibrary=\"", debug ? 3 : 2, "\"", attribSep);
334    if(optimize && compiler.type == vs9)
335          f.Print(attribIndent, "EnableFunctionLevelLinking=\"true\"", attribSep);
336          f.Print(attribIndent, "UsePrecompiledHeader=\"", usePrecompiledHeaders ? 2 : 0, "\"", attribSep);
337          f.Print(attribIndent, "WarningLevel=\"3\"", attribSep);
338    if(compiler.type == vs8)
339          f.Print(attribIndent, "Detect64BitPortabilityProblems=\"true\"", attribSep);
340          f.Print(attribIndent, "DebugInformationFormat=\"", debug ? 4 : 3, "\"", attribSep);
341       IndentPop();
342       f.Print(attribIndent, "/>", tagLine);
343       f.Print(tagIndent, "<Tool", attribSep);
344          IndentPush();
345          f.Print(attribIndent, "Name=\"VCManagedResourceCompilerTool\"", attribSep);
346       IndentPop();
347       f.Print(attribIndent, "/>", tagLine);
348       f.Print(tagIndent, "<Tool", attribSep);
349          IndentPush();
350          f.Print(attribIndent, "Name=\"VCResourceCompilerTool\"", attribSep);
351       IndentPop();
352       f.Print(attribIndent, "/>", tagLine);
353       f.Print(tagIndent, "<Tool", attribSep);
354          IndentPush();
355          f.Print(attribIndent, "Name=\"VCPreLinkEventTool\"", attribSep);
356       IndentPop();
357       f.Print(attribIndent, "/>", tagLine);
358       f.Print(tagIndent, "<Tool", attribSep);
359          IndentPush();
360          f.Print(attribIndent, "Name=\"", (targetType == executable || targetType == sharedLibrary) ? "VCLinkerTool" : "VCLibrarianTool", "\"", attribSep);
361          {
362             Array<String> additionalLibraries { };
363             if(project.options && project.options.libraries)
364             {
365                for(lib : project.options.libraries)
366                   additionalLibraries.Add(CopyString(lib));
367             }
368             if(config && config.options && config.options.libraries)
369             {
370                for(lib : config.options.libraries)
371                   additionalLibraries.Add(CopyString(lib));
372             }
373             CollectPlatformSpecificDirs(project, config, null, null, null, additionalLibraries);
374             if(additionalLibraries.count)
375             {
376                f.Print(attribIndent, "AdditionalDependencies=\"");
377                for(lib : additionalLibraries)
378                   f.Print(lib == additionalLibraries.firstIterator.data ?  "" : " ", lib, ".lib");
379                f.Print("\"", attribSep);
380                additionalLibraries.Free();
381             }
382             delete additionalLibraries;
383          }
384          f.Print(attribIndent, "OutputFile=\"$(OutDir)\\", targetFileName, ".");
385          if(targetType == executable)
386             f.Print("exe");
387          else if(targetType == sharedLibrary)
388             f.Print("dll");
389          else if(targetType == staticLibrary)
390             f.Print("lib");
391          f.Print("\"", attribSep);
392    if(targetType == executable)
393          f.Print(attribIndent, "LinkIncremental=\"", debug ? 2 : 1, "\"", attribSep);
394          {
395             Array<DirPath> additionalLibraryDirs { };
396             if(project.options && project.options.libraryDirs)
397             {
398                for(dir : project.options.libraryDirs)
399                   additionalLibraryDirs.Add(CopySystemPath(dir));
400             }
401             if(config && config.options && config.options.libraryDirs)
402             {
403                for(dir : config.options.libraryDirs)
404                   additionalLibraryDirs.Add(CopySystemPath(dir));
405             }
406             CollectPlatformSpecificDirs(project, config, null, null, additionalLibraryDirs, null);
407             if(additionalLibraryDirs.count)
408             {
409                f.Print(attribIndent, "AdditionalLibraryDirectories=\"");
410                for(dir : additionalLibraryDirs)
411                   f.Print(dir == additionalLibraryDirs.firstIterator.data ?  "" : ";", dir);
412                f.Print("\"", attribSep);
413                additionalLibraryDirs.Free();
414             }
415             delete additionalLibraryDirs;
416          }
417    if(targetType == executable)
418    {
419          f.Print(attribIndent, "GenerateDebugInformation=\"true\"", attribSep);
420          f.Print(attribIndent, "SubSystem=\"1\"", attribSep);
421       if(optimize)
422       {      
423          f.Print(attribIndent, "OptimizeReferences=\"2\"", attribSep);
424          f.Print(attribIndent, "EnableCOMDATFolding=\"2\"", attribSep);
425       }
426          f.Print(attribIndent, "TargetMachine=\"1\"", attribSep);
427    }
428       IndentPop();
429       f.Print(attribIndent, "/>", tagLine);
430       f.Print(tagIndent, "<Tool", attribSep);
431          IndentPush();
432          f.Print(attribIndent, "Name=\"VCALinkTool\"", attribSep);
433       IndentPop();
434       f.Print(attribIndent, "/>", tagLine);
435    if(targetType == executable)
436    {
437       f.Print(tagIndent, "<Tool", attribSep);
438          IndentPush();
439          f.Print(attribIndent, "Name=\"VCManifestTool\"", attribSep);
440       IndentPop();
441       f.Print(attribIndent, "/>", tagLine);
442    }
443       f.Print(tagIndent, "<Tool", attribSep);
444          IndentPush();
445          f.Print(attribIndent, "Name=\"VCXDCMakeTool\"", attribSep);
446       IndentPop();
447       f.Print(attribIndent, "/>", tagLine);
448       f.Print(tagIndent, "<Tool", attribSep);
449          IndentPush();
450          f.Print(attribIndent, "Name=\"VCBscMakeTool\"", attribSep);
451       IndentPop();
452       f.Print(attribIndent, "/>", tagLine);
453       f.Print(tagIndent, "<Tool", attribSep);
454          IndentPush();
455          f.Print(attribIndent, "Name=\"VCFxCopTool\"", attribSep);
456       IndentPop();
457       f.Print(attribIndent, "/>", tagLine);
458    if(targetType == executable)
459    {
460       f.Print(tagIndent, "<Tool", attribSep);
461          IndentPush();
462          f.Print(attribIndent, "Name=\"VCAppVerifierTool\"", attribSep);
463       IndentPop();
464       f.Print(attribIndent, "/>", tagLine);
465       /*
466       f.Print(tagIndent, "<Tool", attribSep);
467          IndentPush();
468          f.Print(attribIndent, "Name=\"VCWebDeploymentTool\"", attribSep);
469       IndentPop();
470       f.Print(attribIndent, "/>", tagLine);
471       */
472    }
473       f.Print(tagIndent, "<Tool", attribSep);
474          IndentPush();
475          f.Print(attribIndent, "Name=\"VCPostBuildEventTool\"", attribSep);
476       IndentPop();
477       f.Print(attribIndent, "/>", tagLine);
478    IndentPop();
479    f.Print(tagIndent, "</Configuration>", tagLine);
480
481    delete objDir;
482    delete targetDir;
483 }
484
485 void CollectPlatformSpecificDirs(Project project, ProjectConfig config, Array<String> additionalPreprocessorDefs,
486       Array<DirPath> additionalIncludeDirs, Array<DirPath> additionalLibraryDirs, Array<String> additionalLibraries)
487 {
488    ProjectOptions options = project.options;
489    TargetTypes targetType = localTargetType;
490
491    Platform platform = win32;
492    //for(platform = firstPlatform; platform <= lastPlatform; platform++)
493    //for(platform = win32; platform <= apple; platform++)
494    
495    //for(platform = (Platform)1; platform < Platform::enumSize; platform++)
496    //{
497       PlatformOptions projectPlatformOptions = null;
498       PlatformOptions configPlatformOptions = null;
499
500       if(project.platforms)
501       {
502          for(p : project.platforms)
503          {
504             if(!strcmpi(p.name, platform))
505             {
506                projectPlatformOptions = p;
507                break;
508             }
509          }
510       }
511       if(config && config.platforms)
512       {
513          for(p : config.platforms)
514          {
515             if(!strcmpi(p.name, platform))
516             {
517                configPlatformOptions = p;
518                break;
519             }
520          }
521       }
522       if(projectPlatformOptions)
523       {
524          if(additionalPreprocessorDefs && projectPlatformOptions.options.preprocessorDefinitions && projectPlatformOptions.options.preprocessorDefinitions.count)
525          {
526             for(def : projectPlatformOptions.options.preprocessorDefinitions)
527                additionalPreprocessorDefs.Add(CopyString(def));
528          }
529          if(additionalIncludeDirs && projectPlatformOptions.options.includeDirs && projectPlatformOptions.options.includeDirs.count)
530          {
531             for(dir : projectPlatformOptions.options.includeDirs)
532                additionalIncludeDirs.Add(CopySystemPath(dir));
533          }
534          if(targetType != staticLibrary)
535          {
536             if(additionalLibraryDirs && projectPlatformOptions && projectPlatformOptions.options.libraryDirs && projectPlatformOptions.options.libraryDirs.count)
537             {
538                for(dir : projectPlatformOptions.options.libraryDirs)
539                   additionalLibraryDirs.Add(CopySystemPath(dir));
540             }
541             if(additionalLibraries && projectPlatformOptions.options.libraries && projectPlatformOptions.options.libraries.count)
542             {
543                for(lib : projectPlatformOptions.options.libraries)
544                   additionalLibraries.Add(CopyString(lib));
545             }
546          }
547       }
548       if(configPlatformOptions)
549       {
550          if(additionalPreprocessorDefs && configPlatformOptions.options.preprocessorDefinitions && configPlatformOptions.options.preprocessorDefinitions.count)
551          {
552             for(def : configPlatformOptions.options.preprocessorDefinitions)
553                additionalPreprocessorDefs.Add(CopyString(def));
554          }
555          if(additionalIncludeDirs && configPlatformOptions.options.includeDirs && configPlatformOptions.options.includeDirs.count)
556          {
557             for(dir : configPlatformOptions.options.includeDirs)
558                additionalIncludeDirs.Add(CopySystemPath(dir));
559          }
560          if(targetType != staticLibrary)
561          {
562             if(additionalLibraryDirs && configPlatformOptions && configPlatformOptions.options.libraryDirs && configPlatformOptions.options.libraryDirs.count)
563             {
564                for(dir : configPlatformOptions.options.libraryDirs)
565                   additionalLibraryDirs.Add(CopySystemPath(dir));
566             }
567             if(additionalLibraries && configPlatformOptions.options.libraries && configPlatformOptions.options.libraries.count)
568             {
569                for(lib : configPlatformOptions.options.libraries)
570                   additionalLibraries.Add(CopyString(lib));
571             }
572          }
573       }
574    //}
575 }
576
577 enum FilesFilter { source, header, resource, other };
578 bool PrintNodes(File f, Project prj, ProjectNode node, Map<String, NameCollisionInfo> namesInfo, FilesFilter filter, bool justHasChild, bool usePrecompiledHeaders)
579 {
580    if(node.type == file)
581    {
582       char extension[MAX_EXTENSION];
583       GetExtension(node.name, extension);
584       if(filter == source)
585       {
586          if(!strcmpi(extension, "cpp") || !strcmpi(extension, "c") ||
587                !strcmpi(extension, "cxx") || !strcmpi(extension, "def") ||
588                !strcmpi(extension, "odl") || !strcmpi(extension, "idl") ||
589                !strcmpi(extension, "hpj") || !strcmpi(extension, "bat") ||
590                !strcmpi(extension, "asm") || !strcmpi(extension, "asmx"))
591          {
592             if(justHasChild)
593                return true;
594             PrintFile(f, prj, node, namesInfo, usePrecompiledHeaders);
595          }
596       }
597       else if(filter == header)
598       {
599          if(!strcmpi(extension, "h") || !strcmpi(extension, "hpp") ||
600                !strcmpi(extension, "hxx") || !strcmpi(extension, "hm") ||
601                !strcmpi(extension, "inl") || !strcmpi(extension, "inc") ||
602                !strcmpi(extension, "xsd"))
603          {
604             if(justHasChild)
605                return true;
606             PrintFile(f, prj, node, namesInfo, usePrecompiledHeaders);
607          }
608       }
609       else if(filter == resource)
610       {
611          if(!strcmpi(extension, "rc") || !strcmpi(extension, "ico") ||
612                !strcmpi(extension, "cur") || !strcmpi(extension, "bmp") ||
613                !strcmpi(extension, "dlg") || !strcmpi(extension, "rc2") ||
614                !strcmpi(extension, "rct") || !strcmpi(extension, "bin") ||
615                !strcmpi(extension, "rgs") || !strcmpi(extension, "gif") ||
616                !strcmpi(extension, "jpg") || !strcmpi(extension, "jpeg") ||
617                !strcmpi(extension, "jpe") || !strcmpi(extension, "resx") ||
618                !strcmpi(extension, "tiff") || !strcmpi(extension, "tif") ||
619                !strcmpi(extension, "png") || !strcmpi(extension, "wav"))
620          {
621             if(justHasChild)
622                return true;
623             PrintFile(f, prj, node, namesInfo, usePrecompiledHeaders);
624          }
625       }
626       else if(filter == other)
627       {
628          if(!(!strcmpi(extension, "cpp") || !strcmpi(extension, "c") ||
629                !strcmpi(extension, "cxx") || !strcmpi(extension, "def") ||
630                !strcmpi(extension, "odl") || !strcmpi(extension, "idl") ||
631                !strcmpi(extension, "hpj") || !strcmpi(extension, "bat") ||
632                !strcmpi(extension, "asm") || !strcmpi(extension, "asmx") ||
633                !strcmpi(extension, "h") || !strcmpi(extension, "hpp") ||
634                !strcmpi(extension, "hxx") || !strcmpi(extension, "hm") ||
635                !strcmpi(extension, "inl") || !strcmpi(extension, "inc") ||
636                !strcmpi(extension, "xsd") ||
637                !strcmpi(extension, "rc") || !strcmpi(extension, "ico") ||
638                !strcmpi(extension, "cur") || !strcmpi(extension, "bmp") ||
639                !strcmpi(extension, "dlg") || !strcmpi(extension, "rc2") ||
640                !strcmpi(extension, "rct") || !strcmpi(extension, "bin") ||
641                !strcmpi(extension, "rgs") || !strcmpi(extension, "gif") ||
642                !strcmpi(extension, "jpg") || !strcmpi(extension, "jpeg") ||
643                !strcmpi(extension, "jpe") || !strcmpi(extension, "resx") ||
644                !strcmpi(extension, "tiff") || !strcmpi(extension, "tif") ||
645                !strcmpi(extension, "png") || !strcmpi(extension, "wav")))
646          {
647             if(justHasChild)
648                return true;
649             PrintFile(f, prj, node, namesInfo, usePrecompiledHeaders);
650          }
651       }
652    }
653    else if(node.files)
654    {
655       bool hasChild = false;
656
657       if(!justHasChild && node.type == folder)
658       {
659          for(child : node.files)
660          {
661             // TOFIX: Exclusion and Config!
662             if(child.type == folder || (child.type != resources && !child.GetIsExcluded(prj.config)))
663             {
664                if((hasChild = PrintNodes(f, prj, child, namesInfo, filter, true, usePrecompiledHeaders)))
665                   break;
666             }
667          }
668
669          if(hasChild)
670          {
671             f.Print(tagIndent, "<Filter", attribSep);
672                IndentPush();
673                f.Print(attribIndent, "Name=\"", node.name, "\"", attribSep);
674                f.Print(attribIndent, ">", tagLine);
675          }
676       }
677
678       for(child : node.files)
679       {
680          // TOFIX: Exclusion and config!
681          if(child.type == folder || (child.type != resources && !child.GetIsExcluded(prj.config)))
682          {
683             if(PrintNodes(f, prj, child, namesInfo, filter, justHasChild, usePrecompiledHeaders) && justHasChild)
684                break;
685          }
686       }
687
688       if(!justHasChild && hasChild && node.type == folder)
689       {
690          IndentPop();
691          f.Print(tagIndent, "</Filter>", tagLine);
692       }
693    }
694    return false;
695 }
696
697 void PrintFile(File f, Project prj, ProjectNode node, Map<String, NameCollisionInfo> namesInfo, bool usePrecompiledHeaders)
698 {
699    char modulePath[MAX_LOCATION];
700    char moduleName[MAX_FILENAME];
701    char relativePath[MAX_LOCATION];
702    ProjectConfig config = null;
703    Array<String> perFilePreprocessorDefs { };
704    Array<DirPath> perFileIncludeDirs { };
705
706    ReplaceSpaces(modulePath, node.path);
707    ReplaceSpaces(moduleName, node.name);
708    //sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b);
709    //items.Add(CopyString(s));
710    //strcpy(relativePath, ".\\");
711    strcpy(relativePath, "");
712    PathCat(relativePath, modulePath);
713    PathCat(relativePath, moduleName);
714    //relativePath = ".\stdafx.cpp";
715
716    f.Print(tagIndent, "<File", attribSep);
717       IndentPush();
718       f.Print(attribIndent, "RelativePath=\"", relativePath, "\"", attribSep);
719       f.Print(attribIndent, ">", tagLine);
720       
721       for(config : prj.configurations)
722       {
723          node.CollectPerFileAndDirOptions(config, perFilePreprocessorDefs, perFileIncludeDirs);
724          PrintFileConfiguration(f, prj, node, namesInfo, config, perFilePreprocessorDefs, perFileIncludeDirs, usePrecompiledHeaders && !strcmpi(relativePath, ".\\stdafx.cpp"));
725          perFilePreprocessorDefs.Free();
726          perFileIncludeDirs.Free();
727       }
728
729    IndentPop();
730    f.Print(tagIndent, "</File>", tagLine);
731
732    delete perFilePreprocessorDefs;
733    delete perFileIncludeDirs;
734 }
735
736 void PrintFileConfiguration(File f, Project prj, ProjectNode node,
737       Map<String, NameCollisionInfo> namesInfo, ProjectConfig config,
738       Array<String> perFilePreprocessorDefs, Array<DirPath> perFileIncludeDirs,
739       bool usePrecompiledHeaders)
740 {
741    char extension[MAX_EXTENSION];
742    char moduleName[MAX_FILENAME];
743    bool nameCollision;
744    NameCollisionInfo info;
745    GetExtension(node.name, extension);
746    ReplaceSpaces(moduleName, node.name);
747    StripExtension(moduleName);
748    info = namesInfo[moduleName];
749    nameCollision = info ? info.IsExtensionColliding(extension) : false;
750    if(perFilePreprocessorDefs.count || perFileIncludeDirs.count ||
751          // TOFIX: Exclusion and config!
752          node.GetIsExcluded(prj.config) || nameCollision ||
753          !strcmpi(extension, "h") || usePrecompiledHeaders)
754    {
755    f.Print(tagIndent, "<FileConfiguration", attribSep);
756       IndentPush();
757       f.Print(attribIndent, "Name=\"", config.name, "|Win32\"", attribSep);
758       // TOFIX: Exclusion and config!
759       if(node.GetIsExcluded(prj.config) || !strcmpi(extension, "h"))
760          f.Print(attribIndent, "ExcludedFromBuild=\"true\"", attribSep);
761       f.Print(attribIndent, ">", tagLine);
762
763       if(perFileIncludeDirs.count || perFileIncludeDirs.count || perFilePreprocessorDefs.count || usePrecompiledHeaders)
764       {
765       f.Print(tagIndent, "<Tool", attribSep);
766       IndentPush();
767          f.Print(attribIndent, "Name=\"VCCLCompilerTool\"", attribSep);
768          if(perFileIncludeDirs.count)
769          {
770          f.Print(attribIndent, "AditionalIncludeDirectories=\"");
771          for(dir : perFileIncludeDirs)
772             f.Print(dir == perFileIncludeDirs.firstIterator.data ?  "" : ";", dir);
773          f.Print("\"", attribSep);
774          }
775
776       if(nameCollision)
777          f.Print(attribIndent, "ObjectFile=\"$(IntDir)\\", node.name, ".obj\"", attribSep);
778
779          if(perFilePreprocessorDefs.count)
780          {
781          f.Print(attribIndent, "PreprocessorDefinitions=\"");
782          for(def : perFilePreprocessorDefs)
783             f.Print(def == perFilePreprocessorDefs.firstIterator.data ?  "" : ";", def);
784          f.Print("\"", attribSep);
785          }
786          if(usePrecompiledHeaders)
787          f.Print(attribIndent, "UsePrecompiledHeader=\"1\"", attribSep);
788       IndentPop();
789       f.Print(attribIndent, "/>", tagLine);
790       }
791    IndentPop();
792    f.Print(tagIndent, "</FileConfiguration>", tagLine);
793    }
794 }
795 #endif