diff --git a/.github/actions/build-ios/action.yml b/.github/actions/build-ios/action.yml new file mode 100644 index 0000000..19d5c09 --- /dev/null +++ b/.github/actions/build-ios/action.yml @@ -0,0 +1,169 @@ +name: Build libgit2 iOS slice +description: Build libgit2, libssh2, and OpenSSL for one iOS SDK/architecture slice +inputs: + libgit2_version: + description: Version of libgit2 to build + required: true + libssh2_version: + description: Version of libssh2 to build + required: true + openssl_version: + description: Version of OpenSSL to build + required: true + ios_sdk: + description: iOS SDK to build for, e.g. iphoneos or iphonesimulator + required: true + architecture: + description: Architecture to build, e.g. arm64 or x86_64 + required: true + openssl_target: + description: OpenSSL Configure target, e.g. ios64-xcrun or iossimulator-xcrun + required: true + artifact_name: + description: GitHub Actions artifact name for this slice + required: true + ios_deployment_target: + description: Minimum iOS deployment target + required: false + default: "12.0" +runs: + using: composite + steps: + - name: Checkout OpenSSL + uses: actions/checkout@v4 + with: + repository: openssl/openssl + ref: refs/tags/openssl-${{ inputs.openssl_version }} + path: ./openssl + + - name: Checkout libssh2 + uses: actions/checkout@v4 + with: + repository: libssh2/libssh2 + ref: refs/tags/libssh2-${{ inputs.libssh2_version }} + path: ./libssh2 + + - name: Checkout libgit2 + uses: actions/checkout@v4 + with: + repository: libgit2/libgit2 + ref: refs/tags/v${{ inputs.libgit2_version }} + path: ./libgit2 + + - name: Build iOS slice + shell: bash + env: + IOS_DEPLOYMENT_TARGET: ${{ inputs.ios_deployment_target }} + IOS_SDK: ${{ inputs.ios_sdk }} + IOS_ARCH: ${{ inputs.architecture }} + OPENSSL_TARGET: ${{ inputs.openssl_target }} + run: | + set -euo pipefail + + slice="$IOS_SDK-$IOS_ARCH" + build_root="/tmp/git2dart-ios-$slice" + output_dir="$build_root/export/$slice" + openssl_install="$build_root/openssl" + libssh2_install="$build_root/libssh2" + libgit2_install="$build_root/libgit2" + sysroot="$(xcrun --sdk "$IOS_SDK" --show-sdk-path)" + + if [ "$IOS_SDK" = "iphoneos" ]; then + min_version_flag="-miphoneos-version-min=$IOS_DEPLOYMENT_TARGET" + else + min_version_flag="-mios-simulator-version-min=$IOS_DEPLOYMENT_TARGET" + fi + + rm -rf "$build_root" + mkdir -p "$output_dir" + + cp -R ./openssl "$build_root/openssl-src" + pushd "$build_root/openssl-src" + CFLAGS="-arch $IOS_ARCH $min_version_flag" \ + LDFLAGS="-arch $IOS_ARCH $min_version_flag" \ + ./Configure "$OPENSSL_TARGET" \ + -static \ + no-shared \ + no-tests \ + --prefix="$openssl_install" + make clean || true + make -j"$(sysctl -n hw.ncpu)" build_libs + make install_dev + popd + + cmake -S ./libssh2 -B "$build_root/libssh2-bld" \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_TESTING=OFF \ + -DBUILD_TESTS=OFF \ + -DCRYPTO_BACKEND=OpenSSL \ + -DOPENSSL_ROOT_DIR="$openssl_install" \ + -DOPENSSL_INCLUDE_DIR="$openssl_install/include" \ + -DOPENSSL_SSL_LIBRARY="$openssl_install/lib/libssl.a" \ + -DOPENSSL_CRYPTO_LIBRARY="$openssl_install/lib/libcrypto.a" \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_SYSROOT="$sysroot" \ + -DCMAKE_OSX_ARCHITECTURES="$IOS_ARCH" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET="$IOS_DEPLOYMENT_TARGET" \ + -DCMAKE_INSTALL_PREFIX="$libssh2_install" + cmake --build "$build_root/libssh2-bld" --target install -- -j"$(sysctl -n hw.ncpu)" + + libssh2_pc="$libssh2_install/lib/pkgconfig/libssh2.pc" + if [ -f "$libssh2_pc" ]; then + zlib_path="$sysroot/usr/lib/libz.tbd" + if [ ! -f "$zlib_path" ]; then + zlib_path="$sysroot/usr/lib/libz.dylib" + fi + sed -i.bak \ + -e "s|-lssh2|$libssh2_install/lib/libssh2.a|g" \ + -e "s|-lssl|$openssl_install/lib/libssl.a|g" \ + -e "s|-lcrypto|$openssl_install/lib/libcrypto.a|g" \ + -e "s|-lz|$zlib_path|g" \ + "$libssh2_pc" + fi + + PKG_CONFIG_PATH="$libssh2_install/lib/pkgconfig" \ + cmake -S ./libgit2 -B "$build_root/libgit2-bld" \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTS=OFF \ + -DUSE_SSH=libssh2 \ + -DUSE_HTTPS=OpenSSL \ + -DEXPERIMENTAL_SHA256=ON \ + -DLIBSSH2_INCLUDE_DIR="$libssh2_install/include" \ + -DLIBSSH2_LIBRARY="$libssh2_install/lib/libssh2.a" \ + -DOPENSSL_ROOT_DIR="$openssl_install" \ + -DOPENSSL_INCLUDE_DIR="$openssl_install/include" \ + -DOPENSSL_SSL_LIBRARY="$openssl_install/lib/libssl.a" \ + -DOPENSSL_CRYPTO_LIBRARY="$openssl_install/lib/libcrypto.a" \ + -DCMAKE_LIBRARY_PATH="$libssh2_install/lib;$openssl_install/lib" \ + -DCMAKE_FIND_ROOT_PATH="$libssh2_install;$openssl_install;$sysroot" \ + -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH \ + -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_SYSROOT="$sysroot" \ + -DCMAKE_OSX_ARCHITECTURES="$IOS_ARCH" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET="$IOS_DEPLOYMENT_TARGET" \ + -DCMAKE_INSTALL_PREFIX="$libgit2_install" + cmake --build "$build_root/libgit2-bld" --target install -- -j"$(sysctl -n hw.ncpu)" + + libgit2_archive="$(find "$libgit2_install/lib" -maxdepth 1 -name 'libgit2*.a' | head -n 1)" + test -n "$libgit2_archive" + + mkdir -p "$output_dir/openssl/lib" "$output_dir/openssl/include" + mkdir -p "$output_dir/libssh2/lib" "$output_dir/libssh2/include" + mkdir -p "$output_dir/libgit2/lib" "$output_dir/libgit2/include" + + cp "$openssl_install/lib/libcrypto.a" "$output_dir/openssl/lib/" + cp "$openssl_install/lib/libssl.a" "$output_dir/openssl/lib/" + cp "$libssh2_install/lib/libssh2.a" "$output_dir/libssh2/lib/" + cp "$libgit2_archive" "$output_dir/libgit2/lib/libgit2.a" + + cp -R "$openssl_install/include/." "$output_dir/openssl/include/" + cp -R "$libssh2_install/include/." "$output_dir/libssh2/include/" + cp -R "$libgit2_install/include/." "$output_dir/libgit2/include/" + + - name: Upload iOS slice + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.artifact_name }} + path: /tmp/git2dart-ios-${{ inputs.ios_sdk }}-${{ inputs.architecture }}/export/** diff --git a/.github/actions/build-macos/action.yml b/.github/actions/build-macos/action.yml index 558ef42..ab1ab7a 100644 --- a/.github/actions/build-macos/action.yml +++ b/.github/actions/build-macos/action.yml @@ -65,12 +65,11 @@ runs: shell: bash run: | mkdir -p export - # Export under the file name that matches the dylib's own - # install_name (@rpath/libgit2-experimental.1.9.dylib). The - # podspec vendors that exact name and util.dart opens it, so the - # built artifact MUST carry it too — otherwise dyld can't resolve - # the library at runtime (and `flutter test` fails to dlopen it). - cp /tmp/libgit2/install/lib/libgit2-experimental.dylib export/libgit2-experimental.1.9.dylib + # Export under a stable file name and make the dylib's own install_name + # match it. The libgit2 version itself is controlled by LIBGIT2_VERSION + # in the workflow, not by platform file names. + cp /tmp/libgit2/install/lib/libgit2-experimental.dylib export/libgit2.dylib + install_name_tool -id @rpath/libgit2.dylib export/libgit2.dylib cp /tmp/libssh2/install/lib/libssh2.dylib export/libssh2.1.dylib - name: Cache git2 library diff --git a/.github/workflows/build_package.yml b/.github/workflows/build_package.yml index 0a271ac..df79e08 100644 --- a/.github/workflows/build_package.yml +++ b/.github/workflows/build_package.yml @@ -11,7 +11,7 @@ on: - "main" env: PUB_ENVIRONMENT: bot.github - LIBGIT2_VERSION: "1.9.1" + LIBGIT2_VERSION: "1.9.4" LIBSSH2_VERSION: "1.11.1" OPENSSL_VERSION: "3.0.15" @@ -52,6 +52,83 @@ jobs: libgit2_version: ${{ env.LIBGIT2_VERSION }} libssh2_version: ${{ env.LIBSSH2_VERSION }} + build_libgit2_ios: + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + include: + - slice: iphoneos-arm64 + sdk: iphoneos + arch: arm64 + openssl_target: ios64-xcrun + - slice: iphonesimulator-arm64 + sdk: iphonesimulator + arch: arm64 + openssl_target: iossimulator-xcrun + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Build iOS slice + uses: ./.github/actions/build-ios + with: + libgit2_version: ${{ env.LIBGIT2_VERSION }} + libssh2_version: ${{ env.LIBSSH2_VERSION }} + openssl_version: ${{ env.OPENSSL_VERSION }} + ios_sdk: ${{ matrix.sdk }} + architecture: ${{ matrix.arch }} + openssl_target: ${{ matrix.openssl_target }} + artifact_name: cache-ios-${{ matrix.slice }} + + assemble_libgit2_ios: + needs: [build_libgit2_ios] + runs-on: macos-latest + steps: + - name: Download iOS slices + uses: actions/download-artifact@v4 + with: + pattern: cache-ios-* + path: /tmp/git2dart-ios/slices + merge-multiple: true + + - name: Assemble iOS XCFrameworks + shell: bash + run: | + set -euo pipefail + + slices_dir="/tmp/git2dart-ios/slices" + output_dir="/tmp/git2dart-ios/export" + simulator_dir="$slices_dir/iphonesimulator-arm64" + + mkdir -p "$output_dir" + + xcodebuild -create-xcframework \ + -library "$slices_dir/iphoneos-arm64/openssl/lib/libcrypto.a" -headers "$slices_dir/iphoneos-arm64/openssl/include" \ + -library "$simulator_dir/openssl/lib/libcrypto.a" -headers "$simulator_dir/openssl/include" \ + -output "$output_dir/libcrypto.xcframework" + + xcodebuild -create-xcframework \ + -library "$slices_dir/iphoneos-arm64/openssl/lib/libssl.a" -headers "$slices_dir/iphoneos-arm64/openssl/include" \ + -library "$simulator_dir/openssl/lib/libssl.a" -headers "$simulator_dir/openssl/include" \ + -output "$output_dir/libssl.xcframework" + + xcodebuild -create-xcframework \ + -library "$slices_dir/iphoneos-arm64/libssh2/lib/libssh2.a" -headers "$slices_dir/iphoneos-arm64/libssh2/include" \ + -library "$simulator_dir/libssh2/lib/libssh2.a" -headers "$simulator_dir/libssh2/include" \ + -output "$output_dir/libssh2.xcframework" + + xcodebuild -create-xcframework \ + -library "$slices_dir/iphoneos-arm64/libgit2/lib/libgit2.a" -headers "$slices_dir/iphoneos-arm64/libgit2/include" \ + -library "$simulator_dir/libgit2/lib/libgit2.a" -headers "$simulator_dir/libgit2/include" \ + -output "$output_dir/libgit2.xcframework" + + - name: Upload iOS XCFrameworks + uses: actions/upload-artifact@v4 + with: + name: cache-ios + path: /tmp/git2dart-ios/export/** + build_libgit2_windows: runs-on: windows-latest steps: @@ -68,11 +145,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - os: [arm64-v8a, x86_64] + os: [armeabi-v7a, arm64-v8a, x86, x86_64] steps: - name: Check out repository uses: actions/checkout@v4 - + - name: Build Android artifacts uses: ./.github/actions/build-android with: @@ -82,7 +159,7 @@ jobs: openssl_version: ${{ env.OPENSSL_VERSION }} run_tests: - needs: [generate_bindings, build_libgit2_linux, build_libgit2_macos, build_libgit2_windows, build_libgit2_android] + needs: [generate_bindings, build_libgit2_linux, build_libgit2_macos, assemble_libgit2_ios, build_libgit2_windows, build_libgit2_android] # needs: [generate_bindings, build_libgit2_android] runs-on: ${{ matrix.os }} strategy: @@ -108,14 +185,14 @@ jobs: if: ${{ runner.os == 'Linux' }} run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update -o Acquire::Retries=3 && sudo DEBIAN_FRONTEND=noninteractive apt-get install -o Acquire::Retries=3 -y --no-install-recommends openssl - + - name: download macos deps uses: actions/download-artifact@v4 if: ${{ runner.os == 'macOS' }} with: path: ./macos name: cache-macos - + - name: Install windows dependencies if: ${{ runner.os == 'Windows' }} run: | @@ -127,15 +204,196 @@ jobs: with: path: ./windows name: cache-windows - + - name: Run ffigen uses: subosito/flutter-action@v2 - run: flutter pub get - run: flutter test -r expanded + run_ios_tests: + needs: [generate_bindings, assemble_libgit2_ios] + runs-on: macos-latest + timeout-minutes: 25 + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: download bindings + uses: actions/download-artifact@v4 + with: + path: ./lib/src/ + name: cache-bindings + + - name: download ios binaries + uses: actions/download-artifact@v4 + with: + path: ./ios + name: cache-ios + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + + - name: Prepare integration test app + shell: bash + run: | + set -euo pipefail + + test_app="$RUNNER_TEMP/git2dart_mobile_test" + flutter create --platforms=ios --org com.dartgit "$test_app" + + TEST_APP="$test_app" ruby <<'RUBY' + require 'yaml' + + pubspec_path = File.join(ENV.fetch('TEST_APP'), 'pubspec.yaml') + pubspec = YAML.load_file(pubspec_path) + pubspec['dependencies'] ||= {} + pubspec['dependencies']['git2dart_binaries'] = { + 'path' => ENV.fetch('GITHUB_WORKSPACE') + } + pubspec['dev_dependencies'] ||= {} + pubspec['dev_dependencies']['flutter_test'] = {'sdk' => 'flutter'} + pubspec['dev_dependencies']['integration_test'] = {'sdk' => 'flutter'} + File.write(pubspec_path, pubspec.to_yaml) + RUBY + + mkdir -p "$test_app/test" "$test_app/integration_test" "$test_app/test_driver" + cp "$GITHUB_WORKSPACE/test/opts_bindings_integration_test.dart" "$test_app/test/" + cp "$GITHUB_WORKSPACE/integration_test/"*.dart "$test_app/integration_test/" + cp "$GITHUB_WORKSPACE/test_driver/integration_test.dart" "$test_app/test_driver/" + + cd "$test_app" + flutter pub get + + - name: Run iOS integration tests + timeout-minutes: 15 + shell: bash + run: | + set -euo pipefail + + test_app="$RUNNER_TEMP/git2dart_mobile_test" + device_id="$(xcrun simctl list devices available | awk -F '[()]' '/iPhone/ && $2 ~ /[0-9A-F-]{36}/ { print $2; exit }')" + + if [ -z "$device_id" ]; then + echo "::error::No available iPhone simulator found" + xcrun simctl list devices available + exit 1 + fi + + xcrun simctl boot "$device_id" || true + xcrun simctl bootstatus "$device_id" -b + + cd "$test_app" + flutter devices + + run_with_timeout() { + local seconds="$1" + shift + ruby -e ' + require "timeout" + + seconds = Integer(ARGV.shift) + command = ARGV + begin + Timeout.timeout(seconds) do + system(*command) + exit($?.exitstatus || 1) + end + rescue Timeout::Error + warn "::error::Timed out after #{seconds}s: #{command.join(" ")}" + exit 124 + end + ' "$seconds" "$@" + } + + run_with_timeout 900 flutter drive \ + -d "$device_id" \ + --driver=test_driver/integration_test.dart \ + --target=integration_test/opts_bindings_integration_test.dart + + run_android_tests: + needs: [generate_bindings, build_libgit2_android] + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: download bindings + uses: actions/download-artifact@v4 + with: + path: ./lib/src/ + name: cache-bindings + + - name: download android binaries x86_64 + uses: actions/download-artifact@v4 + with: + path: ./android/src/main/jniLibs/x86_64 + name: cache-android-x86_64 + + - name: download android binaries arm64-v8a + uses: actions/download-artifact@v4 + with: + path: ./android/src/main/jniLibs/arm64-v8a + name: cache-android-arm64-v8a + + - name: download android binaries x86 + uses: actions/download-artifact@v4 + with: + path: ./android/src/main/jniLibs/x86 + name: cache-android-x86 + + - name: download android binaries armeabi-v7a + uses: actions/download-artifact@v4 + with: + path: ./android/src/main/jniLibs/armeabi-v7a + name: cache-android-armeabi-v7a + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + + - name: Prepare integration test app + shell: bash + run: | + set -euo pipefail + + test_app="$RUNNER_TEMP/git2dart_mobile_test" + flutter create --platforms=android --org com.dartgit "$test_app" + + TEST_APP="$test_app" ruby <<'RUBY' + require 'yaml' + + pubspec_path = File.join(ENV.fetch('TEST_APP'), 'pubspec.yaml') + pubspec = YAML.load_file(pubspec_path) + pubspec['dependencies'] ||= {} + pubspec['dependencies']['git2dart_binaries'] = { + 'path' => ENV.fetch('GITHUB_WORKSPACE') + } + pubspec['dev_dependencies'] ||= {} + pubspec['dev_dependencies']['flutter_test'] = {'sdk' => 'flutter'} + pubspec['dev_dependencies']['integration_test'] = {'sdk' => 'flutter'} + File.write(pubspec_path, pubspec.to_yaml) + RUBY + + mkdir -p "$test_app/test" "$test_app/integration_test" + cp "$GITHUB_WORKSPACE/test/opts_bindings_integration_test.dart" "$test_app/test/" + cp "$GITHUB_WORKSPACE/integration_test/opts_bindings_integration_test.dart" "$test_app/integration_test/" + + cd "$test_app" + flutter pub get + + - name: Run Android integration tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 29 + arch: x86_64 + target: default + disable-animations: true + emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none + script: | + cd "$RUNNER_TEMP/git2dart_mobile_test" && flutter devices + cd "$RUNNER_TEMP/git2dart_mobile_test" && flutter test integration_test/opts_bindings_integration_test.dart -d emulator-5554 -r expanded + publish_package: - if: ${{ github.actor != 'nektos/act' }} - needs: [run_tests] + needs: [run_tests, run_ios_tests, run_android_tests] runs-on: ubuntu-latest steps: - name: Check out repository @@ -145,13 +403,19 @@ jobs: with: path: ./lib/src/ name: cache-bindings - + - name: download macos binaries uses: actions/download-artifact@v4 with: path: ./macos name: cache-macos + - name: download ios binaries + uses: actions/download-artifact@v4 + with: + path: ./ios + name: cache-ios + - name: download windows binaries uses: actions/download-artifact@v4 with: @@ -176,6 +440,18 @@ jobs: path: ./android/src/main/jniLibs/arm64-v8a name: cache-android-arm64-v8a + - name: download android binaries x86 + uses: actions/download-artifact@v4 + with: + path: ./android/src/main/jniLibs/x86 + name: cache-android-x86 + + - name: download android binaries armeabi-v7a + uses: actions/download-artifact@v4 + with: + path: ./android/src/main/jniLibs/armeabi-v7a + name: cache-android-armeabi-v7a + - name: Zip package into cache if: ${{ github.event_name == 'pull_request' }} uses: actions/upload-artifact@v4 diff --git a/.metadata b/.metadata index eec111a..e7a7e12 100644 --- a/.metadata +++ b/.metadata @@ -15,6 +15,9 @@ migration: - platform: root create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72 base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72 + - platform: ios + create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72 + base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72 - platform: linux create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72 base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72 diff --git a/CHANGELOG.md b/CHANGELOG.md index d9439c7..93491b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [1.11.0] - 2026-05-30 +### Added +- Added iOS package support with generated XCFramework artifacts and CI integration tests. +- Added Android build coverage for `armeabi-v7a`, `arm64-v8a`, `x86`, and `x86_64`. + +### Changed +- Updated bundled libgit2 builds to `1.9.4`. +- Re-enabled the full platform build workflow across Linux, macOS, Windows, iOS, and Android. + ## [1.10.4] - 2026-05-29 ### Fixed - macOS: vendored `libgit2.dylib` filename didn't match its diff --git a/integration_test/opts_bindings_integration_test.dart b/integration_test/opts_bindings_integration_test.dart new file mode 100644 index 0000000..616304e --- /dev/null +++ b/integration_test/opts_bindings_integration_test.dart @@ -0,0 +1,8 @@ +import 'package:integration_test/integration_test.dart'; + +import '../test/opts_bindings_integration_test.dart' as opts_bindings; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + opts_bindings.main(); +} diff --git a/ios/Classes/Git2dartBinariesPlugin.swift b/ios/Classes/Git2dartBinariesPlugin.swift new file mode 100644 index 0000000..d9cd02f --- /dev/null +++ b/ios/Classes/Git2dartBinariesPlugin.swift @@ -0,0 +1,19 @@ +import Flutter +import UIKit + +public class Git2dartBinariesPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "git2dart_binaries", binaryMessenger: registrar.messenger()) + let instance = Git2dartBinariesPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getPlatformVersion": + result("iOS " + UIDevice.current.systemVersion) + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/ios/git2dart_binaries.podspec b/ios/git2dart_binaries.podspec new file mode 100644 index 0000000..3177b4f --- /dev/null +++ b/ios/git2dart_binaries.podspec @@ -0,0 +1,51 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# +Pod::Spec.new do |s| + s.name = 'git2dart_binaries' + s.version = '1.11.0' + s.summary = 'Dart bindings to libgit2.' + s.description = <<-DESC +Dart bindings to libgit2. + DESC + s.homepage = 'https://github.com/DartGit-dev/git2dart_binaries' + s.license = { :file => '../LICENSE' } + s.author = { 'Viktor Borisov' => 'vik.borisoff@gmail.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.static_framework = true + s.vendored_frameworks = [ + 'libcrypto.xcframework', + 'libssl.xcframework', + 'libssh2.xcframework', + 'libgit2.xcframework' + ] + s.libraries = ['z', 'iconv'] + + s.platform = :ios, '12.0' + binary_root = '$(PODS_ROOT)/../.symlinks/plugins/git2dart_binaries/ios' + device_library_search_paths = [ + '$(inherited)', + "#{binary_root}/libcrypto.xcframework/ios-arm64", + "#{binary_root}/libssl.xcframework/ios-arm64", + "#{binary_root}/libssh2.xcframework/ios-arm64", + "#{binary_root}/libgit2.xcframework/ios-arm64" + ].map { |path| "\"#{path}\"" }.join(' ') + simulator_library_search_paths = [ + '$(inherited)', + "#{binary_root}/libcrypto.xcframework/ios-arm64-simulator", + "#{binary_root}/libssl.xcframework/ios-arm64-simulator", + "#{binary_root}/libssh2.xcframework/ios-arm64-simulator", + "#{binary_root}/libgit2.xcframework/ios-arm64-simulator" + ].map { |path| "\"#{path}\"" }.join(' ') + binary_xcconfig = { + 'LIBRARY_SEARCH_PATHS[sdk=iphoneos*]' => device_library_search_paths, + 'LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]' => simulator_library_search_paths, + 'OTHER_LDFLAGS[sdk=iphoneos*]' => '$(inherited) -force_load "$(PODS_ROOT)/../.symlinks/plugins/git2dart_binaries/ios/libgit2.xcframework/ios-arm64/libgit2.a"', + 'OTHER_LDFLAGS[sdk=iphonesimulator*]' => '$(inherited) -force_load "$(PODS_ROOT)/../.symlinks/plugins/git2dart_binaries/ios/libgit2.xcframework/ios-arm64-simulator/libgit2.a"' + } + s.pod_target_xcconfig = binary_xcconfig.merge({ 'DEFINES_MODULE' => 'YES' }) + s.user_target_xcconfig = binary_xcconfig + s.swift_version = '5.0' +end diff --git a/lib/src/util.dart b/lib/src/util.dart index 3935f6e..97e789e 100644 --- a/lib/src/util.dart +++ b/lib/src/util.dart @@ -17,11 +17,11 @@ String? _cachedPackageRoot; return (name: 'libgit2.dll', subDir: 'windows'); } else if (Platform.isMacOS) { // Must match the filename the podspec vendors AND the dylib's own - // install_name (`@rpath/libgit2-experimental.1.9.dylib`). The + // install_name (`@rpath/libgit2.dylib`). The // package_config fallback in _loadLibrary doesn't work inside // compiled Flutter apps (no package_config.json at runtime), so the // first DynamicLibrary.open MUST succeed with this exact name. - return (name: 'libgit2-experimental.1.9.dylib', subDir: 'macos'); + return (name: 'libgit2.dylib', subDir: 'macos'); } else if (Platform.isLinux) { return (name: 'libgit2.so', subDir: 'linux'); } else if (Platform.isAndroid) { @@ -31,6 +31,10 @@ String? _cachedPackageRoot; } DynamicLibrary _loadLibrary() { + if (Platform.isIOS) { + return DynamicLibrary.process(); + } + final target = _platformTarget(); try { diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 69fbeb4..293d5b4 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -42,6 +42,6 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) # This list could contain prebuilt libraries, or libraries created by an # external build triggered from this build file. set(git2dart_binaries_bundled_libraries - "${CMAKE_CURRENT_SOURCE_DIR}/libgit2-1.6.2.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libgit2.so" PARENT_SCOPE ) diff --git a/macos/git2dart_binaries.podspec b/macos/git2dart_binaries.podspec index 3009a67..a29cd69 100644 --- a/macos/git2dart_binaries.podspec +++ b/macos/git2dart_binaries.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'git2dart_binaries' - s.version = '1.9.0' + s.version = '1.11.0' s.summary = 'Dart bindings to libgit2.' s.description = <<-DESC Dart bindings to libgit2. @@ -15,12 +15,12 @@ Dart bindings to libgit2. s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'FlutterMacOS' - # The libgit2 dylib's install_name is @rpath/libgit2-experimental.1.9.dylib, + # The libgit2 dylib's install_name is @rpath/libgit2.dylib, # so the file must be vendored under that exact name or dyld can't find # it inside the .app bundle at runtime. libssh2.1.dylib is a transitive # dependency of libgit2 and must also be declared here so CocoaPods # embeds it into the bundle's Frameworks directory. - s.vendored_libraries = ['libgit2-experimental.1.9.dylib', 'libssh2.1.dylib'] + s.vendored_libraries = ['libgit2.dylib', 'libssh2.1.dylib'] s.platform = :osx, '10.11' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } diff --git a/pubspec.yaml b/pubspec.yaml index a9d936c..201f113 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: git2dart_binaries description: Dart bindings to libgit2, provides ability to use libgit2 library in Dart and Flutter. -version: 1.10.4 +version: 1.11.0 repository: https://github.com/DartGit-dev/git2dart_binaries environment: @@ -18,6 +18,10 @@ dependencies: dev_dependencies: ffigen: ^18.1.0 + flutter_test: + sdk: flutter + integration_test: + sdk: flutter lints: ^5.1.1 test: ^1.26.2 @@ -41,6 +45,9 @@ flutter: android: pluginClass: Git2dartBinariesPlugin ffiPlugin: true + ios: + pluginClass: Git2dartBinariesPlugin + ffiPlugin: true linux: pluginClass: Git2dartBinariesPlugin ffiPlugin: true diff --git a/test/opts_bindings_integration_test.dart b/test/opts_bindings_integration_test.dart index 34add34..a142563 100644 --- a/test/opts_bindings_integration_test.dart +++ b/test/opts_bindings_integration_test.dart @@ -1,12 +1,16 @@ import 'dart:ffi' as ffi; import 'package:ffi/ffi.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:git2dart_binaries/src/bindings.dart'; import 'package:git2dart_binaries/src/extensions.dart'; import 'package:git2dart_binaries/src/util.dart'; -import 'package:test/test.dart'; void main() { + tearDownAll(() { + libgit2.git_libgit2_shutdown(); + }); + group('Memory Window Integration Tests', () { test('get and set mwindow size', () { final size = calloc(); @@ -191,9 +195,7 @@ void main() { expect(libgit2Opts.git_libgit2_opts_get_search_path(2, buf), equals(0)); // Cleanup - if (buf.ref.ptr != ffi.nullptr) { - calloc.free(buf.ref.ptr); - } + libgit2.git_buf_dispose(buf); calloc.free(buf); calloc.free(testPath); }); @@ -214,9 +216,7 @@ void main() { ); // Set new user agent - final newAgent = calloc(); - final agentStr = 'git2dart-test/1.0'; - newAgent.value = agentStr.codeUnitAt(0); + final newAgent = 'git2dart-test/1.0'.toNativeUtf8().cast(); expect( libgit2Opts.git_libgit2_opts_set_user_agent(newAgent), @@ -232,9 +232,7 @@ void main() { ); // Cleanup - if (buf.ref.ptr != ffi.nullptr) { - calloc.free(buf.ref.ptr); - } + libgit2.git_buf_dispose(buf); calloc.free(buf); calloc.free(newAgent); }); @@ -335,15 +333,7 @@ void main() { ); // Cleanup - if (extensions.ref.strings != ffi.nullptr) { - for (var i = 0; i < extensions.ref.count; i++) { - final strPtr = extensions.ref.strings + i; - if (strPtr.value != ffi.nullptr) { - calloc.free(strPtr.value); - } - } - calloc.free(extensions.ref.strings); - } + libgit2.git_strarray_dispose(extensions); calloc.free(extensions); }); }); diff --git a/test_driver/integration_test.dart b/test_driver/integration_test.dart new file mode 100644 index 0000000..b38629c --- /dev/null +++ b/test_driver/integration_test.dart @@ -0,0 +1,3 @@ +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 02f0447..b803711 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -49,7 +49,7 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) # external build triggered from this build file. set(git2dart_binaries_bundled_libraries "${CMAKE_CURRENT_SOURCE_DIR}/libcrypto-1_1-x64.dll" - "${CMAKE_CURRENT_SOURCE_DIR}/libgit2-1.6.2.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/libgit2.dll" "${CMAKE_CURRENT_SOURCE_DIR}/libssh2.dll" PARENT_SCOPE )