Skip to content

Commit

Permalink
Create build-jim-ext for building extensions
Browse files Browse the repository at this point in the history
Simplifies the process of building loadable extensions

Signed-off-by: Steve Bennett <steveb@workware.net.au>
  • Loading branch information
msteveb committed Nov 24, 2011
1 parent 7a8c042 commit 1f9fa4a
Show file tree
Hide file tree
Showing 27 changed files with 315 additions and 45 deletions.
7 changes: 2 additions & 5 deletions .gitignore
@@ -1,9 +1,5 @@
autom4te.cache
config.log
config.status
config.h
tags
.clean
/Makefile
Tcl.html
jimautoconf.h
Expand All @@ -17,7 +13,8 @@ jim-oo.c
jimsh
*.exe
libjim.a
libjim.so
*.so
*.o
configure.gnu
jimsh0
build-jim-ext
5 changes: 4 additions & 1 deletion Makefile.in
Expand Up @@ -47,7 +47,7 @@ OBJS := _load-static-exts.o jim-subcmd.o jim-interactive.o jim-format.o jim.o ut

JIMSH := jimsh@EXEEXT@

all: $(JIMSH) @C_EXT_SHOBJS@
all: $(JIMSH) @C_EXT_SHOBJS@ build-jim-ext

# Create C extensions from pure Tcl extensions
.SUFFIXES: .tcl
Expand All @@ -72,13 +72,16 @@ install: all docs @TCL_EXTS@ install-exec
cp jim-config.h $(DESTDIR)$(prefix)/include
mkdir -p $(DESTDIR)$(prefix)/doc/jim
cp Tcl.html $(DESTDIR)$(prefix)/doc/jim
mkdir -p $(DESTDIR)$(prefix)/bin
cp build-jim-ext $(DESTDIR)$(prefix)/bin

install-exec: all
mkdir -p $(DESTDIR)$(prefix)/bin
cp $(JIMSH) $(DESTDIR)$(prefix)/bin

uninstall:
rm -f $(DESTDIR)$(prefix)/bin/$(JIMSH)
rm -f $(DESTDIR)$(prefix)/bin/build-jim-ext
rm -f $(DESTDIR)$(prefix)/lib/$(LIBJIM)
for i in README.extensions @C_EXT_SHOBJS@ @TCL_EXTS@; do rm -f $(DESTDIR)$(prefix)/lib/jim/$$i; done
rm -f $(DESTDIR)$(prefix)/include/jim*.h
Expand Down
3 changes: 3 additions & 0 deletions auto.def
Expand Up @@ -434,3 +434,6 @@ define EXTRA_OBJS $extra_objs
make-config-header jim-config.h -auto {HAVE_LONG_LONG* JIM_UTF8} -none *
make-config-header jimautoconf.h -auto {jim_ext_* TCL_PLATFORM_* TCL_LIBRARY USE_* JIM_*}
make-template Makefile.in
make-template build-jim-ext.in

catch {exec chmod +x build-jim-ext}
219 changes: 219 additions & 0 deletions build-jim-ext.in
@@ -0,0 +1,219 @@
#!/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? ?--install? ?--static? ?cc-options? ?-o modname? sources..."
if {$msg ne ""} {
puts stderr \n$msg
}
exit 1
}

set linker "@CC@"
set testmod 1
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 {
set testmod 0
}
--install {
set install 1
}
--static {
set static 1
}
--verbose {
set verbose 1
}
--keep {
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"

# Now add the standard location after any user include paths
lappend includepaths -I@prefix@/include

set CPPFLAGS "-D_GNU_SOURCE"

if {"@JIM_STATICLIB@" eq "1" && !$static} {
puts stderr "Warning: libjim is static. Dynamic module may not work on some platforms.\n"
set ljim ""
} else {
set ljim -ljim
}

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@"
}
if {$static} {
set shobj_cflags ""
} else {
set shobj_cflags "@SHOBJ_CFLAGS@"
}
set compile "$compiler @CFLAGS@ $CPPFLAGS $shobj_cflags $includepaths $opts -c -o $obj $source"
puts "Compile: $obj"
lappend objs $obj
set rc [catch {
exec {*}$compile
if {$verbose} {
puts stderr $compile
}
} msg]
if {$rc} {
puts stderr $compile
puts stderr $msg
file delete {*}$objs
exit 1
}
}

if {$static} {
set ar "@AR@ cq $target $objs"
set ranlib "@RANLIB@ $target"

puts "Ar: $target"
set rc [catch {
file delete $target
exec {*}$ar
exec {*}$ranlib
if {$verbose} {
puts stderr $ar
}
} msg]

file delete {*}$objs

if {$rc} {
puts stderr $ar
puts stderr $ranlib
puts stderr $msg
file delete $target
exit 1
}
} else {
# 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 [catch {
exec {*}$link
if {$verbose} {
puts stderr $link
}
} msg]

if {!$keep} {
file delete {*}$objs
}

if {$rc} {
file delete $target
puts stderr $link
puts stderr $msg
exit 1
}

if {$testmod} {
# 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
# How to tell if we are cross compiling?
if {[info version] > 0.73 && [exists -command load]} {
set testmod 1
}
} msg]
}

set rc [catch {
if {$testmod} {
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
}
}
29 changes: 29 additions & 0 deletions examples.ext/Makefile
@@ -0,0 +1,29 @@
# Note that if cross compiling, build with:
#
# make NOTEST=1
#
# to avoid trying to load the resulting module.
# Also note that you will need a build-host version of jimsh in the
# PATH in order to build the extension.

# Prefer jimsh in the PATH because it is more likely to be built
# for the build-host rather than the target.

ifdef NOTEST
BUILDOPTS := --notest
endif

export PATH := $(PATH):..

all: helloworld.so

helloworld.so: helloworld.c
../build-jim-ext -I.. -L.. $(BUILDOPTS) $^

# Note: Currently we don't attempt to set LD_LIBRARY_PATH or equivalent

test:
JIMLIB=. ../jimsh -e 'package require helloworld; hello'

clean:
rm -f *.o *.so
7 changes: 7 additions & 0 deletions examples.ext/README
@@ -0,0 +1,7 @@
This directory contains examples of C extensions for Jim.

In general, do:

build-jim-ext extsource.c

See the Makefile
24 changes: 24 additions & 0 deletions examples.ext/helloworld.c
@@ -0,0 +1,24 @@
/*
* hello.c -- A minimal Jim C extension.
*/
#include <jim.h>

static int
Hello_Cmd(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
{
Jim_SetResultString(interp, "Hello, World!", -1);
return JIM_OK;
}

/*
* Jim_helloworldInit -- Called when Jim loads your extension.
*
* Note that the name *must* correspond exactly to the name of the extension:
* Jim_<extname>Init
*/
int
Jim_helloworldInit(Jim_Interp *interp)
{
Jim_CreateCommand(interp, "hello", Hello_Cmd, NULL, NULL);
return JIM_OK;
}
4 changes: 1 addition & 3 deletions jim-array.c
Expand Up @@ -50,9 +50,7 @@
#include <stdio.h>
#include <errno.h>

#include "jim.h"
#include "jimautoconf.h"
#include "jim-subcmd.h"
#include <jim-subcmd.h>

static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Expand Down
3 changes: 1 addition & 2 deletions jim-clock.c
Expand Up @@ -15,9 +15,8 @@
#include <stdio.h>
#include <time.h>

#include "jim.h"
#include "jimautoconf.h"
#include "jim-subcmd.h"
#include <jim-subcmd.h>

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
Expand Down
4 changes: 2 additions & 2 deletions jim-eventloop.c
Expand Up @@ -38,9 +38,9 @@
* official policies, either expressed or implied, of the Jim Tcl Project.
**/

#include "jim.h"
#include "jimautoconf.h"
#include "jim-eventloop.h"
#include <jim.h>
#include <jim-eventloop.h>

/* POSIX includes */
#include <sys/time.h>
Expand Down
2 changes: 1 addition & 1 deletion jim-exec.c
Expand Up @@ -23,8 +23,8 @@
#include <string.h>
#include <ctype.h>

#include "jim.h"
#include "jimautoconf.h"
#include <jim.h>

#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
/* Poor man's implementation of exec with system()
Expand Down
5 changes: 2 additions & 3 deletions jim-file.c
Expand Up @@ -50,9 +50,8 @@
#include <errno.h>
#include <sys/stat.h>

#include "jim.h"
#include "jimautoconf.h"
#include "jim-subcmd.h"
#include <jimautoconf.h>
#include <jim-subcmd.h>

#ifdef HAVE_UTIMES
#include <sys/time.h>
Expand Down

0 comments on commit 1f9fa4a

Please sign in to comment.