Article 8824 of comp.lang.perl: Xref: feenix.metronet.com comp.lang.perl:8824 comp.sys.next.programmer:6151 Path: feenix.metronet.com!news.ecn.bgu.edu!usenet.ins.cwru.edu!agate!doc.ic.ac.uk!uknet!pipex!demon!steffi.demon.co.uk!steffi.demon.co.uk!not-for-mail From: robert@steffi.demon.co.uk (Robert Nicholson) Newsgroups: comp.lang.perl,comp.sys.next.programmer Subject: Building perl for NeXTSTEP : HERE'S HOW (LONG) Date: 11 Dec 1993 10:44:23 -0000 Organization: me organized? That's a joke! Lines: 878 Message-ID: <2ec8a7$74a@steffi.demon.co.uk> NNTP-Posting-Host: steffi.demon.co.uk Postings asking how to build perl under NeXTSTEP come up very often in this group so I decided to put together this tutorial in order to alliviate this problem. NOTE: For Mr Christiansen please archive this and add a pointer in the FAQ. This is certified for NS3.1. Building PERL 4PL36 for NeXTSTEP can be a tricky business owing the some assumptions made by Configure and NeXT's /usr/include/ tree. Common problems are Configure finding dirent.h before dir.h and thus defining both i_dirent and i_sys_dir in config.sh The most common mistake is entering /usr/include when it asks for this path. If you do this Configure then attempts to see if you have certain header files in order to determine what language features to support. So for instance if you entered /usr/include, during Configure it attempts to locate grp.h using test -f /usr/include/grp.h This file doesn't exist there under the NeXTSTEP's include tree thus it is necessary to enter /usr/include/bsd when it asks for the include path. Here is a transcript from a Configure session. root:/Users/robert/archives/perl-4.036>Configure 9:35 Beginning of configuration questions for perl kit. First let's make sure your kit is complete. Checking... Looks good... Checking your sh to see if it knows about # comments... Your sh handles # comments correctly. Okay, let's see if #! works on this system... It does. Checking out how to guarantee sh startup... Let's see if '#!/bin/sh' works... Yup, it does. Checking echo to see how to suppress newlines... ...using \c Type carriage return to continue. Your cursor should be here--> This installation shell script will examine your system and ask you questions to determine how the perl package should be installed. If you get stuck on a question, you may use a ! shell escape to start a subshell or execute a command. Many of the questions will have default answers in square brackets--typing carriage return will give you the default. On some of the questions which ask for file or directory names you are allowed to use the ~name construct to specify the login directory belonging to "name", even if you don't have a shell which knows about that. Questions where this is allowed will be marked "(~name ok)". [Type carriage return to continue] Much effort has been expended to ensure that this shell script will run on any Unix system. If despite that it blows up on you, your best bet is to edit Configure and run it again. Also, let me (lwall@netlabs.com) know how I blew it. If you can't run Configure for some reason, you'll have to generate a config.sh file by hand. This installation script affects things in two ways: 1) it may do direct variable substitutions on some of the files included in this kit, and 2) it builds a config.h file for inclusion in C programs. You may edit any of these files as the need arises after running this script. If you make a mistake on a question, there is no easy way to back up to it currently. The easiest thing to do is to edit config.sh and rerun all the SH files. Configure will offer to let you do this before it runs the SH files. [Type carriage return to continue] Locating common programs... cat is in /bin/cat. cp is in /bin/cp. echo is in /bin/echo. expr is in /bin/expr. grep is in /bin/grep. mkdir is in /bin/mkdir. mv is in /bin/mv. rm is in /bin/rm. sed is in /bin/sed. sort is in /usr/bin/sort. tr is in /usr/bin/tr. uniq is in /usr/bin/uniq. Don't worry if any of the following aren't found... I don't see Mcc out there, offhand. bison is in /usr/local/bin/bison. cpp is in /lib/cpp. csh is in /bin/csh. egrep is in /usr/bin/egrep. I don't see line out there, either. nroff is in /usr/bin/nroff. perl is in /usr/local/bin/perl. test is in /bin/test. I don't see uname out there, either. yacc is in /usr/bin/yacc. Using the test built into your sh. Checking compatibility between /bin/echo and builtin echo (if any)... They are not compatible! You are probably running ksh on a non-USG system. I'll have to use /bin/echo instead of the builtin, since Bourne shell doesn't have echo built in and we may have to run some Bourne shell scripts. That means I'll have to use -n to suppress newlines now. Life is ridiculous. Your cursor should be here--> First time through, eh? I have some defaults handy for the following systems: 3b1 dnix isc_3_2_2 sco_2_3_2 sunos_4_0_2 3b2 dynix isc_3_2_3 sco_2_3_3 svr4 aix_rs fps mc6000 sco_2_3_4 ti1500 aix_rt genix mips sco_3 titan altos486 greenhills mpc sgi ultrix_1 apollo_C6_7 hp9000_300 ncr_tower solaris_2_0 ultrix_3 apollo_C6_8 hp9000_400 next solaris_2_1 ultrix_4 aux hp9000_700 opus stellar unisysdynix cray hp9000_800 osf1 sunos_3_4 utekv dec_osf1 hpux sco_2_3_0 sunos_3_5 uts dgux i386 sco_2_3_1 sunos_4_0_1 vax (You may give one or more space-separated answers, or "none" if appropriate. If your OS version has no hints, do not give a wrong version--say "none".) Which of these apply, if any? [none] next perl has manual pages available in source form. If you don't want the manual sources installed, answer 'none'. Where do the manual pages (source) go (~name ok)? [/usr/man/man1] /usr/local/man/man1 Hmm... Doesn't look like a MIPS system. Where are the include files you want to use? [/usr/include] /usr/include/bsd /usr/include/ctype.h: No such file or directory Looks kind of like a BSD system, but we'll see... Congratulations. You aren't running Eunice. It's not Xenix... Nor is it Venix... Some systems have different model sizes. On most systems they are called small, medium, large, and huge. On the PDP11 they are called unsplit and split. If your system doesn't support different memory models, say "none". If you wish to force everything to one memory model, say "none" here and put the appropriate flags later when it asks you for other cc and ld flags. Venix systems may wish to put "none" and let the compiler figure things out. (In the following question multiple model names should be space separated.) Which models are supported? [none] Use which C compiler? [cc] Some C compilers have problems with their optimizers, by default, perl compiles with the -O flag to use the optimizer. Alternately, you might want to use the symbolic debugger, which uses the -g flag (on traditional Unix systems). Either flag can be specified here. To use neither flag, specify the word "none". What optimizer/debugger flag should be used? [-O] Your C compiler may want other flags. For this question you should include -I/whatever and -DWHATEVER flags and any other flags used by the C compiler, but you should NOT include libraries or ld flags like -lwhatever. For instance, this would be a good place to specify -DDEBUGGING. To use no flags, specify the word "none". Any additional cc flags? [ -I/usr/include] (C preprocessor flags: -I/usr/include) Any additional ld flags (NOT including libraries)? [none] Checking for optional libraries... Found -ldbm. Found -lsys_s. Some versions of Unix support shared libraries, which make executables smaller but make load time slightly longer. On some systems, mostly newer Unix System V's, the shared library is included by putting the option "-lc_s" as the last thing on the cc command line when linking. Other systems use shared libraries by default. There may be other libraries needed to compile perl on your machine as well. If your system needs the "-lc_s" option, include it here. Include any other special libraries here as well. Say "none" for none. Any additional libraries? [-ldbm -lsys_s] Checking alignment constraints... Doubles must be aligned on a how-many-byte boundary? [2] The following questions distinguish the directory in which executables reside from the directory in which they are installed (and from which they are presumably copied to the former directory by occult means). This distinction is often necessary under afs. On most other systems, however, the two directories are the same. In which directory will public executables reside (~name ok)? [/usr/local/bin] In which directory will public executables be installed (~name ok)? [/usr/local/bin] In the following, larger digits indicate more significance. A big-endian machine like a Pyramid or a Motorola 680?0 chip will come out to 4321. A little-endian machine like a Vax or an Intel 80?86 chip would be 1234. Other machines may have weird orders like 3412. A Cray will report 87654321. If the test program works the default is probably right. I'm now running the test program... (The test program ran ok.) What is the order of bytes in a long? [4321] Checking to see if your C compiler can cast weird floats to unsigned Yup, it does. Now, how can we feed standard input to your C preprocessor... Maybe "cc -E" will work... Nope...maybe "cc -E -" will work... Yup, it does. Your (shared) C library seems to be in /lib/libsys_s.a. If the guess above is wrong (which it might be if you're using a strange compiler, or your machine supports multiple models), you can override it here. Your C library is where? [/lib/libsys_s.a] Extracting names from the following files for later perusal: /lib/libsys_s.a /usr/lib/libdbm.a This may take a while...done bcmp() found bcopy() found Checking to see if your bcopy() can do overlapping copies... It can. bzero() found Your sprintf() returns (int). vprintf() found. Your vsprintf() returns (int). chsize() NOT found crypt() found. readdir() found dirent.h found. Some sites have disabled setuid #! scripts because of a bug in the kernel that prevents them from being secure. If you are on such a system, the setuid/setgid bits on scripts are currently useless. It is possible for perl to detect those bits and emulate setuid/setgid in a secure fashion until a better solution is devised for the kernel problem. Do you want to do setuid/setgid emulation? [n] dup2() found fchmod() found fchown() found fcntl() found You can have filenames longer than 14 characters. flock() found getgroups() found gethostent() found getpgrp() found getpgrp2() NOT found getpriority() found htonl() found Your system has both index() and strchr(). Shall I use index() rather than strchr()? [y] isascii() NOT found killpg() found lstat() found memcmp() found memcpy() found Checking to see if your memcpy() can do overlapping copies... It can't. memmove() found memset() found mkdir() found msgctl() NOT found msgget() NOT found msgsnd() NOT found msgrcv() NOT found You don't have the full msg*(2) library. Do you wish to attempt to use the malloc that comes with perl? [n] ndbm.h found. dbm.h found. Looks like you have Berkeley networking support. sys/file.h defines the O_* constants... and you have the 3 argument form of open(). pwd.h found. rename() found rewinddir() NOT found rmdir() found seekdir() found select() found semctl() NOT found semget() NOT found semop() NOT found You don't have the full sem*(2) library. setegid() found seteuid() found setpgrp() found setpgrp2() NOT found setpriority() found setregid() found setresgid() NOT found setreuid() found setresuid() NOT found setrgid() found setruid() found shmctl() NOT found shmget() NOT found shmat() NOT found shmdt() NOT found You don't have the full shm*(2) library. Your stat knows about block sizes. Your stdio is pretty std. Checking to see if your C compiler can copy structs... Yup, it can. strerror() found symlink() found syscall() found Testing to see which of , , and should be included, because this application wants: struct timeval struct tm ctime(3) declarations I'm now running the test program... Trying -DI_SYS_TIME Succeeded with -DI_SYS_TIME telldir() found Configure: /usr/include/bsd/signal.h: cannot open You have void (*signal())() instead of int. truncate() found vfork() found Checking to see if your C compiler knows about "volatile"... Yup, it does. wait4() found waitpid() NOT found What type are groups ids returned by getgid(), etc.? [gid_t] (The following only matters if you have getgroups().) What type are the group ids returned by getgroups()? [int] Checking to see how big your integers are... What is the size of an integer (in bytes)? [4] The perl package has some auxiliary files that should be reside in a library that is accessible by everyone. Where should these "private" but accessible files reside? (~name ok) [/usr/local/lib/perl] On some systems (such as afs) you have to install the library files in a different directory to get them to go to the right place. Where should the library files be installed? (~name ok) [/usr/local/lib/perl] Checking to see how many bits your rand function produces... How many bits does your rand() function produce? [31] Some installations have a separate directory just for executable scripts so that they can mount it across multiple architectures but keep the scripts in one spot. You might, for example, have a subdirectory of /usr/share for this. Or you might just lump your scripts in with all your other executables. Where will publicly executable scripts reside (~name ok)? [/usr/local/bin] Some installations must install scripts in a different directory than where they will eventually reside. On most systems they're the same directory. Where do you install publicly executable scripts (~name ok)? [/usr/local/bin] Generating a list of signal names... Signals are: ZERO HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URG STOP TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH LOST USR1 USR2 Your stdio uses signed chars. What type are user ids returned by getuid(), etc.? [uid_t] Checking to see how well your C compiler groks the void type... Support flag bits are: 1: basic void declarations. 2: arrays of pointers to functions returning void. 4: operations between pointers to and addresses of void functions. It appears to support void to the level perl wants (7). Your void support flags add up to what? [7] Which compiler compiler (yacc or bison -y) will you use? [/usr/bin/yacc] We don't need to if we include . gdbm.h NOT found. grp.h found. netinet/in.h found. We'll be including . sys/ioctl.h found. utime.h found. varargs.h found. No vfork.h found. End of configuration questions. Creating config.sh... Hmm...You had some extra variables I don't know about...I'll try to keep 'em... Propagating recommended variable $libswanted... Propagating recommended variable $usemymalloc... If you didn't make any mistakes, then just type a carriage return here. If you need to edit config.sh, do it as a shell escape here: ! ------------- At this point you can edit config.sh by escaping to the shell. Thus far the following have been indirectly defined in config.sh i_utime='define' i_dirent='define' both of these should be "undef" and make sure i_sys_dir='define' Here's the rest of the transcript Doing variable substitutions on .SH files... Extracting Makefile (with variable substitutions) Extracting c2ph (with variable substitutions) Extracting cflags (with variable substitutions) Extracting config.h (with variable substitutions) Extracting h2ph (with variable substitutions) Extracting makedepend (with variable substitutions) Extracting makedir (with variable substitutions) Extracting x2p/Makefile (with variable substitutions) Extracting cflags (with variable substitutions) Extracting find2perl (with variable substitutions) Extracting s2p (with variable substitutions) Now you need to generate make dependencies by running "make depend". You might prefer to run it in background: "make depend > makedepend.out &" It can take a while, so you might not want to run it right now. Run make depend now? [n] y test -f perly.h || cp /dev/null perly.h ./makedepend echo array.c cmd.c cons.c consarg.c doarg.c doio.c dolist.c dump.c eval.c form.c hash.c perl.c regcomp.c regexec.c stab.c str.c toke.c util.c usersub.c | tr ' ' '\012' >.clist Finding dependencies for array.o. Finding dependencies for cmd.o. Finding dependencies for cons.o. Finding dependencies for consarg.o. Finding dependencies for doarg.o. Finding dependencies for doio.o. Finding dependencies for dolist.o. Finding dependencies for dump.o. Finding dependencies for eval.o. Finding dependencies for form.o. Finding dependencies for hash.o. Finding dependencies for perl.o. Finding dependencies for regcomp.o. Finding dependencies for regexec.o. Finding dependencies for stab.o. Finding dependencies for str.o. Finding dependencies for toke.o. Finding dependencies for util.o. Finding dependencies for usersub.o. echo Makefile.SH makedepend.SH h2ph.SH | tr ' ' '\012' >.shlist Updating makefile... test -s perly.h || /bin/rm -f perly.h cd x2p; make depend ../makedepend echo hash.c str.c util.c walk.c | tr ' ' '\012' >.clist Finding dependencies for hash.o. Finding dependencies for str.o. Finding dependencies for util.o. Finding dependencies for walk.o. echo Makefile.SH makedepend.SH | tr ' ' '\012' >.shlist Updating makefile... Now you must run a make. root:/Users/robert/archives/perl-4.036>make 10:02 Expect 27 shift/reduce and 57 reduce/reduce conflicts /usr/bin/yacc -d perly.y conflicts: 27 shift/reduce, 57 reduce/reduce sh ./perly.fixer y.tab.c perly.c Patching perly.c to allow dynamic yacc stack allocation Assuming bsd4.3 yaccpar mv y.tab.h perly.h echo 'extern YYSTYPE yylval;' >>perly.h `sh cflags perly.o` perly.c CCCMD = cc -c -I/usr/include -O `sh cflags array.o` array.c CCCMD = cc -c -I/usr/include -O `sh cflags cmd.o` cmd.c CCCMD = cc -c -I/usr/include -O `sh cflags cons.o` cons.c CCCMD = cc -c -I/usr/include -O `sh cflags consarg.o` consarg.c CCCMD = cc -c -I/usr/include -O `sh cflags doarg.o` doarg.c CCCMD = cc -c -I/usr/include -O `sh cflags doio.o` doio.c CCCMD = cc -c -I/usr/include -O doio.c: In function `do_open': doio.c:294: warning: passing arg 2 of `getsockname' from incompatible pointer type doio.c: In function `do_bind': doio.c:1451: warning: passing arg 2 of `bind' from incompatible pointer type doio.c: In function `do_connect': doio.c:1482: warning: passing arg 2 of `connect' from incompatible pointer type doio.c: In function `do_getsockname': doio.c:1673: warning: passing arg 2 of `getsockname' from incompatible pointer type doio.c:1677: warning: passing arg 2 of `getpeername' from incompatible pointer type `sh cflags dolist.o` dolist.c CCCMD = cc -c -I/usr/include -O `sh cflags dump.o` dump.c CCCMD = cc -c -I/usr/include -O `sh cflags eval.o` eval.c CCCMD = cc -c -I/usr/include -O `sh cflags form.o` form.c CCCMD = cc -c -I/usr/include -O `sh cflags perl.o` perl.c CCCMD = cc -c -I/usr/include -O `sh cflags regcomp.o` regcomp.c CCCMD = cc -c -I/usr/include -O `sh cflags regexec.o` regexec.c CCCMD = cc -c -I/usr/include -O `sh cflags stab.o` stab.c CCCMD = cc -c -I/usr/include -O `sh cflags str.o` str.c CCCMD = cc -c -I/usr/include -O `sh cflags toke.o` toke.c CCCMD = cc -c -I/usr/include -O `sh cflags util.o` util.c CCCMD = cc -c -I/usr/include -O `sh cflags hash.o` hash.c CCCMD = cc -c -I/usr/include -O `sh cflags usersub.o` usersub.c CCCMD = cc -c -I/usr/include -O cc array.o cmd.o cons.o consarg.o doarg.o doio.o dolist.o dump.o eval.o form.o perl.o regcomp.o regexec.o stab.o str.o toke.o util.o hash.o perly.o usersub.o -ldbm -lsys_s -o perl rm -f tperly.c ln -s perly.c tperly.c `sh cflags tperly.o` -DTAINT tperly.c CCCMD = cc -c -I/usr/include -O rm -f tperly.c rm -f tperl.c ln -s perl.c tperl.c `sh cflags tperl.o` -DTAINT tperl.c CCCMD = cc -c -I/usr/include -O rm -f tperl.c rm -f tarray.c ln -s array.c tarray.c `sh cflags tarray.o` -DTAINT tarray.c CCCMD = cc -c -I/usr/include -O rm -f tarray.c rm -f tcmd.c ln -s cmd.c tcmd.c `sh cflags tcmd.o` -DTAINT tcmd.c CCCMD = cc -c -I/usr/include -O rm -f tcmd.c rm -f tcons.c ln -s cons.c tcons.c `sh cflags tcons.o` -DTAINT tcons.c CCCMD = cc -c -I/usr/include -O rm -f tcons.c rm -f tconsarg.c ln -s consarg.c tconsarg.c `sh cflags tconsarg.o` -DTAINT tconsarg.c CCCMD = cc -c -I/usr/include -O rm -f tconsarg.c rm -f tdoarg.c ln -s doarg.c tdoarg.c `sh cflags tdoarg.o` -DTAINT tdoarg.c CCCMD = cc -c -I/usr/include -O rm -f tdoarg.c rm -f tdoio.c ln -s doio.c tdoio.c `sh cflags tdoio.o` -DTAINT tdoio.c CCCMD = cc -c -I/usr/include -O tdoio.c: In function `do_open': tdoio.c:294: warning: passing arg 2 of `getsockname' from incompatible pointer type tdoio.c: In function `do_bind': tdoio.c:1451: warning: passing arg 2 of `bind' from incompatible pointer type tdoio.c: In function `do_connect': tdoio.c:1482: warning: passing arg 2 of `connect' from incompatible pointer type tdoio.c: In function `do_getsockname': tdoio.c:1673: warning: passing arg 2 of `getsockname' from incompatible pointer type tdoio.c:1677: warning: passing arg 2 of `getpeername' from incompatible pointer type rm -f tdoio.c rm -f tdolist.c ln -s dolist.c tdolist.c `sh cflags tdolist.o` -DTAINT tdolist.c CCCMD = cc -c -I/usr/include -O rm -f tdolist.c rm -f tdump.c ln -s dump.c tdump.c `sh cflags tdump.o` -DTAINT tdump.c CCCMD = cc -c -I/usr/include -O rm -f tdump.c rm -f teval.c ln -s eval.c teval.c `sh cflags teval.o` -DTAINT teval.c CCCMD = cc -c -I/usr/include -O rm -f teval.c rm -f tform.c ln -s form.c tform.c `sh cflags tform.o` -DTAINT tform.c CCCMD = cc -c -I/usr/include -O rm -f tform.c rm -f thash.c ln -s hash.c thash.c `sh cflags thash.o` -DTAINT thash.c CCCMD = cc -c -I/usr/include -O rm -f thash.c rm -f tregcomp.c ln -s regcomp.c tregcomp.c `sh cflags tregcomp.o` -DTAINT tregcomp.c CCCMD = cc -c -I/usr/include -O rm -f tregcomp.c rm -f tregexec.c ln -s regexec.c tregexec.c `sh cflags tregexec.o` -DTAINT tregexec.c CCCMD = cc -c -I/usr/include -O rm -f tregexec.c rm -f tstab.c ln -s stab.c tstab.c `sh cflags tstab.o` -DTAINT tstab.c CCCMD = cc -c -I/usr/include -O rm -f tstab.c rm -f tstr.c ln -s str.c tstr.c `sh cflags tstr.o` -DTAINT tstr.c CCCMD = cc -c -I/usr/include -O rm -f tstr.c rm -f ttoke.c ln -s toke.c ttoke.c `sh cflags ttoke.o` -DTAINT ttoke.c CCCMD = cc -c -I/usr/include -O rm -f ttoke.c rm -f tutil.c ln -s util.c tutil.c `sh cflags tutil.o` -DTAINT tutil.c CCCMD = cc -c -I/usr/include -O rm -f tutil.c cc tperl.o tarray.o tcmd.o tcons.o tconsarg.o tdoarg.o tdoio.o tdolist.o tdump.o teval.o tform.o thash.o tregcomp.o tregexec.o tstab.o tstr.o ttoke.o tutil.o tperly.o usersub.o -ldbm -lsys_s -o taintperl ld -r array.o cmd.o cons.o consarg.o doarg.o doio.o dolist.o dump.o eval.o form.o perl.o regcomp.o regexec.o stab.o str.o toke.o util.o hash.o perly.o -o uperl.o cd x2p; make all `sh cflags hash.o` hash.c CCCMD = cc -c -I/usr/include -O `sh cflags str.o` str.c CCCMD = cc -c -I/usr/include -O `sh cflags util.o` util.c CCCMD = cc -c -I/usr/include -O `sh cflags walk.o` walk.c CCCMD = cc -c -I/usr/include -O Expect 231 shift/reduce conflicts... /usr/bin/yacc a2p.y conflicts: 231 shift/reduce mv y.tab.c a2p.c `sh cflags a2p.o` a2p.c CCCMD = cc -c -I/usr/include -O cc hash.o str.o util.o walk.o a2p.o -ldbm -lsys_s -o a2p touch all touch all ------------ The keen obsverver would have noticed warnings like. doio.c:294: warning: passing arg 2 of `getsockname' from incompatible pointer type doio.c: In function `do_bind': doio.c:1451: warning: passing arg 2 of `bind' from incompatible pointer type doio.c: In function `do_connect': doio.c:1482: warning: passing arg 2 of `connect' from incompatible pointer type doio.c: In function `do_getsockname': doio.c:1673: warning: passing arg 2 of `getsockname' from incompatible pointer type doio.c:1677: warning: passing arg 2 of `getpeername' from incompatible pointer type If we look at the line 294 in doio.c will notice lines of the form. if (getsockname(fileno(fp), tokenbuf, &buflen) >= 0 Looking at the prototype for getsockname we notice. NAME getsockname - get socket name SYNOPSIS getsockname(s, name, namelen) int s; struct sockaddr *name; int *namelen; This means that it's second argument is a struct sockaddr pointer. Hence, to remove warnings you can explicitly cast "tokenbuf" in our last example with (struct sockaddr *)tokenbuf and the warnings will go away. After all of this "make test" looks like. root:/Users/robert/archives/perl-4.036>make test 10:20 cd t && chmod +x TEST */*.t cd t && (rm -f perl; ln -s ../perl perl) && ./perl TEST