blob: 65fa7312450a76d177307deae7707493bfa992f1 [file] [log] [blame]
mistachkin48680192012-07-27 02:36:06 +00001#!/usr/bin/tclsh
2#
3# This script is used to generate a VSIX (Visual Studio Extension) file for
4# SQLite usable by Visual Studio.
mistachkin7c5dbdf2012-10-19 00:23:31 +00005#
6# PREREQUISITES
7#
8# 1. Tcl 8.4 and later are supported, earlier versions have not been tested.
9#
10# 2. The "sqlite3.h" file is assumed to exist in the parent directory of the
11# directory containing this script. The [optional] second command line
12# argument to this script may be used to specify an alternate location.
13# This script also assumes that the "sqlite3.h" file corresponds with the
14# version of the binaries to be packaged. This assumption is not verified
15# by this script.
16#
17# 3. The temporary directory specified in the TEMP or TMP environment variables
18# must refer to an existing directory writable by the current user.
19#
20# 4. The "zip" and "unzip" command line tools must be located either in a
21# directory contained in the PATH environment variable or specified as the
22# exact file names to execute in the "ZipTool" and "UnZipTool" environment
23# variables, respectively.
24#
25# 5. The template VSIX file (which is basically a zip file) must be located in
26# a "win" directory inside the directory containing this script. It should
27# not contain any executable binaries. It should only contain dynamic
28# textual content files to be processed using [subst] and/or static content
29# files to be copied verbatim.
30#
31# 6. The executable and other compiled binary files to be packaged into the
32# final VSIX file (e.g. DLLs, LIBs, and PDBs) must be located in a single
33# directory tree. The top-level directory of the tree must be specified as
34# the first command line argument to this script. The second level
35# sub-directory names must match those of the build configuration (e.g.
36# "Debug" or "Retail"). The third level sub-directory names must match
37# those of the platform (e.g. "x86", "x64", and "ARM"). For example, the
38# binary files to be packaged would need to be organized as follows when
39# packaging the "Debug" and "Retail" build configurations for the "x86" and
40# "x64" platforms (in this example, "C:\temp" is the top-level directory as
41# specified in the first command line argument):
42#
43# C:\Temp\Debug\x86\sqlite3.lib
44# C:\Temp\Debug\x86\sqlite3.dll
45# C:\Temp\Debug\x86\sqlite3.pdb
46# C:\Temp\Debug\x64\sqlite3.lib
47# C:\Temp\Debug\x64\sqlite3.dll
48# C:\Temp\Debug\x64\sqlite3.pdb
49# C:\Temp\Retail\x86\sqlite3.lib
50# C:\Temp\Retail\x86\sqlite3.dll
51# C:\Temp\Retail\x86\sqlite3.pdb
52# C:\Temp\Retail\x64\sqlite3.lib
53# C:\Temp\Retail\x64\sqlite3.dll
54# C:\Temp\Retail\x64\sqlite3.pdb
55#
56# The above directory tree organization is performed automatically if the
57# "tool\build-all-msvc.bat" batch script is used to build the binary files
58# to be packaged.
59#
60# USAGE
61#
mistachkin0f801702012-10-20 08:40:05 +000062# The first argument to this script is required and must be the name of the
63# top-level directory containing the directories and files organized into a
64# tree as described in item 6 of the PREREQUISITES section, above. The second
65# argument is optional and if present must contain the name of the directory
66# containing the root of the source tree for SQLite. The third argument is
67# optional and if present must contain the flavor the VSIX package to build.
mistachkin463f3482013-06-21 07:54:39 +000068# Currently, the only supported package flavors are "WinRT", "WinRT81", and
69# "WP80". The fourth argument is optional and if present must be a string
70# containing a list of platforms to include in the VSIX package. The format
71# of the platform list string is "platform1,platform2,platform3". Typically,
72# when on Windows, this script is executed using commands similar to the
73# following from a normal Windows command prompt:
mistachkin7c5dbdf2012-10-19 00:23:31 +000074#
75# CD /D C:\dev\sqlite\core
76# tclsh85 tool\mkvsix.tcl C:\Temp
77#
78# In the example above, "C:\dev\sqlite\core" represents the root of the source
79# tree for SQLite and "C:\Temp" represents the top-level directory containing
80# the executable and other compiled binary files, organized into a directory
81# tree as described in item 6 of the PREREQUISITES section, above.
82#
83# This script should work on non-Windows platforms as well, provided that all
84# the requirements listed in the PREREQUISITES section are met.
85#
86# NOTES
87#
88# The temporary directory is used as a staging area for the final VSIX file.
89# The template VSIX file is extracted, its contents processed, and then the
90# resulting files are packaged into the final VSIX file.
91#
92package require Tcl 8.4
93
mistachkin48680192012-07-27 02:36:06 +000094proc fail { {error ""} {usage false} } {
95 if {[string length $error] > 0} then {
96 puts stdout $error
97 if {!$usage} then {exit 1}
98 }
99
100 puts stdout "usage:\
101[file tail [info nameofexecutable]]\
mistachkin0f801702012-10-20 08:40:05 +0000102[file tail [info script]] <binaryDirectory> \[sourceDirectory\]\
103\[packageFlavor\] \[platformNames\]"
mistachkin48680192012-07-27 02:36:06 +0000104
105 exit 1
106}
107
108proc getEnvironmentVariable { name } {
109 #
110 # NOTE: Returns the value of the specified environment variable or an empty
111 # string for environment variables that do not exist in the current
112 # process environment.
113 #
114 return [expr {[info exists ::env($name)] ? $::env($name) : ""}]
115}
116
117proc getTemporaryPath {} {
118 #
119 # NOTE: Returns the normalized path to the first temporary directory found
120 # in the typical set of environment variables used for that purpose
121 # or an empty string to signal a failure to locate such a directory.
122 #
123 set names [list]
124
125 foreach name [list TEMP TMP] {
126 lappend names [string toupper $name] [string tolower $name] \
127 [string totitle $name]
128 }
129
130 foreach name $names {
131 set value [getEnvironmentVariable $name]
132
133 if {[string length $value] > 0} then {
134 return [file normalize $value]
135 }
136 }
137
138 return ""
139}
140
141proc appendArgs { args } {
142 #
143 # NOTE: Returns all passed arguments joined together as a single string with
144 # no intervening spaces between arguments.
145 #
146 eval append result $args
147}
148
149proc readFile { fileName } {
150 #
151 # NOTE: Reads and returns the entire contents of the specified file, which
152 # may contain binary data.
153 #
154 set file_id [open $fileName RDONLY]
155 fconfigure $file_id -encoding binary -translation binary
156 set result [read $file_id]
157 close $file_id
158 return $result
159}
160
161proc writeFile { fileName data } {
162 #
163 # NOTE: Writes the entire contents of the specified file, which may contain
164 # binary data.
165 #
166 set file_id [open $fileName {WRONLY CREAT TRUNC}]
167 fconfigure $file_id -encoding binary -translation binary
168 puts -nonewline $file_id $data
169 close $file_id
170 return ""
171}
172
173proc substFile { fileName } {
174 #
175 # NOTE: Performs all Tcl command, variable, and backslash substitutions in
mistachkin0f801702012-10-20 08:40:05 +0000176 # the specified file and then rewrites the contents of that same file
mistachkin48680192012-07-27 02:36:06 +0000177 # with the substituted data.
178 #
179 return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
180}
181
mistachkin0f801702012-10-20 08:40:05 +0000182proc replaceFileNameTokens { fileName name buildName platformName } {
mistachkin48680192012-07-27 02:36:06 +0000183 #
184 # NOTE: Returns the specified file name containing the platform name instead
185 # of platform placeholder tokens.
186 #
mistachkin0f801702012-10-20 08:40:05 +0000187 return [string map [list <build> $buildName <platform> $platformName \
188 <name> $name] $fileName]
mistachkin48680192012-07-27 02:36:06 +0000189}
190
mistachkin0f801702012-10-20 08:40:05 +0000191#
192# NOTE: This is the entry point for this script.
193#
mistachkin48680192012-07-27 02:36:06 +0000194set script [file normalize [info script]]
195
196if {[string length $script] == 0} then {
197 fail "script file currently being evaluated is unknown" true
198}
199
200set path [file dirname $script]
201set rootName [file rootname [file tail $script]]
202
203###############################################################################
204
205#
206# NOTE: Process and verify all the command line arguments.
207#
208set argc [llength $argv]
mistachkin0f801702012-10-20 08:40:05 +0000209if {$argc < 1 || $argc > 4} then {fail}
mistachkin48680192012-07-27 02:36:06 +0000210
211set binaryDirectory [lindex $argv 0]
212
213if {[string length $binaryDirectory] == 0} then {
214 fail "invalid binary directory"
215}
216
217if {![file exists $binaryDirectory] || \
218 ![file isdirectory $binaryDirectory]} then {
219 fail "binary directory does not exist"
220}
221
mistachkin0f801702012-10-20 08:40:05 +0000222if {$argc >= 2} then {
mistachkin48680192012-07-27 02:36:06 +0000223 set sourceDirectory [lindex $argv 1]
224} else {
225 #
226 # NOTE: Assume that the source directory is the parent directory of the one
227 # that contains this script file.
228 #
229 set sourceDirectory [file dirname $path]
230}
231
232if {[string length $sourceDirectory] == 0} then {
233 fail "invalid source directory"
234}
235
236if {![file exists $sourceDirectory] || \
237 ![file isdirectory $sourceDirectory]} then {
238 fail "source directory does not exist"
239}
240
mistachkin0f801702012-10-20 08:40:05 +0000241if {$argc >= 3} then {
242 set packageFlavor [lindex $argv 2]
243} else {
244 #
245 # NOTE: Assume the package flavor is WinRT.
246 #
247 set packageFlavor WinRT
248}
249
250if {[string length $packageFlavor] == 0} then {
251 fail "invalid package flavor"
252}
253
254if {[string equal -nocase $packageFlavor WinRT]} then {
255 set shortName SQLite.WinRT
256 set displayName "SQLite for Windows Runtime"
257 set targetPlatformIdentifier Windows
mistachkin50420542013-06-20 18:53:33 +0000258 set targetPlatformVersion v8.0
259 set minVsVersion 11.0
mistachkin0f801702012-10-20 08:40:05 +0000260 set extraSdkPath ""
261 set extraFileListAttributes [appendArgs \
262 "\r\n " {AppliesTo="WindowsAppContainer"} \
263 "\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
mistachkin50420542013-06-20 18:53:33 +0000264} elseif {[string equal -nocase $packageFlavor WinRT81]} then {
265 set shortName SQLite.WinRT81
266 set displayName "SQLite for Windows Runtime (Windows 8.1)"
267 set targetPlatformIdentifier Windows
268 set targetPlatformVersion v8.1
269 set minVsVersion 12.0
270 set extraSdkPath ""
271 set extraFileListAttributes [appendArgs \
272 "\r\n " {AppliesTo="WindowsAppContainer"} \
273 "\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
mistachkin0f801702012-10-20 08:40:05 +0000274} elseif {[string equal -nocase $packageFlavor WP80]} then {
275 set shortName SQLite.WP80
276 set displayName "SQLite for Windows Phone"
277 set targetPlatformIdentifier "Windows Phone"
mistachkin50420542013-06-20 18:53:33 +0000278 set targetPlatformVersion v8.0
279 set minVsVersion 11.0
mistachkin0f801702012-10-20 08:40:05 +0000280 set extraSdkPath "\\..\\$targetPlatformIdentifier"
281 set extraFileListAttributes ""
mistachkinf13394c2013-04-11 00:13:46 +0000282} elseif {[string equal -nocase $packageFlavor Win32]} then {
283 set shortName SQLite.Win32
284 set displayName "SQLite for Windows"
285 set targetPlatformIdentifier Windows
286 set targetPlatformVersion v8.0
mistachkin0ed02a62013-10-12 02:31:34 +0000287 set minVsVersion 11.0
mistachkinf13394c2013-04-11 00:13:46 +0000288 set extraSdkPath ""
289 set extraFileListAttributes [appendArgs \
mistachkin0ed02a62013-10-12 02:31:34 +0000290 "\r\n " {AppliesTo="VisualC"} \
291 "\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
mistachkin0f801702012-10-20 08:40:05 +0000292} else {
mistachkin0ed02a62013-10-12 02:31:34 +0000293 fail "unsupported package flavor, must be one of: WinRT WinRT81 WP80 Win32"
mistachkin0f801702012-10-20 08:40:05 +0000294}
295
296if {$argc >= 4} then {
297 set platformNames [list]
298
299 foreach platformName [split [lindex $argv 3] ", "] {
300 if {[string length $platformName] > 0} then {
301 lappend platformNames $platformName
302 }
303 }
304}
305
mistachkin48680192012-07-27 02:36:06 +0000306###############################################################################
307
mistachkin391b3642012-07-31 00:43:31 +0000308#
309# NOTE: Evaluate the user-specific customizations file, if it exists.
310#
311set userFile [file join $path [appendArgs \
312 $rootName . $tcl_platform(user) .tcl]]
313
314if {[file exists $userFile] && \
315 [file isfile $userFile]} then {
316 source $userFile
317}
318
319###############################################################################
320
mistachkin48680192012-07-27 02:36:06 +0000321set templateFile [file join $path win sqlite.vsix]
322
323if {![file exists $templateFile] || \
324 ![file isfile $templateFile]} then {
325 fail [appendArgs "template file \"" $templateFile "\" does not exist"]
326}
327
328set currentDirectory [pwd]
mistachkinecf42d52012-10-28 19:35:55 +0000329set outputFile [file join $currentDirectory [appendArgs sqlite- \
330 $packageFlavor -output.vsix]]
mistachkin48680192012-07-27 02:36:06 +0000331
332if {[file exists $outputFile]} then {
333 fail [appendArgs "output file \"" $outputFile "\" already exists"]
334}
335
336###############################################################################
337
338#
339# NOTE: Make sure that a valid temporary directory exists.
340#
341set temporaryDirectory [getTemporaryPath]
342
343if {[string length $temporaryDirectory] == 0 || \
344 ![file exists $temporaryDirectory] || \
345 ![file isdirectory $temporaryDirectory]} then {
346 fail "cannot locate a usable temporary directory"
347}
348
349#
350# NOTE: Setup the staging directory to have a unique name inside of the
351# configured temporary directory.
352#
353set stagingDirectory [file normalize [file join $temporaryDirectory \
354 [appendArgs $rootName . [pid]]]]
355
356###############################################################################
357
358#
359# NOTE: Configure the external zipping tool. First, see if it has already
360# been pre-configured. If not, try to query it from the environment.
361# Finally, fallback on the default of simply "zip", which will then
362# be assumed to exist somewhere along the PATH.
363#
364if {![info exists zip]} then {
365 if {[info exists env(ZipTool)]} then {
366 set zip $env(ZipTool)
367 }
368 if {![info exists zip] || ![file exists $zip]} then {
369 set zip zip
370 }
371}
372
373#
374# NOTE: Configure the external unzipping tool. First, see if it has already
375# been pre-configured. If not, try to query it from the environment.
376# Finally, fallback on the default of simply "unzip", which will then
377# be assumed to exist somewhere along the PATH.
378#
379if {![info exists unzip]} then {
380 if {[info exists env(UnZipTool)]} then {
381 set unzip $env(UnZipTool)
382 }
383 if {![info exists unzip] || ![file exists $unzip]} then {
384 set unzip unzip
385 }
386}
387
388###############################################################################
389
390#
391# NOTE: Attempt to extract the SQLite version from the "sqlite3.h" header file
392# in the source directory. This script assumes that the header file has
393# already been generated by the build process.
394#
mistachkin391b3642012-07-31 00:43:31 +0000395set pattern {^#define\s+SQLITE_VERSION\s+"(.*)"$}
mistachkin48680192012-07-27 02:36:06 +0000396set data [readFile [file join $sourceDirectory sqlite3.h]]
397
398if {![regexp -line -- $pattern $data dummy version]} then {
399 fail [appendArgs "cannot locate SQLITE_VERSION value in \"" \
400 [file join $sourceDirectory sqlite3.h] \"]
401}
402
403###############################################################################
404
405#
mistachkin0f801702012-10-20 08:40:05 +0000406# NOTE: Setup all the master file list data. This includes the source file
407# names, the destination file names, and the file processing flags. The
408# possible file processing flags are:
409#
410# "buildNeutral" -- This flag indicates the file location and content do
411# not depend on the build configuration.
412#
413# "platformNeutral" -- This flag indicates the file location and content
414# do not depend on the build platform.
415#
416# "subst" -- This flag indicates that the file contains dynamic textual
417# content that needs to be processed using [subst] prior to
418# packaging the file into the final VSIX package. The primary
419# use of this flag is to insert the name of the VSIX package,
420# some package flavor-specific value, or the SQLite version
421# into a file.
422#
423# "noDebug" -- This flag indicates that the file should be skipped when
424# processing the debug build.
425#
426# "noRetail" -- This flag indicates that the file should be skipped when
427# processing the retail build.
428#
429# "move" -- This flag indicates that the file should be moved from the
430# source to the destination instead of being copied.
431#
432# This file metadata may be overridden, either in whole or in part, via
433# the user-specific customizations file.
mistachkin48680192012-07-27 02:36:06 +0000434#
mistachkin391b3642012-07-31 00:43:31 +0000435if {![info exists fileNames(source)]} then {
mistachkin0f801702012-10-20 08:40:05 +0000436 set fileNames(source) [list "" "" \
437 [file join $stagingDirectory DesignTime <build> <platform> sqlite3.props] \
438 [file join $sourceDirectory sqlite3.h] \
439 [file join $binaryDirectory <build> <platform> sqlite3.lib] \
440 [file join $binaryDirectory <build> <platform> sqlite3.dll]]
mistachkin48680192012-07-27 02:36:06 +0000441
mistachkin391b3642012-07-31 00:43:31 +0000442 if {![info exists no(symbols)]} then {
443 lappend fileNames(source) \
mistachkin0ec07442012-10-12 18:06:07 +0000444 [file join $binaryDirectory <build> <platform> sqlite3.pdb]
mistachkin391b3642012-07-31 00:43:31 +0000445 }
446}
mistachkin48680192012-07-27 02:36:06 +0000447
mistachkin391b3642012-07-31 00:43:31 +0000448if {![info exists fileNames(destination)]} then {
449 set fileNames(destination) [list \
mistachkin0f801702012-10-20 08:40:05 +0000450 [file join $stagingDirectory extension.vsixmanifest] \
451 [file join $stagingDirectory SDKManifest.xml] \
452 [file join $stagingDirectory DesignTime <build> <platform> <name>.props] \
453 [file join $stagingDirectory DesignTime <build> <platform> sqlite3.h] \
454 [file join $stagingDirectory DesignTime <build> <platform> sqlite3.lib] \
455 [file join $stagingDirectory Redist <build> <platform> sqlite3.dll]]
mistachkin391b3642012-07-31 00:43:31 +0000456
457 if {![info exists no(symbols)]} then {
458 lappend fileNames(destination) \
mistachkin0ec07442012-10-12 18:06:07 +0000459 [file join $stagingDirectory Redist <build> <platform> sqlite3.pdb]
mistachkin391b3642012-07-31 00:43:31 +0000460 }
461}
462
mistachkin0f801702012-10-20 08:40:05 +0000463if {![info exists fileNames(flags)]} then {
464 set fileNames(flags) [list \
465 [list buildNeutral platformNeutral subst] \
466 [list buildNeutral platformNeutral subst] \
467 [list buildNeutral platformNeutral subst move] \
468 [list buildNeutral platformNeutral] \
469 [list] [list] [list noRetail]]
mistachkin391b3642012-07-31 00:43:31 +0000470
471 if {![info exists no(symbols)]} then {
mistachkin0f801702012-10-20 08:40:05 +0000472 lappend fileNames(flags) [list noRetail]
mistachkin0ec07442012-10-12 18:06:07 +0000473 }
474}
475
476###############################################################################
477
478#
mistachkin0f801702012-10-20 08:40:05 +0000479# NOTE: Setup the list of builds supported by this script. These may be
480# overridden via the user-specific customizations file.
mistachkin0ec07442012-10-12 18:06:07 +0000481#
482if {![info exists buildNames]} then {
483 set buildNames [list Debug Retail]
484}
485
mistachkin48680192012-07-27 02:36:06 +0000486###############################################################################
487
488#
mistachkin0f801702012-10-20 08:40:05 +0000489# NOTE: Setup the list of platforms supported by this script. These may be
490# overridden via the command line or the user-specific customizations
491# file.
mistachkin48680192012-07-27 02:36:06 +0000492#
mistachkin391b3642012-07-31 00:43:31 +0000493if {![info exists platformNames]} then {
mistachkin50afa2a2012-07-31 08:15:56 +0000494 set platformNames [list x86 x64 ARM]
mistachkin391b3642012-07-31 00:43:31 +0000495}
mistachkin48680192012-07-27 02:36:06 +0000496
497###############################################################################
498
499#
500# NOTE: Make sure the staging directory exists, creating it if necessary.
501#
502file mkdir $stagingDirectory
503
504#
mistachkin0f801702012-10-20 08:40:05 +0000505# NOTE: Build the Tcl command used to extract the template VSIX package to
506# the staging directory.
mistachkin48680192012-07-27 02:36:06 +0000507#
508set extractCommand [list exec -- $unzip $templateFile -d $stagingDirectory]
509
510#
mistachkin0f801702012-10-20 08:40:05 +0000511# NOTE: Extract the template VSIX package to the staging directory.
mistachkin48680192012-07-27 02:36:06 +0000512#
513eval $extractCommand
514
515###############################################################################
516
517#
mistachkin0f801702012-10-20 08:40:05 +0000518# NOTE: Process each file in the master file list. There are actually three
mistachkin21890122012-10-15 20:28:22 +0000519# parallel lists that contain the source file names, the destination file
mistachkin0f801702012-10-20 08:40:05 +0000520# names, and the file processing flags. If the "buildNeutral" flag is
521# present, the file location and content do not depend on the build
522# configuration and "CommonConfiguration" will be used in place of the
523# build configuration name. If the "platformNeutral" flag is present,
524# the file location and content do not depend on the build platform and
525# "neutral" will be used in place of the build platform name. If the
526# "subst" flag is present, the file is assumed to be a text file that may
527# contain Tcl variable, command, and backslash replacements, to be
528# dynamically replaced during processing using the Tcl [subst] command.
529# If the "noDebug" flag is present, the file will be skipped when
530# processing for the debug build. If the "noRetail" flag is present, the
531# file will be skipped when processing for the retail build. If the
532# "move" flag is present, the source file will be deleted after it is
533# copied to the destination file. If the source file name is an empty
534# string, the destination file name will be assumed to already exist in
535# the staging directory and will not be copied; however, Tcl variable,
536# command, and backslash replacements may still be performed on the
537# destination file prior to the final VSIX package being built if the
538# "subst" flag is present.
mistachkin48680192012-07-27 02:36:06 +0000539#
mistachkin21890122012-10-15 20:28:22 +0000540foreach sourceFileName $fileNames(source) \
541 destinationFileName $fileNames(destination) \
mistachkin0f801702012-10-20 08:40:05 +0000542 fileFlags $fileNames(flags) {
543 #
544 # NOTE: Process the file flags into separate boolean variables that may be
545 # used within the loop.
546 #
547 set isBuildNeutral [expr {[lsearch $fileFlags buildNeutral] != -1}]
548 set isPlatformNeutral [expr {[lsearch $fileFlags platformNeutral] != -1}]
549 set isMove [expr {[lsearch $fileFlags move] != -1}]
550 set useSubst [expr {[lsearch $fileFlags subst] != -1}]
551
mistachkin48680192012-07-27 02:36:06 +0000552 #
mistachkin0ec07442012-10-12 18:06:07 +0000553 # NOTE: If the current file is build-neutral, then only one build will
554 # be processed for it, namely "CommonConfiguration"; otherwise, each
555 # supported build will be processed for it individually.
mistachkin48680192012-07-27 02:36:06 +0000556 #
mistachkin0ec07442012-10-12 18:06:07 +0000557 foreach buildName \
mistachkin0f801702012-10-20 08:40:05 +0000558 [expr {$isBuildNeutral ? [list CommonConfiguration] : $buildNames}] {
mistachkin48680192012-07-27 02:36:06 +0000559 #
mistachkin0ec07442012-10-12 18:06:07 +0000560 # NOTE: Should the current file be skipped for this build?
mistachkin391b3642012-07-31 00:43:31 +0000561 #
mistachkin0f801702012-10-20 08:40:05 +0000562 if {[lsearch $fileFlags no${buildName}] != -1} then {
mistachkin0ec07442012-10-12 18:06:07 +0000563 continue
mistachkin48680192012-07-27 02:36:06 +0000564 }
565
566 #
mistachkin0ec07442012-10-12 18:06:07 +0000567 # NOTE: If the current file is platform-neutral, then only one platform
568 # will be processed for it, namely "neutral"; otherwise, each
569 # supported platform will be processed for it individually.
mistachkin48680192012-07-27 02:36:06 +0000570 #
mistachkin0ec07442012-10-12 18:06:07 +0000571 foreach platformName \
mistachkin0f801702012-10-20 08:40:05 +0000572 [expr {$isPlatformNeutral ? [list neutral] : $platformNames}] {
mistachkin48680192012-07-27 02:36:06 +0000573 #
mistachkin0ec07442012-10-12 18:06:07 +0000574 # NOTE: Use the actual platform name in the destination file name.
mistachkin48680192012-07-27 02:36:06 +0000575 #
mistachkin0f801702012-10-20 08:40:05 +0000576 set newDestinationFileName [replaceFileNameTokens $destinationFileName \
577 $shortName $buildName $platformName]
mistachkin0ec07442012-10-12 18:06:07 +0000578
579 #
580 # NOTE: Does the source file need to be copied to the destination file?
581 #
582 if {[string length $sourceFileName] > 0} then {
583 #
584 # NOTE: First, make sure the destination directory exists.
585 #
586 file mkdir [file dirname $newDestinationFileName]
587
588 #
589 # NOTE: Then, copy the source file to the destination file verbatim.
590 #
mistachkin0f801702012-10-20 08:40:05 +0000591 set newSourceFileName [replaceFileNameTokens $sourceFileName \
592 $shortName $buildName $platformName]
593
594 file copy $newSourceFileName $newDestinationFileName
595
596 #
597 # NOTE: If this is a move instead of a copy, delete the source file
598 # now.
599 #
600 if {$isMove} then {
601 file delete $newSourceFileName
602 }
mistachkin0ec07442012-10-12 18:06:07 +0000603 }
604
605 #
606 # NOTE: Does the destination file contain dynamic replacements that must
607 # be processed now?
608 #
609 if {$useSubst} then {
610 #
611 # NOTE: Perform any dynamic replacements contained in the destination
612 # file and then re-write it in-place.
613 #
614 substFile $newDestinationFileName
615 }
mistachkin48680192012-07-27 02:36:06 +0000616 }
617 }
618}
619
620###############################################################################
621
622#
623# NOTE: Change the current directory to the staging directory so that the
624# external archive building tool can pickup the necessary files using
625# relative paths.
626#
627cd $stagingDirectory
628
629#
mistachkin0f801702012-10-20 08:40:05 +0000630# NOTE: Build the Tcl command used to archive the final VSIX package in the
mistachkin48680192012-07-27 02:36:06 +0000631# output directory.
632#
633set archiveCommand [list exec -- $zip -r $outputFile *]
634
635#
mistachkin0f801702012-10-20 08:40:05 +0000636# NOTE: Build the final VSIX package archive in the output directory.
mistachkin48680192012-07-27 02:36:06 +0000637#
638eval $archiveCommand
639
640#
641# NOTE: Change back to the previously saved current directory.
642#
643cd $currentDirectory
644
645#
646# NOTE: Cleanup the temporary staging directory.
647#
648file delete -force $stagingDirectory
649
650###############################################################################
651
652#
653# NOTE: Success, emit the fully qualified path of the generated VSIX file.
654#
655puts stdout $outputFile