From 1b5ba8e022836fa8ab93bc90df1b34a29ea6e134 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 17 Jan 2013 14:18:26 -0500 Subject: Imported Upstream version 2.1.1 --- tool/mkvsix.tcl | 419 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 tool/mkvsix.tcl (limited to 'tool/mkvsix.tcl') diff --git a/tool/mkvsix.tcl b/tool/mkvsix.tcl new file mode 100644 index 0000000..a751778 --- /dev/null +++ b/tool/mkvsix.tcl @@ -0,0 +1,419 @@ +#!/usr/bin/tclsh +# +# This script is used to generate a VSIX (Visual Studio Extension) file for +# SQLite usable by Visual Studio. + +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]] \[sourceDirectory\]" + + exit 1 +} + +proc getEnvironmentVariable { name } { + # + # NOTE: Returns the value of the specified environment variable or an empty + # string for environment variables that do not exist in the current + # process environment. + # + return [expr {[info exists ::env($name)] ? $::env($name) : ""}] +} + +proc getTemporaryPath {} { + # + # NOTE: Returns the normalized path to the first temporary directory found + # in the typical set of environment variables used for that purpose + # or an empty string to signal a failure to locate such a directory. + # + 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 } { + # + # NOTE: Returns all passed arguments joined together as a single string with + # no intervening spaces between arguments. + # + eval append result $args +} + +proc readFile { fileName } { + # + # NOTE: Reads and returns the entire contents of the specified file, which + # may contain binary data. + # + 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 } { + # + # NOTE: Writes the entire contents of the specified file, which may contain + # binary 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 substFile { fileName } { + # + # NOTE: Performs all Tcl command, variable, and backslash substitutions in + # the specified file and then re-writes the contents of that same file + # with the substituted data. + # + return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]] +} + +proc replacePlatform { fileName platformName } { + # + # NOTE: Returns the specified file name containing the platform name instead + # of platform placeholder tokens. + # + return [string map [list $platformName] $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]] + +############################################################################### + +# +# NOTE: Process and verify all the command line arguments. +# +set argc [llength $argv] +if {$argc != 1 && $argc != 2} 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 { + # + # NOTE: Assume that the source directory is the parent directory of the one + # that contains this script file. + # + 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" +} + +############################################################################### + +# +# NOTE: Evaluate the user-specific customizations file, if it exists. +# +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 sqlite-output.vsix] + +if {[file exists $outputFile]} then { + fail [appendArgs "output file \"" $outputFile "\" already exists"] +} + +############################################################################### + +# +# NOTE: Make sure that a valid temporary directory exists. +# +set temporaryDirectory [getTemporaryPath] + +if {[string length $temporaryDirectory] == 0 || \ + ![file exists $temporaryDirectory] || \ + ![file isdirectory $temporaryDirectory]} then { + fail "cannot locate a usable temporary directory" +} + +# +# NOTE: Setup the staging directory to have a unique name inside of the +# configured temporary directory. +# +set stagingDirectory [file normalize [file join $temporaryDirectory \ + [appendArgs $rootName . [pid]]]] + +############################################################################### + +# +# NOTE: Configure the external zipping tool. First, see if it has already +# been pre-configured. If not, try to query it from the environment. +# Finally, fallback on the default of simply "zip", which will then +# be assumed to exist somewhere along the PATH. +# +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 + } +} + +# +# NOTE: Configure the external unzipping tool. First, see if it has already +# been pre-configured. If not, try to query it from the environment. +# Finally, fallback on the default of simply "unzip", which will then +# be assumed to exist somewhere along the PATH. +# +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 + } +} + +############################################################################### + +# +# NOTE: Attempt to extract the SQLite version from the "sqlite3.h" header file +# in the source directory. This script assumes that the header file has +# already been generated by the build process. +# +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] \"] +} + +############################################################################### + +# +# NOTE: Setup the master file list data, including the necessary flags. +# +if {![info exists fileNames(source)]} then { + set fileNames(source) [list "" "" "" \ + [file join $sourceDirectory sqlite3.h] \ + [file join $binaryDirectory sqlite3.lib] \ + [file join $binaryDirectory sqlite3.dll]] + + if {![info exists no(symbols)]} then { + lappend fileNames(source) \ + [file join $binaryDirectory 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 CommonConfiguration \ + SQLite.WinRT.props] \ + [file join $stagingDirectory DesignTime CommonConfiguration \ + sqlite3.h] \ + [file join $stagingDirectory DesignTime CommonConfiguration \ + sqlite3.lib] \ + [file join $stagingDirectory Redist CommonConfiguration \ + sqlite3.dll]] + + if {![info exists no(symbols)]} then { + lappend fileNames(destination) \ + [file join $stagingDirectory Redist Debug \ + sqlite3.pdb] + } +} + +if {![info exists fileNames(neutral)]} then { + set fileNames(neutral) [list 1 1 1 1 0 0] + + if {![info exists no(symbols)]} then { + lappend fileNames(neutral) 0 + } +} + +if {![info exists fileNames(subst)]} then { + set fileNames(subst) [list 1 1 1 0 0 0] + + if {![info exists no(symbols)]} then { + lappend fileNames(subst) 0 + } +} + +############################################################################### + +# +# NOTE: Setup the list of platforms supported by this script. +# +if {![info exists platformNames]} then { + set platformNames [list x86 x64 ARM] +} + +############################################################################### + +# +# NOTE: Make sure the staging directory exists, creating it if necessary. +# +file mkdir $stagingDirectory + +# +# NOTE: Build the Tcl command used to extract the template package to the +# staging directory. +# +set extractCommand [list exec -- $unzip $templateFile -d $stagingDirectory] + +# +# NOTE: Extract the template package to the staging directory. +# +eval $extractCommand + +############################################################################### + +# +# NOTE: Process each file in the master file list. There are actually four +# parallel lists that contain the source file names, destination file +# names, the platform-neutral flags, and the use-subst flags. When the +# platform-neutral flag is non-zero, the file is not platform-specific. +# When the use-subst flag is non-zero, the file is considered to be a +# text file that may contain Tcl variable and/or command replacements, +# to be dynamically replaced during processing. If the source file name +# is an empty string, then the destination file name will be assumed to +# already exist in the staging directory and will not be copied; however, +# dynamic replacements may still be performed on the destination file +# prior to the package being re-zipped. +# +foreach sourceFileName $fileNames(source) \ + destinationFileName $fileNames(destination) \ + isNeutral $fileNames(neutral) useSubst $fileNames(subst) { + # + # NOTE: If the current file is platform-neutral, then only one platform will + # be processed for it, namely "neutral"; otherwise, each supported + # platform will be processed for it individually. + # + foreach platformName [expr {$isNeutral ? [list neutral] : $platformNames}] { + # + # NOTE: Use the actual platform name in the destination file name. + # + set newDestinationFileName [replacePlatform $destinationFileName \ + $platformName] + + # + # NOTE: Does the source file need to be copied to the destination file? + # + if {[string length $sourceFileName] > 0} then { + # + # NOTE: First, make sure the destination directory exists. + # + file mkdir [file dirname $newDestinationFileName] + + # + # NOTE: Then, copy the source file to the destination file verbatim. + # + file copy [replacePlatform $sourceFileName $platformName] \ + $newDestinationFileName + } + + # + # NOTE: Does the destination file contain dynamic replacements that must + # be processed now? + # + if {$useSubst} then { + # + # NOTE: Perform any dynamic replacements contained in the destination + # file and then re-write it in-place. + # + substFile $newDestinationFileName + } + } +} + +############################################################################### + +# +# NOTE: Change the current directory to the staging directory so that the +# external archive building tool can pickup the necessary files using +# relative paths. +# +cd $stagingDirectory + +# +# NOTE: Build the Tcl command used to archive the final package in the +# output directory. +# +set archiveCommand [list exec -- $zip -r $outputFile *] + +# +# NOTE: Build the final package archive in the output directory. +# +eval $archiveCommand + +# +# NOTE: Change back to the previously saved current directory. +# +cd $currentDirectory + +# +# NOTE: Cleanup the temporary staging directory. +# +file delete -force $stagingDirectory + +############################################################################### + +# +# NOTE: Success, emit the fully qualified path of the generated VSIX file. +# +puts stdout $outputFile -- cgit v1.2.3