(: * 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 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(" ",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") }; (: whether use WinMainCRTStartup as EntryPoint :) declare function local:isWinMain($project) as xs:boolean { contains($project/configuration/text(),"WinMain") }; 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), {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 () } }; (: look for project-specific tool, then a type-specific event :) declare function local:generatePreBuildEvent($project, $config) { local:indent(6), {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 () } }; declare function local:generateCustomBuildTool($project, $config) { local:indent(6), {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 ()} }; declare function local:generateDeploymentTool($project) { local:indent(6), { if ($project/type eq "dll") then (attribute{"RemoteDirectory"}{"\windows"}) else ()} }; (: 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), {attribute{"Name"}{"VCLibrarianTool"}} {local:makeStaticOutputFile($project,$config)} {local:addLinkOptions($project, $platform, $config)} }; declare function local:generateConfigLinkerAndMidl($project, $platform, $config) { local:indent(6), {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 ($mobile) then (attribute{"SubSystem"}{"9"}) else ()} {if ($project/type eq "app" and $mobile) then (attribute{"EntryPointSymbol"}{if (local:isWinMain($project)) then "WinMainCRTStartup" else "mainACRTStartup"}) else ()} }; declare function local:generateConfigCompiler($project, $platform, $config, $static as xs:boolean) { local:indent(6), {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"}} }; declare function local:generateConfigBoilerplate($config) { local:indent(6),, local:indent(6), {attribute{"Name"}{"VCResourceCompilerTool"}} {local:generateResourcePreprocessorDefs($config)} , local:indent(6),, local:indent(6),, local:indent(6), }; (: 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), {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()} }; declare function local:generateStaticConfig($project, $platform, $config) { local:indent(4), {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) } }; declare function local:generateRcFile($file) { local:indent(4), { for $platform in local:getPlatforms($vsversion) return for $config in ("Debug","Release") return (local:indent(6), {local:indent(6)}) } {local:indent(4)} }; 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),) }; 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),) }; 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), {local:generateFilesWithFilter($project,$filter)} {local:indent(4)}) }; declare function local:generatePlatforms() { if (not($mobile)) then (local:indent(4),, local:indent(4),) else (local:indent(4),, local:indent(4),, local:indent(4),) }; 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 {local:indent(2)} {local:generatePlatforms()} {local:indent(2)} {local:indent(2)} { 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)} {local:indent(2)} {local:indent(2)} {local:generateFiles($project)} {local:indent(2)} {local:indent(2)} {" "}