Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/build-windows/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ runs:
cmake --build build --parallel --target install
mkdir -p D:/export
copy D:/libssh2/install/bin/libssh2.dll D:/export/libssh2.dll
Get-ChildItem "$env:OPENSSL_ROOT_DIR/bin/libcrypto*.dll", "$env:OPENSSL_ROOT_DIR/bin/libssl*.dll" -File | Copy-Item -Destination D:/export

- name: Checkout libgit2
uses: actions/checkout@v6
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## [1.11.4] - 2026-06-29
### Fixed
- Windows: bundle OpenSSL runtime DLLs with the generated artifact and load
them before `libssh2.dll`, so plain Dart and Flutter tests no longer depend
on OpenSSL being available on `PATH`.

## [1.11.2] - 2026-06-04
### Fixed
- macOS: build the release `libgit2.dylib` with libssh2 and OpenSSL linked
Expand Down
30 changes: 29 additions & 1 deletion lib/src/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ void _loadPlatformDependencies(String packageRoot) {
} else if (Platform.isMacOS) {
// macOS release artifacts link libssh2/OpenSSL statically into libgit2.
} else if (Platform.isWindows) {
DynamicLibrary.open(p.join(packageRoot, 'windows', 'libssh2.dll'));
_loadWindowsDependencies(packageRoot);
}
} catch (e) {
stderr.writeln(
Expand All @@ -92,6 +92,34 @@ void _loadPlatformDependencies(String packageRoot) {
}
}

void _loadWindowsDependencies(String packageRoot) {
final windowsDir = Directory(p.join(packageRoot, 'windows'));
if (!windowsDir.existsSync()) {
DynamicLibrary.open(p.join(windowsDir.path, 'libssh2.dll'));
return;
}

for (final prefix in ['libcrypto', 'libssl']) {
final libraries =
windowsDir
.listSync()
.whereType<File>()
.where(
(file) =>
p.basename(file.path).toLowerCase().startsWith(prefix) &&
p.extension(file.path).toLowerCase() == '.dll',
)
.toList()
..sort((a, b) => a.path.compareTo(b.path));

for (final library in libraries) {
DynamicLibrary.open(library.path);
}
}

DynamicLibrary.open(p.join(windowsDir.path, 'libssh2.dll'));
}

String _resolvePackageRoot() {
final packageUri = _tryResolvePackageUri();
if (packageUri != null) {
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: git2dart_binaries
description: Dart bindings to libgit2, provides ability to use libgit2 library in Dart and Flutter.
version: 1.11.2
version: 1.11.4
repository: https://github.com/DartGit-dev/git2dart_binaries

environment:
Expand Down
99 changes: 99 additions & 0 deletions test/windows_packaging_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import 'dart:io';

import 'package:flutter_test/flutter_test.dart';
import 'package:path/path.dart' as p;

void main() {
group('Windows packaging', () {
test('exports OpenSSL runtime libraries with Windows artifacts', () {
final action =
File(
p.join('.github', 'actions', 'build-windows', 'action.yml'),
).readAsStringSync();

expect(action, contains('libcrypto*.dll'));
expect(action, contains('libssl*.dll'));
expect(action, contains('Copy-Item -Destination D:/export'));
});

test('bundles versioned OpenSSL runtime libraries in Flutter apps', () {
final cmake =
File(p.join('windows', 'CMakeLists.txt')).readAsStringSync();

expect(cmake, contains('file(GLOB git2dart_binaries_openssl_libraries'));
expect(cmake, contains('libcrypto*.dll'));
expect(cmake, contains('libssl*.dll'));
expect(cmake, isNot(contains('libcrypto-1_1-x64.dll')));
});

test(
'package-root loader works in a plain Dart process',
() async {
final packageConfig = File('.dart_tool/package_config.json').absolute;
expect(await packageConfig.exists(), isTrue);

final tempDir = await Directory.systemTemp.createTemp(
'git2dart_binaries_windows_loader_',
);
try {
final script = File('${tempDir.path}/load_git2dart_binaries.dart');
await script.writeAsString(r'''
import 'dart:io';

import 'package:git2dart_binaries/src/util.dart' as git2;

void main() {
final initCount = git2.libgit2.git_libgit2_init();
if (initCount < 1) {
stderr.writeln('git_libgit2_init returned $initCount');
exit(1);
}

git2.libgit2.git_libgit2_shutdown();
git2.libgit2.git_libgit2_shutdown();
stdout.writeln('plain-dart-libgit2-ok');
}
''');

final result = await Process.run(
_dartExecutable(),
<String>['--packages=${packageConfig.path}', script.path],
workingDirectory: Directory.current.path,
).timeout(const Duration(seconds: 30));

expect(
result.exitCode,
0,
reason:
'plain Dart loader process failed or crashed.\n'
'stdout:\n${result.stdout}\n'
'stderr:\n${result.stderr}',
);
expect(result.stdout, contains('plain-dart-libgit2-ok'));
} finally {
await tempDir.delete(recursive: true);
}
},
skip:
_canRunWindowsLoaderTest()
? null
: 'Windows loader test requires generated bindings and artifacts',
);
});
}

bool _canRunWindowsLoaderTest() {
return Platform.isWindows &&
File(p.join('lib', 'src', 'bindings.dart')).existsSync() &&
File(p.join('windows', 'libgit2.dll')).existsSync() &&
File(p.join('windows', 'libssh2.dll')).existsSync() &&
Directory('windows').listSync().whereType<File>().any((file) {
final name = p.basename(file.path).toLowerCase();
return name.startsWith('libcrypto') && name.endsWith('.dll');
});
}

String _dartExecutable() {
final executable = File(Platform.resolvedExecutable).uri.pathSegments.last;
return executable == 'dart' ? Platform.resolvedExecutable : 'dart';
}
7 changes: 6 additions & 1 deletion windows/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,13 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
# List of absolute paths to libraries that should be bundled with the plugin.
# This list could contain prebuilt libraries, or libraries created by an
# external build triggered from this build file.
file(GLOB git2dart_binaries_openssl_libraries
"${CMAKE_CURRENT_SOURCE_DIR}/libcrypto*.dll"
"${CMAKE_CURRENT_SOURCE_DIR}/libssl*.dll"
)

set(git2dart_binaries_bundled_libraries
"${CMAKE_CURRENT_SOURCE_DIR}/libcrypto-1_1-x64.dll"
${git2dart_binaries_openssl_libraries}
"${CMAKE_CURRENT_SOURCE_DIR}/libgit2.dll"
"${CMAKE_CURRENT_SOURCE_DIR}/libssh2.dll"
PARENT_SCOPE
Expand Down
Loading