summaryrefslogtreecommitdiff
path: root/dist/win_projects/genproject.template
blob: faf8dd960a9e3c81df2b677bf30d142e0c4e75e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
(:
*  IMPORTANT: this file is shared (identical) between the BDB XML and XQilla
*  projects.  It should not be changed independently or in any way that makes
*  it project-dependent.
*
*  @PROJECT_NAME@  - name of the Visual Studio project
*  @PROJECT_INPUT@ - input XML document that drives the script.
* TBD:
*  1. Could drive the remaining variables, including Visual Studio
*  variables, off of the xml file and provide the XML input 
*  file as an external variable to the query.  E.g. some projects
*  may want to parameterize the optimization and warnings levels
*  2. Generate AdditionalIncludeDirectories based on the <depends> elements for 
*  projects rather than just including "all" 
:)
declare variable $projectList := "@PROJECT_INPUT@";
declare variable $vsversion := "@VISUAL_STUDIO_VERSION@";
declare variable $sourcePath := doc($projectList)/projects/variable[@name="sourcePath"];
declare variable $outputBase := doc($projectList)/projects/variable[@name="outputBase.@VISUAL_STUDIO_VERSION@"];
declare variable $mobile := xs:boolean(doc($projectList)/projects/variable[@name="mobile"]);

(: Visual Studio Variables --relatively static :)
declare variable $debugOptLevel := "0";  (: VS -- no optimization :)
declare variable $releaseOptLevel := "2"; (: VS -- level 2 opt :)
declare variable $warnLevel := "3"; (: VS warning level :)
declare variable $appType := "1"; (: VS type 1 is a program :)
declare variable $dllType := "2";  (: VS type 2 is a DLL :)
declare variable $staticType := "4"; (: VS type 4 is a static lib :)
declare variable $debugInfo := "3"; (: VS debug information format :)
declare variable $libExtension := ".lib";

(: formatting :)
declare function local:indent($n)
{
  concat("&#xa;",string-join(for $i in (1 to $n) return " ", ""))
};

(: is it a DLL, Application, or static library? :)
declare function local:configurationType($projectType, $config)
{
  if ($projectType eq "library") then 
    if (contains($config,"Static")) then $staticType else $dllType 
  else $appType
};

(: "normalize" Windows file paths :)
declare function local:windowsPath($path) as xs:string
{
        translate($path,"/","\\")
};

(: debug vs release :)
declare function local:isDebug($config) as xs:boolean
{
  contains($config,"Debug")
};

declare function local:isRelease($config) as xs:boolean
{
  contains($config,"Release")
};

declare function local:characterSet()
{
  if ($mobile) then "1" else "2"
};

(: machine-target-dependent link options :)
declare function local:addLinkOptions($project, $platform, $config)
{
  let $machine :=
    if ($mobile) then ""
    else if (contains($platform,"Win32")) then "/machine:x86"
    else concat("/machine:",$platform)
  let $opt := string-join(($machine,$project/options/link[contains(@config,$config)])," ")
  return if (not($opt eq "")) then attribute{"AdditionalOptions"}{$opt}
         else ()
};

declare function local:addDebugInformation($config)
{
  attribute{"DebugInformationFormat"}{$debugInfo},	
   if (local:isDebug($config)) then attribute{"BasicRuntimeChecks"}{"3"} else ()
};

declare function local:getProjectType($project, $config)
{ 
  if ($project/type eq "library") then if (contains($config,"Static")) then "static_lib"
    else "dll"
  else if ($project/type eq "app") then if (contains($config,"Static")) then "static_app"
    else "app"
  else error(QName("","dbxml"),"getProjectType:unkown project type")
};

declare function local:generateCompilerPreprocessorDefs($project, $config)
{ 
  let $ptype := local:getProjectType($project,$config)
  let $generic := doc($projectList)/projects/preprocessor[@config="all" or @config=$config]
  let $proj := $project/preprocessor[@config="all" or @config=$config or @config=$ptype]
  let $type := doc($projectList)/projects/preprocessor[@config=$ptype]
  return string-join(($generic,$proj,$type),";")
};

declare function local:generateResourcePreprocessorDefs($config)
{
    if (not(empty(doc($projectList)/projects/preprocessor[@config="rc_all"]))) then
        attribute{"PreprocessorDefinitions"}{doc($projectList)/projects/preprocessor[@config="rc_all"]}
    else ()
};

(: Optimization level :)
declare function local:optLevel($config)
{
  if (local:isDebug($config)) then $debugOptLevel
  else $releaseOptLevel
};

(: MDd is 3, MD is 2, MTd is 1, MT is 0 :)
declare function local:runtimeLibrary($config,$static as xs:boolean)
{
  if (local:isDebug($config)) then 
    if ($static or $mobile) then "1" else "3" 
  else 
    if ($static or $mobile) then "0" else "2" 
};

declare function local:getLibName($name, $config)
{
  doc($projectList)/projects/library[@name=$name]/libname[@config=$config]
};

declare function local:makeStaticOutputFile($project, $config)
{
  attribute{"OutputFile"}
  {concat("$(OutDir)/", local:getLibName($project/@name, $config),".lib")
  }
};

declare function local:makeImportLibrary($project, $config)
{
  if ($project/type eq "library") then
    attribute{"ImportLibrary"}{concat("$(OutDir)/", local:getLibName($project/@name, $config),".lib")}
  else ()
};

declare function local:makeModuleDefinition($project, $config)
{
  if (not(empty($project/moddef))) then
    attribute{"ModuleDefinitionFile"}{local:windowsPath(concat($sourcePath,$project/moddef/@file))}
  else ()
};

declare function local:makeOutputPDBFile($project, $config)
{
  attribute{"ProgramDatabaseFile"}
  {
    if ($project/type eq "library") then
       concat("$(OutDir)/",  local:getLibName($project/@name, $config),".pdb")
    else							    
      concat("$(OutDir)/",if (not(empty($project/@output))) then $project/@output else $project/@name,".pdb")
  }
};

declare function local:makeOutputFile($project, $config)
{
  attribute{"OutputFile"}
  {
    if ($project/type eq "library") then
       concat("$(OutDir)/", local:getLibName($project/@name, $config), ".dll")
    else							    
      concat("$(OutDir)/",if (not(empty($project/@output))) then $project/@output else $project/@name,".exe")
  }
};

declare function local:makeOutputObjectFile($project, $config)
{
  attribute{"ObjectFile"}
  {
      concat("$(OutDir)/",if (not(empty($project/@output))) then $project/@output else $project/@name,"/")
  }
};

(: The simple thing is to add all libraries for all projects :)
declare function local:addLibraryDependencies($project,$config)
{
  attribute{"AdditionalDependencies"}{string-join(for $dep in $project/depends
   return concat(local:getLibName($dep, $config),".lib")," ")}
};

declare function local:makeLibraryDirectory($lib,$platform,$config)
{
   for $dir in $lib/platform[contains(@name,$platform)]/config[$config=./@type]/libdir
   return 
      if (not(empty($lib/libbase[@vsver=$vsversion]))) then
   	concat($lib/libbase[@vsver=$vsversion],"/", $dir)
      else $dir
};

(: The simple thing is to add all libraries for all projects :)
(: Add an unconditional "../../lib" to the end :)
declare function local:addLibraryDirectories($project,$platform,$config)
{
  attribute{"AdditionalLibraryDirectories"}{string-join((for $dep in $project/depends
   return local:makeLibraryDirectory(doc($projectList)/projects/library[@name=$dep],$platform,$config),"../../lib"),";")}
};

(: The simple thing is to add all libraries for all projects :)
declare function local:addIncludeDirectories($project,$config)
{
  let $incref := for $inc in $project/include[@type="ref"] return doc($projectList)/projects/include[@name=$inc]
  let $increl := $project/include[@type="rel"]
  return
   attribute{"AdditionalIncludeDirectories"}{string-join(($incref,$increl),",")}
};

(: look for project-specific tool, then a type-specific event :)
declare function local:generatePostBuildEvent($project, $config)
{
local:indent(6),<Tool>
    {attribute{"Name"}{"VCPostBuildEventTool"}}
    {if (not(empty($project/event[@name="postbuild"]))) then
           (attribute{"CommandLine"}{$project/event[@name="postbuild"]/command[@config=$config]},
           attribute{"Description"}{$project/event[@name="postbuild"]/description})
     else let $ev := doc($projectList)/projects/event[@name="postbuild" and @type=$project/type]
           return if (not(empty($ev))) then 
	              (attribute{"CommandLine"}{replace($ev/command[@config=$config],"@pname@",if (not(empty($project/@output))) then $project/@output else $project/@name)},
           	      attribute{"Description"}{$ev/description})
           else ()
    }
</Tool>
};

(: look for project-specific tool, then a type-specific event :)
declare function local:generatePreBuildEvent($project, $config)
{
local:indent(6),<Tool>
    {attribute{"Name"}{"VCPreBuildEventTool"}}
    {if (not(empty($project/event[@name="prebuild"]))) then
           (attribute{"CommandLine"}{$project/event[@name="prebuild"]/command[contains(@config,$config)]},
           attribute{"Description"}{$project/event[@name="prebuild"]/description})
     else let $ev := doc($projectList)/projects/event[@name="prebuild" and @type=$project/type]
           return if (not(empty($ev))) then 
	              (attribute{"CommandLine"}{replace($ev/command[contains(@config,$config)],"@pname@",if (not(empty($project/@output))) then $project/@output else $project/@name)},
           	      attribute{"Description"}{$ev/description})
           else ()
    }
</Tool>
};

declare function local:generateCustomBuildTool($project, $config)
{
local:indent(6),<Tool>
    {attribute{"Name"}{"VCCustomBuildTool"}}
    {if (not(empty($project/event[@name="custom"]))) then
        (attribute{"CommandLine"}{$project/event[@name="custom"]/command[contains(@config,$config)]},
    	attribute{"Outputs"}{$project/event[@name="custom"]/output})
	else ()}
</Tool>
};

declare function local:generateDeploymentTool($project)
{
local:indent(6),<DeploymentTool>
  {  if ($project/type eq "dll") then
        (attribute{"RemoteDirectory"}{"\windows"})
     else ()}
</DeploymentTool>
};

(: 
 static build of libraries; at this time it does *not* add additional
 dependent libraries.  This means that applications need to include them
 for the time being.
:)
declare function local:generateConfigLibrarian($project, $platform, $config)
{
local:indent(6),<Tool>
  {attribute{"Name"}{"VCLibrarianTool"}}
  {local:makeStaticOutputFile($project,$config)}
  {local:addLinkOptions($project, $platform, $config)}
</Tool>
};

declare function local:generateConfigLinkerAndMidl($project, $platform, $config)
{
local:indent(6),<Tool>
  {attribute{"Name"}{"VCLinkerTool"}}
  {local:addLinkOptions($project, $platform, $config)}
  {local:addLibraryDependencies($project,$config)}
  {local:addLibraryDirectories($project,$platform,$config)}
  {local:makeOutputFile($project, $config)}
  {local:makeOutputPDBFile($project, $config)}
  {attribute{"LinkIncremental"}{"1"}}
  {attribute{"GenerateDebugInformation"}{"TRUE"}}
  {attribute{"SuppressStartupBanner"}{"TRUE"}}
  {attribute{"OptimizeReferences"}{"2"}}
  {local:makeImportLibrary($project,$config)}
  {local:makeModuleDefinition($project,$config)}
  {attribute{"TargetMachine"}{if (contains($platform, "(ARMV4)")) then "3" else "0"}}
  {if ($project/type eq "app" and $mobile) then 
      (attribute{"SubSystem"}{"9"},attribute{"EntryPointSymbol"}{"WinMainCRTStartup"})
   else ()}
</Tool>
};

declare function local:generateConfigCompiler($project, $platform, $config, $static as xs:boolean)
{
local:indent(6),<Tool>
  {attribute{"Name"}{"VCCLCompilerTool"}}
  {if ($mobile) then attribute{"BufferSecurityCheck"}{"FALSE"} else ()}
  {attribute{"Optimization"}{local:optLevel($config)}}
  {attribute{"MinimalRebuild"}{"TRUE"}}
  {if (local:isRelease($config)) then attribute{"InlineFunctionExpansion"}{"1"} else ()}
  {if (contains($project/options/compile/@platform, $platform)) then attribute{"AdditionalOptions"}{$project/options/compile/text()} else ()}
  {local:addIncludeDirectories($project,$config)}
  {attribute{"PreprocessorDefinitions"}{local:generateCompilerPreprocessorDefs($project, $config)}}
  {attribute{"StringPooling"}{"TRUE"}}
  {if (not(empty($project/options/rtti))) then attribute{"RuntimeTypeInfo"}{"TRUE"} else ()}
  {attribute{"RuntimeLibrary"}{local:runtimeLibrary($config,$static)}}
  {if (local:isRelease($config)) then attribute{"EnableFunctionLevelLinking"}{"TRUE"} else ()}
  {attribute{"UsePrecompiledHeader"}{"0"}}
  {if ($project/@name eq "dbxml") then attribute{"PrecompiledHeaderThrough"}{"DbXmlInternal.hpp"} else ()}
  {attribute{"PrecompiledHeaderFile"}{concat("./$(OutDir)/",$project/@name,".pch")}}
  {attribute{"AssemblerListingLocation"}{local:makeOutputObjectFile($project, $config)}}
  {attribute{"ObjectFile"}{local:makeOutputObjectFile($project, $config)}}
  {attribute{"WarningLevel"}{$warnLevel}}
  {if (not($vsversion eq "8.00") and not($project/options/nowp64)) then attribute{"Detect64BitPortabilityProblems"}{"TRUE"} else ()}
  {attribute{"SuppressStartupBanner"}{"TRUE"}}
  {local:addDebugInformation($config)}
  {attribute{"CompileAs"}{"0"}}
</Tool>
};

declare function local:generateConfigBoilerplate($config)
{
local:indent(6),<Tool Name="VCPreLinkEventTool"/>,
local:indent(6),<Tool>
  {attribute{"Name"}{"VCResourceCompilerTool"}}
  {local:generateResourcePreprocessorDefs($config)}
</Tool>,
local:indent(6),<Tool Name="VCXMLDataGeneratorTool"/>,
local:indent(6),<Tool Name="VCManagedWrapperGeneratorTool"/>,
local:indent(6),<Tool Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
};

(: use "platform/configuration" :)
declare function local:generateOutputDirectory($platform,$config,$static)
{
    attribute{"OutputDirectory"}{local:windowsPath(concat($outputBase,"$(PlatformName)","/",string-join(tokenize($config," "),"_"),$static))}
};

declare function local:generateConfig($project, $platform, $config)
{
local:indent(4),<Configuration>
    {attribute{"Name"}{concat($config,"|",$platform)}}
    {local:generateOutputDirectory($platform,$config,"")}
    {attribute{"IntermediateDirectory"}{concat("./$(OutDir)/",$project/@name)}}
    {attribute{"ConfigurationType"}{local:configurationType($project/type,$config)}}
    {attribute{"UseOfMFC"}{"0"}}
    {attribute{"ATLMinimizesCRunTimeLibraryUsage"}{"FALSE"}}
    {attribute{"CharacterSet"}{local:characterSet()}}
    {local:generateConfigBoilerplate($config)}
    {local:generateConfigCompiler($project, $platform, $config,xs:boolean("false"))}
    {local:generateConfigLinkerAndMidl($project, $platform, $config)}
    {local:generatePreBuildEvent($project,if (local:isDebug($config)) then "Debug" else "Release")}
    {local:generatePostBuildEvent($project,if (local:isDebug($config)) then "Debug" else "Release")}
    {local:generateCustomBuildTool($project,if (local:isDebug($config)) then "Debug" else "Release")}
    {if ($mobile) then local:generateDeploymentTool($project) else()}
  </Configuration>
};

declare function local:generateStaticConfig($project, $platform, $config)
{
  local:indent(4),<Configuration>
    {attribute{"Name"}{concat($config,"|",$platform)}}
    {local:generateOutputDirectory($platform,$config,"")}
    {attribute{"IntermediateDirectory"}{concat("./$(OutDir)/",$project/@name)}}
    {attribute{"ConfigurationType"}{local:configurationType($project/type,$config)}}
    {attribute{"UseOfMFC"}{"0"}}
    {attribute{"ATLMinimizesCRunTimeLibraryUsage"}{"FALSE"}}
    {attribute{"CharacterSet"}{local:characterSet()}}
    {local:generateConfigBoilerplate($config)}
    {local:generateConfigCompiler($project, $platform, $config,xs:boolean("true"))}
    {if (contains($project/type,"lib")) then 
         local:generateConfigLibrarian($project, $platform, $config)
     else
         local:generateConfigLinkerAndMidl($project, $platform, $config)
    }
  </Configuration>
};

declare function local:generateRcFile($file)
{
	local:indent(4),<File RelativePath="{local:windowsPath(concat($sourcePath,$file/@name))}">
	{ for $platform in local:getPlatforms($vsversion) return 
            for $config in ("Debug","Release") return
              (local:indent(6),<FileConfiguration Name="{concat($config,"|",$platform)}">
                  <Tool Name="VCResourceCompilerTool" PreprocessorDefinitions="{concat(if ($config="Debug") then "_DEBUG" else "NDEBUG",";","$(NoInherit))")}"/>
	      {local:indent(6)}</FileConfiguration>)
        }
	{local:indent(4)}</File>
};

declare function local:generateFilesNoFilter($project)
{
    for $file in $project/files/file
        return  if (ends-with($file/@name,".rc") and not($mobile)) then local:generateRcFile($file)
	  else  (local:indent(4),<File RelativePath="{local:windowsPath(concat($sourcePath,$file/@name))}"/>)
};

declare function local:generateFilesWithFilter($project,$filter)
{
    for $file in $project/files/filter[@name=$filter]/file
        return if (ends-with($file/@name,".rc") and not($mobile)) then local:generateRcFile($file)
	  else (local:indent(6),<File RelativePath="{local:windowsPath(concat($sourcePath,$file/@name))}"/>)
};

declare function local:generateFiles($project)
{
  let $filters := $project/files/filter/@name
  return if (empty($filters)) then
          local:generateFilesNoFilter($project)
     else
         for $filter in $filters
         return (local:indent(4),<Filter Name="{$filter}" Filter="">
               {local:generateFilesWithFilter($project,$filter)}
         {local:indent(4)}</Filter>)
};

declare function local:generatePlatforms()
{
  if (not($mobile)) then
     (local:indent(4),<Platform Name="Win32"/>,
      local:indent(4),<Platform Name="x64"/>)
  else
     (local:indent(4),<Platform Name="Pocket PC 2003 (ARMV4)"/>,
      local:indent(4),<Platform Name="Smartphone 2003 (ARMV4)"/>,
      local:indent(4),<Platform Name="Windows Mobile 6.5.3 Professional DTK (ARMV4I)"/>)
};

declare function local:getGuid($project)
{
	concat("{",$project/@guid,"}")	
};

declare function local:getPlatforms($version)
{
  if (not($mobile)) then
     (if ($version eq "7.10") then ("Win32")
      else ("Win32", "x64"))
  else
     ("Pocket PC 2003 (ARMV4)", "Smartphone 2003 (ARMV4)",
     "Windows Mobile 6.5.3 Professional DTK (ARMV4I)")
};

declare function local:getProjects()
{
  (: doc($projectList)/projects/project :)
  doc($projectList)/projects/project[@name="@PROJECT_NAME@"]
};

for $project in local:getProjects() return
<VisualStudioProject
   ProjectType="Visual C++"
   Version="{$vsversion}"
   Name="{string($project/@name)}"
   ProjectGUID="{local:getGuid($project)}">
   {local:indent(2)}<Platforms>
     {local:generatePlatforms()}
   {local:indent(2)}</Platforms>
   {local:indent(2)}<Configurations>
    {
    for $platform in local:getPlatforms($vsversion) return 
    for $configuration in $project/configuration
    let $static := contains($configuration/text(),"Static") return
    for $config in ("Debug","Release") return if ($static) then let $config := concat("Static ",$config) return local:generateStaticConfig($project, $platform, $config) else local:generateConfig($project, $platform, $config)
    }
  {local:indent(2)}</Configurations>
  {local:indent(2)}<References/>
  {local:indent(2)}<Files>
    {local:generateFiles($project)}
  {local:indent(2)}</Files>
  {local:indent(2)}<Globals/>
{"&#xa;"}</VisualStudioProject>