package require Tcl 8.4
proc fail { {error ""} {usage false} } {
if {[string length $error] > 0} then {
puts stdout $error
if {!$usage} then {exit 1}
}
puts stdout "usage:\
[file tail [info nameofexecutable]]\
[file tail [info script]] <binaryDirectory> \[sourceDirectory\]\
\[packageFlavor\] \[platformNames\] \[vsVersion\]"
exit 1
}
proc getEnvironmentVariable { name } {
return [expr {[info exists ::env($name)] ? $::env($name) : ""}]
}
proc getTemporaryPath {} {
set names [list]
foreach name [list TEMP TMP] {
lappend names [string toupper $name] [string tolower $name] \
[string totitle $name]
}
foreach name $names {
set value [getEnvironmentVariable $name]
if {[string length $value] > 0} then {
return [file normalize $value]
}
}
return ""
}
proc appendArgs { args } {
eval append result $args
}
proc readFile { fileName } {
set file_id [open $fileName RDONLY]
fconfigure $file_id -encoding binary -translation binary
set result [read $file_id]
close $file_id
return $result
}
proc writeFile { fileName data } {
set file_id [open $fileName {WRONLY CREAT TRUNC}]
fconfigure $file_id -encoding binary -translation binary
puts -nonewline $file_id $data
close $file_id
return ""
}
proc getMinVsVersionXmlChunk { vsVersion } {
switch -exact $vsVersion {
2012 {
return [appendArgs \
"\r\n " {MinVSVersion="11.0"}]
}
2013 {
return [appendArgs \
"\r\n " {MinVSVersion="12.0"}]
}
2015 {
return [appendArgs \
"\r\n " {MinVSVersion="14.0"}]
}
default {
return ""
}
}
}
proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } {
if {![string equal $vsVersion 2013] && \
![string equal $vsVersion 2015]} then {
return ""
}
switch -exact $packageFlavor {
WinRT {
return [appendArgs \
"\r\n " {MaxPlatformVersion="8.0"}]
}
WinRT81 {
return [appendArgs \
"\r\n " {MaxPlatformVersion="8.1"}]
}
WP80 {
return [appendArgs \
"\r\n " {MaxPlatformVersion="8.0"}]
}
WP81 {
return [appendArgs \
"\r\n " {MaxPlatformVersion="8.1"}]
}
default {
return ""
}
}
}
proc getExtraFileListXmlChunk { packageFlavor vsVersion } {
if {[string equal $packageFlavor WP80]} then {
return ""
}
set appliesTo [expr {[string equal $packageFlavor Win32] ? \
"VisualC" : "WindowsAppContainer"}]
switch -exact $vsVersion {
2012 {
return [appendArgs \
"\r\n " AppliesTo=\" $appliesTo \" \
"\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
}
2013 {
return [appendArgs \
"\r\n " AppliesTo=\" $appliesTo \" \
"\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
}
2015 {
return [appendArgs \
"\r\n " AppliesTo=\" $appliesTo \" \
"\r\n " {DependsOn="Microsoft.VCLibs, version=14.0"}]
}
default {
return ""
}
}
}
proc replaceFileNameTokens { fileName name buildName platformName } {
return [string map [list <build> $buildName <platform> $platformName \
<name> $name] $fileName]
}
proc substFile { fileName } {
return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
}
set script [file normalize [info script]]
if {[string length $script] == 0} then {
fail "script file currently being evaluated is unknown" true
}
set path [file dirname $script]
set rootName [file rootname [file tail $script]]
set argc [llength $argv]
if {$argc < 1 || $argc > 5} then {fail}
set binaryDirectory [lindex $argv 0]
if {[string length $binaryDirectory] == 0} then {
fail "invalid binary directory"
}
if {![file exists $binaryDirectory] || \
![file isdirectory $binaryDirectory]} then {
fail "binary directory does not exist"
}
if {$argc >= 2} then {
set sourceDirectory [lindex $argv 1]
} else {
set sourceDirectory [file dirname $path]
}
if {[string length $sourceDirectory] == 0} then {
fail "invalid source directory"
}
if {![file exists $sourceDirectory] || \
![file isdirectory $sourceDirectory]} then {
fail "source directory does not exist"
}
if {$argc >= 3} then {
set packageFlavor [lindex $argv 2]
} else {
set packageFlavor WinRT
}
if {[string length $packageFlavor] == 0} then {
fail "invalid package flavor"
}
if {$argc >= 4} then {
set platformNames [list]
foreach platformName [split [lindex $argv 3] ", "] {
set platformName [string trim $platformName]
if {[string length $platformName] > 0} then {
lappend platformNames $platformName
}
}
}
if {$argc >= 5} then {
set vsVersion [lindex $argv 4]
} else {
set vsVersion 2012
}
if {[string length $vsVersion] == 0} then {
fail "invalid Visual Studio version"
}
if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013] && \
![string equal $vsVersion 2015]} then {
fail [appendArgs \
"unsupported Visual Studio version, must be one of: " \
[list 2012 2013 2015]]
}
set shortNames(WinRT,2012) SQLite.WinRT
set shortNames(WinRT,2013) SQLite.WinRT.2013
set shortNames(WinRT81,2013) SQLite.WinRT81
set shortNames(WP80,2012) SQLite.WP80
set shortNames(WP80,2013) SQLite.WP80.2013
set shortNames(WP81,2013) SQLite.WP81
set shortNames(Win32,2012) SQLite.Win32
set shortNames(Win32,2013) SQLite.Win32.2013
set shortNames(UWP,2015) SQLite.UWP.2015
set displayNames(WinRT,2012) "SQLite for Windows Runtime"
set displayNames(WinRT,2013) "SQLite for Windows Runtime"
set displayNames(WinRT81,2013) "SQLite for Windows Runtime (Windows 8.1)"
set displayNames(WP80,2012) "SQLite for Windows Phone"
set displayNames(WP80,2013) "SQLite for Windows Phone"
set displayNames(WP81,2013) "SQLite for Windows Phone 8.1"
set displayNames(Win32,2012) "SQLite for Windows"
set displayNames(Win32,2013) "SQLite for Windows"
set displayNames(UWP,2015) "SQLite for Universal Windows Platform"
if {[string equal $packageFlavor WinRT]} then {
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.0
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath ""
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor WinRT81]} then {
if {$vsVersion ne "2013"} then {
fail [appendArgs \
"unsupported combination, package flavor " $packageFlavor \
" is only supported with Visual Studio 2013"]
}
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.1
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath ""
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor WP80]} then {
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier "Windows Phone"
set targetPlatformVersion v8.0
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath "\\..\\$targetPlatformIdentifier"
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor WP81]} then {
if {$vsVersion ne "2013"} then {
fail [appendArgs \
"unsupported combination, package flavor " $packageFlavor \
" is only supported with Visual Studio 2013"]
}
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier WindowsPhoneApp
set targetPlatformVersion v8.1
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath "\\..\\$targetPlatformIdentifier"
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor UWP]} then {
if {$vsVersion ne "2015"} then {
fail [appendArgs \
"unsupported combination, package flavor " $packageFlavor \
" is only supported with Visual Studio 2015"]
}
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier UAP; set targetPlatformVersion v0.8.0.0
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath "\\..\\$targetPlatformIdentifier"
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor Win32]} then {
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.0
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath ""
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} else {
fail [appendArgs \
"unsupported package flavor, must be one of: " \
[list WinRT WinRT81 WP80 WP81 UWP Win32]]
}
set userFile [file join $path [appendArgs \
$rootName . $tcl_platform(user) .tcl]]
if {[file exists $userFile] && \
[file isfile $userFile]} then {
source $userFile
}
set templateFile [file join $path win sqlite.vsix]
if {![file exists $templateFile] || \
![file isfile $templateFile]} then {
fail [appendArgs "template file \"" $templateFile "\" does not exist"]
}
set currentDirectory [pwd]
set outputFile [file join $currentDirectory [appendArgs sqlite- \
$packageFlavor -output.vsix]]
if {[file exists $outputFile]} then {
fail [appendArgs "output file \"" $outputFile "\" already exists"]
}
set temporaryDirectory [getTemporaryPath]
if {[string length $temporaryDirectory] == 0 || \
![file exists $temporaryDirectory] || \
![file isdirectory $temporaryDirectory]} then {
fail "cannot locate a usable temporary directory"
}
set stagingDirectory [file normalize [file join $temporaryDirectory \
[appendArgs $rootName . [pid]]]]
if {![info exists zip]} then {
if {[info exists env(ZipTool)]} then {
set zip $env(ZipTool)
}
if {![info exists zip] || ![file exists $zip]} then {
set zip zip
}
}
if {![info exists unzip]} then {
if {[info exists env(UnZipTool)]} then {
set unzip $env(UnZipTool)
}
if {![info exists unzip] || ![file exists $unzip]} then {
set unzip unzip
}
}
set pattern {^#define\s+SQLITE_VERSION\s+"(.*)"$}
set data [readFile [file join $sourceDirectory sqlite3.h]]
if {![regexp -line -- $pattern $data dummy version]} then {
fail [appendArgs "cannot locate SQLITE_VERSION value in \"" \
[file join $sourceDirectory sqlite3.h] \"]
}
if {![info exists fileNames(source)]} then {
set fileNames(source) [list "" "" \
[file join $stagingDirectory DesignTime <build> <platform> sqlite3.props] \
[file join $sourceDirectory sqlite3.h] \
[file join $binaryDirectory <build> <platform> sqlite3.lib] \
[file join $binaryDirectory <build> <platform> sqlite3.dll]]
if {![info exists no(symbols)]} then {
lappend fileNames(source) \
[file join $binaryDirectory <build> <platform> sqlite3.pdb]
}
}
if {![info exists fileNames(destination)]} then {
set fileNames(destination) [list \
[file join $stagingDirectory extension.vsixmanifest] \
[file join $stagingDirectory SDKManifest.xml] \
[file join $stagingDirectory DesignTime <build> <platform> <name>.props] \
[file join $stagingDirectory DesignTime <build> <platform> sqlite3.h] \
[file join $stagingDirectory DesignTime <build> <platform> sqlite3.lib] \
[file join $stagingDirectory Redist <build> <platform> sqlite3.dll]]
if {![info exists no(symbols)]} then {
lappend fileNames(destination) \
[file join $stagingDirectory Redist <build> <platform> sqlite3.pdb]
}
}
if {![info exists fileNames(flags)]} then {
set fileNames(flags) [list \
[list buildNeutral platformNeutral subst] \
[list buildNeutral platformNeutral subst] \
[list buildNeutral platformNeutral subst move] \
[list buildNeutral platformNeutral] \
[list] [list] [list noRetail]]
if {![info exists no(symbols)]} then {
lappend fileNames(flags) [list noRetail]
}
}
if {![info exists buildNames]} then {
set buildNames [list Debug Retail]
}
if {![info exists platformNames] || [llength $platformNames] == 0} then {
set platformNames [list x86 x64 ARM]
}
file mkdir $stagingDirectory
set extractCommand [list exec -- $unzip $templateFile -d $stagingDirectory]
eval $extractCommand
foreach sourceFileName $fileNames(source) \
destinationFileName $fileNames(destination) \
fileFlags $fileNames(flags) {
set isBuildNeutral [expr {[lsearch $fileFlags buildNeutral] != -1}]
set isPlatformNeutral [expr {[lsearch $fileFlags platformNeutral] != -1}]
set isMove [expr {[lsearch $fileFlags move] != -1}]
set useSubst [expr {[lsearch $fileFlags subst] != -1}]
foreach buildName \
[expr {$isBuildNeutral ? [list CommonConfiguration] : $buildNames}] {
if {[lsearch $fileFlags no${buildName}] != -1} then {
continue
}
foreach platformName \
[expr {$isPlatformNeutral ? [list neutral] : $platformNames}] {
set newDestinationFileName [replaceFileNameTokens $destinationFileName \
$shortName $buildName $platformName]
if {[string length $sourceFileName] > 0} then {
file mkdir [file dirname $newDestinationFileName]
set newSourceFileName [replaceFileNameTokens $sourceFileName \
$shortName $buildName $platformName]
file copy $newSourceFileName $newDestinationFileName
if {$isMove} then {
file delete $newSourceFileName
}
}
if {$useSubst} then {
substFile $newDestinationFileName
}
}
}
}
cd $stagingDirectory
set archiveCommand [list exec -- $zip -r $outputFile *]
eval $archiveCommand
cd $currentDirectory
file delete -force $stagingDirectory
puts stdout $outputFile