important: several revisions, simplifications (this commit is tested and stable)

This commit is contained in:
pls.153 2022-03-17 16:15:32 +01:00
parent fee4358760
commit 5bd6b31630
19 changed files with 216 additions and 324 deletions

View file

@ -19,7 +19,7 @@ PRE_TARGETDEPS += tmp/libapp.a
QT += quick qml QT += quick qml
TEMPLATE = app TEMPLATE = app
CONFIG += no_keywords release CONFIG += no_keywords release
DEFINES += INI_LISP INI_ECL_CONTRIB DEFINES += DESKTOP_APP INI_LISP INI_ECL_CONTRIB
INCLUDEPATH = /usr/local/include INCLUDEPATH = /usr/local/include
ECL_VERSION = $$lower($$system(ecl -v)) ECL_VERSION = $$lower($$system(ecl -v))
ECL_VERSION = $$replace(ECL_VERSION, " ", "-") ECL_VERSION = $$replace(ECL_VERSION, " ", "-")
@ -36,12 +36,14 @@ macx: LIBS += -L../../../platforms/macos/lib
android { android {
QT += androidextras QT += androidextras
DEFINES += INI_ASDF
DEFINES -= DESKTOP_APP
INCLUDEPATH = $$(ECL_ANDROID)/include INCLUDEPATH = $$(ECL_ANDROID)/include
ECL_VERSION = $$lower($$system($ECL_ANDROID/../ecl-android-host/bin/ecl -v)) ECL_VERSION = $$lower($$system($ECL_ANDROID/../ecl-android-host/bin/ecl -v))
ECL_VERSION = $$replace(ECL_VERSION, " ", "-") ECL_VERSION = $$replace(ECL_VERSION, " ", "-")
LIBS = -L$$(ECL_ANDROID)/lib -lecl LIBS = -L$$(ECL_ANDROID)/lib -lecl
LIBS += -L$$(ECL_ANDROID)/lib/$$ECL_VERSION LIBS += -L$$(ECL_ANDROID)/lib/$$ECL_VERSION
LIBS += -lecl-help -ldeflate -lecl-cdb -lecl-curl -lql-minitar -lsockets LIBS += -lasdf -lecl-help -ldeflate -lecl-cdb -lecl-curl -lql-minitar -lsockets
LIBS += -L../../../platforms/android/lib LIBS += -L../../../platforms/android/lib
ANDROID_ABIS = "arm64-v8a" ANDROID_ABIS = "arm64-v8a"
@ -50,6 +52,8 @@ android {
} }
ios { ios {
DEFINES += INI_ASDF
DEFINES -= DESKTOP_APP
INCLUDEPATH = $$(ECL_IOS)/include INCLUDEPATH = $$(ECL_IOS)/include
ECL_VERSION = $$lower($$system($ECL_IOS/../ecl-ios-host/bin/ecl -v)) ECL_VERSION = $$lower($$system($ECL_IOS/../ecl-ios-host/bin/ecl -v))
ECL_VERSION = $$replace(ECL_VERSION, " ", "-") ECL_VERSION = $$replace(ECL_VERSION, " ", "-")

View file

@ -0,0 +1 @@
ecl -shell qml/.create-qml-loaders.lisp

View file

@ -173,11 +173,7 @@
~% :q (quicklisp)") ~% :q (quicklisp)")
(values)) (values))
(defun ini () (progn
(x:while (not (find-quick-item ui:*repl-model*))
(qsleep 0.5))
(ini-streams) (ini-streams)
(in-package :qml-user) (in-package :qml-user)
(eval-in-thread "(qml::help)" nil)) (eval-in-thread "(qml::help)" nil))
(qlater 'ini)

View file

@ -2,5 +2,5 @@
(in-package :qml-user) (in-package :qml-user)
;; delay needed here ;; delay needed here because of initial reload
(qsingle-shot 500 (lambda () (eval:eval-in-thread "(qml::help)"))) ; show help in REPL (qsingle-shot 1000 (lambda () (eval:eval-in-thread "(qml::help)"))) ; show help in REPL

View file

@ -2,88 +2,20 @@
(in-package :qml) (in-package :qml)
;; for mobile app updates: #+(and (or android ios) (not interpreter))
;; to be incremented on every ECL upgrade in order to replace all asset files
#+(or android ios)
(defconstant +app-version+ 1)
#+(and ios (not interpreter))
(ffi:clines "extern void init_lib_ASDF(cl_object);") (ffi:clines "extern void init_lib_ASDF(cl_object);")
#+(or android ios)
(defvar *assets* #+android "assets:/lib/"
#+ios "assets/")
#+ios
(defvar *bundle-root* (namestring *default-pathname-defaults*))
#+(or android ios)
(defun copy-asset-files (&optional (dir-name *assets*) origin)
"Copy asset files to home directory."
(flet ((directory-p (path)
(x:ends-with "/" path))
(translate (name)
#+android
(if (x:starts-with *assets* name)
(subseq name (length *assets*))
name)
#+ios
(namestring
(merge-pathnames (x:cc "../" (subseq name (length origin)))))))
(ensure-directories-exist (translate dir-name))
;; note: both QDIRECTORY and QCOPY-FILE are prepared for accessing
;; APK asset files, which can't be accessed directly from Lisp
(dolist (from (qdirectory dir-name))
(if (directory-p from)
(copy-asset-files from origin)
(let ((to (translate from)))
(when (probe-file to)
(delete-file to))
(unless (qcopy-file from to)
(qlog "Error copying asset file: ~S" from)
(return-from copy-asset-files))))))
t)
#+(or android ios)
(let ((file ".app-version"))
(defun app-version ()
(if (probe-file file)
(with-open-file (s file)
(let ((str (make-string (file-length s))))
(read-sequence str s)
(values (parse-integer str))))
0))
(defun save-app-version ()
(with-open-file (s file :direction :output :if-exists :supersede)
(princ +app-version+ s))
(values)))
(defun %sym (symbol package) (defun %sym (symbol package)
(intern (symbol-name symbol) package)) (intern (symbol-name symbol) package))
;;; Quicklisp setup ;;; Quicklisp setup
#+ios
(defun load-asdf ()
(unless (find-package :asdf)
;; needed for ASDF and Quicklisp
(setf (logical-pathname-translations "SYS")
(list (list "sys:**;*.*"
(merge-pathnames "**/*.*" (user-homedir-pathname)))))
(setf (logical-pathname-translations "HOME")
(list (list "home:**;*.*"
(merge-pathnames "**/*.*" (user-homedir-pathname)))))
(ffi:c-inline nil nil :void "ecl_init_module(NULL, init_lib_ASDF)" :one-liner t)
(in-package :qml-user))
:asdf)
#+(or android ios) #+(or android ios)
(defun ensure-asdf () (defun ensure-asdf ()
(unless (find-package :asdf) (unless (find-package :asdf)
#+android (ffi:c-inline nil nil :void "ecl_init_module(NULL, init_lib_ASDF)" :one-liner t)
(require :asdf) (in-package :qml-user))
#+ios :asdf)
(load-asdf)))
#+(or android ios) #+(or android ios)
(defun quicklisp () (defun quicklisp ()
@ -147,45 +79,6 @@
#+(or android ios) #+(or android ios)
(export (list #+ios (export (list #+ios
'load-asdf
'start-swank 'start-swank
'stop-swank 'stop-swank
'quicklisp)) 'quicklisp))
#+ios
(progn
;; adapt paths to iOS specific values
(defvar *user-homedir-pathname-orig* (symbol-function 'user-homedir-pathname))
(ext:package-lock :common-lisp nil)
(defun cl:user-homedir-pathname (&optional host)
(merge-pathnames "Library/" (funcall *user-homedir-pathname-orig* host)))
(ext:package-lock :common-lisp t)
(dolist (el '(("XDG_DATA_HOME" . "")
("XDG_CONFIG_HOME" . "")
("XDG_DATA_DIRS" . "")
("XDG_CONFIG_DIRS" . "")
("XDG_CACHE_HOME" . ".cache")))
(ext:setenv (car el) (namestring (merge-pathnames (cdr el)
(user-homedir-pathname))))))
;;; ini
#+(or android ios)
(defun startup-ini ()
#+ios
(setf *default-pathname-defaults* (user-homedir-pathname))
(ext:install-bytecodes-compiler)
(and (/= +app-version+ (app-version))
#+ios
(let ((dir (namestring (merge-pathnames *assets* *bundle-root*))))
(copy-asset-files dir dir))
#+android
(copy-asset-files)
(save-app-version)))
#+(or android ios)
(qlater 'startup-ini)

View file

@ -30,16 +30,9 @@
(let ((to (cc *assets* "quicklisp/local-projects/slime/"))) (let ((to (cc *assets* "quicklisp/local-projects/slime/")))
(ensure-directories-exist to) (ensure-directories-exist to)
(shell (cc "cp -r ../../../slime/src/* " to)))) (shell (cc "cp -r ../../../slime/src/* " to))))
#+android
(let ((lib (cc (ext:getenv "ECL_ANDROID") "/lib/ecl-*/")))
(shell (cc "cp -f " lib "asdf.fas " *assets*))
(shell (cc (ext:getenv "ANDROID_NDK_TOOLCHAIN") "/bin/aarch64-linux-android-strip " (cc *assets* "asdf.fas")))
(unless (probe-file (cc *assets* "encodings")) (unless (probe-file (cc *assets* "encodings"))
(shell (cc "cp " lib "*.doc " *assets*)) (let ((lib (cc (ext:getenv #+android "ECL_ANDROID" #+ios "ECL_IOS")
(shell (cc "cp -r " lib "encodings " *assets*)))) "/lib/ecl-*/")))
#+ios
(unless (probe-file (cc *assets* "encodings"))
(let ((lib (cc (ext:getenv "ECL_IOS") "/lib/ecl-*/")))
(shell (cc "cp " lib "*.doc " *assets*)) (shell (cc "cp " lib "*.doc " *assets*))
(shell (cc "cp -r " lib "encodings " *assets*))))) (shell (cc "cp -r " lib "encodings " *assets*)))))

View file

@ -9,7 +9,12 @@ A small demo can be found here: [short video clip](http://cl-repl.org/lqml.htm)
Prepare Prepare
------- -------
Please copy the app template files first: Run this script once, and every time after adding new qml files:
```
$ ./ini-reload.sh
```
Copy the app template files:
``` ```
$ cd .. $ cd ..
$ ./copy.sh advanced-qml-auto-reload $ ./copy.sh advanced-qml-auto-reload

View file

@ -25,4 +25,3 @@
(when (option "-slime") (when (option "-slime")
(load "~/slime/lqml-start-swank")) ; for 'slime-connect' from Emacs (load "~/slime/lqml-start-swank")) ; for 'slime-connect' from Emacs
(load "qml/.create-qml-loaders.lisp")

View file

@ -19,7 +19,7 @@ PRE_TARGETDEPS += tmp/libapp.a
QT += quick qml QT += quick qml
TEMPLATE = app TEMPLATE = app
CONFIG += no_keywords release CONFIG += no_keywords release
DEFINES += INI_LISP # NO_QT_RESTART DEFINES = DESKTOP_APP INI_LISP
INCLUDEPATH = /usr/local/include INCLUDEPATH = /usr/local/include
LIBS = -L/usr/local/lib -lecl LIBS = -L/usr/local/lib -lecl
DESTDIR = . DESTDIR = .
@ -32,6 +32,7 @@ macx: LIBS += -L../../../platforms/macos/lib
android { android {
QT += androidextras QT += androidextras
DEFINES -= DESKTOP_APP
INCLUDEPATH = $$(ECL_ANDROID)/include INCLUDEPATH = $$(ECL_ANDROID)/include
LIBS = -L$$(ECL_ANDROID)/lib -lecl LIBS = -L$$(ECL_ANDROID)/lib -lecl
LIBS += -L../../../platforms/android/lib LIBS += -L../../../platforms/android/lib
@ -42,6 +43,7 @@ android {
} }
ios { ios {
DEFINES -= DESKTOP_APP
INCLUDEPATH = $$(ECL_IOS)/include INCLUDEPATH = $$(ECL_IOS)/include
LIBS = -L$$(ECL_IOS)/lib -lecl LIBS = -L$$(ECL_IOS)/lib -lecl
LIBS += -leclatomic -leclffi -leclgc -leclgmp LIBS += -leclatomic -leclffi -leclgc -leclgmp

View file

@ -1,5 +1,4 @@
;;; check target ;; check target
(let ((arg (first (ext:command-args)))) (let ((arg (first (ext:command-args))))
(mapc (lambda (name feature) (mapc (lambda (name feature)
(when (search name arg) (when (search name arg)
@ -21,8 +20,7 @@
(length (namestring *default-pathname-defaults*)) (length (namestring *default-pathname-defaults*))
(1+ (position #\/ name :from-end t))))) (1+ (position #\/ name :from-end t)))))
;; load all LQML symbols (dolist (file (list "package" "x" "ecl-ext" "ini" "qml")) ; load LQML symbols
(dolist (file (list "package" "x" "ecl-ext" "ini" "qml"))
(load (merge-pathnames file "src/lisp/"))) (load (merge-pathnames file "src/lisp/")))
(defun cc (&rest args) (defun cc (&rest args)

View file

@ -19,7 +19,7 @@ PRE_TARGETDEPS += tmp/libapp.a
QT += quick qml QT += quick qml
TEMPLATE = app TEMPLATE = app
CONFIG += no_keywords release CONFIG += no_keywords release
DEFINES += INI_LISP INI_ECL_CONTRIB DEFINES += DESKTOP_APP INI_LISP INI_ECL_CONTRIB
INCLUDEPATH = /usr/local/include INCLUDEPATH = /usr/local/include
ECL_VERSION = $$lower($$system(ecl -v)) ECL_VERSION = $$lower($$system(ecl -v))
ECL_VERSION = $$replace(ECL_VERSION, " ", "-") ECL_VERSION = $$replace(ECL_VERSION, " ", "-")
@ -36,12 +36,14 @@ macx: LIBS += -L../../../platforms/macos/lib
android { android {
QT += androidextras QT += androidextras
DEFINES += INI_ASDF
DEFINES -= DESKTOP_APP
INCLUDEPATH = $$(ECL_ANDROID)/include INCLUDEPATH = $$(ECL_ANDROID)/include
ECL_VERSION = $$lower($$system($ECL_ANDROID/../ecl-android-host/bin/ecl -v)) ECL_VERSION = $$lower($$system($ECL_ANDROID/../ecl-android-host/bin/ecl -v))
ECL_VERSION = $$replace(ECL_VERSION, " ", "-") ECL_VERSION = $$replace(ECL_VERSION, " ", "-")
LIBS = -L$$(ECL_ANDROID)/lib -lecl LIBS = -L$$(ECL_ANDROID)/lib -lecl
LIBS += -L$$(ECL_ANDROID)/lib/$$ECL_VERSION LIBS += -L$$(ECL_ANDROID)/lib/$$ECL_VERSION
LIBS += -lecl-help -ldeflate -lecl-cdb -lecl-curl -lql-minitar -lsockets LIBS += -lasdf -lecl-help -ldeflate -lecl-cdb -lecl-curl -lql-minitar -lsockets
LIBS += -L../../../platforms/android/lib LIBS += -L../../../platforms/android/lib
ANDROID_ABIS = "arm64-v8a" ANDROID_ABIS = "arm64-v8a"
@ -50,6 +52,8 @@ android {
} }
ios { ios {
DEFINES += INI_ASDF
DEFINES -= DESKTOP_APP
INCLUDEPATH = $$(ECL_IOS)/include INCLUDEPATH = $$(ECL_IOS)/include
ECL_VERSION = $$lower($$system($ECL_IOS/../ecl-ios-host/bin/ecl -v)) ECL_VERSION = $$lower($$system($ECL_IOS/../ecl-ios-host/bin/ecl -v))
ECL_VERSION = $$replace(ECL_VERSION, " ", "-") ECL_VERSION = $$replace(ECL_VERSION, " ", "-")

View file

@ -175,7 +175,5 @@
(progn (progn
(ini-streams) (ini-streams)
(qlater (lambda ()
(in-package :qml-user) (in-package :qml-user)
(eval-in-thread "(qml::help)" nil)))) (eval-in-thread "(qml::help)" nil))

View file

@ -2,88 +2,20 @@
(in-package :qml) (in-package :qml)
;; for mobile app updates: #+(and (or android ios) (not interpreter))
;; to be incremented on every ECL upgrade in order to replace all asset files
#+(or android ios)
(defconstant +app-version+ 1)
#+(and ios (not interpreter))
(ffi:clines "extern void init_lib_ASDF(cl_object);") (ffi:clines "extern void init_lib_ASDF(cl_object);")
#+(or android ios)
(defvar *assets* #+android "assets:/lib/"
#+ios "assets/")
#+ios
(defvar *bundle-root* (namestring *default-pathname-defaults*))
#+(or android ios)
(defun copy-asset-files (&optional (dir-name *assets*) origin)
"Copy asset files to home directory."
(flet ((directory-p (path)
(x:ends-with "/" path))
(translate (name)
#+android
(if (x:starts-with *assets* name)
(subseq name (length *assets*))
name)
#+ios
(namestring
(merge-pathnames (x:cc "../" (subseq name (length origin)))))))
(ensure-directories-exist (translate dir-name))
;; note: both QDIRECTORY and QCOPY-FILE are prepared for accessing
;; APK asset files, which can't be accessed directly from Lisp
(dolist (from (qdirectory dir-name))
(if (directory-p from)
(copy-asset-files from origin)
(let ((to (translate from)))
(when (probe-file to)
(delete-file to))
(unless (qcopy-file from to)
(qlog "Error copying asset file: ~S" from)
(return-from copy-asset-files))))))
t)
#+(or android ios)
(let ((file ".app-version"))
(defun app-version ()
(if (probe-file file)
(with-open-file (s file)
(let ((str (make-string (file-length s))))
(read-sequence str s)
(values (parse-integer str))))
0))
(defun save-app-version ()
(with-open-file (s file :direction :output :if-exists :supersede)
(princ +app-version+ s))
(values)))
(defun %sym (symbol package) (defun %sym (symbol package)
(intern (symbol-name symbol) package)) (intern (symbol-name symbol) package))
;;; Quicklisp setup ;;; Quicklisp setup
#+ios
(defun load-asdf ()
(unless (find-package :asdf)
;; needed for ASDF and Quicklisp
(setf (logical-pathname-translations "SYS")
(list (list "sys:**;*.*"
(merge-pathnames "**/*.*" (user-homedir-pathname)))))
(setf (logical-pathname-translations "HOME")
(list (list "home:**;*.*"
(merge-pathnames "**/*.*" (user-homedir-pathname)))))
(ffi:c-inline nil nil :void "ecl_init_module(NULL, init_lib_ASDF)" :one-liner t)
(in-package :qml-user))
:asdf)
#+(or android ios) #+(or android ios)
(defun ensure-asdf () (defun ensure-asdf ()
(unless (find-package :asdf) (unless (find-package :asdf)
#+android (ffi:c-inline nil nil :void "ecl_init_module(NULL, init_lib_ASDF)" :one-liner t)
(require :asdf) (in-package :qml-user))
#+ios :asdf)
(load-asdf)))
#+(or android ios) #+(or android ios)
(defun quicklisp () (defun quicklisp ()
@ -147,45 +79,6 @@
#+(or android ios) #+(or android ios)
(export (list #+ios (export (list #+ios
'load-asdf
'start-swank 'start-swank
'stop-swank 'stop-swank
'quicklisp)) 'quicklisp))
#+ios
(progn
;; adapt paths to iOS specific values
(defvar *user-homedir-pathname-orig* (symbol-function 'user-homedir-pathname))
(ext:package-lock :common-lisp nil)
(defun cl:user-homedir-pathname (&optional host)
(merge-pathnames "Library/" (funcall *user-homedir-pathname-orig* host)))
(ext:package-lock :common-lisp t)
(dolist (el '(("XDG_DATA_HOME" . "")
("XDG_CONFIG_HOME" . "")
("XDG_DATA_DIRS" . "")
("XDG_CONFIG_DIRS" . "")
("XDG_CACHE_HOME" . ".cache")))
(ext:setenv (car el) (namestring (merge-pathnames (cdr el)
(user-homedir-pathname))))))
;;; ini
#+(or android ios)
(defun startup-ini ()
#+ios
(setf *default-pathname-defaults* (user-homedir-pathname))
(ext:install-bytecodes-compiler)
(and (/= +app-version+ (app-version))
#+ios
(let ((dir (namestring (merge-pathnames *assets* *bundle-root*))))
(copy-asset-files dir dir))
#+android
(copy-asset-files)
(save-app-version)))
#+(or android ios)
(qlater 'startup-ini)

View file

@ -30,16 +30,9 @@
(let ((to (cc *assets* "quicklisp/local-projects/slime/"))) (let ((to (cc *assets* "quicklisp/local-projects/slime/")))
(ensure-directories-exist to) (ensure-directories-exist to)
(shell (cc "cp -r ../../../slime/src/* " to)))) (shell (cc "cp -r ../../../slime/src/* " to))))
#+android
(let ((lib (cc (ext:getenv "ECL_ANDROID") "/lib/ecl-*/")))
(shell (cc "cp -f " lib "asdf.fas " *assets*))
(shell (cc (ext:getenv "ANDROID_NDK_TOOLCHAIN") "/bin/aarch64-linux-android-strip " (cc *assets* "asdf.fas")))
(unless (probe-file (cc *assets* "encodings")) (unless (probe-file (cc *assets* "encodings"))
(shell (cc "cp " lib "*.doc " *assets*)) (let ((lib (cc (ext:getenv #+android "ECL_ANDROID" #+ios "ECL_IOS")
(shell (cc "cp -r " lib "encodings " *assets*)))) "/lib/ecl-*/")))
#+ios
(unless (probe-file (cc *assets* "encodings"))
(let ((lib (cc (ext:getenv "ECL_IOS") "/lib/ecl-*/")))
(shell (cc "cp " lib "*.doc " *assets*)) (shell (cc "cp " lib "*.doc " *assets*))
(shell (cc "cp -r " lib "encodings " *assets*))))) (shell (cc "cp -r " lib "encodings " *assets*)))))

View file

@ -9,11 +9,12 @@
(in-package :cl-user) (in-package :cl-user)
(dolist (lib *require*)
(require lib))
;; optional, to be set in 'make.lisp' in your app dir ;; optional, to be set in 'make.lisp' in your app dir
(defvar *ql-libs* nil) (defvar *ql-libs* nil)
(defvar *require* nil)
(dolist (lib *require*)
(require lib))
(defun cc (&rest args) (defun cc (&rest args)
(apply 'concatenate 'string args)) (apply 'concatenate 'string args))
@ -33,12 +34,11 @@
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp" (let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname)))) (user-homedir-pathname))))
(when (probe-file quicklisp-init) (when (probe-file quicklisp-init)
(load quicklisp-init)))) (load quicklisp-init)))
(load *ql-libs*)) ; eventual, not yet installed dependencies
;;; load ASDF system ;;; load ASDF system
(load *ql-libs*) ; eventual, not yet installed dependencies
(asdf:load-system *asdf-system*) (asdf:load-system *asdf-system*)
;;; *** (2) cross-compile *** ;;; *** (2) cross-compile ***
@ -65,14 +65,14 @@
(load (merge-pathnames "src/lisp/tr.lisp")) ; i18n (load (merge-pathnames "src/lisp/tr.lisp")) ; i18n
;;; --- HACK begin ---
(in-package :asdf/lisp-action) (in-package :asdf/lisp-action)
(defmethod asdf:perform ((o asdf:load-op) (c asdf:cl-source-file)) (defmethod asdf:perform ((o asdf:load-op) (c asdf:cl-source-file))
(if-let (fasl (first (input-files o c))) (if-let (fasl (first (input-files o c)))
(progn
;; load above compiled *.fasc instead of cross-compiled *.fas ;; load above compiled *.fasc instead of cross-compiled *.fas
(setf fasl (cl-user::cc (namestring fasl) "c")) (load (cl-user::cc (namestring fasl) "c"))))
(load fasl))))
(in-package :cl-user) (in-package :cl-user)
@ -80,6 +80,8 @@
;; do nothing (not needed when cross-compiling) ;; do nothing (not needed when cross-compiling)
file) file)
;;; --- HACK end ---
(asdf:make-build *asdf-system* (asdf:make-build *asdf-system*
:monolithic t :monolithic t
:type :static-library :type :static-library

View file

@ -7,7 +7,7 @@
#include <QQuickView> #include <QQuickView>
#include <QDebug> #include <QDebug>
const char LQML::version[] = "22.3.4"; // Mar 2022 const char LQML::version[] = "22.3.5"; // Mar 2022
extern "C" void ini_LQML(cl_object); extern "C" void ini_LQML(cl_object);

View file

@ -8,8 +8,13 @@
#include <QQmlEngine> #include <QQmlEngine>
#include <QQmlFileSelector> #include <QQmlFileSelector>
#include <QQuickView> #include <QQuickView>
#include <QtDebug>
#include <iostream> #include <iostream>
#ifdef INI_WEBVIEW
#include <QtWebView>
#endif
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
#define ADD_MACOS_BUNDLE_IMPORT_PATH \ #define ADD_MACOS_BUNDLE_IMPORT_PATH \
view.engine()->addImportPath(app.applicationDirPath() + QStringLiteral("/../PlugIns")); view.engine()->addImportPath(app.applicationDirPath() + QStringLiteral("/../PlugIns"));
@ -32,6 +37,10 @@
} }
#endif #endif
#ifdef INI_ASDF
extern "C" void init_lib_ASDF(cl_object);
#endif
int catch_all_qexec() { int catch_all_qexec() {
int ret = 0; int ret = 0;
CL_CATCH_ALL_BEGIN(ecl_process_env()) { CL_CATCH_ALL_BEGIN(ecl_process_env()) {
@ -43,6 +52,9 @@ int catch_all_qexec() {
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#ifdef INI_WEBVIEW
QtWebView::initialize();
#endif
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
//app.setOrganizationName("MyProject"); //app.setOrganizationName("MyProject");
//app.setOrganizationDomain("my.org"); //app.setOrganizationDomain("my.org");
@ -74,31 +86,6 @@ int main(int argc, char* argv[]) {
exit(0); exit(0);
} }
#ifdef Q_OS_WIN
lqml.ignoreIOStreams();
#endif
// load .eclrc
if (arguments.contains("-norc")) {
arguments.removeAll("-norc");
} else {
#if (defined Q_OS_ANDROID) || (defined Q_OS_IOS)
// mobile: don't hang on startup
LQML::eval("(x:when-it (probe-file \"~/.eclrc\")"
" (ignore-errors (load x:it)))");
#else
LQML::eval("(x:when-it (probe-file \"~/.eclrc\")"
" (load x:it))");
#endif
}
// load Lisp file
QStringList files = arguments.filter(".lisp");
if (!files.isEmpty()) {
QString file = QDir::fromNativeSeparators(files.first());
LQML::eval(QString("(load \"%1\")").arg(file), true);
}
new QQmlFileSelector(view.engine(), &view); new QQmlFileSelector(view.engine(), &view);
QString qml("qml/main.qml"); QString qml("qml/main.qml");
QUrl url; QUrl url;
@ -110,15 +97,19 @@ int main(int argc, char* argv[]) {
view.setSource(url); view.setSource(url);
if (view.status() != QQuickView::Error) { if (view.status() != QQuickView::Error) {
view.setResizeMode(QQuickView::SizeRootObjectToView); view.setResizeMode(QQuickView::SizeRootObjectToView);
#if (defined Q_OS_ANDROID) || (defined Q_OS_IOS)
view.show(); view.show();
#else
QTimer::singleShot(0, &view, &QQuickView::show);
#endif
} }
#ifdef Q_OS_WIN
// uncomment for apps without console
//lqml.ignoreIOStreams();
#endif
#if (defined Q_OS_ANDROID) || (defined Q_OS_IOS)
LQML::eval("(qml::%ini-mobile)");
#endif
#ifdef INI_ECL_CONTRIB #ifdef INI_ECL_CONTRIB
// ASDF is loaded on demand (slow)
ecl_init_module(NULL, init_lib_DEFLATE); ecl_init_module(NULL, init_lib_DEFLATE);
ecl_init_module(NULL, init_lib_ECL_CDB); ecl_init_module(NULL, init_lib_ECL_CDB);
ecl_init_module(NULL, init_lib_ECL_HELP); ecl_init_module(NULL, init_lib_ECL_HELP);
@ -127,6 +118,42 @@ int main(int argc, char* argv[]) {
ecl_init_module(NULL, init_lib_ECL_CURL); ecl_init_module(NULL, init_lib_ECL_CURL);
#endif #endif
#ifdef INI_ASDF
ecl_init_module(NULL, init_lib_ASDF);
#endif
#ifdef INI_SSL
#ifdef Q_OS_ANDROID
// ssl libs need to be loaded manually
LQML::eval("(ffi:load-foreign-library \"libcrypto.so\")");
LQML::eval("(ffi:load-foreign-library \"libssl.so\")");
#endif
LQML::eval("(push :cl+ssl-foreign-libs-already-loaded *features*)");
#endif
// load .eclrc
if (arguments.contains("-norc")) {
arguments.removeAll("-norc");
} else {
#if (defined Q_OS_ANDROID) || (defined Q_OS_IOS)
// mobile: don't hang on startup
LQML::eval("(x:when-it (probe-file \"~/.eclrc\")"
" (ignore-errors (load x:it)))");
#else
#ifndef DESKTOP_APP
LQML::eval("(x:when-it (probe-file \"~/.eclrc\")"
" (load x:it))");
#endif
#endif
}
// load Lisp file
QStringList files = arguments.filter(".lisp");
if (!files.isEmpty()) {
QString file = QDir::fromNativeSeparators(files.first());
LQML::eval(QString("(load \"%1\")").arg(file), true);
}
#ifdef INI_LISP #ifdef INI_LISP
ecl_init_module(NULL, ini_app); ecl_init_module(NULL, ini_app);
#endif #endif

View file

@ -236,6 +236,80 @@
(apply 'format nil arg1 args) (apply 'format nil arg1 args)
(x:join (mapcar 'princ-to-string (cons arg1 args)))))) (x:join (mapcar 'princ-to-string (cons arg1 args))))))
;;; mobile ini
#+(or android ios)
(defvar *assets* #+android "assets:/lib/"
#+ios "assets/")
#+ios
(defvar *bundle-root* (namestring *default-pathname-defaults*))
#+ios
(progn
;; adapt paths to iOS specific values
(defvar *user-homedir-pathname-orig* (symbol-function 'user-homedir-pathname))
(ext:package-lock :common-lisp nil)
(defun cl:user-homedir-pathname (&optional host)
(merge-pathnames "Library/" (funcall *user-homedir-pathname-orig* host)))
(ext:package-lock :common-lisp t)
(dolist (el '(("XDG_DATA_HOME" . "")
("XDG_CONFIG_HOME" . "")
("XDG_DATA_DIRS" . "")
("XDG_CONFIG_DIRS" . "")
("XDG_CACHE_HOME" . ".cache")))
(ext:setenv (car el) (namestring (merge-pathnames (cdr el)
(user-homedir-pathname))))))
#+(or android ios)
(defun copy-asset-files (&optional (dir-name *assets*) origin)
"Copy asset files to home directory."
(flet ((directory-p (path)
(x:ends-with "/" path))
(translate (name)
#+android
(if (x:starts-with *assets* name)
(subseq name (length *assets*))
name)
#+ios
(namestring
(merge-pathnames (x:cc "../" (subseq name (length origin)))))))
(ensure-directories-exist (translate dir-name))
;; note: both QDIRECTORY and QCOPY-FILE are prepared for accessing
;; APK asset files, which can't be accessed directly from Lisp
(dolist (from (qdirectory dir-name))
(if (directory-p from)
(copy-asset-files from origin)
(let ((to (translate from)))
(when (probe-file to)
(delete-file to))
(unless (qcopy-file from to)
(qlog "Error copying asset file: ~S" from)
(return-from copy-asset-files))))))
t)
#+(or android ios)
(defun %ini-mobile ()
;; internal use, see 'main.cpp'
(ext:install-bytecodes-compiler)
#+ios
(progn
(setf *default-pathname-defaults* (user-homedir-pathname))
(setf (logical-pathname-translations "SYS")
(list (list "sys:**;*.*"
(merge-pathnames "**/*.*" (user-homedir-pathname)))))
(setf (logical-pathname-translations "HOME")
(list (list "home:**;*.*"
(merge-pathnames "**/*.*" (user-homedir-pathname)))))
(let ((dir (namestring (merge-pathnames *assets* *bundle-root*))))
(copy-asset-files dir dir)))
#+android
(copy-asset-files))
;;; alias ;;; alias
(defmacro alias (s1 s2) (defmacro alias (s1 s2)

View file

@ -1,3 +1,5 @@
;;; check target
(let ((arg (first (ext:command-args)))) (let ((arg (first (ext:command-args))))
(mapc (lambda (name feature) (mapc (lambda (name feature)
(when (search name arg) (when (search name arg)
@ -5,6 +7,8 @@
(list "/ecl-android/" "/ecl-ios/") (list "/ecl-android/" "/ecl-ios/")
(list :android :ios))) (list :android :ios)))
;;; compile ASDF system
(require :asdf) (require :asdf)
(push (merge-pathnames "../") (push (merge-pathnames "../")
@ -14,7 +18,6 @@
(merge-pathnames "../../")) ; LQML root (merge-pathnames "../../")) ; LQML root
#-(or android ios) #-(or android ios)
(progn
(asdf:make-build "lqml" (asdf:make-build "lqml"
:monolithic t :monolithic t
:type :static-library :type :static-library
@ -22,26 +25,33 @@
#+linux "linux" #+linux "linux"
#+darwin "macos") #+darwin "macos")
:init-name "ini_LQML") :init-name "ini_LQML")
(let* ((from (format nil "platforms/~A/lib/lqml--all-systems.a"
#+linux "linux"
#+darwin "macos"))
(to "liblisp.a")
(to* (format nil "platforms/~A/lib/~A"
#+linux "linux"
#+darwin "macos"
to)))
(when (probe-file to*)
(delete-file to*))
(rename-file from to)))
#+(or android ios) #+(or android ios)
(progn (progn
(pushnew :interpreter *features*)
(defvar *asdf-system* "lqml") (defvar *asdf-system* "lqml")
(defvar *init-name* "ini_LQML") (defvar *init-name* "ini_LQML")
(defvar *library-name* (format nil "platforms/~A/lib/lisp" (defvar *library-path* (format nil "platforms/~A/lib/"
#+android "android" #+android "android"
#+ios "ios")) #+ios "ios"))
(load "platforms/shared/make")) (load "platforms/shared/make"))
(terpri) ;;; rename lib
(let* ((from (format nil "platforms/~A/lib/lqml--all-systems.a"
#+(and linux (not android)) "linux"
#+darwin "macos"
#+android "android"
#+ios "ios"))
(to "liblisp.a")
(to* (format nil "platforms/~A/lib/~A"
#+(and linux (not android)) "linux"
#+darwin "macos"
#+android "android"
#+ios "ios"
to)))
(when (probe-file to*)
(delete-file to*))
(rename-file from to))
(terpri)