What: JTcl Where: ftp://ftp.gaertner.de/pub/j/jtcl-1.0.tar.gz Description: Java script library allowing access to the Tcl language. Can invoke Tcl extensions such as Tk, allowing Java programmers to create GUI interfaces for Java applications. Updated: 09/2001 Contact: mailto: [email protected]
JTcl Interpreter is an implementation of Tcl 8.4 in Java.
(zdia 10/2011)
The conditions of this feasibility study were
Create an Android project with something like:
$ android create project \ --package tcl.lang \ --activity JTcl \ --target 1 \ --path ~/Projekte/jtcl
To get info about your existing existing targets:
$ android list targets Available Android targets: id: 1 or "android-8" Name: Android 2.2 Type: Platform API level: 8 Revision: 3 Skins: WVGA854, WVGA800 (default), QVGA, HVGA, WQVGA432, WQVGA400
We add an folder assets/ and put as folder src/ the folder jtcl-2.0.0/src/main/java/tcl/lang of Jtcl into our development directory. We have still to put the jtcl-2.0.0/src/main/resources/tcl/lang/library/init.tcl file into the assets/ folder. JTcl will need it for initialization. Finally your tree hierarchy should look similar to the following:
|-- AndroidManifest.xml |-- android | |-- bin | | |-- classes | | |-- classes.dex | | `-- jtcl.ap_ | `-- jtcl.jar |-- assets | `-- init.tcl |-- bin |-- build |-- build.xml |-- development.txt |-- jtcl.properties |-- libs |-- proguard.cfg |-- res | |-- drawable-hdpi | | `-- icon.png | |-- drawable-ldpi | | `-- icon.png | |-- drawable-mdpi | | `-- icon.png | |-- layout | | `-- main.xml | `-- values | `-- strings.xml `-- src `-- tcl `-- lang
The file jtcl.properties will define our local Android environment:
$ cat jtcl.properties sdk-folder=~/Projekte/jtcl android-tools=~/Programme/android-sdk-linux_x86/tools android-platform=~/Programme/android-sdk-linux_x86/platforms/android-8 android-platform-tools=~/Programme/android-sdk-linux_x86/platform-tools
The file Interpr.java in src/tcl/lang/ has to be modified to load the init.tcl from our assets/ directory:
// evalResource("/tcl/lang/library/init.tcl"); evalResource("assets/init.tcl");
Then all is ready for ant which will be fed by the following build.xml:
<?xml version="1.0" encoding="UTF-8"?> <!-- Inspirations taken from the build.xml found in David Weltons "Hecl for Android": http://www.hecl.org/ --> <project name="JTcl for Android" default="help"> <!-- ====================================================================== --> <!-- Build environment properties --> <!-- ====================================================================== --> <property name="outdir" value="android/bin" /> <property file="jtcl.properties" /> <property name="android.build" value="android/bin/classes"/> <property name="android-jar" value="${android-platform}/android.jar" /> <property name="dx" value="${android-platform-tools}/dx" /> <property name="dex-file" value="classes.dex" /> <property name="intermediate-dex" value="${outdir}/${dex-file}" /> <property name="aapt" value="${android-platform-tools}/aapt" /> <property name="resource-dir" value="res" /> <property name="asset-dir" value="assets" /> <property name="srcdir" value="src" /> <property name="resources-package" value="${outdir}/jtcl.ap_" /> <!-- ====================================================================== --> <!-- Help target --> <!-- ====================================================================== --> <target name="help"> <echo message="Possible targets: compile jar dex aapt"/> </target> <!-- ====================================================================== --> <!-- Dirs target --> <!-- ====================================================================== --> <target name="dirs"> <echo>Creating output directories if needed...</echo> <mkdir dir="${outdir}"/> <mkdir dir="${android.build}"/> </target> <!-- ====================================================================== --> <!-- Compilation target --> <!-- ====================================================================== --> <target name="compile" description="Compile the code" depends= "dirs"> <echo>bootclasspath: ${android-jar}</echo> <javac destdir="${android.build}" srcdir="src/tcl/lang" source="1.5" bootclasspath="${android-jar}" > </javac> </target> <!-- ====================================================================== --> <!-- Jar package target --> <!-- ====================================================================== --> <target name="jtcl-jar" depends="compile"> <echo> Building android/jtlc.jar from dir: ${android.build} ...</echo> <jar destfile="android/jtcl.jar" basedir="${android.build}"> <manifest> <attribute name="Main-Class" value="tcl.lang.Shell"/> </manifest> </jar> </target> <!-- ====================================================================== --> <!-- Dex target --> <!-- ====================================================================== --> <target name="dex" depends="jtcl-jar"> <echo>Converting compiled files and external libraries into ${outdir}/${dex-file}...</echo> <apply executable="${dx}" failonerror="true" parallel="true"> <arg value="-JXmx512m" /> <arg value="--dex" /> <arg value="--output=${intermediate-dex}" /> <arg path="android/jtcl.jar" /> <fileset dir="${android-platform-tools}/lib" includes="*.jar"/> </apply> </target> <!-- ====================================================================== --> <!-- aapt target --> <!-- ====================================================================== --> <!-- Put the project's resources into the output package file. We will use the folder assets to store init.tcl. An Android app has only access to the application folders, no chance to create a folder: /tcl/lang/library/ --> <target name="aapt" depends="dex"> <echo>Packaging resources and assets...</echo> <exec executable="${aapt}" failonerror="true"> <arg value="package" /> <arg value="-f" /> <arg value="-M" /> <arg value="AndroidManifest.xml" /> <arg value="-S" /> <arg value="${resource-dir}" /> <arg value="-A" /> <arg value="${asset-dir}" /> <arg value="-I" /> <arg value="${android-jar}" /> <arg value="-F" /> <arg value="${resources-package}" /> </exec> </target> <!-- ====================================================================== --> <!-- Cleaning up target --> <!-- ====================================================================== --> <target name="clean" description="Clean the output directory"> <echo>Deleting dir: ${android.build}</echo> <delete dir="${outdir}"/> </target> </project>
In the directory /android/bin we will find now the executable file classes.dex and a file jtcl.ap_ with the resources compiled in, so we still have to add the executable to our jtcl.ap_:
aapt add jtcl.ap_ classes.dex
The above mentioned assets/init.tcl still has to be modified. For the moment we have no tcllib files in our assets folder so we comment out autoloading of tcllib packages:
# set dir resource:/tcl/pkg/tcllib/library # source $dir/pkgIndex.tcl puts "Note: No tcllib package available"
Now jtcl.ap_ is ready for a test:
We push jtcl.ap_ to Android assumed the folder /data/local/bin has been already created by use of adb shell:
$ adb push jtcl.ap_ /data/local/bin
After connection to a running Android device with adb shell you call JTcl with its entrypoint tcl.lang.Shell:
# dalvikvm -Xbootclasspath:/system/framework/core.jar -classpath /data/local/bin/jtcl.ap_ tcl.lang.Shell
That's it. Sure, you can use this call inside a "Terminal emulator" Android application.
The next steps will be:
MHo 2013-03-01: The tool paraffin.tcl doesn't work for me (Windows XP platform). The command
set jtclJar [ziplib::getClassLocation [java::getinterp]]
gives an unusable filename on windows, with a leading slash '/'. But even working around this, somethings going wrong (did not have the time to look further yet):
c:\Programme\jtcl-2.4.0>jtcl paraffin.tcl iskvprep6 ./iskvprep6 iskvprep6.bat . could not open file ".\echopath": file is not a zip file while executing "error "could not open file \"$fileName\": file is not a zip file"" ("if" then script line 2) invoked from within "if {[java::isnull $ent]} { error "could not open file \"$fileName\": file is not a zip file" }" (procedure "ziplib::openInputZip" line 16) invoked from within "ziplib::openInputZip $jar" invoked from within "set jarin [ziplib::openInputZip $jar]" ("foreach" body line 5) invoked from within "foreach jar $jars { if {! [file isfile $jar]} { continue } set jarin [ziplib::openInputZip $jar] ziplib::c..." (procedure "mkJar" line 22) invoked from within "mkJar $app $srcdir $start $libdir" (procedure "cmdLine" line 32) invoked from within "cmdLine" (file "paraffin.tcl" line 79)
TP Could you file a bug report at http://kenai.com/bugzilla/buglist.cgi?product=jtcl ? Please include Java version, and the pathname of your Java installation. MHo: No, I don't, because doing this requires a login/registration. The JRE used was 1.6.0_41.
TP What is the pathname of your Java install? Please attach the output of "parray env" from the JTcl interactive shell. By the way, http://mailinator.com is useful for one-time email addresses :-)
% parray env env(CLASSPATH) = C:\Programme\jtcl-2.4.0\\jtcl-2.4.0.jar;.;C:\Programme\Java\jre1.6.0_07\lib\ext\QTJ ava.zip env(HOME) = D:\Home\Hoffmann env(USER) = HOFFMANN env(awt.toolkit) = sun.awt.windows.WToolkit env(file.encoding) = Cp1252 env(file.encoding.pkg) = sun.io env(file.separator) = \ env(java.awt.graphicsenv) = sun.awt.Win32GraphicsEnvironment env(java.awt.printerjob) = sun.awt.windows.WPrinterJob env(java.class.path) = C:\Programme\jtcl-2.4.0\\jtcl-2.4.0.jar;.;C:\Programme\Java\jre1.6.0_07\lib\ext\QTJ ava.zip env(java.class.version) = 50.0 env(java.endorsed.dirs) = C:\Programme\Java\jre6\lib\endorsed env(java.ext.dirs) = C:\Programme\Java\jre6\lib\ext;C:\WINDOWS\Sun\Java\lib\ext env(java.home) = C:\Programme\Java\jre6 env(java.io.tmpdir) = d:\var\temp\ env(java.library.path) = C:\WINDOWS\system32;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Progr amme\Tcl\bin;C:\Programme\ActiveState Komodo Edit 7\;C:\Programme\caesar\OraClientNet\bin;C:\Programme\caesar\OraClientN et\;C:\Programme\Python27\;C:\Programme\Python27\Scripts;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32\WBEM;c:\Prog ramme\misctool;d:\home\Hoffmann\pgm\tcl\usr\bin;c:\Programme\sysinternals2;C:\Programme\ResKits\Tools\;C:\Programme\Supp ort Tools\;C:\Programme\Pbx;C:\Programme\Perl\site\bin;C:\Programme\Perl\bin;c:\Programme\Regina;C:\Programme\Lua\5.1;C: \Programme\Lua\5.1\clibs;C:\Programme\coreutils;C:\WINDOWS\system32\WindowsPowerShell\v1.0;C:\Programme\ooRexx;C:\Progra mme\Subversion\bin;C:\Programme\Gemeinsame Dateien\Acronis\SnapAPI\;C:\Programme\Citrix\System32\;C:\WINDOWS\system32\Wi ndowsPowerShell\v1.0;C:\Programme\Citrix\System32\;%APPDATA%\Python\Scripts;c:\programme\unix2;C:\programme\texlive\2011 \bin\win32;c:\programme\mingw\bin;c:\Programme\MinGW\msys\1.0\bin;;. env(java.runtime.name) = Java(TM) SE Runtime Environment env(java.runtime.version) = 1.6.0_41-b02 env(java.specification.name) = Java Platform API Specification env(java.specification.vendor) = Sun Microsystems Inc. env(java.specification.version) = 1.6 env(java.vendor) = Sun Microsystems Inc. env(java.vendor.url) = http://java.sun.com/ env(java.vendor.url.bug) = http://java.sun.com/cgi-bin/bugreport.cgi env(java.version) = 1.6.0_41 env(java.vm.info) = mixed mode, sharing env(java.vm.name) = Java HotSpot(TM) Client VM env(java.vm.specification.name) = Java Virtual Machine Specification env(java.vm.specification.vendor) = Sun Microsystems Inc. env(java.vm.specification.version) = 1.0 env(java.vm.vendor) = Sun Microsystems Inc. env(java.vm.version) = 20.14-b01 env(line.separator) = env(os.arch) = x86 env(os.name) = Windows XP env(os.version) = 5.1 env(path.separator) = ; env(sun.arch.data.model) = 32 env(sun.boot.class.path) = C:\Programme\Java\jre6\lib\resources.jar;C:\Programme\Java\jre6\lib\rt.jar;C:\Progr amme\Java\jre6\lib\sunrsasign.jar;C:\Programme\Java\jre6\lib\jsse.jar;C:\Programme\Java\jre6\lib\jce.jar;C:\Programme\Ja va\jre6\lib\charsets.jar;C:\Programme\Java\jre6\lib\modules\jdk.boot.jar;C:\Programme\Java\jre6\classes env(sun.boot.library.path) = C:\Programme\Java\jre6\bin env(sun.cpu.endian) = little env(sun.cpu.isalist) = pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86 env(sun.desktop) = windows env(sun.io.unicode.encoding) = UnicodeLittle env(sun.java.command) = tcl.lang.Shell env(sun.java.launcher) = SUN_STANDARD env(sun.jnu.encoding) = Cp1252 env(sun.management.compiler) = HotSpot Client Compiler env(sun.os.patch.level) = Service Pack 3 env(user.country) = DE env(user.dir) = C:\Programme\jtcl-2.4.0 env(user.home) = D:\Home\Hoffmann env(user.language) = de env(user.name) = HOFFMANN env(user.timezone) = env(user.variant) = %
TP I think I might see your problem, look at your command line:
c:\Programme\jtcl-2.4.0>jtcl paraffin.tcl iskvprep6 ./iskvprep6 iskvprep6.bat .
The parameters to paraffin.tcl are app-name source-directory start-file [ jar-directory ]
start-file should be the Tcl file that is your main script, not a batch file. jar-directory should be a directory that only contains the additional jar files you need for your application. You are using "." as the jar-directory, which probably contains files other than jar files. Does your application require additional jar files? If so, place all of those jar files in a clean directory.
See the example at: http://jtcl.kenai.com/docs/paraffin.html for more information.
MHo: iskvprep6.bat is a tcl script. Some scripts that I write allways start this way:
#!/bin/sh # \ exec /iskv/tools/tclkitsh "$0" ${1+"$@"} ::if 0 { @cls @tclkitsh859.exe "%~dpn0.bat" %* @goto :EOF } : :
And I don't need additional JARs, I think. But of course I will look at the example.
MHo 2013-03-08: Don't know what I made different than before (besides looking at the documentation page which I missed before), but the paraffin step now works ok and produces a .jar file. Running the .jar file gives the following error:
C:\Programme\jtcl-2.4.0>java -jar iskvprep6.jar could not read "resource:tcl/app/iskvprep6.bat": no such file or directory while executing "file mtime [info script" invoked from within "clock format [file mtime [info script]] -format %d.%m.%Y" invoked from within "puts stderr " $script - [clock format [file mtime [info script]] -format %d.%m.%Y] - Anlegen von Unix-Gruppen, -Be nutzern und HomeDirs fuer 21c Aufru..." ("if" then script line 2) invoked from within "if {$argc == 0 || $cIx < 0} { puts stderr " $script - [clock format [file mtime [info script]] -format %d.%m.%Y] -\ Anlegen von Unix-Gruppen, -Benu..."
TP This error is from the file command not understanding the resource: convention. Instead of a true virtual file system (like C/Tcl), JTcl only recognizes resource: in open and source commands. To make this work, you'll have to modify your application to not use file on a resource: pathname.
MHo: Then, how to get the filetime of the script itself?