sqlite/tool/buildtclext.tcl
drh dcea6335c7 New MSVC makefile targets: tclextension, tclextension-install,
tclextension-uninstall, and tclextension-list.

FossilOrigin-Name: c38734f57509c50dd28029738dd602600950703b773d9b7b60fdb1dcb06e8fd8
2024-08-02 15:28:40 +00:00

255 lines
6.6 KiB
Tcl

#!/usr/bin/tclsh
#
set help \
{Run this TCL script to build and install the TCL interface library for
SQLite. Run the script with the specific "tclsh" for which the installation
should occur.
There must be a valid "tclsqlite3.c" file in the working directory prior
to running this script. Use "make tclsqlite3.c" to generate that file.
Options:
--build-only Only build the extension, don't install it
--cc COMPILER Build using this compiler
--info Show info on existing SQLite TCL extension installs
--install-only Install an extension previously build
--uninstall Uninstall the extension
Other options are retained and passed through into the compiler.}
set build 1
set install 1
set uninstall 0
set infoonly 0
set CC {}
set OPTS {}
for {set ii 0} {$ii<[llength $argv]} {incr ii} {
set a0 [lindex $argv $ii]
if {$a0=="--install-only"} {
set build 0
} elseif {$a0=="--build-only"} {
set install 0
} elseif {$a0=="--uninstall"} {
set build 0
set install 0
set uninstall 1
} elseif {$a0=="--info"} {
set build 0
set install 0
set infoonly 1
} elseif {$a0=="--cc" && $ii+1<[llength $argv]} {
incr ii
set CC [lindex $argv $ii]
} elseif {[string match -* $a0]} {
append OPTS " $a0"
} else {
puts stderr "Unknown option: \"$a0\"\n"
puts stderr $help
exit 1
}
}
# Find the root of the SQLite source tree
#
set srcdir [file normalize [file dir $argv0]/..]
# Get the SQLite version number into $VERSION
#
set fd [open $srcdir/VERSION]
set VERSION [string trim [read $fd]]
close $fd
if {$tcl_platform(platform)=="windows"} {
# We are only able to install, uninstall, and list on Windows.
# The build process is handled by the Makefile.msc, specifically
# using "nmake /f Makefile.msc pkgIndex.tcl tclsqlite3.dll"
#
if {$build} {
puts "Unable to build on Windows using the builttclext.tcl script."
puts "To build, run\n"
puts " \"nmake /f Makefile.msc pkgIndex.tcl tclsqlite3.dll"
exit 1
}
set OUT tclsqlite3.dll
} else {
# Figure out the location of the tclConfig.sh file used by the
# tclsh that is executing this script.
#
if {[catch {
set LIBDIR [tcl::pkgconfig get libdir,install]
}]} {
puts stderr "$argv0: tclsh does not support tcl::pkgconfig."
exit 1
}
if {![file exists $LIBDIR]} {
puts stderr "$argv0: cannot find the tclConfig.sh file."
puts stderr "$argv0: tclsh reported library directory \"$LIBDIR\"\
does not exist."
exit 1
}
if {![file exists $LIBDIR/tclConfig.sh]
|| [file size $LIBDIR/tclConfig.sh]<5000} {
set n1 $LIBDIR/tcl$::tcl_version
if {[file exists $n1/tclConfig.sh]
&& [file size $n1/tclConfig.sh]>5000} {
set LIBDIR $n1
} else {
puts stderr "$argv0: cannot find tclConfig.sh in either $LIBDIR or $n1"
exit 1
}
}
# Read the tclConfig.sh file into the $tclConfig variable
#
#puts "using $LIBDIR/tclConfig.sh"
set fd [open $LIBDIR/tclConfig.sh rb]
set tclConfig [read $fd]
close $fd
# Extract parameter we will need from the tclConfig.sh file
#
set TCLMAJOR 8
regexp {TCL_MAJOR_VERSION='(\d)'} $tclConfig all TCLMAJOR
set SUFFIX so
regexp {TCL_SHLIB_SUFFIX='\.([^']+)'} $tclConfig all SUFFIX
if {$CC==""} {
set cc {}
regexp {TCL_CC='([^']+)'} $tclConfig all cc
if {$cc!=""} {
set CC $cc
}
}
if {$CC==""} {
set CC gcc
}
set CFLAGS -fPIC
regexp {TCL_SHLIB_CFLAGS='([^']+)'} $tclConfig all CFLAGS
set LIBS {}
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBS
set INC "-I$srcdir/src"
set inc {}
regexp {TCL_INCLUDE_SPEC='([^']+)'} $tclConfig all inc
if {$inc!=""} {
append INC " $inc"
}
set cmd {${CC} ${CFLAGS} ${LDFLAGS} -shared}
regexp {TCL_SHLIB_LD='([^']+)'} $tclConfig all cmd
set LDFLAGS "$INC -DUSE_TCL_STUBS"
if {[string length $OPTS]>1} {
append LDFLAGS $OPTS
}
set CMD [subst $cmd]
if {$TCLMAJOR>8} {
set OUT libtcl9sqlite$VERSION.$SUFFIX
} else {
set OUT libsqlite$VERSION.$SUFFIX
}
}
# Show information about prior installs
#
if {$infoonly} {
set cnt 0
foreach dir $auto_path {
foreach subdir [glob -nocomplain -types d $dir/sqlite3*] {
if {[file exists $subdir/pkgIndex.tcl]} {
puts $subdir
incr cnt
}
}
}
if {$cnt==0} {
puts "no current installations of the SQLite TCL extension"
}
exit
}
# Uninstall the extension
#
if {$uninstall} {
set cnt 0
foreach dir $auto_path {
if {[file isdirectory $dir/sqlite$VERSION]} {
incr cnt
if {![file writable $dir] || ![file writable $dir/sqlite$VERSION]} {
puts "cannot uninstall $dir/sqlite$VERSION - permission denied"
} else {
puts "uninstalling $dir/sqlite$VERSION..."
file delete -force $dir/sqlite$VERSION
}
}
}
if {$cnt==0} {
puts "nothing to uninstall"
}
exit
}
if {$install} {
# Figure out where the extension will be installed. Put the extension
# in the first writable directory on $auto_path.
#
set DEST {}
foreach dir $auto_path {
if {[file writable $dir]} {
set DEST $dir
break
} elseif {[glob -nocomplain $dir/sqlite3*/pkgIndex.tcl]!=""} {
set conflict [lindex [glob $dir/sqlite3*/pkgIndex.tcl] 0]
puts "Unable to install. There is already a conflicting version"
puts "of the SQLite TCL Extension that cannot be overwritten at\n"
puts " [file dirname $conflict]\n"
puts "Consider running using sudo to work around this problem."
exit 1
}
}
if {$DEST==""} {
puts "None of the directories on \$auto_path are writable by this process,"
puts "so the installation cannot take place. Consider running using sudo"
puts "to work around this problem.\n"
puts "These are the (unwritable) \$auto_path directories:\n"
foreach dir $auto_path {
puts " * $dir"
}
exit 1
}
}
if {$build} {
# Generate the pkgIndex.tcl file
#
puts "generating pkgIndex.tcl..."
set fd [open pkgIndex.tcl w]
puts $fd [subst -nocommands {# -*- tcl -*-
# Tcl package index file, version ???
#
package ifneeded sqlite3 $VERSION \\
[list load [file join \$dir $OUT] sqlite3]
}]
close $fd
# Generate and execute the command with which to do the compilation.
#
set cmd "$CMD tclsqlite3.c -o $OUT $LIBS"
puts $cmd
file delete -force $OUT
catch {exec {*}$cmd} errmsg
if {$errmsg!="" && ![file exists $OUT]} {
puts $errmsg
exit 1
}
}
if {$install} {
# Install the extension
set DEST2 $DEST/sqlite$VERSION
file mkdir $DEST2
puts "installing $DEST2/pkgIndex.tcl"
file copy -force pkgIndex.tcl $DEST2
puts "installing $DEST2/$OUT"
file copy -force $OUT $DEST2
}