buildtclext.tcl 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #!/usr/bin/tclsh
  2. #
  3. set help \
  4. {Run this TCL script to build and install the TCL interface library for
  5. SQLite. Run the script with the specific "tclsh" for which the installation
  6. should occur.
  7. There must be a valid "tclsqlite3.c" file in the working directory prior
  8. to running this script. Use "make tclsqlite3.c" to generate that file.
  9. Options:
  10. --build-only Only build the extension, don't install it
  11. --cc COMPILER Build using this compiler
  12. --info Show info on existing SQLite TCL extension installs
  13. --install-only Install an extension previously build
  14. --uninstall Uninstall the extension
  15. --destdir DIR Installation root (used by "make install DESTDIR=...")
  16. Other options are retained and passed through into the compiler.}
  17. set build 1
  18. set install 1
  19. set uninstall 0
  20. set infoonly 0
  21. set CC {}
  22. set OPTS {}
  23. set DESTDIR ""; # --destdir "$(DESTDIR)"
  24. for {set ii 0} {$ii<[llength $argv]} {incr ii} {
  25. set a0 [lindex $argv $ii]
  26. if {$a0=="--install-only"} {
  27. set build 0
  28. } elseif {$a0=="--build-only"} {
  29. set install 0
  30. } elseif {$a0=="--uninstall"} {
  31. set build 0
  32. set install 0
  33. set uninstall 1
  34. } elseif {$a0=="--info"} {
  35. set build 0
  36. set install 0
  37. set infoonly 1
  38. } elseif {$a0=="--cc" && $ii+1<[llength $argv]} {
  39. incr ii
  40. set CC [lindex $argv $ii]
  41. } elseif {$a0=="--destdir" && $ii+1<[llength $argv]} {
  42. incr ii
  43. set DESTDIR [lindex $argv $ii]
  44. } elseif {[string match -* $a0]} {
  45. append OPTS " $a0"
  46. } else {
  47. puts stderr "Unknown option: \"$a0\"\n"
  48. puts stderr $help
  49. exit 1
  50. }
  51. }
  52. # Find the root of the SQLite source tree
  53. #
  54. set srcdir [file normalize [file dir $argv0]/..]
  55. # Get the SQLite version number into $VERSION
  56. #
  57. set fd [open $srcdir/VERSION]
  58. set VERSION [string trim [read $fd]]
  59. close $fd
  60. if {$tcl_platform(platform)=="windows"} {
  61. # We are only able to install, uninstall, and list on Windows.
  62. # The build process is handled by the Makefile.msc, specifically
  63. # using "nmake /f Makefile.msc pkgIndex.tcl tclsqlite3.dll"
  64. #
  65. if {$build} {
  66. puts "Unable to build on Windows using the builttclext.tcl script."
  67. puts "To build, run\n"
  68. puts " \"nmake /f Makefile.msc pkgIndex.tcl tclsqlite3.dll"
  69. exit 1
  70. }
  71. set OUT tclsqlite3.dll
  72. } else {
  73. # Figure out the location of the tclConfig.sh file used by the
  74. # tclsh that is executing this script.
  75. #
  76. if {[catch {
  77. set LIBDIR [tcl::pkgconfig get libdir,install]
  78. }]} {
  79. puts stderr "$argv0: tclsh does not support tcl::pkgconfig."
  80. exit 1
  81. }
  82. if {![file exists $LIBDIR]} {
  83. puts stderr "$argv0: cannot find the tclConfig.sh file."
  84. puts stderr "$argv0: tclsh reported library directory \"$LIBDIR\"\
  85. does not exist."
  86. exit 1
  87. }
  88. if {![file exists $LIBDIR/tclConfig.sh]
  89. || [file size $LIBDIR/tclConfig.sh]<5000} {
  90. set n1 $LIBDIR/tcl$::tcl_version
  91. if {[file exists $n1/tclConfig.sh]
  92. && [file size $n1/tclConfig.sh]>5000} {
  93. set LIBDIR $n1
  94. } else {
  95. puts stderr "$argv0: cannot find tclConfig.sh in either $LIBDIR or $n1"
  96. exit 1
  97. }
  98. }
  99. # Read the tclConfig.sh file into the $tclConfig variable
  100. #
  101. #puts "using $LIBDIR/tclConfig.sh"
  102. set fd [open $LIBDIR/tclConfig.sh rb]
  103. set tclConfig [read $fd]
  104. close $fd
  105. # Extract parameter we will need from the tclConfig.sh file
  106. #
  107. set TCLMAJOR 8
  108. regexp {TCL_MAJOR_VERSION='(\d)'} $tclConfig all TCLMAJOR
  109. set SUFFIX so
  110. regexp {TCL_SHLIB_SUFFIX='\.([^']+)'} $tclConfig all SUFFIX
  111. if {$CC==""} {
  112. set cc {}
  113. regexp {TCL_CC='([^']+)'} $tclConfig all cc
  114. if {$cc!=""} {
  115. set CC $cc
  116. }
  117. }
  118. if {$CC==""} {
  119. set CC gcc
  120. }
  121. set CFLAGS -fPIC
  122. regexp {TCL_SHLIB_CFLAGS='([^']+)'} $tclConfig all CFLAGS
  123. set LIBS {}
  124. regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBS
  125. set INC "-I$srcdir/src"
  126. set inc {}
  127. regexp {TCL_INCLUDE_SPEC='([^']+)'} $tclConfig all inc
  128. if {$inc!=""} {
  129. append INC " $inc"
  130. }
  131. set cmd {${CC} ${CFLAGS} ${LDFLAGS} -shared}
  132. regexp {TCL_SHLIB_LD='([^']+)'} $tclConfig all cmd
  133. set LDFLAGS "$INC -DUSE_TCL_STUBS"
  134. if {[string length $OPTS]>1} {
  135. append LDFLAGS $OPTS
  136. }
  137. if {$TCLMAJOR>8} {
  138. set OUT libtcl9sqlite$VERSION.$SUFFIX
  139. } else {
  140. set OUT libsqlite$VERSION.$SUFFIX
  141. }
  142. set @ $OUT; # Workaround for https://sqlite.org/forum/forumpost/0683a49cb02f31a1
  143. # in which Gentoo edits their tclConfig.sh to include an soname
  144. # linker flag which includes ${@} (the target file's name).
  145. set CMD [subst $cmd]
  146. }
  147. # Show information about prior installs
  148. #
  149. if {$infoonly} {
  150. set cnt 0
  151. foreach dir $auto_path {
  152. foreach subdir [glob -nocomplain -types d $dir/sqlite3*] {
  153. if {[file exists $subdir/pkgIndex.tcl]} {
  154. puts $subdir
  155. incr cnt
  156. }
  157. }
  158. }
  159. if {$cnt==0} {
  160. puts "no current installations of the SQLite TCL extension"
  161. }
  162. exit
  163. }
  164. # Uninstall the extension
  165. #
  166. if {$uninstall} {
  167. set cnt 0
  168. foreach dir $auto_path {
  169. if {[file isdirectory $dir/sqlite$VERSION]} {
  170. incr cnt
  171. if {![file writable $dir] || ![file writable $dir/sqlite$VERSION]} {
  172. puts "cannot uninstall $dir/sqlite$VERSION - permission denied"
  173. } else {
  174. puts "uninstalling $dir/sqlite$VERSION..."
  175. file delete -force $dir/sqlite$VERSION
  176. }
  177. }
  178. }
  179. if {$cnt==0} {
  180. puts "nothing to uninstall"
  181. }
  182. exit
  183. }
  184. if {$install} {
  185. # Figure out where the extension will be installed. Put the extension
  186. # in the first writable directory on $auto_path.
  187. #
  188. set DEST {}
  189. foreach dir $auto_path {
  190. if {[string match //*:* $dir]} {
  191. # We can't install to //zipfs: paths
  192. continue
  193. } elseif {"" ne $DESTDIR && ![file writable $DESTDIR]} {
  194. # In the common case, ${DESTDIR}${dir} will not exist when we
  195. # get to this point of the installation, and the "is writable?"
  196. # check just below this will fail for that case.
  197. #
  198. # Assumption made for simplification's sake: if ${DESTDIR} is
  199. # not writable, no part of the remaining path will
  200. # be. ${DESTDIR} is typically used by OS package maintainers,
  201. # not normal installations, and it "shouldn't" ever happen that
  202. # the DESTDIR is read-only while the target ${DESTDIR}${prefix}
  203. # is not, as it's typical for such installations to create
  204. # ${prefix} on-demand under ${DESTDIR}.
  205. break
  206. }
  207. set dir ${DESTDIR}$dir
  208. if {[file writable $dir] || "" ne $DESTDIR} {
  209. # the dir will be created later ^^^^^^^^
  210. set DEST $dir
  211. break
  212. } elseif {[glob -nocomplain $dir/sqlite3*/pkgIndex.tcl]!=""} {
  213. set conflict [lindex [glob $dir/sqlite3*/pkgIndex.tcl] 0]
  214. puts "Unable to install. There is already a conflicting version"
  215. puts "of the SQLite TCL Extension that cannot be overwritten at\n"
  216. puts " [file dirname $conflict]\n"
  217. puts "Consider running using sudo to work around this problem."
  218. exit 1
  219. }
  220. }
  221. if {$DEST==""} {
  222. puts "None of the directories on \$auto_path are writable by this process,"
  223. puts "so the installation cannot take place. Consider running using sudo"
  224. puts "to work around this problem.\n"
  225. puts "These are the (unwritable) \$auto_path directories:\n"
  226. foreach dir $auto_path {
  227. puts " * ${DESTDIR}$dir"
  228. }
  229. exit 1
  230. }
  231. }
  232. if {$build} {
  233. # Generate the pkgIndex.tcl file
  234. #
  235. puts "generating pkgIndex.tcl..."
  236. set fd [open pkgIndex.tcl w]
  237. puts $fd [subst -nocommands {# -*- tcl -*-
  238. # Tcl package index file, version ???
  239. #
  240. package ifneeded sqlite3 $VERSION \\
  241. [list load [file join \$dir $OUT] sqlite3]
  242. }]
  243. close $fd
  244. # Generate and execute the command with which to do the compilation.
  245. #
  246. set cmd "$CMD tclsqlite3.c -o $OUT $LIBS"
  247. puts $cmd
  248. file delete -force $OUT
  249. catch {exec {*}$cmd} errmsg
  250. if {$errmsg!="" && ![file exists $OUT]} {
  251. puts $errmsg
  252. exit 1
  253. }
  254. }
  255. if {$install} {
  256. # Install the extension
  257. set DEST2 $DEST/sqlite$VERSION
  258. file mkdir $DEST2
  259. puts "installing $DEST2/pkgIndex.tcl"
  260. file copy -force pkgIndex.tcl $DEST2
  261. puts "installing $DEST2/$OUT"
  262. file copy -force $OUT $DEST2
  263. }