# vim:se syn=tcl: # define JIM_VERSION 79 options-defaults { silent-rules 1 } # Note: modules which support options *must* be included before 'options' use cc cc-shared cc-db cc-lib pkg-config util use local options { utf8 => "include support for utf8-encoded strings" lineedit=1 => "disable line editing" references=1 => "disable support for references" math => "include support for math functions" ssl => "include ssl/tls support in the aio extension" ipv6 => "include ipv6 support in the aio extension" maintainer => {enable the [debug] command and JimPanic} full => "Enable some optional features: ipv6, ssl, math, utf8, binary, oo, tree" with-jim-shared shared => "build a shared library instead of a static library" jim-regexp=1 => "prefer POSIX regex if over the the built-in (Tcl-compatible) regex" docs=1 => "don't build or install the documentation" docdir:path => "path to install docs (if built)" random-hash => "randomise hash tables. more secure but hash table results are not predicable" with-jim-ext: {with-ext:"ext1,ext2,..."} => { Specify additional jim extensions to include. These are enabled by default: aio - ANSI I/O, including open and socket eventloop - after, vwait, update array - Tcl-compatible array command clock - Tcl-compatible clock command exec - Tcl-compatible exec command file - Tcl-compatible file command glob - Tcl-compatible glob command history - Tcl access to interactive history readdir - Required for glob package - Package management with the package command load - Load binary extensions at runtime with load or package posix - Posix APIs including os.fork, os.uptime regexp - Tcl-compatible regexp, regsub commands signal - Signal handling stdlib - Built-in commands including lassign, lambda, alias syslog - System logging with syslog tclcompat - Tcl compatible read, gets, puts, parray, case, ... namespace - Tcl compatible namespace support These are disabled by default, but enabled by --full: oo - Jim OO extension tree - OO tree structure, similar to tcllib ::struct::tree binary - Tcl-compatible 'binary' command tclprefix - Support for the tcl::prefix command zlib - Interface to zlib json - JSON encode/decode These are disabled unless explicitly enabled: readline - Interface to libreadline rlprompt - Tcl wrapper around the readline extension mk - Interface to Metakit sqlite3 - Interface to sqlite3 win32 - Interface to win32 } with-out-jim-ext: {without-ext:"default|ext1,ext2,..."} => { Specify jim extensions to exclude. If 'default' is given, the default extensions will not be added. } with-jim-extmod: {with-mod:"ext1,ext2,..."} => { Specify jim extensions to build as separate modules (either C or Tcl). Note that not all extensions can be built as loadable modules. } # To help out openocd with automake install-jim=1 } # Save the user-specified LIBS # We add detected libs to LDLIBS explicitly set LIBS [get-define LIBS] # In case -Werror is passed in CFLAGS, set -Wno-error when doing checks # to prevent warnings from becoming errors if {"-Werror" in [get-define CFLAGS] && [cctest -cflags -Wno-error]} { cc-with {-cflags -Wno-error} } cc-check-types "long long" cc-check-sizeof int define CCOPTS "" define CXXOPTS "" if {[cctest -cflags -fno-unwind-tables]} { define-append CCOPTS -fno-unwind-tables } if {[cctest -cflags -fno-asynchronous-unwind-tables]} { define-append CCOPTS -fno-asynchronous-unwind-tables } cc-check-includes sys/time.h sys/socket.h netinet/in.h arpa/inet.h netdb.h cc-check-includes sys/un.h dlfcn.h unistd.h dirent.h crt_externs.h define LDLIBS "" # Haiku needs -lnetwork, Solaris needs -lnsl if {[cc-check-function-in-lib inet_ntop {nsl network}]} { # This does nothing if no libs are needed cc-with [list -libs [get-define lib_inet_ntop]] define-append LDLIBS [get-define lib_inet_ntop] } # Solaris needs -lsocket, Windows needs -lwsock32 if {[cc-check-function-in-lib socket socket]} { define-append LDLIBS [get-define lib_socket] } cc-check-functions ualarm lstat fork vfork system select execvpe cc-check-functions geteuid mkstemp realpath isatty cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist isascii cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes cc-check-functions shutdown socketpair isinf isnan link symlink fsync dup umask cc-check-functions localtime gmtime strptime clock_gettime if {[cc-check-function-in-lib backtrace execinfo]} { define-append LDLIBS [get-define lib_backtrace] } if {[cc-check-functions sysinfo]} { cc-with {-includes sys/sysinfo.h} { cc-check-members "struct sysinfo.uptime" } } cc-with {-includes {sys/types.h sys/stat.h}} { cc-check-members "struct stat.st_mtimespec" cc-check-members "struct stat.st_mtim" } cc-with {-includes fcntl.h} { cc-check-types "struct flock" } cc-check-lfs cc-check-functions fseeko ftello define TCL_LIBRARY [get-define prefix]/lib/jim lassign [split [get-define host] -] host_cpu host_vendor host_os # Scrub revision from the host_os regsub -all {[0-9.]} $host_os {} host_os switch -glob -- $host_os { mingw* { # We provide our own implementation of dlopen for mingw32 define-feature dlopen-compat define-feature winconsole define TCL_PLATFORM_OS $host_os define TCL_PLATFORM_PLATFORM windows define TCL_PLATFORM_PATH_SEPARATOR {;} } default { # Note that cygwin is considered a unix platform define TCL_PLATFORM_OS $host_os define TCL_PLATFORM_PLATFORM unix define TCL_PLATFORM_PATH_SEPARATOR : } } # Find some tools cc-check-tools ar ranlib strip define tclsh [info nameofexecutable] # We only support silent-rules for GNU Make define NO_SILENT_RULES if {[get-define AM_SILENT_RULES 0]} { if {[cc-check-progs [get-define MAKE make]]} { # Are we using GNU make? catch {exec [get-define MAKE] --version} makeversion if {[string match "GNU Make*" $makeversion]} { define NO_SILENT_RULES 0 } } } if {[opt-bool docs]} { if {[cc-check-progs asciidoc sed]} { define INSTALL_DOCS docs define HAVE_ASCIIDOC } else { define INSTALL_DOCS shipped } } else { define INSTALL_DOCS nodocs } if {![cc-check-functions _NSGetEnviron]} { msg-checking "Checking environ declared in unistd.h..." if {[cctest -cflags {-D_GNU_SOURCE -D_POSIX_SOURCE} -includes unistd.h -code {char **ep = environ;}]} { define NO_ENVIRON_EXTERN msg-result "yes" } else { msg-result "no" } } # Windows has a mkdir with no permission arg cc-check-includes sys/types.h sys/stat.h msg-checking "Checking for mkdir with one arg..." if {[cctest -includes {sys/types.h sys/stat.h} -code {mkdir("/dummy");}]} { define HAVE_MKDIR_ONE_ARG msg-result yes } else { msg-result no } cc-with {-includes sys/stat.h} { foreach i {S_IXUSR S_IRWXG S_IRWXO} { if {![cc-check-decls $i]} { define $i 0 } } } set extra_objs {} set jimregexp 0 # Returns 1 if either the given option is enabled, or # --full is enabled and the option isn't explicitly disabled # proc opt-bool-or-full {opt} { if {[opt-bool $opt]} { return 1 } if {[opt-bool full] && [opt-bool -nodefault $opt] != 0} { return 1 } return 0 } if {[opt-bool-or-full utf8]} { msg-result "Enabling UTF-8" define JIM_UTF8 define-append CCOPTS -DUSE_UTF8 define PARSE_UNIDATA_FLAGS "" incr jimregexp } else { define JIM_UTF8 0 } if {[opt-bool maintainer]} { msg-result "Enabling maintainer settings" define JIM_MAINTAINER } # If --math or --full and not --disable-math if {[opt-bool-or-full math]} { msg-result "Enabling math functions" define JIM_MATH_FUNCTIONS cc-check-function-in-lib sin m define-append LDLIBS [get-define lib_sin] } if {[opt-bool-or-full ipv6]} { msg-result "Enabling IPv6" define JIM_IPV6 } define-append PKG_CONFIG_REQUIRES "" if {[opt-bool-or-full ssl]} { if {[pkg-config-init 0]} { foreach pkg {openssl libssl} { if {[pkg-config $pkg]} { define JIM_SSL define-append LDLIBS [pkg-config-get $pkg LIBS] define-append LDFLAGS [pkg-config-get $pkg LDFLAGS] define-append CCOPTS [pkg-config-get $pkg CFLAGS] msg-result "Enabling SSL ($pkg)" define-append PKG_CONFIG_REQUIRES $pkg break } } } if {![is-defined JIM_SSL]} { if {[cc-check-includes openssl/ssl.h] && [cc-check-function-in-lib ERR_error_string crypto] && [cc-check-function-in-lib TLSv1_2_method ssl]} { msg-result "Enabling SSL" define JIM_SSL define-append LDLIBS [get-define lib_ERR_error_string] [get-define lib_TLSv1_2_method] } elseif {[opt-bool ssl]} { user-error "SSL support requires OpenSSL" } } # Later versions deprecate TLSv1_2_method, but older versions don't have TLS_method if {![cc-check-function-in-lib TLS_method ssl]} { define-append CCOPTS -DUSE_TLSv1_2_method } } if {[opt-bool-or-full lineedit]} { if {([cc-check-includes termios.h] && [have-feature isatty]) || [have-feature winconsole]} { msg-result "Enabling line editing" define USE_LINENOISE define-append PARSE_UNIDATA_FLAGS -width lappend extra_objs linenoise.o if {[cc-check-inline] && [is-defined inline]} { define-append CCOPTS -Dinline=[get-define inline] } } } if {[opt-bool references]} { msg-result "Enabling references" define JIM_REFERENCES } if {[opt-bool shared with-jim-shared]} { msg-result "Building shared library" } else { msg-result "Building static library" define JIM_STATICLIB } define VERSION [format %.2f [expr {[get-define JIM_VERSION] / 100.0}]] define LIBSOEXT [format [get-define SH_SOEXTVER] [get-define VERSION]] # Disable RPATH support in Debian builds define SH_LINKRPATH_FLAGS "" define JIM_INSTALL [opt-bool install-jim] define JIM_DOCS [opt-bool docs] define JIM_RANDOMISE_HASH [opt-bool random-hash] define docdir [opt-str docdir o {${prefix}/docs/jim}] # Attributes of the extensions # tcl=Pure Tcl extension # static=Can't be built as a module # off=Off unless explicitly enabled # optional=Off by default, but selected by --full # cpp=Is a C++ extension global extdb dict set extdb attrs { aio { static } array {} binary { tcl optional } clock {} eventloop { static } exec { static } file {} glob { tcl } history {} interp { } json { optional } jsonencode { tcl optional } load { static } mk { cpp off } namespace { static } nshelper { tcl optional } oo { tcl } pack {} package { static } posix {} readdir {} readline { off } regexp {} rlprompt { tcl off } sdl { off } signal { static } sqlite3 { off } zlib { optional } stdlib { tcl static } syslog {} tclcompat { tcl static } tclprefix { optional } tree { tcl } win32 { off } } # Additional information about certain extensions # dep=list of extensions which are required for this extension # check=[expr] expression to evaluate to determine if the extension can be used # libdep=list of 'define' symbols for dependent libraries dict set extdb info { binary { dep pack } exec { check {([have-feature vfork] && [have-feature waitpid]) || [have-feature system]} } glob { dep readdir } load { check {[have-feature dlopen-compat] || [cc-check-function-in-lib dlopen dl]} libdep lib_dlopen } mk { check {[check-metakit]} libdep lib_mk } namespace { dep nshelper } json { dep jsonencode extrasrcs jsmn/jsmn.c } posix { check {[have-feature waitpid]} } readdir { check {[have-feature opendir]} } readline { pkg-config readline check {[cc-check-function-in-lib readline readline]} libdep lib_readline} rlprompt { dep readline } tree { dep oo } sdl { pkg-config SDL_gfx check {[cc-check-function-in-lib SDL_SetVideoMode SDL] && [cc-check-function-in-lib rectangleRGBA SDL_gfx]} libdep {lib_SDL_SetVideoMode lib_rectangleRGBA} } signal { check {[have-feature sigaction]} } sqlite3 { pkg-config sqlite3 check {[cc-check-function-in-lib sqlite3_prepare_v2 sqlite3]} libdep lib_sqlite3_prepare_v2 } zlib { pkg-config zlib check {[cc-check-function-in-lib deflate z]} libdep lib_deflate } syslog { check {[have-feature syslog]} } tree { dep oo } win32 { check {[have-feature windows]} } } # autosetup cc-check-function-in-library can't handle C++ libraries proc check-metakit {} { set found 0 msg-checking "Checking for Metakit..." cc-with {-lang c++} { if {[cctest -includes mk4.h -libs -lmk4 -code {c4_Storage dummy();}]} { msg-result ok define lib_mk -lmk4 incr found } else { msg-result "not found" } } return $found } # Takes a list of module names, separated by spaces or commas # and returns them as a single list proc join-ext-names {list} { set result {} # Replace comma with space in each list then concatenate the result foreach l $list { lappend result {*}[string map {, " "} $l] } return $result } # Set up the withinfo array based on what the user selected global withinfo set withinfo(without) [join-ext-names [opt-val {without-ext with-out-jim-ext}]] set withinfo(ext) [join-ext-names [opt-val {with-ext with-jim-ext}]] set withinfo(mod) [join-ext-names [opt-val {with-mod with-jim-extmod}]] set withinfo(nodefault) 0 set withinfo(optional) [opt-bool full] if {$withinfo(without) eq "default"} { set withinfo(without) {} set withinfo(nodefault) 1 } # Now go check everything - see autosetup/local.tcl array set extinfo [check-extensions] # Now special checks if {[have-feature windows]} { lappend extra_objs jim-win32compat.o if {[llength $extinfo(module-c)] && [get-define JIM_STATICLIB]} { user-error "cygwin/mingw require --shared for dynamic modules" } } if {[have-feature termios.h]} { lappend extra_objs jim-tty.o } if {[ext-get-status regexp] in {y m}} { if {![have-feature regcomp]} { # No regcomp means we need to use the built-in version incr jimregexp } } if {$jimregexp || [opt-bool jim-regexp]} { msg-result "Using built-in regexp" define JIM_REGEXP # If the built-in regexp overrides the system regcomp, etc. # jim must be built shared so that the correct symbols are found if {[ext-get-status regexp] eq "m" && [get-define JIM_STATICLIB] && [have-feature regcomp]} { user-error "Must use --shared with regexp module and built-in regexp" } } foreach mod $extinfo(static-c) { if {[dict exists $extdb info $mod extrasrcs]} { foreach src [dict get $extdb info $mod extrasrcs] { # In case we are building out-of-tree and $src is in a subdir file mkdir [file dirname $src] lappend extra_objs {*}[file rootname $src].o } } } # poor-man's signals if {"signal" ni $extinfo(static-c)} { lappend extra_objs jim-nosignal.o } if {[ext-get-status load] eq "n"} { # If we don't have load, no need to support shared objects define SH_LINKFLAGS "" } # Are we cross compiling? if {[get-define host] ne [get-define build]} { define cross_compiling 1 } else { define cross_compiling 0 } msg-result "Jim static extensions: [lsort [concat $extinfo(static-tcl) $extinfo(static-c)]]" if {[llength $extinfo(module-tcl)]} { msg-result "Jim Tcl extensions: [lsort $extinfo(module-tcl)]" } if {[llength $extinfo(module-c)]} { msg-result "Jim dynamic extensions: [lsort $extinfo(module-c)]" } define STATIC_EXTS [concat $extinfo(static-c) $extinfo(static-tcl)] define C_EXT_OBJS [prefix jim- [suffix .o $extinfo(static-c)]] define TCL_EXT_OBJS [suffix .o $extinfo(static-tcl)] define C_EXT_SHOBJS [suffix .so $extinfo(module-c)] define TCL_EXTS [suffix .tcl $extinfo(module-tcl)] define EXTRA_OBJS $extra_objs # Restore the user-specified LIBS define LIBS $LIBS # Now generate the Makefile rules to build the external C shared objects # It is easier to do this here rather than listing them out explicitly in Makefile.in set lines {} foreach mod $extinfo(module-c) { set objs {} set libs [get-define LDLIBS_$mod] set srcs jim-$mod.c if {[dict exists $extdb info $mod extrasrcs]} { lappend srcs {*}[dict get $extdb info $mod extrasrcs] } lappend lines "$mod.so: $srcs" foreach src $srcs { set obj [file rootname $src].o lappend objs $obj lappend lines "\t\$(ECHO)\t\"\tCC\t$obj\"" lappend lines "\t\$(Q)\$(CC) \$(CFLAGS) \$(SHOBJ_CFLAGS) -c -o $obj $src" } lappend lines "\t\$(ECHO)\t\"\tLDSO\t\$@\"" lappend lines "\t\$(Q)\$(CC) \$(CFLAGS) \$(LDFLAGS) \$(SHOBJ_LDFLAGS) -o \$@ $objs \$(SH_LIBJIM) $libs" lappend lines "" } define BUILD_SHOBJS [join $lines \n] make-config-header jim-config.h -auto {HAVE_LONG_LONG* JIM_UTF8 SIZEOF_INT} -bare JIM_VERSION -none * make-config-header jimautoconf.h -auto {jim_ext_* TCL_PLATFORM_* TCL_LIBRARY USE_* JIM_* _FILE_OFFSET*} -bare {S_I*} make-template Makefile.in make-template tests/Makefile.in make-template build-jim-ext.in make-template jimtcl.pc.in catch {exec chmod +x build-jim-ext}