Hello,

As part of the android port, I wanted to add some existing external
libraries to the cross-compiled ecl. I needed to add them as static
libraries directly linked in with ECL.

My cross compiled ecl doesn't have a compiler or asdf. I looked at the
build-modules function from the "compile.lsp" file which almost did what
I needed except it doesn't allow compiling directly from an asdf system
definition which would be much easier.

I first tried to add a new "cross-compile-op" operation to asdf but I
ran into the problem that the c::builder function insists on creating
and loading fasl files which is a problem because in this case it's
trying to load arm code into a x86 ecl.

I ended up with a solution that works well but is not very elegant.
Still mentioning it in case someone wants to add this functionality
properly (see attached script):
The basic idea is to modify compiler::builder and asdf::compile-file* in
such a way that they create both object files for the host and for the
target platform. FASL are still created and loaded but only for the
host. The resulting cross-compiled library is just a by-product of the
build.

Usage:
(load "cross_compile")

(asdf:make-build :ironclad
                 :type :static-library
                 :move-here t
                 :prologue-code '(provide :ironclad))


Sylvain

(require 'asdf)

;; (setq *asdf-verbose* t)
;; (setf *load-verbose* t)
;; (setf *compile-verbose* t)

(ext:package-lock "COMMON-LISP" nil)
(ext:package-lock "C" nil)

;; (trace c::builder)
;; (trace c::compile)
;; (trace c::compile-file)
;; (trace c::build-fasl)

(push :cross *features*)


(defpackage :util
  (:use :cl)
  (:export
   :join))

(in-package :util)

(defun join (seq sep)
  "Concatenate the strings in `seq' delimited by the separator `sep'."
  (format nil (concatenate 'string "~{~a~^" sep "~}") seq))


(in-package "COMPILER")


(defmacro with-android-env (body)
  `(let* ((sdk "/opt/android/android-ndk-r5")
          (sdk-ver "android-9")
          (toolchain (format nil "~a/toolchains/~a" 
"/opt/android/android-ndk-r5" "arm-linux-androideabi-4.4.3/prebuilt/linux-x86"))
          (sysroot (format nil "~a/platforms/~a" "/opt/android/android-ndk-r5" 
sdk-ver))
          (compiler::*ecl-include-directory* "/opt/ecl/android/include/")
          (compiler::*ecl-library-directory* "/opt/ecl/android/lib/")

          (compiler::*cc* (format nil "~a/bin/arm-linux-androideabi-gcc" 
toolchain))
          (compiler::*ld* (format nil "~a/bin/arm-linux-androideabi-gcc" 
toolchain))
          (compiler::*ar* (format nil "~a/bin/arm-linux-androideabi-ar" 
toolchain))
          (compiler::*ranlib* (format nil "~a/bin/arm-linux-androideabi-ranlib" 
toolchain))
          (compiler::*cc-flags* (util:join (list "-g"
                                                 (format nil "--sysroot=~a" 
sysroot)
                                                 "-DANDROID  -DPLATFORM_ANDROID"
                                                 "-O2 -fPIC -fno-common 
-D_THREAD_SAFE"
                                                 
"-I/opt/android/android-ndk-r5/platforms/android-9/arch-arm/usr/include"
                                                 "-I/opt/gmp/android/include")
                                          " "))
          (compiler::*ld-flags* (util:join (list "-g"
                                                 (format nil "--sysroot=~a" 
sysroot))
                                           " ")))
     (,@body)))


(setf (symbol-function 'builder-orig) (symbol-function 'builder))

(defun builder (target output-name &rest args &key lisp-files &allow-other-keys)
  (case target
    ((:library :static-library :lib)
     (let ((lisp-files-cross (mapcar #'(lambda (x) (merge-pathnames (format nil 
"~a-cross" (pathname-name x)) x)) lisp-files))
           (output-name-cross (merge-pathnames (format nil "~a-cross" 
(pathname-name output-name)) output-name)))
       (with-android-env
           (apply #'builder-orig target output-name :lisp-files 
lisp-files-cross args))
       (rename-file output-name output-name-cross))
     (apply #'builder-orig target output-name :lisp-files lisp-files args))
    (otherwise
     (apply #'builder-orig target output-name args))))

(in-package :asdf)
(require 'cmp)

(defun* compile-file* (input-file &rest keys &key output-file &allow-other-keys)
  (let* ((output-file (or output-file (apply 'compile-file-pathname* input-file 
keys)))
         (output-file-cross (merge-pathnames (format nil "~a-cross" 
(pathname-name output-file)) output-file))
         (tmp-file (tmpize-pathname output-file))
         (tmp-file-cross (tmpize-pathname output-file-cross))
         (status :error))
    (multiple-value-bind (output-truename warnings-p failure-p)
        (compiler::with-android-env
            (apply 'compiler::compile-file input-file :output-file 
tmp-file-cross :c-file t keys))
      (cond
        (failure-p
         (setf status *compile-file-failure-behaviour*))
        (warnings-p
         (setf status *compile-file-warnings-behaviour*))
        (t
         (setf status :success)))
      (ecase status
        ((:success :warn :ignore)
         (delete-file-if-exists output-file-cross)
         (when output-truename
           (rename-file output-truename output-file-cross)
           (setf output-truename output-file-cross)))
        (:error
         (delete-file-if-exists output-truename)
         (setf output-truename nil)))
      (values output-truename warnings-p failure-p))

    (multiple-value-bind (output-truename warnings-p failure-p)
        (apply 'compiler::compile-file input-file :output-file tmp-file :c-file 
t keys)
      (cond
        (failure-p
         (setf status *compile-file-failure-behaviour*))
        (warnings-p
         (setf status *compile-file-warnings-behaviour*))
        (t
         (setf status :success)))
      (ecase status
        ((:success :warn :ignore)
         (delete-file-if-exists output-file)
         (when output-truename
           (rename-file output-truename output-file)
           (setf output-truename output-file)))
        (:error
         (delete-file-if-exists output-truename)
         (setf output-truename nil)))
      (values output-truename warnings-p failure-p))))
------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
Ecls-list mailing list
Ecls-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ecls-list

Reply via email to