CMUCL commit: src (8 files)

Raymond Toy rtoy at common-lisp.net
Sat Jul 31 00:51:58 CEST 2010


    Date: Friday, July 30, 2010 @ 18:51:58
  Author: rtoy
    Path: /project/cmucl/cvsroot/src

   Added: lisp/mach-o.c
Modified: bootfiles/20a/boot-2010-07-1.lisp code/bsd-os.lisp
          lisp/Config.x86_darwin lisp/lisp.c lisp/save.c tools/linker-x86.sh
          tools/make-main-dist.sh

First cut at executable images on Darwin/x86.  The resulting
executable appears to work!

bootfiles/20a/boot-2010-07-1.lisp:
o Add :executable for darwin/x86.

code/bsd-os.lisp:
o Make :elf and :mach-o runtime features too.
o Register :executable of :executable is defined.

lisp/Config.x86_darwin:
o Need mach-o.c
o Add exec-final.c

lisp/lisp.c:
o Don't include elf.h if we're on Darwin since Darwin uses Mach-O, not
  ELF.
o For Darwin, we get the initial function address from
  initial_function_addr, not from &initial_function_addr, like for
  Linux. 

lisp/save.c
o Don't include libgen.h and elf.h on Darwin.

tools/linker-x86.sh:
o Update to support Darwin.

tools/make-main-dist.sh:
o Add support for executables on Darwin.

lisp/mach-o.c:
o Initial support for writing Mach-O files for the Lisp spaces.
o Initial support for reading a Mach-O executable to find and map the
  Lisp spaces.


-----------------------------------+
 bootfiles/20a/boot-2010-07-1.lisp |    2 
 code/bsd-os.lisp                  |    8 
 lisp/Config.x86_darwin            |    5 
 lisp/lisp.c                       |   10 
 lisp/mach-o.c                     |  393 ++++++++++++++++++++++++++++++++++++
 lisp/save.c                       |    4 
 tools/linker-x86.sh               |   46 +++-
 tools/make-main-dist.sh           |   32 +-
 8 files changed, 468 insertions(+), 32 deletions(-)


Index: src/bootfiles/20a/boot-2010-07-1.lisp
diff -u src/bootfiles/20a/boot-2010-07-1.lisp:1.4 src/bootfiles/20a/boot-2010-07-1.lisp:1.5
--- src/bootfiles/20a/boot-2010-07-1.lisp:1.4	Wed Jul 21 09:32:25 2010
+++ src/bootfiles/20a/boot-2010-07-1.lisp	Fri Jul 30 18:51:58 2010
@@ -34,5 +34,5 @@
 )
 
 ;; Executable feature works on sparc!
-#+sparc
+#+(or sparc (and x86 darwin))
 (pushnew :executable *features*)
Index: src/code/bsd-os.lisp
diff -u src/code/bsd-os.lisp:1.16 src/code/bsd-os.lisp:1.17
--- src/code/bsd-os.lisp:1.16	Tue Apr 20 13:57:43 2010
+++ src/code/bsd-os.lisp	Fri Jul 30 18:51:58 2010
@@ -5,7 +5,7 @@
 ;;; Carnegie Mellon University, and has been placed in the public domain.
 ;;;
 (ext:file-comment
-  "$Header: /project/cmucl/cvsroot/src/code/bsd-os.lisp,v 1.16 2010-04-20 17:57:43 rtoy Exp $")
+  "$Header: /project/cmucl/cvsroot/src/code/bsd-os.lisp,v 1.17 2010-07-30 22:51:58 rtoy Exp $")
 ;;;
 ;;; **********************************************************************
 ;;;
@@ -35,11 +35,11 @@
 		       #-(or freebsd NetBSD OpenBSD Darwin) :bsd)
 
 #+elf
-(register-lisp-feature :elf)
+(register-lisp-runtime-feature :elf)
 #+mach-o
-(register-lisp-feature :mach-o)
+(register-lisp-runtime-feature :mach-o)
 
-#+freebsd
+#+executable
 (register-lisp-runtime-feature :executable)
 
 (setq *software-type* #+OpenBSD "OpenBSD"
Index: src/lisp/Config.x86_darwin
diff -u src/lisp/Config.x86_darwin:1.8 src/lisp/Config.x86_darwin:1.9
--- src/lisp/Config.x86_darwin:1.8	Sun Jan 11 12:52:44 2009
+++ src/lisp/Config.x86_darwin	Fri Jul 30 18:51:58 2010
@@ -12,7 +12,10 @@
 
 UNDEFSYMPATTERN = -Xlinker -u -Xlinker &
 
-OS_SRC += Darwin-os.c 
+OS_SRC += Darwin-os.c mach-o.c
 OS_LINK_FLAGS = $(MIN_VER)
 OS_LIBS =
 
+EXEC_FINAL_OBJ = exec-final.o
+
+
Index: src/lisp/lisp.c
diff -u src/lisp/lisp.c:1.72 src/lisp/lisp.c:1.73
--- src/lisp/lisp.c:1.72	Fri Jul 30 16:26:11 2010
+++ src/lisp/lisp.c	Fri Jul 30 18:51:58 2010
@@ -1,7 +1,7 @@
 /*
  * main() entry point for a stand alone lisp image.
  *
- * $Header: /project/cmucl/cvsroot/src/lisp/lisp.c,v 1.72 2010-07-30 20:26:11 rtoy Exp $
+ * $Header: /project/cmucl/cvsroot/src/lisp/lisp.c,v 1.73 2010-07-30 22:51:58 rtoy Exp $
  *
  */
 
@@ -32,9 +32,11 @@
 #include "core.h"
 #include "save.h"
 #include "lispregs.h"
-#if defined FEATURE_EXECUTABLE
+#if defined(FEATURE_EXECUTABLE)
+#if !defined(DARWIN)
 #include "elf.h"
 #endif
+#endif
 
 
 /* SIGINT handler that invokes the monitor. */
@@ -437,8 +439,8 @@
     lispobj initial_function = 0;
 
     if (builtin_image_flag != 0) {
-#if defined(i386) && defined(__linux__)
-        initial_function = initial_function_addr;
+#if defined(i386) && (defined(__linux__) || defined(DARWIN))
+      initial_function = (lispobj) initial_function_addr;
 #else
         initial_function = (lispobj) & initial_function_addr;
 #endif
Index: src/lisp/mach-o.c
diff -u /dev/null src/lisp/mach-o.c:1.1
--- /dev/null	Fri Jul 30 18:51:58 2010
+++ src/lisp/mach-o.c	Fri Jul 30 18:51:58 2010
@@ -0,0 +1,393 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "os.h"
+#include "core.h"
+#include "internals.h"
+#include "globals.h"
+#include "validate.h"
+
+#include "mach-o/loader.h"
+
+#define LINKER_SCRIPT "linker-x86.sh"
+#define C_COMPILER "cc"
+
+typedef struct mach_header MachO_hdr;
+
+/* Elf data structures. */
+static MachO_hdr eh;
+
+/* Names of the Lisp image ELF sections. These names must be the same as
+   the corresponding names found in the linker script.  */
+
+static char *section_names[] = {"CORDYN", "CORSTA", "CORRO"};
+
+/* Note: write errors are not fatal. */
+static int
+ewrite(int fd, const void *buf, size_t nbytes, const char *func)
+{
+    if (write(fd, buf, nbytes) < nbytes) {
+	perror(func);
+	return -1;	/* Simple way to indicate error. */
+    }
+    return 0;
+}
+
+/*
+  Read errors are fatal, because these reads have to succeed for lisp to
+  get off the ground.
+ */
+static void
+eread(int d, void *buf, size_t nbytes, const char *func)
+{
+    int res = read(d, buf, nbytes);
+
+    if (res == -1) {
+	perror(func);
+	exit(-1);
+    }
+
+    if (res < nbytes) {
+	fprintf(stderr, "Short read in %s!\n", func);
+	exit(-1);
+    }
+}
+
+static void
+elseek(int d, off_t o, int whence, const char *func)
+{
+    if (lseek(d, o, whence) == -1) {
+	perror(func);
+	exit(-1);
+    }
+}
+
+
+static int
+create_elf_file (const char *dir, int id)
+{
+    char outfilename[FILENAME_MAX + 1];
+    int out;
+
+    /* Note: the space id will be either 1, 2 or 3.  Subtract one to index
+       the name array. */
+    snprintf(outfilename, FILENAME_MAX, "%s/%s.o", dir, section_names[id - 1]);
+    out = open(outfilename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+    if(!out) {
+	perror("write_elf_object: can't open file");
+	fprintf(stderr, "%s\n", outfilename);
+    }
+
+    return out;
+}
+
+
+static int
+write_elf_header(int fd)
+{
+    extern MachO_hdr eh;
+
+    /* Ident array. */
+    eh.magic = MH_MAGIC;
+    /* Support any kind x86.  (Should we be more specific?) */
+    eh.cputype = CPU_TYPE_I386;
+    eh.cpusubtype = CPU_SUBTYPE_I386_ALL;
+
+    eh.filetype = MH_OBJECT;
+
+    /* We only have 1 load command in our object */
+    eh.ncmds = 1;
+    /* Size of 1 segment command plus size of 1 section */
+    eh.sizeofcmds = sizeof(struct segment_command) + sizeof(struct section);
+    eh.flags = MH_NOUNDEFS | MH_NOMULTIDEFS;
+
+    return ewrite(fd, &eh, sizeof(MachO_hdr), __func__);
+}
+
+static int
+write_load_command(int fd, char* name, int length, os_vm_address_t start)
+{
+    struct segment_command lc;
+
+    lc.cmd = LC_SEGMENT;
+    /* Size is 1 segment command + 1 section command */
+    lc.cmdsize = sizeof(lc) + sizeof(struct section);
+    strncpy(lc.segname, name, sizeof(lc.segname));
+    lc.vmaddr = start;
+    lc.vmsize = length;
+    /* Offset where the data is.  It's the header, the segment
+     * command, and one section */
+    lc.fileoff = lc.cmdsize + sizeof(struct mach_header);
+    lc.filesize = length;
+    lc.maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
+    lc.initprot = lc.maxprot;
+    lc.nsects = 1;
+    lc.flags = 0;
+
+    return ewrite(fd, &lc, sizeof(lc), __func__);
+}
+
+static int
+write_section(int fd, int length, os_vm_address_t start, char* object_name)
+{
+    struct section sc;
+
+    strncpy(sc.sectname, object_name, sizeof(sc.sectname));
+    strncpy(sc.segname, object_name, sizeof(sc.segname));
+    sc.addr = start;
+    sc.size = length;
+    /* Offset of the data.  We have one header, one segment and one
+     * section */
+    sc.offset = sizeof(struct mach_header) + sizeof(struct segment_command) +
+        sizeof(struct section);
+    sc.align = 12;              /* Align on 2^12 = 4096 boundary */
+    sc.reloff = 0;
+    sc.nreloc = 0;
+    sc.flags = 0;
+    sc.reserved1 = 0;
+    sc.reserved2 = 0;
+
+    return ewrite(fd, &sc, sizeof(sc), __func__);
+}
+
+static int
+write_section_data(int fd, long length, os_vm_address_t real_addr)
+{
+    return ewrite(fd, (void *)real_addr, length, __func__);
+}
+
+
+int
+write_elf_object(const char *dir, int id, os_vm_address_t start, os_vm_address_t end)
+{
+    int out = create_elf_file(dir, id);
+    int ret = 0;
+    /* The length should be a multiple of the page size. */
+    size_t length = end - start + (os_vm_page_size -
+				   ((end - start) % os_vm_page_size));
+
+    if(id < 1 || id > 3) {
+	fprintf(stderr, "Invalid space id in %s: %d\n", __func__, id);
+	fprintf(stderr, "Executable not built.\n");
+	ret = -1;
+    }
+
+    /* Make id be 0-based to match array. */
+    id--;
+
+    if ((write_elf_header(out) == -1)
+        || (write_load_command(out, section_names[id], length, start) == -1)
+        || (write_section(out, length, start, section_names[id]) == -1)
+        || (write_section_data(out, length, start) == -1)) {
+	fprintf(stderr, "Executable not built.\n");
+	ret = -1;
+    }
+
+    close(out);
+    return ret;
+}
+
+void
+elf_cleanup(const char *dirname)
+{
+    char filename[FILENAME_MAX + 1];
+    int i;
+
+    /* Get rid of lisp space files. */
+    for(i = 0; i < 3; i++) {
+	/* Delete core space .o files. */
+	sprintf(filename, "%s/%s.o", dirname, section_names[i]);
+	unlink(filename);
+    }
+}
+
+int
+elf_run_linker(long init_func_address, char *file)
+{
+    lispobj libstring = SymbolValue(CMUCL_LIB);     /* Get library: */
+    struct vector *vec = (struct vector *)PTR(libstring);
+    char *paths;
+    char command[FILENAME_MAX + 1];
+    char command_line[FILENAME_MAX + FILENAME_MAX + 10];
+    char *strptr;
+    struct stat st;
+    int ret;
+    extern int debug_lisp_search;
+#ifndef UNICODE
+    paths = strdup((char *)vec->data);
+#else
+    /*
+     * What should we do here with 16-bit characters?  For now we just
+     * take the low 8-bits.
+     */
+    paths = malloc(vec->length);
+    {
+        int k;
+        unsigned short *data;
+        data = (unsigned short*) vec->data;
+        
+        for (k = 0; k < vec->length; ++k) {
+            paths[k] = data[k] & 0xff;
+        }
+    }
+#endif
+    strptr = strtok(paths, ":");
+
+    if (debug_lisp_search) {
+        printf("Searching for linker.sh script\n");
+    }
+
+    while(strptr != NULL) {
+        
+	sprintf(command, "%s/%s", strptr, LINKER_SCRIPT);
+
+        if (debug_lisp_search) {
+            printf("  %s\n", command);
+        }
+        
+	if (stat(command, &st) == 0) {
+            extern int main();
+            
+	    free(paths);
+	    printf("\t[%s: linking %s... \n", command, file);
+	    fflush(stdout);
+            sprintf(command_line, "%s %s 0x%lx '%s' 0x%lx 0x%lx 0x%lx", command,
+                    C_COMPILER, init_func_address, file,
+                    (unsigned long) READ_ONLY_SPACE_START,
+                    (unsigned long) STATIC_SPACE_START,
+                    (unsigned long) DYNAMIC_0_SPACE_START);
+	    ret = system(command_line);
+	    if(ret == -1) {
+		perror("Can't run link script");
+	    } else {
+		printf("\tdone]\n");
+		fflush(stdout);
+	    }
+	    return ret;
+	}
+	strptr = strtok(NULL, ":");
+    }
+
+    fprintf(stderr,
+	    "Can't find %s script in CMUCL library directory list.\n", LINKER_SCRIPT);
+    free(paths);
+    return -1;
+}
+
+
+/* Read the ELF header from a file descriptor and stuff it into a
+	 structure.	 Make sure it is really an elf header etc. */
+static void
+read_elf_header(int fd, MachO_hdr *ehp)
+{
+    eread(fd, ehp, sizeof(MachO_hdr), __func__);
+
+    if (ehp->magic != MH_MAGIC) {
+	fprintf(stderr,
+		"Bad ELF magic number --- not an elf file.	Exiting in %s.\n",
+		__func__);
+	exit(-1);
+    }
+}
+
+
+/*
+  Map the built-in lisp core sections.
+
+  NOTE!  We need to do this without using malloc because the memory layout
+  is not set until some time after this is done.
+*/
+void
+map_core_sections(const char *exec_name)
+{
+    int exec_fd;
+    int sections_remaining = 3;
+    int i, j;
+    extern int image_dynamic_space_size;
+    extern int image_static_space_size;
+    extern int image_read_only_space_size;
+
+    if (!(exec_fd = open(exec_name, O_RDONLY))) {
+	perror("Can't open executable!");
+	exit(-1);
+    }
+
+    read_elf_header(exec_fd, &eh);
+
+    for (i = 0; i < eh.ncmds && sections_remaining > 0; i++) {
+        struct load_command lc;
+        struct segment_command sc;
+        
+        /* Read the load command and see if its segname matches one of
+         * our section names.  If it does, save the file offset for
+         * later so we can map the data */
+        
+        eread(exec_fd, &lc, sizeof(lc), __func__);
+        fprintf(stderr, "Load %d:  cmd = %d, cmdsize = %d\n", i, lc.cmd, lc.cmdsize);
+        
+        if (lc.cmd == LC_SEGMENT) {
+            /* Read the segment command and save the file offset */
+            fprintf(stderr, "Reading next %d bytes for SEGMENT\n", sizeof(sc) - sizeof(lc));
+            eread(exec_fd, &sc.segname, sizeof(sc) - sizeof(lc), __func__);
+            fprintf(stderr, "LC_SEGMENT: name = %s\n", sc.segname);
+            
+            for (j = 0; j < 3; ++j) {
+                if (strncmp(sc.segname, section_names[j], sizeof(sc.segname)) == 0) {
+                    /* Found a core segment.  Map it! */
+                    fprintf(stderr, "Matched!\n");
+                    fprintf(stderr, " Fileoff = %ld\n", sc.fileoff);
+                    fprintf(stderr, " vmaddr  = 0x%lx\n", sc.vmaddr);
+                    fprintf(stderr, " vmsize  = 0x%lx\n", sc.vmsize);
+                    
+                    if ((os_vm_address_t) os_map(exec_fd, sc.fileoff,
+                                                 (os_vm_address_t) sc.vmaddr,
+                                                 sc.vmsize)
+                        == (os_vm_address_t) -1) {
+			fprintf(stderr, "%s: Can't map section %s\n", __func__, section_names[j]);
+			exit(-1);
+                    }
+                    switch (j) {
+                      case 0:
+                          /* Dynamic space */
+                          image_dynamic_space_size = sc.vmsize;
+                          break;
+                      case 1:
+                          /* Static space */
+                          image_static_space_size = sc.vmsize;
+                          break;
+                      case 2:
+                          /* Read only */
+                          image_read_only_space_size = sc.vmsize;
+                          break;
+                      default:
+                          /* Shouldn't happen! */
+                          abort();
+                    }
+                    --sections_remaining;
+                    break;
+                }
+            }
+            fprintf(stderr, "Reading %d remainder bytes left in command\n",
+                    lc.cmdsize - sizeof(sc));
+            elseek(exec_fd, lc.cmdsize - sizeof(sc), SEEK_CUR, __func__);
+        } else {
+            /* Seek to the next command */
+            fprintf(stderr, "Seeking by %d bytes\n", lc.cmdsize - sizeof(lc));
+            elseek(exec_fd, lc.cmdsize - sizeof(lc), SEEK_CUR, __func__);
+        }
+    }
+
+    close(exec_fd);
+
+    if (sections_remaining != 0) {
+	fprintf(stderr, "Couldn't map all core sections!	Exiting!\n");
+	exit(-1);
+    }
+}
+
Index: src/lisp/save.c
diff -u src/lisp/save.c:1.25 src/lisp/save.c:1.26
--- src/lisp/save.c:1.25	Fri Jul 30 16:26:11 2010
+++ src/lisp/save.c	Fri Jul 30 18:51:58 2010
@@ -1,6 +1,6 @@
 /*
 
- $Header: /project/cmucl/cvsroot/src/lisp/save.c,v 1.25 2010-07-30 20:26:11 rtoy Exp $
+ $Header: /project/cmucl/cvsroot/src/lisp/save.c,v 1.26 2010-07-30 22:51:58 rtoy Exp $
 
  This code was written as part of the CMU Common Lisp project at
  Carnegie Mellon University, and has been placed in the public domain.
@@ -28,9 +28,11 @@
 #endif
 
 #ifdef FEATURE_EXECUTABLE
+#if !defined(DARWIN)
 #include <libgen.h>
 #include "elf.h"
 #endif
+#endif
 
 extern int version;
 
Index: src/tools/linker-x86.sh
diff -u src/tools/linker-x86.sh:1.2 src/tools/linker-x86.sh:1.3
--- src/tools/linker-x86.sh:1.2	Fri Jul 30 16:26:12 2010
+++ src/tools/linker-x86.sh	Fri Jul 30 18:51:58 2010
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# $Id: linker-x86.sh,v 1.2 2010-07-30 20:26:12 rtoy Exp $
+# $Id: linker-x86.sh,v 1.3 2010-07-30 22:51:58 rtoy Exp $
 
 # This file written by Raymond Toy as part of CMU Common Lisp and is
 # placed in the public domain.
@@ -19,23 +19,53 @@
 CCOMPILER=$1
 IFADDR=$2
 EXEC=$3
-RO_ADDR="-Wl,--section-start=CORRO=$4"
-STATIC_ADDR="-Wl,--section-start=CORSTA=$5"
-DYN_ADDR="-Wl,--section-start=CORDYN=$6"
 
 OUTDIR=`dirname $EXEC`
 OUTNAME=`basename $EXEC`
 
 CMUCLLIB=`dirname $0`
 
-#OPT_IFADDR="-Wl,--defsym -Wl,initial_function_addr=$IFADDR"
-OPT_IFADDR="ifaddr.c"
-OPT_ARCHIVE="-Wl,--whole-archive -Wl,$CMUCLLIB/lisp.a -Wl,--no-whole-archive"
+# Name of file where we write the actual initial function address.
+OPT_IFADDR="cmu-ifaddr-$$.c"
+# Names of the core sections from Lisp.
 OPT_CORE="CORRO.o CORSTA.o CORDYN.o"
 
+case `uname` in
+  Linux*)
+      # How to specify the starting address for each of the sections
+      RO_ADDR="-Wl,--section-start=CORRO=$4"
+      STATIC_ADDR="-Wl,--section-start=CORSTA=$5"
+      DYN_ADDR="-Wl,--section-start=CORDYN=$6"
+
+      #OPT_IFADDR="-Wl,--defsym -Wl,initial_function_addr=$IFADDR"
+
+      # Specify how to link the entire lisp.a library
+      OPT_ARCHIVE="-Wl,--whole-archive -Wl,$CMUCLLIB/lisp.a -Wl,--no-whole-archive"
+      # See Config.x86_linux
+      OS_LIBS=-ldl
+      ;;
+  Darwin*)
+      # How to specify the starting address for each of the sections
+      RO_ADDR="-segaddr CORRO $4"
+      STATIC_ADDR="-segaddr CORSTA $5"
+      DYN_ADDR="-segaddr CORDYN $6"
+
+      # Specify how to link the entire lisp.a library
+      OPT_ARCHIVE="-all_load $CMUCLLIB/lisp.a"
+
+      # Extra stuff.  For some reason one __LINKEDIT segment is mapped
+      # just past the dynamic space.  This messes things up, so we move it
+      # to another address.  This seems to be free, at least on 10.5.
+
+      OPT_EXTRA="-segaddr __LINKEDIT 0x99000000"
+      # See Config.x86_darwin
+      OS_LIBS=
+      ;;
+esac
+
 trap 'rm -f $OUTDIR/$OPT_IFADDR' 0
 
 (cd $OUTDIR
 echo "long initial_function_addr = $IFADDR;" > $OPT_IFADDR
-$CCOMPILER -m32 -o $OUTNAME -rdynamic $OPT_IFADDR $OPT_ARCHIVE $OPT_CORE $RO_ADDR $STATIC_ADDR $DYN_ADDR -ldl -lm)
+$CCOMPILER -m32 -o $OUTNAME -rdynamic $OPT_IFADDR $OPT_ARCHIVE $OPT_CORE $RO_ADDR $STATIC_ADDR $DYN_ADDR $OPT_EXTRA $OS_LIBS -lm)
 
Index: src/tools/make-main-dist.sh
diff -u src/tools/make-main-dist.sh:1.22 src/tools/make-main-dist.sh:1.23
--- src/tools/make-main-dist.sh:1.22	Thu Jul 29 00:34:10 2010
+++ src/tools/make-main-dist.sh	Fri Jul 30 18:51:58 2010
@@ -51,19 +51,24 @@
 esac
 
 case $OS in
-	FreeBSD*)	
-	    EXECUTABLE=true
-	    SCRIPT=FreeBSD
-	    ;;
-	linux*)		
-	    EXECUTABLE=true
-	    SCRIPT=Linux
-	    ;;
-	solaris*)		
-	    EXECUTABLE=true
-	    SCRIPT=SunOS
-	    ;;
-        *)              EXECUTABLE=""   ;;
+  FreeBSD*)	
+      EXECUTABLE=true
+      SCRIPT=FreeBSD
+      ;;
+  linux*)		
+      EXECUTABLE=true
+      SCRIPT=Linux
+      ;;
+  solaris*)		
+      EXECUTABLE=true
+      SCRIPT=SunOS
+      ;;
+  darwin*)
+      EXECUTABLE=true
+      ;;
+  *)
+      EXECUTABLE=""
+      ;;
 esac
 
 # Frob PATH to use /usr/ucb/install for Solaris
@@ -93,6 +98,7 @@
     install ${GROUP} ${OWNER} -m 0755 $TARGET/lisp/lisp.a $DESTDIR/lib/cmucl/lib/
     install ${GROUP} ${OWNER} -m 0755 src/tools/linker.sh $DESTDIR/lib/cmucl/lib/
     install ${GROUP} ${OWNER} -m 0755 src/tools/linker-x86.sh $DESTDIR/lib/cmucl/lib/
+    install ${GROUP} ${OWNER} -m 0755 src/tools/linker-darwin.sh $DESTDIR/lib/cmucl/lib/
     install ${GROUP} ${OWNER} -m 0755 src/tools/$SCRIPT-cmucl-linker-script $DESTDIR/lib/cmucl/lib/
 fi
 for corefile in $TARGET/lisp/$CORE



More information about the cmucl-commit mailing list