diff --git a/examples/advanced-qml-auto-reload/app.pro b/examples/advanced-qml-auto-reload/app.pro index 142e3c1..967d72c 100644 --- a/examples/advanced-qml-auto-reload/app.pro +++ b/examples/advanced-qml-auto-reload/app.pro @@ -19,7 +19,7 @@ PRE_TARGETDEPS += tmp/libapp.a QT += quick qml TEMPLATE = app CONFIG += no_keywords release -DEFINES += INI_LISP INI_ECL_CONTRIB +DEFINES += DESKTOP_APP INI_LISP INI_ECL_CONTRIB INCLUDEPATH = /usr/local/include ECL_VERSION = $$lower($$system(ecl -v)) ECL_VERSION = $$replace(ECL_VERSION, " ", "-") @@ -36,12 +36,14 @@ macx: LIBS += -L../../../platforms/macos/lib android { QT += androidextras + DEFINES += INI_ASDF + DEFINES -= DESKTOP_APP INCLUDEPATH = $$(ECL_ANDROID)/include ECL_VERSION = $$lower($$system($ECL_ANDROID/../ecl-android-host/bin/ecl -v)) ECL_VERSION = $$replace(ECL_VERSION, " ", "-") LIBS = -L$$(ECL_ANDROID)/lib -lecl 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 ANDROID_ABIS = "arm64-v8a" @@ -50,6 +52,8 @@ android { } ios { + DEFINES += INI_ASDF + DEFINES -= DESKTOP_APP INCLUDEPATH = $$(ECL_IOS)/include ECL_VERSION = $$lower($$system($ECL_IOS/../ecl-ios-host/bin/ecl -v)) ECL_VERSION = $$replace(ECL_VERSION, " ", "-") diff --git a/examples/advanced-qml-auto-reload/ini-reload.sh b/examples/advanced-qml-auto-reload/ini-reload.sh new file mode 100755 index 0000000..89bff1b --- /dev/null +++ b/examples/advanced-qml-auto-reload/ini-reload.sh @@ -0,0 +1 @@ +ecl -shell qml/.create-qml-loaders.lisp diff --git a/examples/advanced-qml-auto-reload/lisp/eval.lisp b/examples/advanced-qml-auto-reload/lisp/eval.lisp index 7985d54..426f98f 100644 --- a/examples/advanced-qml-auto-reload/lisp/eval.lisp +++ b/examples/advanced-qml-auto-reload/lisp/eval.lisp @@ -173,11 +173,7 @@ ~% :q (quicklisp)") (values)) -(defun ini () - (x:while (not (find-quick-item ui:*repl-model*)) - (qsleep 0.5)) +(progn (ini-streams) (in-package :qml-user) (eval-in-thread "(qml::help)" nil)) - -(qlater 'ini) diff --git a/examples/advanced-qml-auto-reload/lisp/qml-reload/on-reloaded.lisp b/examples/advanced-qml-auto-reload/lisp/qml-reload/on-reloaded.lisp index 8be6b3e..035b0a4 100644 --- a/examples/advanced-qml-auto-reload/lisp/qml-reload/on-reloaded.lisp +++ b/examples/advanced-qml-auto-reload/lisp/qml-reload/on-reloaded.lisp @@ -2,5 +2,5 @@ (in-package :qml-user) -;; delay needed here -(qsingle-shot 500 (lambda () (eval:eval-in-thread "(qml::help)"))) ; show help in REPL +;; delay needed here because of initial reload +(qsingle-shot 1000 (lambda () (eval:eval-in-thread "(qml::help)"))) ; show help in REPL diff --git a/examples/advanced-qml-auto-reload/lisp/swank-quicklisp.lisp b/examples/advanced-qml-auto-reload/lisp/swank-quicklisp.lisp index 5de7061..d9389e2 100644 --- a/examples/advanced-qml-auto-reload/lisp/swank-quicklisp.lisp +++ b/examples/advanced-qml-auto-reload/lisp/swank-quicklisp.lisp @@ -2,88 +2,20 @@ (in-package :qml) -;; for mobile app updates: -;; 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)) +#+(and (or android ios) (not interpreter)) (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) (intern (symbol-name symbol) package)) ;;; 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) (defun ensure-asdf () (unless (find-package :asdf) - #+android - (require :asdf) - #+ios - (load-asdf))) + (ffi:c-inline nil nil :void "ecl_init_module(NULL, init_lib_ASDF)" :one-liner t) + (in-package :qml-user)) + :asdf) #+(or android ios) (defun quicklisp () @@ -147,45 +79,6 @@ #+(or android ios) (export (list #+ios - 'load-asdf 'start-swank 'stop-swank '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) diff --git a/examples/advanced-qml-auto-reload/make.lisp b/examples/advanced-qml-auto-reload/make.lisp index a3824bb..d937c4f 100644 --- a/examples/advanced-qml-auto-reload/make.lisp +++ b/examples/advanced-qml-auto-reload/make.lisp @@ -30,16 +30,9 @@ (let ((to (cc *assets* "quicklisp/local-projects/slime/"))) (ensure-directories-exist 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")) - (shell (cc "cp " lib "*.doc " *assets*)) - (shell (cc "cp -r " lib "encodings " *assets*)))) - #+ios (unless (probe-file (cc *assets* "encodings")) - (let ((lib (cc (ext:getenv "ECL_IOS") "/lib/ecl-*/"))) + (let ((lib (cc (ext:getenv #+android "ECL_ANDROID" #+ios "ECL_IOS") + "/lib/ecl-*/"))) (shell (cc "cp " lib "*.doc " *assets*)) (shell (cc "cp -r " lib "encodings " *assets*))))) diff --git a/examples/advanced-qml-auto-reload/readme.md b/examples/advanced-qml-auto-reload/readme.md index c76e42e..e26771b 100644 --- a/examples/advanced-qml-auto-reload/readme.md +++ b/examples/advanced-qml-auto-reload/readme.md @@ -9,7 +9,12 @@ A small demo can be found here: [short video clip](http://cl-repl.org/lqml.htm) 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 .. $ ./copy.sh advanced-qml-auto-reload diff --git a/examples/advanced-qml-auto-reload/run.lisp b/examples/advanced-qml-auto-reload/run.lisp index a7ff05a..8a9fc87 100644 --- a/examples/advanced-qml-auto-reload/run.lisp +++ b/examples/advanced-qml-auto-reload/run.lisp @@ -25,4 +25,3 @@ (when (option "-slime") (load "~/slime/lqml-start-swank")) ; for 'slime-connect' from Emacs -(load "qml/.create-qml-loaders.lisp") diff --git a/examples/app-template/app.pro b/examples/app-template/app.pro index 004a853..d39e652 100644 --- a/examples/app-template/app.pro +++ b/examples/app-template/app.pro @@ -19,7 +19,7 @@ PRE_TARGETDEPS += tmp/libapp.a QT += quick qml TEMPLATE = app CONFIG += no_keywords release -DEFINES += INI_LISP # NO_QT_RESTART +DEFINES = DESKTOP_APP INI_LISP INCLUDEPATH = /usr/local/include LIBS = -L/usr/local/lib -lecl DESTDIR = . @@ -32,6 +32,7 @@ macx: LIBS += -L../../../platforms/macos/lib android { QT += androidextras + DEFINES -= DESKTOP_APP INCLUDEPATH = $$(ECL_ANDROID)/include LIBS = -L$$(ECL_ANDROID)/lib -lecl LIBS += -L../../../platforms/android/lib @@ -42,6 +43,7 @@ android { } ios { + DEFINES -= DESKTOP_APP INCLUDEPATH = $$(ECL_IOS)/include LIBS = -L$$(ECL_IOS)/lib -lecl LIBS += -leclatomic -leclffi -leclgc -leclgmp diff --git a/examples/app-template/make.lisp b/examples/app-template/make.lisp index 4a96686..c5c1567 100644 --- a/examples/app-template/make.lisp +++ b/examples/app-template/make.lisp @@ -1,5 +1,4 @@ -;;; check target - +;; check target (let ((arg (first (ext:command-args)))) (mapc (lambda (name feature) (when (search name arg) @@ -21,8 +20,7 @@ (length (namestring *default-pathname-defaults*)) (1+ (position #\/ name :from-end t))))) -;; load all LQML symbols -(dolist (file (list "package" "x" "ecl-ext" "ini" "qml")) +(dolist (file (list "package" "x" "ecl-ext" "ini" "qml")) ; load LQML symbols (load (merge-pathnames file "src/lisp/"))) (defun cc (&rest args) diff --git a/examples/swank-server/app.pro b/examples/swank-server/app.pro index 4ce4a64..170066c 100644 --- a/examples/swank-server/app.pro +++ b/examples/swank-server/app.pro @@ -19,7 +19,7 @@ PRE_TARGETDEPS += tmp/libapp.a QT += quick qml TEMPLATE = app CONFIG += no_keywords release -DEFINES += INI_LISP INI_ECL_CONTRIB +DEFINES += DESKTOP_APP INI_LISP INI_ECL_CONTRIB INCLUDEPATH = /usr/local/include ECL_VERSION = $$lower($$system(ecl -v)) ECL_VERSION = $$replace(ECL_VERSION, " ", "-") @@ -36,12 +36,14 @@ macx: LIBS += -L../../../platforms/macos/lib android { QT += androidextras + DEFINES += INI_ASDF + DEFINES -= DESKTOP_APP INCLUDEPATH = $$(ECL_ANDROID)/include ECL_VERSION = $$lower($$system($ECL_ANDROID/../ecl-android-host/bin/ecl -v)) ECL_VERSION = $$replace(ECL_VERSION, " ", "-") LIBS = -L$$(ECL_ANDROID)/lib -lecl 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 ANDROID_ABIS = "arm64-v8a" @@ -50,6 +52,8 @@ android { } ios { + DEFINES += INI_ASDF + DEFINES -= DESKTOP_APP INCLUDEPATH = $$(ECL_IOS)/include ECL_VERSION = $$lower($$system($ECL_IOS/../ecl-ios-host/bin/ecl -v)) ECL_VERSION = $$replace(ECL_VERSION, " ", "-") diff --git a/examples/swank-server/lisp/eval.lisp b/examples/swank-server/lisp/eval.lisp index dbaa731..426f98f 100644 --- a/examples/swank-server/lisp/eval.lisp +++ b/examples/swank-server/lisp/eval.lisp @@ -175,7 +175,5 @@ (progn (ini-streams) - (qlater (lambda () - (in-package :qml-user) - (eval-in-thread "(qml::help)" nil)))) - + (in-package :qml-user) + (eval-in-thread "(qml::help)" nil)) diff --git a/examples/swank-server/lisp/swank-quicklisp.lisp b/examples/swank-server/lisp/swank-quicklisp.lisp index 5de7061..d9389e2 100644 --- a/examples/swank-server/lisp/swank-quicklisp.lisp +++ b/examples/swank-server/lisp/swank-quicklisp.lisp @@ -2,88 +2,20 @@ (in-package :qml) -;; for mobile app updates: -;; 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)) +#+(and (or android ios) (not interpreter)) (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) (intern (symbol-name symbol) package)) ;;; 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) (defun ensure-asdf () (unless (find-package :asdf) - #+android - (require :asdf) - #+ios - (load-asdf))) + (ffi:c-inline nil nil :void "ecl_init_module(NULL, init_lib_ASDF)" :one-liner t) + (in-package :qml-user)) + :asdf) #+(or android ios) (defun quicklisp () @@ -147,45 +79,6 @@ #+(or android ios) (export (list #+ios - 'load-asdf 'start-swank 'stop-swank '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) diff --git a/examples/swank-server/make.lisp b/examples/swank-server/make.lisp index a3824bb..d937c4f 100644 --- a/examples/swank-server/make.lisp +++ b/examples/swank-server/make.lisp @@ -30,16 +30,9 @@ (let ((to (cc *assets* "quicklisp/local-projects/slime/"))) (ensure-directories-exist 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")) - (shell (cc "cp " lib "*.doc " *assets*)) - (shell (cc "cp -r " lib "encodings " *assets*)))) - #+ios (unless (probe-file (cc *assets* "encodings")) - (let ((lib (cc (ext:getenv "ECL_IOS") "/lib/ecl-*/"))) + (let ((lib (cc (ext:getenv #+android "ECL_ANDROID" #+ios "ECL_IOS") + "/lib/ecl-*/"))) (shell (cc "cp " lib "*.doc " *assets*)) (shell (cc "cp -r " lib "encodings " *assets*))))) diff --git a/platforms/shared/make.lisp b/platforms/shared/make.lisp index b79c251..a784b1a 100644 --- a/platforms/shared/make.lisp +++ b/platforms/shared/make.lisp @@ -9,11 +9,12 @@ (in-package :cl-user) -(dolist (lib *require*) - (require lib)) - ;; optional, to be set in 'make.lisp' in your app dir (defvar *ql-libs* nil) +(defvar *require* nil) + +(dolist (lib *require*) + (require lib)) (defun cc (&rest args) (apply 'concatenate 'string args)) @@ -33,12 +34,11 @@ (let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))) (when (probe-file quicklisp-init) - (load quicklisp-init)))) + (load quicklisp-init))) + (load *ql-libs*)) ; eventual, not yet installed dependencies ;;; load ASDF system -(load *ql-libs*) ; eventual, not yet installed dependencies - (asdf:load-system *asdf-system*) ;;; *** (2) cross-compile *** @@ -65,14 +65,14 @@ (load (merge-pathnames "src/lisp/tr.lisp")) ; i18n +;;; --- HACK begin --- + (in-package :asdf/lisp-action) (defmethod asdf:perform ((o asdf:load-op) (c asdf:cl-source-file)) (if-let (fasl (first (input-files o c))) - (progn - ;; load above compiled *.fasc instead of cross-compiled *.fas - (setf fasl (cl-user::cc (namestring fasl) "c")) - (load fasl)))) + ;; load above compiled *.fasc instead of cross-compiled *.fas + (load (cl-user::cc (namestring fasl) "c")))) (in-package :cl-user) @@ -80,6 +80,8 @@ ;; do nothing (not needed when cross-compiling) file) +;;; --- HACK end --- + (asdf:make-build *asdf-system* :monolithic t :type :static-library diff --git a/src/cpp/lqml.cpp b/src/cpp/lqml.cpp index 4f89663..2c300f9 100644 --- a/src/cpp/lqml.cpp +++ b/src/cpp/lqml.cpp @@ -7,7 +7,7 @@ #include #include -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); diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index bbc9058..997e51b 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -8,8 +8,13 @@ #include #include #include +#include #include +#ifdef INI_WEBVIEW + #include +#endif + #ifdef Q_OS_MACOS #define ADD_MACOS_BUNDLE_IMPORT_PATH \ view.engine()->addImportPath(app.applicationDirPath() + QStringLiteral("/../PlugIns")); @@ -32,6 +37,10 @@ } #endif +#ifdef INI_ASDF + extern "C" void init_lib_ASDF(cl_object); +#endif + int catch_all_qexec() { int ret = 0; CL_CATCH_ALL_BEGIN(ecl_process_env()) { @@ -43,6 +52,9 @@ int catch_all_qexec() { int main(int argc, char* argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#ifdef INI_WEBVIEW + QtWebView::initialize(); +#endif QGuiApplication app(argc, argv); //app.setOrganizationName("MyProject"); //app.setOrganizationDomain("my.org"); @@ -74,31 +86,6 @@ int main(int argc, char* argv[]) { 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); QString qml("qml/main.qml"); QUrl url; @@ -110,15 +97,19 @@ int main(int argc, char* argv[]) { view.setSource(url); if (view.status() != QQuickView::Error) { view.setResizeMode(QQuickView::SizeRootObjectToView); -#if (defined Q_OS_ANDROID) || (defined Q_OS_IOS) 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 - // ASDF is loaded on demand (slow) ecl_init_module(NULL, init_lib_DEFLATE); ecl_init_module(NULL, init_lib_ECL_CDB); 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); #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 ecl_init_module(NULL, ini_app); #endif diff --git a/src/lisp/ini.lisp b/src/lisp/ini.lisp index 0ee3118..47180a7 100644 --- a/src/lisp/ini.lisp +++ b/src/lisp/ini.lisp @@ -236,6 +236,80 @@ (apply 'format nil 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 (defmacro alias (s1 s2) diff --git a/src/make.lisp b/src/make.lisp index c5b20ef..228e3ec 100644 --- a/src/make.lisp +++ b/src/make.lisp @@ -1,3 +1,5 @@ +;;; check target + (let ((arg (first (ext:command-args)))) (mapc (lambda (name feature) (when (search name arg) @@ -5,6 +7,8 @@ (list "/ecl-android/" "/ecl-ios/") (list :android :ios))) +;;; compile ASDF system + (require :asdf) (push (merge-pathnames "../") @@ -14,34 +18,40 @@ (merge-pathnames "../../")) ; LQML root #-(or android ios) -(progn - (asdf:make-build "lqml" - :monolithic t - :type :static-library - :move-here (format nil "platforms/~A/lib/" - #+linux "linux" - #+darwin "macos") - :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))) +(asdf:make-build "lqml" + :monolithic t + :type :static-library + :move-here (format nil "platforms/~A/lib/" + #+linux "linux" + #+darwin "macos") + :init-name "ini_LQML") #+(or android ios) (progn + (pushnew :interpreter *features*) (defvar *asdf-system* "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" #+ios "ios")) (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)