123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- #!/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
- --destdir DIR Installation root (used by "make install DESTDIR=...")
- 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 {}
- set DESTDIR ""; # --destdir "$(DESTDIR)"
- 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 {$a0=="--destdir" && $ii+1<[llength $argv]} {
- incr ii
- set DESTDIR [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
- }
- if {$TCLMAJOR>8} {
- set OUT libtcl9sqlite$VERSION.$SUFFIX
- } else {
- set OUT libsqlite$VERSION.$SUFFIX
- }
- set @ $OUT; # Workaround for https://sqlite.org/forum/forumpost/0683a49cb02f31a1
- # in which Gentoo edits their tclConfig.sh to include an soname
- # linker flag which includes ${@} (the target file's name).
- set CMD [subst $cmd]
- }
- # 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 {[string match //*:* $dir]} {
- # We can't install to //zipfs: paths
- continue
- } elseif {"" ne $DESTDIR && ![file writable $DESTDIR]} {
- # In the common case, ${DESTDIR}${dir} will not exist when we
- # get to this point of the installation, and the "is writable?"
- # check just below this will fail for that case.
- #
- # Assumption made for simplification's sake: if ${DESTDIR} is
- # not writable, no part of the remaining path will
- # be. ${DESTDIR} is typically used by OS package maintainers,
- # not normal installations, and it "shouldn't" ever happen that
- # the DESTDIR is read-only while the target ${DESTDIR}${prefix}
- # is not, as it's typical for such installations to create
- # ${prefix} on-demand under ${DESTDIR}.
- break
- }
- set dir ${DESTDIR}$dir
- if {[file writable $dir] || "" ne $DESTDIR} {
- # the dir will be created later ^^^^^^^^
- 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 " * ${DESTDIR}$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
- }
|