| 1 | #!/bin/bash |
| 2 | |
| 3 | set -e -x |
| 4 | |
| 5 | if [[ "$1" == "--install" ]]; then |
| 6 | # install go > 1.24: |
| 7 | brew install go |
| 8 | export PATH=$PATH:~/go/bin |
| 9 | fi |
| 10 | |
| 11 | BASE_DIR="$(pwd)" |
| 12 | MWEB_GO_DIR="${BASE_DIR}/../../cw_mweb/go" |
| 13 | IOS_OUTPUT_DIR="${BASE_DIR}/../../cw_mweb/ios" |
| 14 | TMP_DIR="${BASE_DIR}/tmp_mweb_frameworks" |
| 15 | FRAMEWORK_NAME="Mwebd" |
| 16 | |
| 17 | rm -rf "$TMP_DIR" |
| 18 | mkdir -p "$TMP_DIR" |
| 19 | |
| 20 | mkdir -p "$IOS_OUTPUT_DIR" |
| 21 | |
| 22 | write_info_plist() { |
| 23 | local framework_bundle="$1" |
| 24 | local framework_name="$2" |
| 25 | local target="$3" |
| 26 | local arch="$4" |
| 27 | local plist_path="${framework_bundle}/Info.plist" |
| 28 | |
| 29 | local platform min_os_version dtplatformname dtsdkname |
| 30 | |
| 31 | if [[ "$target" == "ios-simulator" ]]; then |
| 32 | platform="iPhoneSimulator" |
| 33 | dtplatformname="iphonesimulator" |
| 34 | dtsdkname="iphonesimulator17.4" |
| 35 | min_os_version="12.0" |
| 36 | elif [[ "$target" == "ios" ]]; then |
| 37 | platform="iPhoneOS" |
| 38 | dtplatformname="iphoneos" |
| 39 | dtsdkname="iphoneos17.4" |
| 40 | min_os_version="12.0" |
| 41 | else |
| 42 | echo "Unknown target: $target" |
| 43 | exit 1 |
| 44 | fi |
| 45 | |
| 46 | cat > "$plist_path" <<EOF |
| 47 | <?xml version="1.0" encoding="UTF-8"?> |
| 48 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| 49 | <plist version="1.0"> |
| 50 | <dict> |
| 51 | <key>BuildMachineOSBuild</key> |
| 52 | <string>23F79</string> |
| 53 | <key>CFBundleDevelopmentRegion</key> |
| 54 | <string>en</string> |
| 55 | <key>CFBundleExecutable</key> |
| 56 | <string>${framework_name}</string> |
| 57 | <key>CFBundleIdentifier</key> |
| 58 | <string>com.cakewallet.${framework_name}</string> |
| 59 | <key>CFBundleInfoDictionaryVersion</key> |
| 60 | <string>6.0</string> |
| 61 | <key>CFBundleName</key> |
| 62 | <string>${framework_name}</string> |
| 63 | <key>CFBundlePackageType</key> |
| 64 | <string>FMWK</string> |
| 65 | <key>CFBundleShortVersionString</key> |
| 66 | <string>1.0</string> |
| 67 | <key>CFBundleVersion</key> |
| 68 | <string>1</string> |
| 69 | <key>CFBundleSupportedPlatforms</key> |
| 70 | <array> |
| 71 | <string>${platform}</string> |
| 72 | </array> |
| 73 | <key>DTCompiler</key> |
| 74 | <string>com.apple.compilers.llvm.clang.1_0</string> |
| 75 | <key>DTPlatformName</key> |
| 76 | <string>${dtplatformname}</string> |
| 77 | <key>DTPlatformVersion</key> |
| 78 | <string>17.4</string> |
| 79 | <key>DTSDKBuild</key> |
| 80 | <string>21E213</string> |
| 81 | <key>DTSDKName</key> |
| 82 | <string>${dtsdkname}</string> |
| 83 | <key>DTSDKVersion</key> |
| 84 | <string>17.4</string> |
| 85 | <key>DTXcode</key> |
| 86 | <string>1530</string> |
| 87 | <key>DTXcodeBuild</key> |
| 88 | <string>15E204a</string> |
| 89 | <key>MinimumOSVersion</key> |
| 90 | <string>${min_os_version}</string> |
| 91 | <key>UIDeviceFamily</key> |
| 92 | <array> |
| 93 | <integer>1</integer> |
| 94 | <integer>2</integer> |
| 95 | </array> |
| 96 | </dict> |
| 97 | </plist> |
| 98 | EOF |
| 99 | } |
| 100 | |
| 101 | build_go_library() { |
| 102 | local goos="$1" |
| 103 | local goarch="$2" |
| 104 | local cc_target="$3" |
| 105 | local sdk="$4" |
| 106 | local output_file="$5" |
| 107 | |
| 108 | echo "Building Go library for ${goos}/${goarch} with target ${cc_target}..." |
| 109 | |
| 110 | cd "$MWEB_GO_DIR" |
| 111 | |
| 112 | export GOOS="$goos" |
| 113 | export GOARCH="$goarch" |
| 114 | export CGO_ENABLED=1 |
| 115 | export CGO_CFLAGS="-fembed-bitcode" |
| 116 | |
| 117 | if [[ "$sdk" == "iphoneos" ]]; then |
| 118 | export CC="$(xcrun -f clang) -target $cc_target -mios-version-min=12 --sysroot $(xcrun --sdk iphoneos --show-sdk-path)" |
| 119 | else |
| 120 | export CC="$(xcrun -f clang) -target $cc_target -mios-simulator-version-min=12 --sysroot $(xcrun --sdk iphonesimulator --show-sdk-path)" |
| 121 | fi |
| 122 | |
| 123 | go build -buildmode=c-archive -trimpath -o "$output_file" mweb.go |
| 124 | |
| 125 | echo "Built: $output_file" |
| 126 | cd - > /dev/null |
| 127 | } |
| 128 | |
| 129 | create_framework() { |
| 130 | local archive_path="$1" |
| 131 | local framework_name="$2" |
| 132 | local target="$3" |
| 133 | local out_dir="$4" |
| 134 | local arch="$5" |
| 135 | |
| 136 | echo "Creating ${framework_name}.framework for target ${target} (${arch}) in ${out_dir}..." |
| 137 | |
| 138 | local framework_bundle="${out_dir}/${framework_name}.framework" |
| 139 | |
| 140 | rm -rf "$framework_bundle" |
| 141 | mkdir -p "$framework_bundle" |
| 142 | |
| 143 | if [[ ! -f "$archive_path" ]]; then |
| 144 | echo "Error: Input archive not found: $archive_path" |
| 145 | exit 1 |
| 146 | fi |
| 147 | |
| 148 | local temp_dir="${TMP_DIR}/temp_${arch}" |
| 149 | mkdir -p "$temp_dir" |
| 150 | |
| 151 | pushd "$temp_dir" |
| 152 | ar x "$archive_path" |
| 153 | |
| 154 | if [[ "$target" == "ios" ]]; then |
| 155 | xcrun -sdk iphoneos clang -dynamiclib -arch "${arch}" -mios-version-min=12 \ |
| 156 | -install_name "@rpath/${framework_name}.framework/${framework_name}" \ |
| 157 | -framework CoreFoundation -framework Security -lresolv \ |
| 158 | -o "${framework_bundle}/${framework_name}" ./*.o |
| 159 | else |
| 160 | xcrun -sdk iphonesimulator clang -dynamiclib -arch "${arch}" -mios-simulator-version-min=12 \ |
| 161 | -install_name "@rpath/${framework_name}.framework/${framework_name}" \ |
| 162 | -framework CoreFoundation -framework Security -lresolv \ |
| 163 | -o "${framework_bundle}/${framework_name}" ./*.o |
| 164 | fi |
| 165 | popd |
| 166 | |
| 167 | echo "Created binary: ${framework_bundle}/${framework_name}" |
| 168 | |
| 169 | write_info_plist "$framework_bundle" "$framework_name" "$target" "$arch" |
| 170 | |
| 171 | mkdir -p "${framework_bundle}/Headers" |
| 172 | local header_file="${archive_path%.a}.h" |
| 173 | if [[ -f "$header_file" ]]; then |
| 174 | cp "$header_file" "${framework_bundle}/Headers/${framework_name}.h" |
| 175 | echo "Copied header: ${framework_bundle}/Headers/${framework_name}.h" |
| 176 | fi |
| 177 | |
| 178 | echo "Framework created: ${framework_bundle}" |
| 179 | } |
| 180 | |
| 181 | create_xcframework() { |
| 182 | local framework_name="$1" |
| 183 | local xcframework_output="$2" |
| 184 | shift 2 |
| 185 | local frameworks=("$@") |
| 186 | |
| 187 | echo "Creating ${xcframework_output} by bundling:" |
| 188 | for fw in "${frameworks[@]}"; do |
| 189 | echo " Framework: ${fw}" |
| 190 | done |
| 191 | |
| 192 | local xcodebuild_args=() |
| 193 | for fw in "${frameworks[@]}"; do |
| 194 | xcodebuild_args+=("-framework" "$fw") |
| 195 | done |
| 196 | |
| 197 | rm -rf "$xcframework_output" |
| 198 | xcodebuild -create-xcframework "${xcodebuild_args[@]}" -output "$xcframework_output" |
| 199 | |
| 200 | echo "Created XCFramework: ${xcframework_output}" |
| 201 | } |
| 202 | |
| 203 | echo "Building MWEB XCFramework for iOS..." |
| 204 | |
| 205 | IOS_DEVICE_OUT="${TMP_DIR}/ios_device" |
| 206 | IOS_SIMULATOR_ARM64_OUT="${TMP_DIR}/ios_simulator_arm64" |
| 207 | IOS_SIMULATOR_X86_64_OUT="${TMP_DIR}/ios_simulator_x86_64" |
| 208 | |
| 209 | mkdir -p "$IOS_DEVICE_OUT" "$IOS_SIMULATOR_ARM64_OUT" "$IOS_SIMULATOR_X86_64_OUT" |
| 210 | |
| 211 | IOS_DEVICE_ARCHIVE="${TMP_DIR}/${FRAMEWORK_NAME}_device.a" |
| 212 | IOS_SIMULATOR_ARM64_ARCHIVE="${TMP_DIR}/${FRAMEWORK_NAME}_sim_arm64.a" |
| 213 | IOS_SIMULATOR_X86_64_ARCHIVE="${TMP_DIR}/${FRAMEWORK_NAME}_sim_x86_64.a" |
| 214 | |
| 215 | build_go_library "ios" "arm64" "aarch64-apple-ios" "iphoneos" "$IOS_DEVICE_ARCHIVE" |
| 216 | build_go_library "ios" "arm64" "aarch64-apple-ios-simulator" "iphonesimulator" "$IOS_SIMULATOR_ARM64_ARCHIVE" |
| 217 | build_go_library "ios" "amd64" "x86_64-apple-ios-simulator" "iphonesimulator" "$IOS_SIMULATOR_X86_64_ARCHIVE" |
| 218 | |
| 219 | create_framework "$IOS_DEVICE_ARCHIVE" "$FRAMEWORK_NAME" "ios" "$IOS_DEVICE_OUT" "arm64" |
| 220 | create_framework "$IOS_SIMULATOR_ARM64_ARCHIVE" "$FRAMEWORK_NAME" "ios-simulator" "$IOS_SIMULATOR_ARM64_OUT" "arm64" |
| 221 | create_framework "$IOS_SIMULATOR_X86_64_ARCHIVE" "$FRAMEWORK_NAME" "ios-simulator" "$IOS_SIMULATOR_X86_64_OUT" "x86_64" |
| 222 | |
| 223 | IOS_SIMULATOR_UNIVERSAL_OUT="${TMP_DIR}/ios_simulator_universal" |
| 224 | mkdir -p "$IOS_SIMULATOR_UNIVERSAL_OUT" |
| 225 | |
| 226 | SIMULATOR_UNIVERSAL_FRAMEWORK="${IOS_SIMULATOR_UNIVERSAL_OUT}/${FRAMEWORK_NAME}.framework" |
| 227 | mkdir -p "$SIMULATOR_UNIVERSAL_FRAMEWORK" |
| 228 | |
| 229 | lipo -create \ |
| 230 | "${IOS_SIMULATOR_ARM64_OUT}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" \ |
| 231 | "${IOS_SIMULATOR_X86_64_OUT}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" \ |
| 232 | -output "${SIMULATOR_UNIVERSAL_FRAMEWORK}/${FRAMEWORK_NAME}" |
| 233 | |
| 234 | echo "Created universal simulator binary: ${SIMULATOR_UNIVERSAL_FRAMEWORK}/${FRAMEWORK_NAME}" |
| 235 | |
| 236 | cp -r "${IOS_SIMULATOR_ARM64_OUT}/${FRAMEWORK_NAME}.framework/Info.plist" "${SIMULATOR_UNIVERSAL_FRAMEWORK}/" |
| 237 | cp -r "${IOS_SIMULATOR_ARM64_OUT}/${FRAMEWORK_NAME}.framework/Headers" "${SIMULATOR_UNIVERSAL_FRAMEWORK}/" |
| 238 | |
| 239 | IOS_DEVICE_FRAMEWORK="${IOS_DEVICE_OUT}/${FRAMEWORK_NAME}.framework" |
| 240 | IOS_SIMULATOR_FRAMEWORK="${SIMULATOR_UNIVERSAL_FRAMEWORK}" |
| 241 | |
| 242 | IOS_XCFRAMEWORK="${IOS_OUTPUT_DIR}/${FRAMEWORK_NAME}.xcframework" |
| 243 | create_xcframework "$FRAMEWORK_NAME" "$IOS_XCFRAMEWORK" "$IOS_DEVICE_FRAMEWORK" "$IOS_SIMULATOR_FRAMEWORK" |
| 244 | |
| 245 | echo "" |
| 246 | echo "XCFramework created successfully:" |
| 247 | echo " iOS XCFramework: ${IOS_XCFRAMEWORK}" |
| 248 | echo "" |
| 249 | |
| 250 | FFIGEN_CONFIG="${BASE_DIR}/../../cw_mweb/ffigen_config.yaml" |
| 251 | if [[ -f "$FFIGEN_CONFIG" ]]; then |
| 252 | echo "Updating ffigen configuration..." |
| 253 | sed -i.bak "s|android/src/main/jniLibs/arm64-v8a/mweb.h|ios/${FRAMEWORK_NAME}.xcframework/ios-arm64/${FRAMEWORK_NAME}.framework/Headers/${FRAMEWORK_NAME}.h|g" "$FFIGEN_CONFIG" |
| 254 | mv "$FFIGEN_CONFIG.bak" "$FFIGEN_CONFIG" |
| 255 | echo "Updated ffigen config to use XCFramework header" |
| 256 | fi |
| 257 | |
| 258 | cd "${BASE_DIR}/../../cw_mweb" |
| 259 | echo "Generating Dart FFI bindings..." |
| 260 | dart run ffigen --config ffigen_config.yaml |
| 261 | |
| 262 | echo "Build completed successfully!" |
| 263 | |
| 264 | rm -rf "$TMP_DIR" |
| 265 | echo "Temporary files cleaned up." |