feat(ios): add iOS simulator support and improve build system

- Extended iOS platform support to handle simulator targets with arm64-apple-ios-simulator
- Added new ios-simulator.yml configuration for building simulator-compatible executables
- Created build-ios.sh script to handle both device and simulator builds with parameter selection
- Implemented dynamic SDK directory selection based on target platform (iphoneos vs iphonesimulator)
- Updated error messages to reflect generic iOS SDK terminology instead of iPhoneOS specific
- Added package-ios-simulator-app.sh for packaging simulator applications without provisioning profiles
- Updated README documentation with complete iOS simulator setup and build instructions
- Modified codesign commands to include --generate-entitlement-der flag for proper entitlement handling
- Adjusted gitignore to exclude new ios-simulator-build directory and simulator executable
master
韩天峰 3 weeks ago
parent dddff48650
commit b9c42eed1f
  1. 2
      examples/apple-native/.gitignore
  2. 56
      examples/apple-native/README.md
  3. 36
      examples/apple-native/build-ios.sh
  4. 26
      examples/apple-native/ios-simulator.yml
  5. 1
      examples/apple-native/package-ios-app.sh
  6. 23
      examples/apple-native/package-ios-simulator-app.sh
  7. 13
      src/Build/NativeBuildConfigurationTrait.php
  8. 2
      src/Platform/Ios.php

@ -1,7 +1,9 @@
/build/
/build-*/
/ios-build/
/ios-simulator-build/
/dist/
/*.rsp
/typephp_macos_hello
/typephp_ios_hello
/typephp_ios_simulator_hello

@ -89,10 +89,10 @@ SDK:
```sh
export PHPX_HOME=/path/to/swoole-cli/thirdparty/phpx
php bin/tpc.php examples/objective-c-macos/ios.yml --no-progress
php bin/tpc.php examples/apple-native/ios.yml --no-progress
```
The compiler produces `examples/objective-c-macos/typephp_ios_hello`. Package
The compiler produces `examples/apple-native/typephp_ios_hello`. Package
and sign it with a development provisioning profile and identity installed in
the login keychain:
@ -101,7 +101,7 @@ export TYPEPHP_IOS_PROVISIONING_PROFILE=/path/to/profile.mobileprovision
export TYPEPHP_IOS_CODE_SIGN_IDENTITY='Apple Development: Your Name (TEAMID)'
# Set this when the profile uses a different identifier than the example.
export TYPEPHP_IOS_BUNDLE_IDENTIFIER='your.provisioned.bundle.identifier'
sh examples/objective-c-macos/package-ios-app.sh
sh examples/apple-native/package-ios-app.sh
```
The package includes iPhone icon sizes generated from the repository's
@ -109,7 +109,7 @@ The package includes iPhone icon sizes generated from the repository's
and run:
```sh
sh examples/objective-c-macos/generate-ios-icons.sh
sh examples/apple-native/generate-ios-icons.sh
```
Find the connected iPhone and install the bundle:
@ -118,8 +118,54 @@ Find the connected iPhone and install the bundle:
xcrun devicectl list devices
xcrun devicectl device install app \
--device <device-id> \
'examples/objective-c-macos/dist/TypePHP iOS Hello.app'
'examples/apple-native/dist/TypePHP iOS Hello.app'
```
## iOS Simulator (Apple silicon)
The simulator needs archives compiled for `arm64-apple-ios-simulator`.
The physical iPhone SDK above cannot be reused. Build the separate runtime
and PHPX SDK on the Mac:
```sh
cd /path/to/swoole-cli
php prepare.php @iphonesimulator-arm64 --with-parallel-jobs=8
./make.sh all-library
./make.sh config
./make.sh libphp
bash sapi/scripts/package-php-runtime-layer.sh iphonesimulator-arm64
# Copy the packaged runtime's include/ and lib/ trees into this prefix.
mkdir -p /path/to/phpx/ios/iphonesimulator-arm64
cp -R runtime-layer/php-runtime-layer_*_iphonesimulator-arm64/include \
runtime-layer/php-runtime-layer_*_iphonesimulator-arm64/lib \
/path/to/phpx/ios/iphonesimulator-arm64/
cp runtime-layer/php-runtime-layer_*_iphonesimulator-arm64/.typephp-php-runtime-abi \
/path/to/phpx/ios/iphonesimulator-arm64/
cp var/iphonesimulator-arm64/deps/gmp/lib/libgmp.a \
var/iphonesimulator-arm64/deps/gmp/lib/libgmpxx.a \
var/iphonesimulator-arm64/deps/mpfr/lib/libmpfr.a \
/path/to/phpx/ios/iphonesimulator-arm64/lib/
cd /path/to/phpx
./ios/build.sh --platform simulator
```
Build and install the app with the simulator SDK:
```sh
cd /path/to/typephp
export PHPX_HOME=/path/to/phpx
sh examples/apple-native/build-ios.sh simulator
xcrun simctl install booted 'examples/apple-native/dist/TypePHP iOS Simulator Hello.app'
xcrun simctl launch booted org.swoole.typephp.ios-simulator-hello
```
The simulator bundle uses ad hoc signing and does not need a provisioning
profile or a physical iPhone.
The same source files are used for both targets. Select `device` instead of
`simulator` in `build-ios.sh` to build the physical iPhone executable. Set
`TYPEPHP_IOS_PROVISIONING_PROFILE` and `TYPEPHP_IOS_CODE_SIGN_IDENTITY` to
package and sign the device app in the same command.
The `.mm` bridges are deliberately thin. AppKit/UIKit own native controls and
deliver events, but the shared TypePHP class owns the application behavior.

@ -0,0 +1,36 @@
#!/bin/sh
set -eu
project_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
repo_dir=$(CDPATH= cd -- "$project_dir/../.." && pwd)
if [ -z "${PHPX_HOME:-}" ]; then
echo "Set PHPX_HOME to the PHPX checkout containing both iOS SDK prefixes." >&2
exit 2
fi
case "${1:-}" in
device)
config=ios.yml
package_script=package-ios-app.sh
;;
simulator)
config=ios-simulator.yml
package_script=package-ios-simulator-app.sh
;;
*)
echo "Usage: $0 <device|simulator>" >&2
exit 2
;;
esac
cd "$repo_dir"
php bin/tpc.php "examples/apple-native/$config" --no-progress
if [ "$package_script" = package-ios-app.sh ] &&
{ [ -z "${TYPEPHP_IOS_PROVISIONING_PROFILE:-}" ] || [ -z "${TYPEPHP_IOS_CODE_SIGN_IDENTITY:-}" ]; }; then
echo "Device executable built. Set the provisioning profile and signing identity, then run $project_dir/$package_script to package it."
else
sh "$project_dir/$package_script"
fi

@ -0,0 +1,26 @@
name: typephp_ios_simulator_hello
version: 0.1.0
mode: bin
output: typephp_ios_simulator_hello
php-version: "8.4"
cxx-std: c++17
cpp-compiler: xcrun --sdk iphonesimulator clang++
target-platform: arm64-apple-ios15.0-simulator
build-dir: ios-simulator-build
sources:
- php-src/application.php
- php-src/ios-main.php
- ios-src
cxx-flags:
- -fobjc-arc
- -mios-simulator-version-min=15.0
ld-flags:
- -mios-simulator-version-min=15.0
- -Wl,-dead_strip
- -framework UIKit
- -framework Foundation
- -framework CoreGraphics
- -lresolv

@ -46,6 +46,7 @@ codesign \
--sign "$identity" \
--entitlements "$entitlements" \
--timestamp=none \
--generate-entitlement-der \
"$bundle"
codesign --verify --deep --strict --verbose=2 "$bundle"

@ -0,0 +1,23 @@
#!/bin/sh
set -eu
project_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
executable="$project_dir/typephp_ios_simulator_hello"
bundle="$project_dir/dist/TypePHP iOS Simulator Hello.app"
if [ ! -x "$executable" ]; then
echo "Missing $executable; build ios-simulator.yml first." >&2
exit 1
fi
mkdir -p "$bundle"
cp "$project_dir/Info-iOS.plist" "$bundle/Info.plist"
plutil -replace CFBundleExecutable -string typephp_ios_simulator_hello "$bundle/Info.plist"
plutil -replace CFBundleIdentifier -string org.swoole.typephp.ios-simulator-hello "$bundle/Info.plist"
cp "$executable" "$bundle/typephp_ios_simulator_hello"
cp "$project_dir"/ios-assets/AppIcon*.png "$bundle/"
codesign --force --sign - --timestamp=none "$bundle"
codesign --verify --deep --strict "$bundle"
echo "Created $bundle"

@ -52,19 +52,22 @@ trait NativeBuildConfigurationTrait
protected function getIosSdkDir(): string
{
$sdkDir = $this->getPhpxDir() . '/ios/iphoneos-arm64';
$target = str_ends_with(strtolower($this->targetPlatform), '-simulator')
? 'iphonesimulator-arm64'
: 'iphoneos-arm64';
$sdkDir = $this->getPhpxDir() . '/ios/' . $target;
if (!is_dir($sdkDir)) {
$this->error(
'The iPhoneOS SDK was not found at: ' . $sdkDir . "\n"
'The iOS SDK was not found at: ' . $sdkDir . "\n"
. ' Build/install the matching SDK inside PHPX before compiling this target.'
);
}
$abiStamp = $sdkDir . '/.typephp-ios-sdk-abi';
if (!is_file($abiStamp)
|| trim((string) file_get_contents($abiStamp)) !== 'typephp-iphoneos-arm64-sdk-abi-v1'
|| trim((string) file_get_contents($abiStamp)) !== 'typephp-' . $target . '-sdk-abi-v1'
) {
$this->error(
'The iPhoneOS SDK is missing or ABI-incompatible: ' . $sdkDir . "\n"
'The iOS SDK is missing or ABI-incompatible: ' . $sdkDir . "\n"
. ' Rebuild it with PHPX ios/build.sh and the matching PHP SDK.'
);
}
@ -365,7 +368,7 @@ trait NativeBuildConfigurationTrait
$buildHint = 'Build PHPX first (for example, run `nmake phpx` in ' . $this->getPhpxDir() . '\\build)';
} elseif ($this->isIosTarget()) {
$expected = $this->getPhpDir() . '/lib/libphpx.a';
$buildHint = 'Build the integrated iPhoneOS SDK in PHPX_HOME/ios/iphoneos-arm64';
$buildHint = 'Build the matching iOS SDK in PHPX_HOME/ios';
} elseif ($this->isAndroidTarget()) {
$expected = $this->getAndroidSdkDir() . '/lib/libphpx.a';
$buildHint = 'Build the Android SDK with PHPX sdk/build-native.sh';

@ -12,7 +12,7 @@ class Ios extends UnixPlatform
{
public static function supportsTarget(string $target): bool
{
return preg_match('/^(?:arm64|aarch64)-apple-ios(?:\d+(?:\.\d+)*)?$/i', $target) === 1;
return preg_match('/^(?:arm64|aarch64)-apple-ios(?:\d+(?:\.\d+)*)?(?:-simulator)?$/i', $target) === 1;
}
public function getName(): string

Loading…
Cancel
Save