make example work on iOS; revisions

This commit is contained in:
pls.153 2022-02-12 14:08:16 +01:00
parent e1ece6dc50
commit a4d2405ca7
14 changed files with 317 additions and 25 deletions

View file

@ -45,6 +45,13 @@ android {
#ANDROID_PACKAGE_SOURCE_DIR = ../platforms/android/sources
}
ios {
INCLUDEPATH = $$(ECL_IOS)/include
LIBS = -L$$(ECL_IOS)/lib -lecl
LIBS += -leclatomic -leclffi -leclgc -leclgmp
LIBS += -L../../../platforms/ios/lib -llqml -llisp -Ltmp -lapp
}
SOURCES += ../../src/cpp/main.cpp
RESOURCES = app.qrc

View file

@ -0,0 +1,3 @@
../../../platforms/ios/cross-compile.sh ../make.lisp
open app.xcodeproj

View file

@ -1,5 +1,9 @@
(when (search "/ecl-android/" (first (ext:command-args)))
(pushnew :android *features*))
(let ((arg (first (ext:command-args))))
(mapc (lambda (name feature)
(when (search name arg)
(pushnew feature *features*)))
(list "/ecl-android/" "/ecl-ios/")
(list :android :ios)))
(require :asdf)
@ -22,7 +26,7 @@
(defun cc (&rest args)
(apply 'concatenate 'string args))
#-android
#-(or android ios)
(progn
(asdf:make-build "app"
:monolithic t
@ -36,12 +40,14 @@
(delete-file to*))
(rename-file from to)))
#+android
#+(or android ios)
(progn
(defvar *asdf-system* "app")
(defvar *ql-libs* (cc *current* "/ql-libs.lisp"))
(defvar *library-name* (cc *current* "/build-android/tmp/app"))
(defvar *init-name* "ini_app")
(defvar *library-name* (cc *current* (format nil "/build-~A/tmp/app"
#+android "android"
#+ios "ios")))
(defvar *epilogue-code* nil)
(load "platforms/shared/make"))

View file

@ -29,7 +29,8 @@ Rectangle {
width: parent.width
height: {
var h = Qt.inputMethod.keyboardRectangle.y
h = (h === 0) ? main.height : h / Screen.devicePixelRatio
var f = (Qt.platform.os === "android") ? Screen.devicePixelRatio : 1
h = (h === 0) ? main.height : h / f
return (h - input.height)
}

View file

@ -1,7 +1,6 @@
Run desktop
-----------
```
$ lqml run.lisp
```
@ -9,7 +8,6 @@ $ lqml run.lisp
Build desktop app
-----------------
```
$ cd build
@ -20,7 +18,6 @@ $ make
Build android APK
-----------------
```
$ cd build-android
@ -30,3 +27,21 @@ $ make apk
$ adb install -r android-build/*.apk
```
Build iOS app
-------------
```
$ cd build-ios
$ qmake-ios ../app.pro
$ ./xcode.sh
```
The script above first cross-compiles the Lisp code, then opens **Xcode**.
N.B: Before building the app, go to Build Settings / Build Options and set
**Enable Bitcode** to **No**.
The simulator will not work here, because we didn't cross-compile ECL and
the app code for the simulator.

View file

@ -0,0 +1,8 @@
# build host ECL, needed for cross-compiling
./configure --prefix=`pwd`/ecl-ios-host \
--disable-c99complex \
--enable-manual=no
make
make install

View file

@ -0,0 +1,106 @@
#!/bin/sh
script_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source_dir=$script_dir
config_options="--disable-shared --disable-c99complex --enable-manual=no --with-cross-config=$source_dir/src/util/iOS-arm64.cross_config"
# please note: we need to add -DGC_DISABLE_INCREMENTAL, which will remove a private API call
# from the binary, since those are not allowed in iOS (for security reasons)
export CFLAGS="-DECL_C_COMPATIBLE_VARIADIC_DISPATCH -DECL_RWLOCK -DGC_DISABLE_INCREMENTAL"
build_dir="$source_dir/build_ios/"
install_prefix="$source_dir/ecl-ios/"
mkdir -p "$build_dir"
mkdir -p "$install_prefix"
num_simultaneous_jobs=1
select_ios()
{
platform_type="$1"
arch="$2"
ios_platform="$platform_type.platform"
developer_dir="`xcode-select --print-path`"
platforms_dir="$developer_dir/Platforms"
ios_platform_dir="$platforms_dir/$ios_platform"
ios_sdks="$ios_platform_dir/Developer/SDKs"
sdk_version=`(cd "$ios_sdks"; ls -1d *.sdk |sed -e 's/\.sdk$//' -e 's/^[^0-9\.]*//' |awk 'BEGIN{best = 0.0}($0 + 0.0) > best + 0.0{best = $0;}END{print best}')`
ios_sdk="$platform_type$sdk_version.sdk"
ios_sdk_dir="$ios_sdks/$ios_sdk"
echo "*** Selecting platform \"$ios_platform\" and SDK \"$ios_sdk\" for \"$arch\"."
case "$platform_type" in
iPhoneOS) config_options_extras=--host=aarch64-apple-darwin
sdk_name="iphoneos"
;;
iPhoneSimulator) config_options_extras=
sdk_name="iphonesimulator"
;;
esac
# this needs to be updated when a new Xcode is released
iphoneos_version_min="11.0"
export CC="clang"
export CXX="clang++"
export CFLAGS="$CFLAGS -arch $arch -miphoneos-version-min=$iphoneos_version_min -isysroot $ios_sdk_dir"
export CFLAGS="$CFLAGS -pipe -Wno-trigraphs -Wreturn-type -Wunused-variable"
export CFLAGS="$CFLAGS -fpascal-strings -fasm-blocks -fmessage-length=0 -fvisibility=hidden"
export CFLAGS="$CFLAGS -O0 -DNO_ASM"
export CXXFLAGS="$CFLAGS"
# export LD="ld -arch $arch"
export LD="ld"
export LDFLAGS="-arch $arch -pipe -std=c99 -gdwarf-2 -isysroot $ios_sdk_dir"
export LIBS="-framework Foundation"
}
configure_ecl()
{
cd "$build_dir"
$source_dir/src/configure --prefix="$install_prefix" $config_options $config_options_extras
cd -
}
make_ecl()
{
cd "$build_dir"
# make clean
make -j $num_simultaneous_jobs || exit 1
make install
cd -
}
build_one_ios()
{
platform_type="$1"
arch="$2"
select_ios "$platform_type" "$arch"
configure_ecl
make_ecl
}
export ECL_TO_RUN="../ecl-ios-host/bin/ecl"
build_one_ios iPhoneOS arm64

View file

@ -0,0 +1,27 @@
;;; cross-compile for iOS arm64
;;;
;;; expects the below environment variables to be set in a script which
;;; needs to call this file
(defvar *architecture* "aarch64-apple-darwin")
(pushnew :ios *features*)
(pushnew :aarch64 *features*)
(require :cmp)
(defun env (name)
(ext:getenv name))
(defvar *ecl-ios* (env "ECL_IOS"))
(defun cc (&rest args)
(apply 'concatenate 'string args))
(setf compiler::*ecl-include-directory* (cc *ecl-ios* "/include/")
compiler::*ecl-library-directory* (cc *ecl-ios* "/lib/")
compiler::*cc* (env "CC")
compiler::*cc-flags* (env "CFLAGS")
compiler::*ld* "ld"
compiler::*ld-flags* (env "LDFLAGS"))

View file

@ -0,0 +1,60 @@
# set up all environment variables needed for cross-compiling
#
# they will be read into ECL using (ext:getenv) in order to
# set the C compiler variables
select_ios()
{
platform_type="$1"
arch="$2"
ios_platform="$platform_type.platform"
developer_dir="`xcode-select --print-path`"
platforms_dir="$developer_dir/Platforms"
ios_platform_dir="$platforms_dir/$ios_platform"
ios_sdks="$ios_platform_dir/Developer/SDKs"
sdk_version=`(cd "$ios_sdks"; ls -1d *.sdk |sed -e 's/\.sdk$//' -e 's/^[^0-9\.]*//' |awk 'BEGIN{best = 0.0}($0 + 0.0) > best + 0.0{best = $0;}END{print best}')`
ios_sdk="$platform_type$sdk_version.sdk"
ios_sdk_dir="$ios_sdks/$ios_sdk"
echo "*** Selecting platform \"$ios_platform\" and SDK \"$ios_sdk\" for \"$arch\"."
case "$platform_type" in
iPhoneOS) config_options_extras=--host=aarch64-apple-darwin
sdk_name="iphoneos"
;;
iPhoneSimulator) config_options_extras=
sdk_name="iphonesimulator"
;;
esac
# this needs to be updated when a new Xcode is released
iphoneos_version_min="11.0"
export CC="clang"
export CXX="clang++"
export CFLAGS="-arch $arch -miphoneos-version-min=$iphoneos_version_min -isysroot $ios_sdk_dir"
export CFLAGS="$CFLAGS -pipe -Wno-trigraphs -Wreturn-type -Wunused-variable"
export CFLAGS="$CFLAGS -fpascal-strings -fasm-blocks -fmessage-length=0 -fvisibility=hidden"
export CFLAGS="$CFLAGS -O0 -DNO_ASM"
export CXXFLAGS="$CFLAGS"
export LD="ld"
export LDFLAGS="-arch $arch -miphoneos-version-min=$iphoneos_version_min -pipe -std=c99 -gdwarf-2 -isysroot $ios_sdk_dir"
export LIBS="-framework Foundation"
}
select_ios "iPhoneOS" "arm64"
#select_ios "iPhoneSimulator" "x86_64"
$ECL_IOS/../ecl-ios-host/bin/ecl -norc -shell $1

View file

@ -36,7 +36,16 @@
(si:install-c-compiler)
(load #+android (merge-pathnames "platforms/android/cross-compile"))
(defun cc (&rest args)
(apply 'concatenate 'string args))
#+android
(load (merge-pathnames "platforms/android/cross-compile"))
#+ios
(let ((cross-compile (merge-pathnames "platforms/ios/cross-compile")))
(ext:run-program (cc (namestring cross-compile) ".sh") nil)
(load cross-compile))
(setf *load-verbose* nil
*compile-verbose* t)
@ -45,6 +54,8 @@
c::*suppress-compiler-notes* nil
c::*compile-in-constants* t)
;;(setf c::*compile-print* t) ; for debugging compile errors
(load (merge-pathnames "src/lisp/tr.lisp")) ; i18n
(setf *break-on-signals* 'error)
@ -53,12 +64,12 @@
(defvar *object-files* nil)
(defun cc (&rest args)
(apply 'concatenate 'string args))
(dolist (file *source-files*)
(let ((src (cc file ".lisp"))
(obj (merge-pathnames (cc "src/.cache/" *architecture* file ".o"))))
(obj (merge-pathnames (format nil "src/.cache/ecl~A-~A/~A.o"
(lisp-implementation-version)
*architecture*
file))))
(when (or (not (probe-file obj))
(> (file-write-date src)
(file-write-date obj)))

43
readme-prepare-ios.md Normal file
View file

@ -0,0 +1,43 @@
Define environment variable and alias
-------------------------------------
Put this in e.g. `~/.profile`:
```
export ECL_IOS='<path-to-cross-compiled-ecl>/ecl-ios'
alias qmake-ios='<path-to-qt5.15>/ios/bin/qmake'
```
(Use `source ~/.profile` to make new environment variables take effect
immediately in your current terminal session.)
Build cross-compiled ECL for iOS
--------------------------------
* extract a fresh copy of the ECL sources in e.g. `~/ecl`, and rename
`ecl-21.2.1` to `ios`
* copy the 2 scripts from [platforms/ios/build-ecl/](platforms/ios/build-ecl/)
to `~/ecl/ios/`
* run first script
```
./1-make-ecl-host.sh
```
Edit `src/c/unixsys.d` and search for `HAVE_SYSTEM`; right before the function
definition inside which it occurs, put this line:
```
#undef HAVE_SYSTEM
```
Edit `src/c/thread/process.d`, search for `pthread_attr_init` (around line 588)
and add the following below that line:
```
pthread_attr_setstacksize(&pthreadattr, 2 * 236 * 4096); // double default size
```
* run second script
```
`./2-make-ecl-ios.sh`
```
Now you should have your cross-compiled ECL under `~/ecl/ios/ecl-ios/`, and
your host ECL (for cross-compiling) under `~/ecl/ios/ecl-ios-host/`.

View file

@ -2,8 +2,8 @@
WIP
---
Currently Linux/macOS/desktop only, will be extended to mobile; not sure about
Windows though.
The (very simple) example currently works on Linux/macOS/android/iOS. More
examples and Swank integration will follow.
Description
@ -37,7 +37,7 @@ port still lacks significant parts of mobile (as of Qt6.2).
TODO
----
* make example work on iOS
* integrate Swank server for Slime
* add item model example
* add sokoban example
* port to CMake

View file

@ -53,8 +53,7 @@ android {
QMAKE_POST_LINK = $$(ECL_ANDROID)/../ecl-android-host/bin/ecl \
-norc -shell $$PWD/make.lisp
} else:ios {
QMAKE_POST_LINK = $$(ECL_IOS)/../ecl-ios-host/bin/ecl \
-norc -shell $$PWD/make.lisp
QMAKE_POST_LINK = ../../platforms/ios/cross-compile.sh ../make.lisp
} else:unix {
QMAKE_POST_LINK = ecl -shell $$PWD/make.lisp
}

View file

@ -1,5 +1,9 @@
(when (search "/ecl-android/" (first (ext:command-args)))
(pushnew :android *features*))
(let ((arg (first (ext:command-args))))
(mapc (lambda (name feature)
(when (search name arg)
(pushnew feature *features*)))
(list "/ecl-android/" "/ecl-ios/")
(list :android :ios)))
(require :asdf)
@ -9,7 +13,7 @@
(setf *default-pathname-defaults*
(merge-pathnames "../../")) ; LQML root
#-android
#-(or android ios)
(progn
(asdf:make-build "lqml"
:monolithic t
@ -30,11 +34,13 @@
(delete-file to*))
(rename-file from to)))
#+android
#+(or android ios)
(progn
(defvar *asdf-system* :lqml)
(defvar *library-name* "platforms/android/lib/lisp")
(defvar *asdf-system* "lqml")
(defvar *init-name* "ini_LQML")
(defvar *library-name* (format nil "platforms/~A/lib/lisp"
#+android "android"
#+ios "ios"))
(load "platforms/shared/make"))
(terpri)