[jnigen] fix: pr_checks now works on macOS (https://github.com/dart-lang/jnigen/issues/108)

diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 6e252d8..a57feba 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -247,6 +247,55 @@
       - run: dart run jnigen:setup
       - run: dart test
 
+  test_jni_macos_minimal:
+    needs: [analyze_jni]
+    runs-on: macos-latest
+    defaults:
+      run:
+        working-directory: ./pkgs/jni
+    steps:
+      - uses: actions/checkout@v3
+      - uses: subosito/flutter-action@v2
+        with:
+          channel: 'stable'
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+      - uses: actions/setup-java@v2
+        with:
+          distribution: 'temurin'
+          java-version: '11'
+      - run: dart pub get
+      - run: dart run jni:setup
+      ## TODO(#51): -j 1 is required to avoid a rare race condition which is caused by
+      ## all tests which spawn JVM being run in same process.
+      - run: dart test -j 1
+
+  test_jnigen_macos_minimal:
+    needs: [analyze_jnigen]
+    runs-on: macos-latest
+    defaults:
+      run:
+        working-directory: ./pkgs/jnigen
+    steps:
+      - uses: actions/checkout@v3
+      - name: Setup clang format
+        uses: ConorMacBride/install-package@v1
+        with:
+          brew: clang-format
+      - uses: subosito/flutter-action@v2
+        with:
+          channel: 'stable'
+          cache: true
+          cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+      - uses: actions/setup-java@v2
+        with:
+          distribution: 'temurin'
+          java-version: '11'
+      - run: git config --global core.autocrlf true
+      - run: dart pub get
+      - run: dart run jnigen:setup
+      - run: dart test
+
   build_jni_example_linux:
     runs-on: ubuntu-latest
     defaults:
diff --git a/pkgs/jni/bin/setup.dart b/pkgs/jni/bin/setup.dart
index 23226c3..eb4f9c9 100644
--- a/pkgs/jni/bin/setup.dart
+++ b/pkgs/jni/bin/setup.dart
@@ -236,7 +236,12 @@
         Platform.isWindows ? tempDir.uri.resolve("Debug") : tempDir.uri;
     final dllDir = Directory.fromUri(dllDirUri);
     for (var entry in dllDir.listSync()) {
-      final dllSuffix = Platform.isWindows ? "dll" : "so";
+      verboseLog(entry.toString());
+      final dllSuffix = Platform.isWindows
+          ? "dll"
+          : Platform.isMacOS
+              ? "dylib"
+              : "so";
       if (entry.path.endsWith(dllSuffix)) {
         final dllName = entry.uri.pathSegments.last;
         final target = buildDir.uri.resolve(dllName);
diff --git a/pkgs/jni/example/macos/Flutter/Flutter-Debug.xcconfig b/pkgs/jni/example/macos/Flutter/Flutter-Debug.xcconfig
index c2efd0b..4b81f9b 100644
--- a/pkgs/jni/example/macos/Flutter/Flutter-Debug.xcconfig
+++ b/pkgs/jni/example/macos/Flutter/Flutter-Debug.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
 #include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/pkgs/jni/example/macos/Flutter/Flutter-Release.xcconfig b/pkgs/jni/example/macos/Flutter/Flutter-Release.xcconfig
index c2efd0b..5caa9d1 100644
--- a/pkgs/jni/example/macos/Flutter/Flutter-Release.xcconfig
+++ b/pkgs/jni/example/macos/Flutter/Flutter-Release.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
 #include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/pkgs/jni/example/macos/Podfile b/pkgs/jni/example/macos/Podfile
new file mode 100644
index 0000000..dade8df
--- /dev/null
+++ b/pkgs/jni/example/macos/Podfile
@@ -0,0 +1,40 @@
+platform :osx, '10.11'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+  'Debug' => :debug,
+  'Profile' => :release,
+  'Release' => :release,
+}
+
+def flutter_root
+  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
+  unless File.exist?(generated_xcode_build_settings_path)
+    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
+  end
+
+  File.foreach(generated_xcode_build_settings_path) do |line|
+    matches = line.match(/FLUTTER_ROOT\=(.*)/)
+    return matches[1].strip if matches
+  end
+  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_macos_podfile_setup
+
+target 'Runner' do
+  use_frameworks!
+  use_modular_headers!
+
+  flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
+end
+
+post_install do |installer|
+  installer.pods_project.targets.each do |target|
+    flutter_additional_macos_build_settings(target)
+  end
+end
diff --git a/pkgs/jni/example/pubspec.lock b/pkgs/jni/example/pubspec.lock
index 129041a..03efa2c 100644
--- a/pkgs/jni/example/pubspec.lock
+++ b/pkgs/jni/example/pubspec.lock
@@ -7,7 +7,7 @@
       name: archive
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.1.11"
+    version: "3.3.0"
   args:
     dependency: transitive
     description:
@@ -21,7 +21,7 @@
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.8.2"
+    version: "2.9.0"
   boolean_selector:
     dependency: transitive
     description:
@@ -35,21 +35,14 @@
       name: characters
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0"
-  charcode:
-    dependency: transitive
-    description:
-      name: charcode
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.3.1"
+    version: "1.2.1"
   clock:
     dependency: transitive
     description:
       name: clock
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0"
+    version: "1.1.1"
   collection:
     dependency: transitive
     description:
@@ -63,7 +56,7 @@
       name: crypto
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.0.1"
+    version: "3.0.2"
   cupertino_icons:
     dependency: "direct main"
     description:
@@ -77,7 +70,7 @@
       name: fake_async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0"
+    version: "1.3.1"
   ffi:
     dependency: "direct main"
     description:
@@ -144,21 +137,21 @@
       name: matcher
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.12.11"
+    version: "0.12.12"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.1.4"
+    version: "0.1.5"
   meta:
     dependency: transitive
     description:
       name: meta
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.7.0"
+    version: "1.8.0"
   package_config:
     dependency: transitive
     description:
@@ -172,7 +165,7 @@
       name: path
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.1"
+    version: "1.8.2"
   platform:
     dependency: transitive
     description:
@@ -205,7 +198,7 @@
       name: source_span
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.2"
+    version: "1.9.0"
   stack_trace:
     dependency: transitive
     description:
@@ -226,35 +219,35 @@
       name: string_scanner
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0"
+    version: "1.1.1"
   sync_http:
     dependency: transitive
     description:
       name: sync_http
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.3.0"
+    version: "0.3.1"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0"
+    version: "1.2.1"
   test_api:
     dependency: transitive
     description:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.4.9"
+    version: "0.4.12"
   typed_data:
     dependency: transitive
     description:
       name: typed_data
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0"
+    version: "1.3.1"
   vector_math:
     dependency: transitive
     description:
@@ -268,7 +261,7 @@
       name: vm_service
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "8.2.2"
+    version: "9.0.0"
   webdriver:
     dependency: transitive
     description:
diff --git a/pkgs/jni/ffigen.yaml b/pkgs/jni/ffigen.yaml
index 3833215..b022309 100644
--- a/pkgs/jni/ffigen.yaml
+++ b/pkgs/jni/ffigen.yaml
@@ -49,6 +49,7 @@
 typedefs:
   exclude:
     - 'va_list'
+    - '__builtin_va_list'
   rename:
     'JNI(.*)': 'Jni$1'
     'jint': 'JInt'
diff --git a/pkgs/jni/lib/src/jni.dart b/pkgs/jni/lib/src/jni.dart
index 36c5220..96ba918 100644
--- a/pkgs/jni/lib/src/jni.dart
+++ b/pkgs/jni/lib/src/jni.dart
@@ -20,7 +20,7 @@
   } else if (Platform.isWindows) {
     return "$base.dll";
   } else if (Platform.isMacOS) {
-    return "$base.framework/$base";
+    return "lib$base.dylib";
   } else {
     throw UnsupportedError("cannot derive library name: unsupported platform");
   }
diff --git a/pkgs/jnigen/.gitignore b/pkgs/jnigen/.gitignore
index c66a8b6..a63fd72 100644
--- a/pkgs/jnigen/.gitignore
+++ b/pkgs/jnigen/.gitignore
@@ -5,6 +5,8 @@
 .packages
 build/
 pubspec.lock
+.flutter-plugins
+.flutter-plugins-dependencies
 
 # created by maven
 /target/
diff --git a/pkgs/jnigen/tool/pre_commit_checks.dart b/pkgs/jnigen/tool/pr_checks.dart
similarity index 72%
rename from pkgs/jnigen/tool/pre_commit_checks.dart
rename to pkgs/jnigen/tool/pr_checks.dart
index 07eb0b6..0b8ad52 100644
--- a/pkgs/jnigen/tool/pre_commit_checks.dart
+++ b/pkgs/jnigen/tool/pr_checks.dart
@@ -16,26 +16,46 @@
 import 'dart:async';
 import 'dart:io';
 
+import 'package:args/args.dart';
+
 import 'command_runner.dart';
 
-void main() async {
+// Flags
+const _clone = 'clone';
+
+void main(List<String> arguments) async {
+  final parser = ArgParser()
+    ..addFlag(
+      _clone,
+      help: 'Run checks in a cloned copy of the project.',
+      defaultsTo: true,
+      negatable: true,
+    );
+  final argResults = parser.parse(arguments);
+  final shouldClone = argResults[_clone] as bool;
   final gitRoot = getRepositoryRoot();
 
   // change to project root
   Directory.current = gitRoot.toFilePath();
 
-  final tempDir = Directory.current.createTempSync('jnigen_checks_clone_');
-  final tempJniPath = tempDir.uri.resolve("jni/");
-  final tempJnigenPath = tempDir.uri.resolve("jnigen/");
-  final gitClone = Runner("Clone jni", Directory.current.uri)
-    ..chainCommand('git', ['clone', '.', tempDir.path])
-    ..chainCommand("flutter", ["pub", "get", "--offline"],
-        workingDirectory: tempJniPath)
-    ..chainCommand("dart", ["pub", "get", "--offline"],
-        workingDirectory: tempJnigenPath);
-  await gitClone.run();
+  var tempDir = Directory.current;
+  if (shouldClone) {
+    tempDir = Directory.current.createTempSync('jnigen_checks_clone_');
+    final gitClone = Runner("Clone jni", Directory.current.uri)
+      ..chainCommand('git', ['clone', '.', tempDir.path]);
+    await gitClone.run();
+  }
 
-  final jniAnalyze = Runner("Analyze JNI", tempJniPath);
+  final jniPath = tempDir.uri.resolve("jni/");
+  final jnigenPath = tempDir.uri.resolve("jnigen/");
+  final pubGet = Runner("Pub get", tempDir.uri)
+    ..chainCommand("flutter", ["pub", "get", "--offline"],
+        workingDirectory: jniPath)
+    ..chainCommand("dart", ["pub", "get", "--offline"],
+        workingDirectory: jnigenPath);
+  await pubGet.run();
+
+  final jniAnalyze = Runner("Analyze JNI", jniPath);
   jniAnalyze
     ..chainCommand("dart", ["analyze", "--fatal-infos"])
     ..chainCommand(
@@ -50,8 +70,8 @@
           "third_party/global_jni_env.c",
           "third_party/global_jni_env.h",
         ],
-        workingDirectory: tempJniPath.resolve("src/"));
-  final jniTest = Runner("Test JNI", tempJniPath)
+        workingDirectory: jniPath.resolve("src/"));
+  final jniTest = Runner("Test JNI", jniPath)
     ..chainCommand("dart", ["run", "jni:setup"])
     ..chainCommand("dart", ["test", "-j", "1"]);
   unawaited(jniAnalyze.run().then((f) => jniTest.run()));
@@ -60,19 +80,18 @@
       .resolve("jni/lib/src/third_party/jni_bindings_generated.dart");
   final ffigenBindings = File.fromUri(ffigenBindingsPath);
   final oldBindingsText = ffigenBindings.readAsStringSync();
-  final ffigenCompare =
-      Runner("Generate & Compare FFIGEN bindings", tempJniPath)
-        ..chainCommand("dart", ["run", "ffigen", "--config", "ffigen.yaml"])
-        ..chainCallback("compare bindings", () async {
-          final newBindingsText = await ffigenBindings.readAsString();
-          if (newBindingsText != oldBindingsText) {
-            await ffigenBindings.writeAsString(oldBindingsText);
-            throw "new JNI.h bindings differ from old bindings";
-          }
-        });
+  final ffigenCompare = Runner("Generate & Compare FFIGEN bindings", jniPath)
+    ..chainCommand("dart", ["run", "ffigen", "--config", "ffigen.yaml"])
+    ..chainCallback("compare bindings", () async {
+      final newBindingsText = await ffigenBindings.readAsString();
+      if (newBindingsText != oldBindingsText) {
+        await ffigenBindings.writeAsString(oldBindingsText);
+        throw "new JNI.h bindings differ from old bindings";
+      }
+    });
   unawaited(ffigenCompare.run());
 
-  final jnigenAnalyze = Runner("Analyze jnigen", tempJnigenPath)
+  final jnigenAnalyze = Runner("Analyze jnigen", jnigenPath)
     ..chainCommand("dart", ["analyze", "--fatal-infos"])
     ..chainCommand(
         "dart", ["format", "--output=none", "--set-exit-if-changed", "."])
@@ -136,6 +155,8 @@
     final notificationPlugin = compareNotificationPluginBindings.run();
     return Future.wait([test, inAppJava, pdfBox, notificationPlugin]);
   }).then((_) {
-    tempDir.deleteSync(recursive: true);
+    if (shouldClone) {
+      tempDir.deleteSync(recursive: true);
+    }
   }));
 }