ENGLISH | JAPANESE |
SWI-prolog is an efficient prolog compiler/interpreter developed by Jan Wielemaker and his collegues at University of Amsterdam. We employ SWI-prolog as our prolog compiler/interpreter because it is runnable on various platforms including Solaris, Linux, and Windows9X. We will install SWI-prolog and the interface to Java.
You may notice that there is a binary package for installing SWI-prolog on Windows. We need, however, to compile it from source because we need the runtime environment, 'libpl.a', which will be created under '/usr/local/lib/pl-3.3.8/runtime', to add SWI-prolog the interface to Java, JPL.
We install Java Development Kit before installing SWI-prolog. After installing both jdk and SWI-prolog, we install JPL, a Java Interface to Prolog.
There is no drama in installing JDK. We install JDK1.2.2 for Windows provided by Sun Microsystems. Some people claim that the runtime environment provided by IBM runs faster than the one by Sun, but we take the safer side.(3)
Wherever you can find it.
We install jdk1.2.2 under 'C:\cygnus\usr\local\jdk1.2.2' and the runtime environment under 'C:\cygnus\usr\local\JavaSoft'.
We do not test jdk. (It is very unlikely that you will encounter any problem with installation.) You should instead add the following line to 'c:\AUTOEXEC.BAT'.
set JAVA_HOME=c:\cygnus\usr\local\jdk1.2.2
It is also convenient to set a path to the binaries of jdk under bin so that you can for example compile and execute java programs anywhere. Set the path as follows:
set PATH=c:\cygnus\usr\local\jdk1.2.2\bin;%PATH%Restart your PC when you have finished.
You can down load the source from SWI-prolog download page. The latest is version 3.3.8 (1.12MB). Place the file, pl-3.3.8.tar.gz, under /tmp (i.e., c:\cygnus\tmp).
/tmp/pl-3.3.8/src> ./configure creating cache ./config.cache checking for gcc... gcc checking whether the C compiler (gcc ) works... yes checking whether the C compiler (gcc ) is a cross-compiler... no checking whether we are using GNU C... yes checking whether gcc accepts -g... yes checking for ranlib... ranlib checking host system type... Invalid configuration `i386-unknown-cygwin32': system `cygwin32' not recognized checking for make... make (...to be continued)
gcc -c -I. -I. -I./rc -Wall -O2 pl-os.c -o pl-os.o pl-os.c: In function `Which': pl-os.c:2608: warning: implicit declaration of function `okToExec' pl-os.c:2608: warning: assignment makes pointer from integer without a cast pl-os.c:2630: `PATHSEP' undeclared (first use in this function) pl-os.c:2630: (Each undeclared identifier is reported only once pl-os.c:2630: for each function it appears in.) pl-os.c:2631: warning: assignment makes pointer from integer without a cast pl-os.c:2646: warning: assignment makes pointer from integer without a cast make: *** [pl-os.o] Error 1 /tmp/pl-3.3.8/src>
If this is the case, open the file, src/pl-os.c. You skip to Line 642 and comment out the line and Line 656 so that the part between the two lines are compiled.
// #if unix (to be commented out) char * PrologPath(const char *p, char *buf) { strcpy(buf, p); return buf; } char * OsPath(const char *p, char *buf) { strcpy(buf, p); return buf; } // #endif /*unix*/ (to be commented out)
You also need to comment out the lines Line 2567 and 2570 so that the lines between them are forced to compile in:
// #if defined(OS2) || defined(__DOS__) || defined(__WINDOWS__) || defined(__WIN32__) #define EXEC_EXTENSIONS { ".exe", ".com", ".bat", ".cmd", NULL } #define PATHSEP ';' // #endif
Once you have successfully compiled SWI-prolog, check if it works.
/tmp/pl-3.3.8/src> ls -l /usr/local/bin total 1767 -rwxr-xr-x 1 fuji unknown 3612344 Jun 15 21:48 emacs.exe* lrw-r--r-- 1 fuji unknown 33 Jun 21 14:09 pl -> ../lib/pl-3.3.8/bin/pl* lrw-r--r-- 1 fuji unknown 35 Jun 21 14:09 plld -> ../lib/pl-3.3.8/bin/plld* lrw-r--r-- 1 fuji unknown 35 Jun 21 14:09 plrc -> ../lib/pl-3.3.8/bin/plrc* /tmp/pl-3.3.8/src>
c:/cygnus/home> pl Welcome to SWI-Prolog (Version 3.3.8) Copyright (c) 1990-2000 University of Amsterdam. Copy policy: GPL-2 (see www.gnu.org) For help, use ?- help(Topic). or ?- apropos(Word). 1 ?- write('Hello World!'). Hello World! Yes 2 ?-
JPL is a Java Interface to Prolog, with which you can call SWI-prolog from within Java. JPL is developed by Fred Dushin. The package is available from Separately distributed packages for SWI-Prolog. The package is well documented, thus, I only explain how to install it on Windows.
The package is available from Separately distributed packages for SWI-Prolog. Download the package from SWI-prolog site by clicking the sentence, "a local copy of the source (version 1.0.1, June 16, 1999) ", not 'JPL'. You will obtain a gzipped tar file called 'jpl-1.0.1.tar.gz'(as is on the 21st July, 2000).
You have to install the following packages:
We had better keep the followings in mind:
The difficult point lies in creating the DLL module of JPL because the package only provides us with a means to compile it for Unix platforms, where modules are loaded dynamically through the mechanism of shared library object. For our relief, Cygnus tools include the DLL tool, with which we can create DLL modules.
Tips and examples are found in GNU Win32 related projects written by Mumit Khan. Download first the file entitled as 'README.jni.txt' to read a brief introduction to compiling DLLs using Cygnus tools, which you can find as the sixth item of the list. Download 'java-jni-examples.tar.gz' if you want to take a look of the samples. (The README file is included in the package, too.) We are going to create our own Makefile by slightly modifying 'java-jni/c/Makefile.cyg' in the sample for C.
We are going to compile Java sources by hand, not using Makefiles provided in the package of jpl-1.0.1 because the package is primary designed for installing it on Unix platforms, not for Windows.
You can unpack the archive, jpl-1.0.1.tar, wherever. We unpack it, for example, under /cygdrive/d/tmp in what follows. We are going to create the files, jpl.jar (a Java archive) and jpl.dll (the DLL), and copy them later to appropriate directories. Unpack the archive as follows:
/cygdrive/d/tmp> tar xvfz jpl-1.0.1.tar.gzYou must have created the following directories and files under jpl-1.0.1 as shown in figure[The directories and files of jpl]:
/cygdrive/d/tmp> ls jpl-1.0.1 ChangeLog INSTALL Makefile README TODO demo/ doc/ export.script* jsrc/ rules.mk src/ stamp.script* test/ version
The steps are depicted below:
/cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl/fli> javac *.java /cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl/fli> cd .. /cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> mkdir jpl /cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> mkdir jpl/fli /cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> mv fli/*.class jpl/fli /cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> javac *.java /cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> mv *.class jpl
You must have created the class files under jsrc/jpl/jpl and jsrc/jpl/jpl/fli. The last thing to do is to make the archive of files under jsrc/jpl as shown in *unresolved*:
/cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> jar cvf jpl.jar jpl added manifest adding: jpl/(in = 0) (out= 0)(stored 0%) adding: jpl/fli/(in = 0) (out= 0)(stored 0%) adding: jpl/fli/DoubleHolder.class(in = 226) (out= 182)(deflated 19%) (... suppressed by Fujinami for readability) adding: jpl/fli/IntHolder.class(in = 220) (out= 181)(deflated 17%) adding: jpl/fli/LongHolder.class(in = 245) (out= 203)(deflated 17%) adding: jpl/Version.class(in = 432) (out= 302)(deflated 30%) /cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> ls -lt jpl.jar -rw-r--r-- 1 fuji unknown 27613 Jun 22 13:45 jpl.jarCheck the size of 'jpl.tar' to see if you have successfully made the archive.
Once you have successfully created the archive, 'jpl.jar', you can place it under an appropriate directory and extend your classpath in AUTOEXEC.BAT. Below we make a directory, /usr/local/lib/jpl, and place the jar file there (figure[Placing jpl.jar]).
/cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> mkdir /usr/local/lib/jpl /cygdrive/d/tmp/jpl-1.0.1/jsrc/jpl> cp jpl.jar /usr/local/lib/jplYou should then include the following line in AUTOEXEC.BAT (list[Setting Classpath to jpl.jar]).
set CLASSPATH=c:\cygnus\usr\local\lib\jpl\jpl.jarRestart your PC to take the change into effect.
Before compiling the source, 'jpl_fli_Prolog.c', under (d:/tmp/)jpl-1.0.1/src, we have to do the followings:
~> cd /usr/local/lib/pl-3.3.8/runtime /usr/local/lib/pl-3.3.8/runtime> ls libpl.a /usr/local/lib/pl-3.3.8/runtime> cp libpl.a /usr/lib
/usr/local/lib/pl-3.3.8/runtime> cd ../include /usr/local/lib/pl-3.3.8/include> ls *.h SWI-Prolog.h SWI-Stream.h /usr/local/lib/pl-3.3.8/include> cp *.h d:/tmp/jpl-1.0.1/src
/* * @(#)jni_md.h 1.9 98/09/21 * * Copyright 1996-1998 by Sun Microsystems, Inc., * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. * * This software is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Sun. */ #ifndef _JAVASOFT_JNI_MD_H_ #define _JAVASOFT_JNI_MD_H_ #define JNIEXPORT __declspec(dllexport) #define JNIIMPORT __declspec(dllimport) #define JNICALL __stdcall typedef long jint; #ifdef __GNUC__ typedef long long jlong; #else typedef __int64 jlong; #endif typedef signed char jbyte; #endif /* !_JAVASOFT_JNI_MD_H_ */
To create a DLL file, you copy Makefile.cyg below (*unresolved*) to the src directory, (d:/tmp/)jpl-1.0.1/src, and edit the variable, JDK_ROOT, to fit it to your environment.
# JDK_ROOT = c:/jdk1.1.7A JDK_ROOT = c:/cygnus/usr/local/jdk1.2.2
The crucial part is to set 'LDLIBS' as 'LDLIBS = -lpl -ltermcap -lm' so that 'libpl.a' under /usr/lib can be linked while building the load module.
# any extra libraries that your DLL may depend on. # DLL_LDLIBS = c:\\usr\\local\\lib\\pl-3.6.6\\runtime\\libpl.a # DLL_LDLIBDIR = c:/usr/local/lib/pl-3.6.6/runtime # LDLIBS = -L/usr/local/lib/pl-3.3.6/runtime -lpl -ltermcap -lm LDLIBS = -lpl -ltermcap -lm
You should also replace the following lines:
#$(DLL_NAME): $(DLL_OBJS) # $(DLLWRAP) $(DLLWRAP_FLAGS) -o $(DLL_NAME) \ # $(DLL_OBJS) $(DLL_LDFLAGS) $(DLL_LDLIBS)
with the lines below:
$(DLL_NAME): $(DLL_OBJS) $(DLLWRAP) $(DLLWRAP_FLAGS) -o $(DLL_NAME) \ $(DLL_OBJS) $(DLL_LDFLAGS) $(LDLIBS)
The Makefile is otherwise identical with the one provided by Mumit Khan.
# # Sample makefile to create Java JNI with Cygwin b20.1 tools. This *will not* # work with Cygwin versions earlier than b20.1. # # The only difference from creating a regular DLL is to supply a different # entry point, __cygwin_noncygwin_dll_entry@12, since Java is an MSVC app. # # See Makefile.nocyg if you want to use -mno-cygwin and build a Mingw JNI. # CC = gcc CXX = c++ DEBUG = -g -Wall -O2 CXXFLAGS = $(DEBUG) CFLAGS = $(DEBUG) CPPFLAGS = -I. -I$(JDK_ROOT)/include -I$(JDK_ROOT)/include/win32 # JDK_ROOT = c:/jdk1.1.7A JDK_ROOT = c:/cygnus/usr/local/jdk1.2.2 AS = as DLLTOOL = dlltool DLLWRAP = dllwrap # # Various targets to build. # DLL_NAME = jpl.dll DLL_EXP_DEF = jpl.def all: $(DLL_NAME) # # DLL related variables. These are used when building the DLL. See later. # # Some tools require special CPP macros when building a DLL (eg., _DLL etc). # Here we don't need anything. DLL_CFLAGS = -DBUILDING_DLL=1 -D_DLL=1 # The default entry point defined by dllwrap is __cygwin_dll_entry@12 # defined in libcygwin.a, but that's only appropriate for Cygwin apps, # but since Java is a MSVC app, we need to provide a different entry # point. Note the leading underscore and the trailing @12. # The -s flag strips the DLL to shrink the size. DLL_LDFLAGS = -Wl,-e,__cygwin_noncygwin_dll_entry@12 -s # any extra libraries that your DLL may depend on. # DLL_LDLIBS = c:\\usr\\local\\lib\\pl-3.6.6\\runtime\\libpl.a # DLL_LDLIBDIR = c:/usr/local/lib/pl-3.6.6/runtime # LDLIBS = -L/usr/local/lib/pl-3.3.6/runtime -lpl -ltermcap -lm LDLIBS = -lpl -ltermcap -lm DLL_SRCS = jpl_fli_Prolog.c DLL_OBJS = $(DLL_SRCS:.cc=.o) DLL_OBJS := $(DLL_OBJS:.c=.o) ### # # Making DLL # ### DLLWRAP_FLAGS = --output-def $(DLL_EXP_DEF) \ --add-stdcall-alias \ --driver-name $(CC) \ $(IMAGE_BASE) #$(DLL_NAME): $(DLL_OBJS) # $(DLLWRAP) $(DLLWRAP_FLAGS) -o $(DLL_NAME) \ # $(DLL_OBJS) $(DLL_LDFLAGS) $(DLL_LDLIBS) $(DLL_NAME): $(DLL_OBJS) $(DLLWRAP) $(DLLWRAP_FLAGS) -o $(DLL_NAME) \ $(DLL_OBJS) $(DLL_LDFLAGS) $(LDLIBS) # # dependencies. # # # default rules for building DLL objects. Note that client programs (ie., # the ones that *use* the DLL) have to be compiled without the DLL_CFLAGS # flags. # .cc.o: $(CXX) -c $(DLL_CFLAGS) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< .c.o: $(CC) -c $(DLL_CFLAGS) $(CPPFLAGS) $(CFLAGS) -o $@ $< # Note that we omit the $(DLL_CFLAGS) for client programs. usedll.o: %o: %c $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< clean: -rm -f $(OBJS) $(DLL_OBJS) $(DLL_NAME) $(DLL_EXP_LIB) $(DLL_EXP_DEF) $(TESTPROGS)
/cygdrive/d/tmp/jpl-1.0.1/src> make -f Makefile.cyg dllwrap --output-def jpl.def --add-stdcall-alias --driver-name gcc -o jpl.dll \ jpl_fli_Prolog.o -Wl,-e,__cygwin_noncygwin_dll_entry@12 -s -lpl -ltermcap -lm Warning: no export definition file provided dllwrap will create one, but may not be what you want /cygdrive/d/tmp/jpl-1.0.1/src>
/cygdrive/d/tmp/jpl-1.0.1/src> ls -l total 250 -rw-r--r-- 1 fuji unknown 1658 May 5 1999 Makefile -rw-r--r-- 1 fuji unknown 2556 Jun 22 17:46 Makefile.cyg -rw-r--r-- 1 fuji unknown 2542 Jun 13 10:30 Makefile.cyg~ -rw-r--r-- 1 fuji unknown 25205 Jun 22 17:43 SWI-Prolog.h -rw-r--r-- 1 fuji unknown 8719 Jun 22 17:43 SWI-Stream.h -rw-r--r-- 1 fuji unknown 8788 Jun 22 17:51 jpl.def -rw-r--r-- 1 fuji unknown 345600 Jun 22 17:51 jpl.dll -rw-r--r-- 1 fuji unknown 39909 May 5 1999 jpl_fli_Prolog.c -rw-r--r-- 1 fuji unknown 66834 Jun 22 17:47 jpl_fli_Prolog.o
You can copy 'jpl.dll' to a directory that can be found by JVM, e.g., /usr/local/lib/jpl as follows:
/cygdrive/d/tmp/jpl-1.0.1/src> cp jpl.dll /usr/local/lib/jpl /cygdrive/d/tmp/jpl-1.0.1/src> ls /usr/local/lib/jpl jpl.dll jpl.jar /cygdrive/d/tmp/jpl-1.0.1/src>
You have to of course include the directory into your PATH by editing your AUTOEXEC.BAT as follows:
set PATH=c:\cygnus\usr\local\lib\jpl;%PATH%Restart your PC to take the change into effect.
JPL package includes test programs so that we can check if we have successfully installed JPL. For testing, change directory to jpl-1.0.1/test to compile and run Test.java program as follows:
~> cd d:/tmp/jpl-1.0.1/test /cygdrive/d/tmp/jpl-1.0.1/test> javac Test.java /cygdrive/d/tmp/jpl-1.0.1/test> java Test test 0...Warning: (/cygdrive/d/tmp/jpl-1.0.1/test/test.pl:4): Singleton variables: [X] Warning: (/cygdrive/d/tmp/jpl-1.0.1/test/test.pl:10): Singleton variables: [X, Y] Warning: (/cygdrive/d/tmp/jpl-1.0.1/test/test.pl:13): Singleton variables: [Y] Warning: (/cygdrive/d/tmp/jpl-1.0.1/test/test.pl:16): Singleton variables: [Y] % test.pl compiled 0.02 sec, 2,416 bytes passed. test 1...passed. test 2...passed. test 3...passed. test 4...passed. test 5...passed. test 6...passed. test 7...passed. test 8...passed. test 9...passed. test 10...passed. test 11...passed. test 101...0123456789012345678901234567890 123456789012345678901234567890123456789012 345678901234567890123467890123456789012345 678901234567890123456789012345678901234567 890123456789012345678901234567890123456789 5passed.
Beaware that the output by Test.class may not be visible on Bash window. You should run the shell in Meadow if it is the case.