#!/usr/bin/env bash # build.sh — Build and install native-hello-ios to the iOS Simulator. # # Usage: # ./build.sh # gen C sources + xcodebuild for simulator # ./build.sh gen # regenerate C sources only # ./build.sh build # xcodebuild only (skip elc step) # ./build.sh install # gen + build + boot simulator + install + launch # ./build.sh clean # remove build/ directory # # Requirements: # - Xcode with iOS Simulator SDK installed # - elc at ../../../lang/dist/platform/elc (or in PATH) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang" EL_UI_ROOT="${SCRIPT_DIR}/../.." EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime" EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el" EL_APP_ENTRY="${EL_UI_ROOT}/examples/native-hello/src/main.el" EL_MANIFEST="${EL_UI_ROOT}/examples/native-hello/manifest.el" SOURCES_DIR="${SCRIPT_DIR}/NativeHello" BUILD_DIR="${SCRIPT_DIR}/build" # Locate elc. if command -v elc &>/dev/null; then ELC="elc" elif [ -x "${EL_LANG_ROOT}/dist/platform/elc" ]; then ELC="${EL_LANG_ROOT}/dist/platform/elc" else echo "Error: elc not found. Add it to PATH or place it at:" echo " ${EL_LANG_ROOT}/dist/platform/elc" exit 1 fi gen() { echo "==> Generating native_hello.c..." EL_MANIFEST="${EL_MANIFEST}" \ "${ELC}" "${EL_APP_ENTRY}" \ > "${SOURCES_DIR}/native_hello.c" # Rename the compiled el main() to el_app_main so it doesn't conflict with # main.m's main(). main.m's main() is the real entry point for UIApplicationMain. # Use a simple sed substitution on the exact signature elc emits. sed -i '' 's/^int main(int _argc, char\*\* _argv) {/int el_app_main(int _argc, char** _argv) {/' \ "${SOURCES_DIR}/native_hello.c" echo "==> Generating el_native_vessel.c..." "${ELC}" "${EL_NATIVE_VESSEL}" \ > "${SOURCES_DIR}/el_native_vessel.c" # Rename vessel main() similarly. sed -i '' 's/^int main(int _argc, char\*\* _argv) {/int el_vessel_main(int _argc, char** _argv) {/' \ "${SOURCES_DIR}/el_native_vessel.c" echo "==> Copying runtime files..." cp "${EL_RUNTIME}/el_uikit.m" "${SOURCES_DIR}/" cp "${EL_RUNTIME}/el_seed.c" "${SOURCES_DIR}/" cp "${EL_RUNTIME}/el_runtime.c" "${SOURCES_DIR}/" cp "${EL_RUNTIME}/el_runtime.h" "${SOURCES_DIR}/" cp "${EL_RUNTIME}/el_native_target.h" "${SOURCES_DIR}/" echo "==> Source generation complete." } xcode_build() { echo "==> Building with xcodebuild (iphonesimulator)..." xcodebuild \ -project "${SCRIPT_DIR}/NativeHello.xcodeproj" \ -scheme NativeHello \ -sdk iphonesimulator \ -configuration Debug \ -derivedDataPath "${BUILD_DIR}" \ CLANG_ENABLE_OBJC_ARC=NO \ OTHER_CFLAGS="-DEL_TARGET_IOS" \ OTHER_LDFLAGS="-ldl" \ build APP_PATH=$(find "${BUILD_DIR}" -name "NativeHello.app" -maxdepth 6 | head -1) if [ -n "${APP_PATH}" ]; then echo "==> Build complete." echo " App bundle: ${APP_PATH}" else echo "==> Build complete (app bundle in ${BUILD_DIR})." fi } install_and_launch() { gen xcode_build APP_PATH=$(find "${BUILD_DIR}" -name "NativeHello.app" -maxdepth 6 | head -1) if [ -z "${APP_PATH}" ]; then echo "Error: could not find NativeHello.app in ${BUILD_DIR}" exit 1 fi # Boot the default simulator if not already booted. SIM_UDID=$(xcrun simctl list devices available --json \ | python3 -c " import json,sys d=json.load(sys.stdin)['devices'] for runtime,devs in d.items(): for dev in devs: if 'iPhone' in dev['name'] and dev['isAvailable']: print(dev['udid']) exit() ") if [ -z "${SIM_UDID}" ]; then echo "Error: no available iPhone simulator found." exit 1 fi echo "==> Using simulator: ${SIM_UDID}" xcrun simctl boot "${SIM_UDID}" 2>/dev/null || true open -a Simulator echo "==> Installing app..." xcrun simctl install "${SIM_UDID}" "${APP_PATH}" echo "==> Launching app..." xcrun simctl launch "${SIM_UDID}" "ai.neurontechnologies.el.nativehello" } clean() { echo "==> Cleaning..." rm -rf "${BUILD_DIR}" echo "==> Clean complete." } case "${1:-all}" in gen) gen ;; build) xcode_build ;; install) install_and_launch ;; clean) clean ;; all|*) gen && xcode_build ;; esac