Skip to content

Commit fff67e1

Browse files
authored
Merge branch 'master' into fix/service-disco-ipv6-iptree
2 parents e742502 + 1ce12fb commit fff67e1

8 files changed

Lines changed: 514 additions & 2 deletions

File tree

.github/workflows/mobile_android.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,31 @@ jobs:
6969
7070
file "$out/lib/liblibp2p.so"
7171
file "$out/bin/libp2p_ffi_android_check"
72+
73+
- name: Enable KVM for Android emulator
74+
if: matrix.abi == 'x86_64'
75+
run: |
76+
sudo tee /etc/udev/rules.d/99-kvm4all.rules >/dev/null <<'EOF'
77+
KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"
78+
EOF
79+
sudo udevadm control --reload-rules
80+
sudo udevadm trigger --name-match=kvm
81+
82+
- name: Run FFI check on Android emulator
83+
if: matrix.abi == 'x86_64'
84+
uses: reactivecircus/android-emulator-runner@v2
85+
with:
86+
api-level: 23
87+
arch: x86_64
88+
target: default
89+
force-avd-creation: false
90+
emulator-options: -no-window -no-audio -no-boot-anim -no-metrics -gpu swiftshader_indirect
91+
disable-animations: true
92+
script: |
93+
adb shell "mkdir -p /data/local/tmp/nim-libp2p"
94+
adb push "result-x86_64/lib/liblibp2p.so" "/data/local/tmp/nim-libp2p/"
95+
adb push "result-x86_64/lib/libc++_shared.so" "/data/local/tmp/nim-libp2p/"
96+
adb push "result-x86_64/bin/libp2p_ffi_android_check" "/data/local/tmp/nim-libp2p/"
97+
adb shell "chmod 755 /data/local/tmp/nim-libp2p/libp2p_ffi_android_check"
98+
adb shell "cd /data/local/tmp/nim-libp2p && LD_LIBRARY_PATH=/data/local/tmp/nim-libp2p ./libp2p_ffi_android_check; echo RC=\$?" | tee run.log
99+
grep -q '^RC=0' run.log

.github/workflows/mobile_ios.yml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
name: Mobile iOS
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
merge_group:
9+
workflow_dispatch:
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
cbind-ffi-ios:
17+
timeout-minutes: 90
18+
runs-on: macos-15
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
include:
23+
- target: arm64
24+
attr: cbind-ffi-ios-arm64
25+
sdk: iphoneos
26+
platform: IOS
27+
platform_id: 2
28+
- target: simulator-arm64
29+
attr: cbind-ffi-ios-simulator-arm64
30+
sdk: iphonesimulator
31+
platform: IOSSIMULATOR
32+
platform_id: 7
33+
34+
defaults:
35+
run:
36+
shell: bash
37+
38+
name: "iOS ${{ matrix.target }} FFI check build"
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@v6
42+
with:
43+
submodules: true
44+
45+
- name: Install Nix
46+
uses: cachix/install-nix-action@v31
47+
with:
48+
extra_nix_config: |
49+
sandbox = false
50+
51+
- name: Show Xcode SDK
52+
run: |
53+
xcodebuild -version
54+
xcrun --sdk "${{ matrix.sdk }}" --show-sdk-path
55+
xcrun --sdk "${{ matrix.sdk }}" --find clang
56+
57+
- name: Build iOS C ABI package
58+
run: |
59+
nix --extra-experimental-features "nix-command flakes" \
60+
build ".#${{ matrix.attr }}" \
61+
-o "result-${{ matrix.target }}"
62+
63+
- name: Verify iOS artifacts
64+
run: |
65+
out="result-${{ matrix.target }}"
66+
67+
test -f "$out/lib/liblibp2p.dylib"
68+
test -f "$out/lib/liblibp2p.a"
69+
test -f "$out/include/libp2p.h"
70+
test -f "$out/include/nim_ffi_cbor.h"
71+
test -f "$out/include/nim_ffi_prelude.h"
72+
test -f "$out/include/tinycbor/cbor.h"
73+
test -f "$out/include/cddl_bindings/libp2p.cddl"
74+
test -x "$out/bin/libp2p_ffi_ios_check"
75+
76+
otool -l "$out/lib/liblibp2p.dylib" | tee liblibp2p.otool
77+
otool -l "$out/bin/libp2p_ffi_ios_check" | tee check.otool
78+
lipo -info "$out/lib/liblibp2p.dylib" | tee liblibp2p.lipo
79+
lipo -info "$out/lib/liblibp2p.a" | tee liblibp2p_static.lipo
80+
81+
grep -Eq "platform (${{ matrix.platform }}|${{ matrix.platform_id }})|LC_VERSION_MIN_IPHONEOS" liblibp2p.otool
82+
grep -Eq "platform (${{ matrix.platform }}|${{ matrix.platform_id }})|LC_VERSION_MIN_IPHONEOS" check.otool
83+
grep -q "arm64" liblibp2p.lipo
84+
grep -q "arm64" liblibp2p_static.lipo
85+
86+
file "$out/lib/liblibp2p.dylib"
87+
file "$out/bin/libp2p_ffi_ios_check"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ static int create_node(LibP2PCtx **out_ctx) {
150150
return 1;
151151
}
152152
if (wait_for_callback(&create_wait, "create") != 0) {
153+
if (create_wait.ctx != NULL) {
154+
libp2p_ctx_destroy(create_wait.ctx);
155+
}
153156
wait_destroy(&create_wait);
154157
return 1;
155158
}

docs/mobile_android.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ together with the Android C++ runtime selected by your application.
8888

8989
## Android Check Harness
9090

91-
The Nix Android derivation compiles `cbind/examples/libp2p_ffi_android_check.c`
91+
The Nix Android derivation compiles `cbind/examples/libp2p_ffi_mobile_check.c`
9292
for each ABI. The harness includes the generated nim-ffi C header, creates a
9393
default TCP/Yamux node, starts it, stops it, destroys the context, and fails on
9494
callback errors or timeouts.

docs/mobile_ios.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# iOS Mobile Builds For libp2p_ffi
2+
3+
`cbind/libp2p_ffi.nim` is the supported C ABI target for iOS builds. The legacy
4+
`cbind/libp2p.nim` target is not extended for iOS.
5+
6+
## Supported Targets
7+
8+
The iOS build targets iOS 13.0 or newer by default and uses SDKs from an
9+
installed Xcode bundle:
10+
11+
| Target | Nim CPU | SDK | Clang target |
12+
| --- | --- | --- | --- |
13+
| iOS device `arm64` | `arm64` | `iphoneos` | `arm64-apple-ios13.0` |
14+
| iOS simulator `arm64` | `arm64` | `iphonesimulator` | `arm64-apple-ios13.0-simulator` |
15+
16+
These targets must be built on macOS with Xcode installed. They are not exposed
17+
on Linux Nix hosts because the iPhoneOS and iPhoneSimulator SDKs are provided by
18+
Xcode, not by nixpkgs.
19+
20+
## Build Commands
21+
22+
Build a single target on macOS:
23+
24+
```sh
25+
nix build .#cbind-ffi-ios-arm64
26+
nix build .#cbind-ffi-ios-simulator-arm64
27+
```
28+
29+
Build both iOS layouts in one output:
30+
31+
```sh
32+
nix build .#cbind-ffi-ios
33+
```
34+
35+
If your Nix installation uses sandboxing on macOS, disable it for this build so
36+
the derivation can access the host Xcode bundle and SDKs:
37+
38+
```sh
39+
nix --extra-experimental-features "nix-command flakes" \
40+
--option sandbox false \
41+
build .#cbind-ffi-ios-arm64
42+
```
43+
44+
## Artifact Layout
45+
46+
Single-target outputs are flat:
47+
48+
```text
49+
result/
50+
bin/libp2p_ffi_ios_check
51+
include/libp2p.h
52+
include/nim_ffi_cbor.h
53+
include/nim_ffi_prelude.h
54+
include/tinycbor/...
55+
include/cddl_bindings/libp2p.cddl
56+
lib/liblibp2p.dylib
57+
lib/liblibp2p.a
58+
nix-support/ios-target
59+
```
60+
61+
The aggregate output nests the same layout by target:
62+
63+
```text
64+
result/ios/arm64/...
65+
result/ios/simulator-arm64/...
66+
```
67+
68+
`liblibp2p.dylib` and `liblibp2p.a` intentionally keep the same naming as the
69+
host `cbind-ffi` package.
70+
71+
## Downstream Linking Notes
72+
73+
Use the generated high-level C helpers in `include/libp2p.h`:
74+
75+
- `libp2p_ctx_create`
76+
- `libp2p_ctx_start`
77+
- `libp2p_ctx_stop`
78+
- `libp2p_ctx_destroy`
79+
80+
The generated header uses TinyCBOR for request and response encoding. The Nix
81+
output installs the required TinyCBOR headers and C sources under
82+
`include/tinycbor`. Downstream C, C++, Objective-C, or Swift wrapper code that
83+
calls the generated helper functions should compile those TinyCBOR `.c` files
84+
into the app or a support library.
85+
86+
For shared-library linking, package the matching target's `lib/liblibp2p.dylib`
87+
with the iOS application using the normal Xcode embedding/signing flow. For
88+
static linking, link `lib/liblibp2p.a` together with the C++ runtime selected by
89+
the application.
90+
91+
## iOS Check Harness
92+
93+
The Nix iOS derivation compiles `cbind/examples/libp2p_ffi_mobile_check.c` for
94+
each target. The harness includes the generated nim-ffi C header, creates a
95+
default TCP/Yamux node, starts it, stops it, destroys the context, and fails on
96+
callback errors or timeouts.
97+
98+
The derivation only compiles and links the harness. It does not run the harness
99+
on a simulator or physical device.
100+
101+
## CI Coverage
102+
103+
`.github/workflows/mobile_ios.yml` runs on macOS and builds both iOS packages.
104+
The workflow checks that each output contains:
105+
106+
- shared and static `liblibp2p` libraries
107+
- generated C headers and CDDL
108+
- TinyCBOR headers used by the generated C helper layer
109+
- the linked iOS check executable
110+
- Mach-O platform metadata matching the selected SDK
111+
- `arm64` architecture metadata for the dynamic library, static library,
112+
and check executable

flake.nix

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
let
4343
pkgs = pkgsFor system;
4444
androidSupported = pkgs.stdenv.hostPlatform.isLinux || pkgs.stdenv.hostPlatform.isDarwin;
45+
iosSupported = pkgs.stdenv.hostPlatform.isDarwin;
4546
androidArm64 = import ./nix/cbind-ffi-android.nix {
4647
inherit pkgs;
4748
src = ./.;
@@ -56,6 +57,22 @@
5657
androidTriple = "x86_64-linux-android";
5758
nimCpu = "amd64";
5859
};
60+
iosArm64 = import ./nix/cbind-ffi-ios.nix {
61+
inherit pkgs;
62+
src = ./.;
63+
targetName = "arm64";
64+
sdk = "iphoneos";
65+
platformName = "IOS";
66+
targetTriple = "arm64-apple-ios13.0";
67+
};
68+
iosSimulatorArm64 = import ./nix/cbind-ffi-ios.nix {
69+
inherit pkgs;
70+
src = ./.;
71+
targetName = "simulator-arm64";
72+
sdk = "iphonesimulator";
73+
platformName = "IOSSIMULATOR";
74+
targetTriple = "arm64-apple-ios13.0-simulator";
75+
};
5976
in {
6077
default = import ./nix/default.nix {
6178
inherit pkgs;
@@ -84,6 +101,16 @@
84101
cp -R ${androidArm64}/. $out/android/arm64-v8a/
85102
cp -R ${androidX86}/. $out/android/x86_64/
86103
'';
104+
} // pkgs.lib.optionalAttrs iosSupported {
105+
cbind-ffi-ios-arm64 = iosArm64;
106+
107+
cbind-ffi-ios-simulator-arm64 = iosSimulatorArm64;
108+
109+
cbind-ffi-ios = pkgs.runCommand "nim-libp2p-cbind-ffi-ios" { } ''
110+
mkdir -p $out/ios/arm64 $out/ios/simulator-arm64
111+
cp -R ${iosArm64}/. $out/ios/arm64/
112+
cp -R ${iosSimulatorArm64}/. $out/ios/simulator-arm64/
113+
'';
87114
}
88115
);
89116

nix/cbind-ffi-android.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ pkgs.stdenv.mkDerivation {
131131
mkdir -p build/check-objects
132132
"$ANDROID_CC" -std=c11 -fPIE -pthread \
133133
-I cbind/c_bindings -I cbind/c_bindings/tinycbor \
134-
-c cbind/examples/libp2p_ffi_android_check.c \
134+
-c cbind/examples/libp2p_ffi_mobile_check.c \
135135
-o build/check-objects/libp2p_ffi_android_check.o
136136
for src in cbind/c_bindings/tinycbor/*.c; do
137137
obj=build/check-objects/$(basename "$src" .c).o

0 commit comments

Comments
 (0)