240 lines
4.7 KiB
Plaintext
240 lines
4.7 KiB
Plaintext
|
#!/usr/bin/env jimsh
|
||
|
|
||
|
# Separate command line arguments into options and source files
|
||
|
set opts {}
|
||
|
set sources {}
|
||
|
|
||
|
proc usage {{msg {}}} {
|
||
|
puts stderr "Usage: build-jim-ext ?--notest? ?--cross? ?--install? ?--static? ?cc-options? ?-o modname? sources..."
|
||
|
if {$msg ne ""} {
|
||
|
puts stderr \n$msg
|
||
|
}
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
set linker "@CC@"
|
||
|
set testmod 1
|
||
|
set cross @cross_compiling@
|
||
|
set install 0
|
||
|
set static 0
|
||
|
set verbose 0
|
||
|
set keep 0
|
||
|
set includepaths {}
|
||
|
set libpaths {}
|
||
|
set libs {}
|
||
|
for {set i 0} {$i < [llength $argv]} {incr i} {
|
||
|
set arg [lindex $argv $i]
|
||
|
switch -glob -- $arg {
|
||
|
*.c {
|
||
|
lappend sources $arg
|
||
|
}
|
||
|
*.cpp {
|
||
|
lappend sources $arg
|
||
|
set linker "@CXX@"
|
||
|
}
|
||
|
--notest {
|
||
|
# Don't test to see if the module can be loaded
|
||
|
set testmod 0
|
||
|
}
|
||
|
--cross {
|
||
|
# Don't use standard include/lib paths if cross compiling
|
||
|
set cross 1
|
||
|
}
|
||
|
--install {
|
||
|
# Install to $DESTDIR/@prefix@/lib/jim
|
||
|
set install 1
|
||
|
}
|
||
|
--static {
|
||
|
# Build a static extension that can be linked
|
||
|
set static 1
|
||
|
}
|
||
|
--verbose {
|
||
|
set verbose 1
|
||
|
}
|
||
|
--keep {
|
||
|
# Don't remove intermediate files
|
||
|
set keep 1
|
||
|
}
|
||
|
--help {
|
||
|
usage "Easily builds dynamic (loadable) modules for jim"
|
||
|
}
|
||
|
-o {
|
||
|
incr i
|
||
|
set modname [file rootname [lindex $argv $i]]
|
||
|
if {$modname eq ""} {
|
||
|
usage "Option -o requires an argument"
|
||
|
}
|
||
|
}
|
||
|
-I* {
|
||
|
lappend includepaths $arg
|
||
|
if {$arg eq "-I"} {
|
||
|
lappend includepaths [lindex $argv $i]
|
||
|
}
|
||
|
}
|
||
|
-L* {
|
||
|
lappend libpaths $arg
|
||
|
if {$arg eq "-L"} {
|
||
|
lappend libpaths [lindex $argv $i]
|
||
|
}
|
||
|
}
|
||
|
-l* {
|
||
|
lappend libs $arg
|
||
|
}
|
||
|
-* {
|
||
|
lappend opts $arg
|
||
|
}
|
||
|
default {
|
||
|
usage "Unexpected '$arg'"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if {$sources eq ""} {
|
||
|
usage "No sources provided"
|
||
|
}
|
||
|
if {![info exists modname]} {
|
||
|
set modname [file rootname [file tail [lindex $sources 0]]]
|
||
|
# Remove jim- prefix if one exists
|
||
|
regsub "^jim-" $modname "" modname
|
||
|
}
|
||
|
|
||
|
if {$static} {
|
||
|
set target libjim-$modname.a
|
||
|
} else {
|
||
|
set target $modname.so
|
||
|
}
|
||
|
puts "Building $target from $sources\n"
|
||
|
|
||
|
if {!$cross} {
|
||
|
# If not cross compiling, add the standard location after any user include paths
|
||
|
lappend includepaths -I@prefix@/include
|
||
|
}
|
||
|
|
||
|
# Work around Tcl's strange behaviour of exec failing if stderr is produced
|
||
|
#
|
||
|
proc exec-catch {verbose cmdlist} {
|
||
|
if {$verbose} {
|
||
|
puts [join $cmdlist]
|
||
|
}
|
||
|
flush stdout
|
||
|
set rc [catch {
|
||
|
exec {*}$cmdlist
|
||
|
} msg errinfo]
|
||
|
|
||
|
# Handle failed case.
|
||
|
# Note that Tcl returns rc=1 if there is any stderr,
|
||
|
# even if the exit code is 0
|
||
|
if {$rc} {
|
||
|
if {[dict get $errinfo -errorcode] ne "NONE"} {
|
||
|
if {!$verbose} {
|
||
|
puts stderr [join $cmdlist]
|
||
|
}
|
||
|
puts stderr $msg
|
||
|
return 1
|
||
|
}
|
||
|
}
|
||
|
if {$msg ne ""} {
|
||
|
puts stderr $msg
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
set CPPFLAGS "-D_GNU_SOURCE"
|
||
|
|
||
|
set ljim ""
|
||
|
set shobj_cflags ""
|
||
|
set shobj_ldflags ""
|
||
|
if {!$static} {
|
||
|
set shobj_cflags "@SHOBJ_CFLAGS@"
|
||
|
if {"@JIM_STATICLIB@" eq "1"} {
|
||
|
puts stderr "Warning: libjim is static. Dynamic module may not work on some platforms.\n"
|
||
|
set shobj_ldflags "@SHOBJ_LDFLAGS@"
|
||
|
} else {
|
||
|
# If shared, link against the shared libjim to resolve symbols
|
||
|
set ljim -ljim
|
||
|
set shobj_ldflags "@SHOBJ_LDFLAGS_R@"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set objs {}
|
||
|
foreach source $sources {
|
||
|
set obj [file rootname [file tail $source]].o
|
||
|
if {[string match *.c $source]} {
|
||
|
set compiler "@CC@"
|
||
|
} else {
|
||
|
set compiler "@CXX@"
|
||
|
}
|
||
|
set compile "$compiler @CFLAGS@ $CPPFLAGS $shobj_cflags $includepaths $opts -c -o $obj $source"
|
||
|
puts "Compile: $obj"
|
||
|
lappend objs $obj
|
||
|
|
||
|
set rc [exec-catch $verbose $compile]
|
||
|
if {$rc} {
|
||
|
file delete {*}$objs
|
||
|
exit $rc
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if {$static} {
|
||
|
set ar "@AR@ cq $target $objs"
|
||
|
set ranlib "@RANLIB@ $target"
|
||
|
|
||
|
puts "Ar: $target"
|
||
|
set rc [exec-catch $verbose $ar]
|
||
|
if {rc == 0} {
|
||
|
set rc [exec-catch $verbose $ranlib]
|
||
|
}
|
||
|
file delete {*}$objs
|
||
|
if {$rc} {
|
||
|
file delete $target
|
||
|
exit $rc
|
||
|
}
|
||
|
} else {
|
||
|
if {!$cross} {
|
||
|
# If not cross compiling, add the standard location after any user lib paths
|
||
|
lappend libpaths -L@prefix@/lib
|
||
|
}
|
||
|
|
||
|
set link "$linker @CFLAGS@ @LDFLAGS@ $shobj_ldflags $libpaths $opts -o $target $objs $ljim @LIBS@ $libs"
|
||
|
|
||
|
puts "Link: $target"
|
||
|
set rc [exec-catch $verbose $link]
|
||
|
if {!$keep} {
|
||
|
file delete {*}$objs
|
||
|
}
|
||
|
if {$rc} {
|
||
|
file delete $target
|
||
|
exit $rc
|
||
|
}
|
||
|
|
||
|
if {$testmod && !$cross} {
|
||
|
# Now, is testing even possible?
|
||
|
# We must be running a compatible jimsh with the load command at least
|
||
|
set testmod 0
|
||
|
set rc [catch {
|
||
|
# This will avoid attempting on Tcl and on jimsh without load
|
||
|
if {[info version] > 0.73 && [exists -command load]} {
|
||
|
set testmod 1
|
||
|
}
|
||
|
} msg]
|
||
|
}
|
||
|
|
||
|
set rc [catch {
|
||
|
if {$testmod && !$cross} {
|
||
|
puts "Test: load $target"
|
||
|
load ./$target
|
||
|
}
|
||
|
if {$install} {
|
||
|
set dest [env DESTDIR ""]@prefix@/lib/jim
|
||
|
puts "Install: $target => $dest"
|
||
|
file mkdir $dest
|
||
|
file copy $target $dest/$target
|
||
|
}
|
||
|
puts "\nSuccess!"
|
||
|
} msg]
|
||
|
if {$rc} {
|
||
|
puts stderr $msg
|
||
|
exit 1
|
||
|
}
|
||
|
}
|