diff --git a/.github/workflows/build_macos_arm64.yaml b/.github/workflows/build_macos_arm64.yaml new file mode 100644 index 00000000..f544ce6f --- /dev/null +++ b/.github/workflows/build_macos_arm64.yaml @@ -0,0 +1,55 @@ +name: TEST build for macos arm64 + +on: + push: + branches: [ "macos_apple_silicon" ] + tags: + - "v*.*.*" + pull_request: + branches: [ "macos_apple_silicon" ] + +env: + ANDROID_NDK_VERSION: r26c + OPENCV_VERSION: 4.9.0 + +jobs: + build-macos-arm64: + name: build-macos-arm64 + runs-on: macos-14 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: setup + run: | + # brew update + brew install --force --overwrite ninja ccache ffmpeg + cd ${{github.workspace}} + - name: build + run: | + python3 scripts/build.py --opencv --src src --build-dir build macos --arch arm64 + python3 scripts/build.py --dart --src src --build-dir build macos --arch arm64 + - uses: subosito/flutter-action@v2 + with: + # flutter-version: '3.16.9' + channel: "stable" + + - uses: actions/upload-artifact@v4 + name: upload-libopencv_dart-macos-arm64 + with: + path: build/publish/libopencv_dart-macos-arm64.tar.gz + name: libopencv_dart-macos-arm64.tar.gz + - name: Run Test + run: | + ls -alh $GITHUB_WORKSPACE/macos + export DYLD_LIBRARY_PATH=$GITHUB_WORKSPACE/macos:$DYLD_LIBRARY_PATH + flutter pub get + flutter test -x no-local-files + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + draft: true + prerelease: false + files: | + build/publish/libopencv_dart-macos-arm64.tar.gz diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index ff2a3174..acfba11d 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -43,12 +43,12 @@ jobs: mv build/android-ndk-$ANDROID_NDK_VERSION build/android-ndk - name: build-android run: | - python3 scripts/build.py --dart --os android --arch x64 --src src --build-dir build \ - --android-ndk build/android-ndk --android-abi x86_64 - python3 scripts/build.py --dart --os android --arch x64 --src src --build-dir build \ - --android-ndk build/android-ndk --android-abi arm64-v8a - python3 scripts/build.py --dart --os android --arch x64 --src src --build-dir build \ - --android-ndk build/android-ndk --android-abi armeabi-v7a + python3 scripts/build.py --dart --src src --build-dir build \ + --android-ndk build/android-ndk android --arch x86_64 + python3 scripts/build.py --dart --src src --build-dir build \ + --android-ndk build/android-ndk android --arch arm64-v8a + python3 scripts/build.py --dart --src src --build-dir build \ + --android-ndk build/android-ndk android --arch armeabi-v7a - uses: actions/upload-artifact@v4 name: upload-libopencv_dart-android-x86_64 @@ -96,8 +96,8 @@ jobs: submodules: true - name: build-opencv-dart run: | - python3 scripts/build.py --opencv --os linux --arch x64 --src src --build-dir build - python3 scripts/build.py --dart --os linux --arch x64 --src src --build-dir build + python3 scripts/build.py --opencv --src src --build-dir build linux --arch x64 + python3 scripts/build.py --dart --src src --build-dir build linux --arch x64 - uses: subosito/flutter-action@v2 with: # flutter-version: '3.16.9' @@ -134,8 +134,8 @@ jobs: python-version: '3.11' - name: build-opencv-dart run: | - python3 ${{github.workspace}}\scripts\build.py --opencv --os windows --arch x64 --src src --build-dir build - python3 ${{github.workspace}}\scripts\build.py --dart --os windows --arch x64 --src src --build-dir build + python3 ${{github.workspace}}\scripts\build.py --opencv --src src --build-dir build windows --arch x64 + python3 ${{github.workspace}}\scripts\build.py --dart --src src --build-dir build windows --arch x64 - uses: subosito/flutter-action@v2 with: # flutter-version: '3.16.9' @@ -172,8 +172,8 @@ jobs: cd ${{github.workspace}} - name: build run: | - python3 scripts/build.py --opencv --os macos --arch x64 --src src --build-dir build - python3 scripts/build.py --dart --os macos --arch x64 --src src --build-dir build + python3 scripts/build.py --opencv --src src --build-dir build macos --arch x64 + python3 scripts/build.py --dart --src src --build-dir build macos --arch x64 - uses: subosito/flutter-action@v2 with: # flutter-version: '3.16.9' diff --git a/.gitignore b/.gitignore index a72a6f98..ce93443c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ __pycache__ .cache/ small2.mp4 test/models/ +*.dylib # Files and directories created by pub .dart_tool/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 37a89855..4c836669 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.3 + +- add support for macOS with Apple Silicon + ## 0.6.2 * try add support for macos, see [this workflow](https://github.com/rainyl/opencv_dart/actions/workflows/build_macos.yaml) diff --git a/README.md b/README.md index 3e03bbe8..c60c8927 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ please run `dart run opencv_dart:setup -p -a ` to download prebuilt binaries. - `platform`: `auto` `android` `linux` `windows` `macos` -- `arch`: `auto` `x86` `x64` `x86_64`(android only) `arm64-v8a`(android only) `armeabi-v7a`(android only) +- `arch`: `auto` `x86` `x64` `x86_64`(android only) `arm64` (macOS only) `arm64-v8a`(android only) `armeabi-v7a`(android only) **Please use v0.3.0 and later version.** @@ -101,6 +101,12 @@ This package is in heavy development, dynamic libraries for Windows and linux ha libgflags-dev python3 libjpeg-dev libpng-dev libtiff-dev ``` + macos: + + ```bash + brew install --force --overwrite ninja ccache ffmpeg nasm + ``` + 2. install dependencies: `cmake`, `python`, add to PATH 3. clone this repo, `git clone --recursive https://github.com/rainyl/opencv_dart.git` 4. `cd opencv_dart` @@ -118,7 +124,13 @@ This package is in heavy development, dynamic libraries for Windows and linux ha python ./scripts/build.py --opencv --os linux --arch x64 --build-dir build --src src ``` - for android, you need to download [android ndk](https://developer.android.com/ndk/downloads) and [opencv for android sdk](https://opencv.org/releases/), extract opencv sdk and copy and rename `OpenCV-android-sdk` to `build/opencv/android` directory. + for macOS: + + ```bash + python3 ./scripts/build.py --opencv --os macos --arch arm64 --build-dir build --src src + ``` + + for android, you need to download [android ndk](https://developer.android.com/ndk/downloads) and [opencv for android sdk](https://opencv.org/releases/), extract opencv sdk and copy and rename `OpenCV-android-sdk` to `build/opencv/android` directory. 6. compile this package along with gocv. @@ -132,7 +144,13 @@ This package is in heavy development, dynamic libraries for Windows and linux ha ```bash python ./scripts/build.py --dart --os linux --arch x64 --build-dir build --src src - ``` + ``` + + macOS: + + ```bash + python3 ./scripts/build.py --dart --os macos --arch arm64 --build-dir build --src src + ``` Android: diff --git a/bin/setup.dart b/bin/setup.dart index f1d6c47d..2daf4c5a 100644 --- a/bin/setup.dart +++ b/bin/setup.dart @@ -1,147 +1,13 @@ -import 'dart:convert'; -import 'dart:io'; +import 'package:args/command_runner.dart'; -import 'package:args/args.dart'; -import 'package:yaml/yaml.dart'; -import 'package:archive/archive_io.dart'; -import 'package:path/path.dart' as p; - -class OS { - static const auto = "auto"; - static const windows = "windows"; - static const linux = "linux"; - static const android = "android"; - static const fuchsia = "fuchsia"; - static const ios = "ios"; - static const macos = "macos"; -} +import 'setup_commands.dart'; void main(List args) async { - final parser = ArgParser(); - // parser.addFlag( - // "flutter", - // negatable: true, - // defaultsTo: false, - // help: "Setup for Flutter", - // ); - parser.addOption( - "platform", - abbr: "p", - allowed: [ - "auto", - "windows", - "linux", - "android", - "fuchsia", - "ios", - "macos", - ], - defaultsTo: "auto", - help: "Platform to setup", - ); - parser.addOption( - "arch", - abbr: "a", - allowed: [ - "auto", - "x86", - "x64", - "x86_64", - "arm64-v8a", - "armeabi-v7a", - ], - defaultsTo: "auto", - help: "Architecture to setup", - ); - - final argsParsed = parser.parse(args); - final platform = - argsParsed["platform"] == OS.auto ? Platform.operatingSystem : argsParsed["platform"] as String; - final arch = argsParsed["arch"] == OS.auto - ? (platform == "android" ? "arm64-v8a" : "x64") - : argsParsed["arch"] as String; - final setupPkgName = "opencv_dart"; - - // Assumed package root - final root = Directory.current.uri; - print('Building with assumed project root in:'); - print(root.toFilePath()); - - // Assumed package_config.json - final packageConfigFile = File.fromUri( - root.resolve('.dart_tool/package_config.json'), - ); - dynamic packageConfig; - try { - packageConfig = json.decode(await packageConfigFile.readAsString()); - } on FileSystemException { - print('Missing .dart_tool/package_config.json'); - print('Run `flutter pub get` first.'); - exit(1); - } on FormatException { - print('Invalid .dart_tool/package_config.json'); - print('Run `flutter pub get` first.'); - exit(1); - } - - // Determine the source path of package:webcrypto in the PUB_CACHE - final pkg = (packageConfig['packages'] ?? []).firstWhere( - (e) => e['name'] == setupPkgName, - orElse: () => null, - ); - if (pkg == null) { - print('dependency on package:$setupPkgName is required'); - exit(1); - } - final opencvRoot = packageConfigFile.uri.resolve(pkg['rootUri'] ?? ''); - print('Using package:$setupPkgName from ${opencvRoot.toFilePath()}'); - - final doc = loadYaml(File("${opencvRoot.toFilePath()}/pubspec.yaml").readAsStringSync()); - final _version = doc["version"] as String; - final version = _version.replaceAll(RegExp(r"\-dev.*"), ""); - final libTarName = "libopencv_dart-$platform-$arch.tar.gz"; - - print('Downloading prebuilt binary...'); - String url = "https://github.com/rainyl/opencv_dart/releases/download/v$version/$libTarName"; - - final cacheTarPath = p.join(opencvRoot.toFilePath(), ".cache", libTarName); - final saveFile = File(cacheTarPath); - if (!saveFile.parent.existsSync()) saveFile.parent.createSync(recursive: true); - - print("Downloading $url"); - final request = await HttpClient().getUrl(Uri.parse(url)); - final response = await request.close(); - if (response.statusCode == 200) { - await response.pipe(saveFile.openWrite()); - print("Cached to $cacheTarPath"); - } else { - print("Download Failed with status: ${response.statusCode}"); - exit(1); - } - - print("Extracting..."); - String extractPath = ""; - switch (platform) { - case OS.windows: - extractPath = p.join(opencvRoot.toFilePath(), "windows"); - break; - case OS.linux: - extractPath = p.join(opencvRoot.toFilePath(), "linux"); - break; - case OS.android: - extractPath = p.join(opencvRoot.toFilePath(), "android", "src", "main", "jniLibs", arch); - case OS.macos: - extractPath = p.join(opencvRoot.toFilePath(), "macos"); - case OS.fuchsia: - case OS.ios: - throw UnimplementedError(); - default: - throw UnsupportedError("Platform $platform not supported"); - } - - if (!Directory(extractPath).existsSync()) Directory(extractPath).createSync(recursive: true); - await extractFileToDisk(cacheTarPath, extractPath); - - print("Finished"); - exit(0); + final runner = CommandRunner("setup", "Setup for opencv_dart") + ..addCommand(WindowsSetupCommand()) + ..addCommand(LinuxSetupCommand()) + ..addCommand(MacOsSetupCommand()) + ..addCommand(AndroidSetupCommand()) + // ..addCommand(IosSetupCommand()) + ..run(args); } diff --git a/bin/setup_commands.dart b/bin/setup_commands.dart new file mode 100644 index 00000000..7bd374a9 --- /dev/null +++ b/bin/setup_commands.dart @@ -0,0 +1,198 @@ +import 'dart:convert'; +import 'dart:ffi'; +import 'dart:io'; + +import 'package:archive/archive_io.dart'; +import 'package:args/command_runner.dart'; +import 'package:yaml/yaml.dart'; +import 'package:path/path.dart' as p; + +const setupPkgName = "opencv_dart"; + +abstract class BaseSetupCommand extends Command { + @override + String get description => "Setup"; + + @override + String get name => "base"; + + String get arch { + final arch_ = argResults?["arch"] as String; + return arch_ == "auto" ? Abi.current().toString().split("_").last : arch_; + } + + String get os => name; + + Future downloadAndExtract() async { + // Detect dependencies + // Assumed package root + final root = Directory.current.uri; + print('Building with assumed project root in:'); + print(root.toFilePath()); + + // Assumed package_config.json + final packageConfigFile = File.fromUri( + root.resolve('.dart_tool/package_config.json'), + ); + dynamic packageConfig; + try { + packageConfig = json.decode(await packageConfigFile.readAsString()); + } on FileSystemException { + print('Missing .dart_tool/package_config.json'); + print('Run `flutter pub get` first.'); + exit(1); + } on FormatException { + print('Invalid .dart_tool/package_config.json'); + print('Run `flutter pub get` first.'); + exit(1); + } + + // Determine the source path of package:webcrypto in the PUB_CACHE + final pkg = (packageConfig['packages'] ?? []).firstWhere( + (e) => e['name'] == setupPkgName, + orElse: () => null, + ); + if (pkg == null) { + print('dependency on package:$setupPkgName is required'); + exit(1); + } + final opencvRoot = packageConfigFile.uri.resolve(pkg['rootUri'] ?? ''); + print('Using package:$setupPkgName from ${opencvRoot.toFilePath()}'); + + final doc = loadYaml(File("${opencvRoot.toFilePath()}/pubspec.yaml").readAsStringSync()); + final _version = doc["version"] as String; + final libTarName = "libopencv_dart-$os-$arch.tar.gz"; + final version = _version.replaceAll(RegExp(r"\-dev.*"), ""); + + print('Downloading prebuilt binary...'); + String url = "https://github.com/rainyl/opencv_dart/releases/download/v$version/$libTarName"; + + final cacheTarPath = p.join(opencvRoot.toFilePath(), ".cache", libTarName); + final saveFile = File(cacheTarPath); + if (!saveFile.parent.existsSync()) saveFile.parent.createSync(recursive: true); + + print("Downloading $url"); + final request = await HttpClient().getUrl(Uri.parse(url)); + final response = await request.close(); + if (response.statusCode == 200) { + await response.pipe(saveFile.openWrite()); + print("Cached to $cacheTarPath"); + } else { + print("Download Failed with status: ${response.statusCode}"); + exit(1); + } + + print("Extracting..."); + String extractPath = ""; + switch (os) { + case OS.windows: + extractPath = p.join(opencvRoot.toFilePath(), "windows"); + break; + case OS.linux: + extractPath = p.join(opencvRoot.toFilePath(), "linux"); + break; + case OS.android: + extractPath = p.join(opencvRoot.toFilePath(), "android", "src", "main", "jniLibs", arch); + case OS.macos: + extractPath = p.join(opencvRoot.toFilePath(), "macos"); + case OS.fuchsia: + case OS.ios: + throw UnimplementedError(); + default: + throw UnsupportedError("Platform $os not supported"); + } + if (!Directory(extractPath).existsSync()) Directory(extractPath).createSync(recursive: true); + await extractFileToDisk(cacheTarPath, extractPath); + } + + @override + void run() async { + print("opencv_dart: working for $os $arch"); + await downloadAndExtract(); + print("Finished"); + exit(0); + } +} + +class MacOsSetupCommand extends BaseSetupCommand { + @override + String get description => "Setup for macOS"; + + @override + String get name => "macos"; + + MacOsSetupCommand() { + argParser.addOption("arch", allowed: ["auto", "x64", "arm64"], defaultsTo: "auto"); + } + + @override + void run() { + super.run(); + } +} + +class WindowsSetupCommand extends BaseSetupCommand { + @override + String get description => "Setup for Windows"; + + @override + String get name => "windows"; + + WindowsSetupCommand() { + argParser.addOption("arch", allowed: ["x64"], defaultsTo: "x64"); + } + @override + void run() { + super.run(); + } +} + +class LinuxSetupCommand extends BaseSetupCommand { + @override + String get description => "Setup for Linux"; + + @override + String get name => "linux"; + + LinuxSetupCommand() { + argParser.addOption("arch", allowed: ["x64"], defaultsTo: "x64"); + } +} + +class AndroidSetupCommand extends BaseSetupCommand { + @override + String get description => "Setup for Android"; + + @override + String get name => "android"; + + AndroidSetupCommand() { + argParser.addOption( + "arch", + allowed: ["auto", "x86_64", "arm64-v8a", "armeabi-v7a"], + defaultsTo: "auto", + ); + } +} + +class IosSetupCommand extends BaseSetupCommand { + @override + String get description => "Setup for IOS"; + + @override + String get name => "ios"; + + IosSetupCommand() { + // argParser.addOption("arch", allowed: ["auto", "x64", "arm64"], defaultsTo: "auto"); + throw UnimplementedError(); + } +} + +class OS { + static const windows = "windows"; + static const linux = "linux"; + static const android = "android"; + static const fuchsia = "fuchsia"; + static const ios = "ios"; + static const macos = "macos"; +} diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 00000000..cccf817a --- /dev/null +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,10 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { +} diff --git a/pubspec.yaml b/pubspec.yaml index aa033bad..1805ef53 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: opencv_dart description: "OpenCV4 bindings for Dart language and Flutter, using dart:ffi. The most complete OpenCV bindings for Dart!" -version: 0.6.2 +version: 0.6.3 homepage: https://github.com/rainyl/opencv_dart environment: diff --git a/scripts/build.py b/scripts/build.py index 241f3dd5..78e4cd07 100644 --- a/scripts/build.py +++ b/scripts/build.py @@ -9,42 +9,72 @@ LIB_NAME = "opencv_dart" +def generate_windows(args: Namespace): + arch = "x64" if args.arch == "x64" else "Win32" + cmake_cmd = ( + "cmake " + # f"-D CMAKE_TOOLCHAIN_FILE={args.dst / 'conan_toolchain.cmake'} " + # '-G "Visual Studio 16 2019" ' + "-D BUILD_WITH_STATIC_CRT=OFF " + f"-D CMAKE_GENERATOR_PLATFORM={arch} " + ) + return cmake_cmd + + +def generate_linux(args: Namespace): + flags = ( + "-D CMAKE_C_FLAGS=-m32 -D CMAKE_CXX_FLAGS=-m32" if args.arch == "x86" else "" + ) + cmake_cmd = f'cmake -G "Ninja" -D OPENCV_DART_ARCH={args.arch} {flags} ' + return cmake_cmd + + +def generate_macos(args: Namespace): + target = "arm64-apple-macos" if args.arch == "arm64" else "x86_64-apple-macos" + cmake_cmd = ( + "cmake " + f'-G "Ninja" -D OPENCV_DART_ARCH={args.arch} ' + f"-D CMAKE_CXX_FLAGS='-target {target}' " + f"-D CMAKE_C_FLAGS='-target {target}' " + ) + return cmake_cmd + + +def generate_android(args: Namespace): + if not args.ndk.exists(): + raise FileNotFoundError(f"Android NDK not found at {args.ndk}") + cmake_cmd = ( + "cmake " + '-G "Ninja" ' + "-D ANDROID_STL=c++_static " + f"-D ANDROID_NDK={args.ndk} " + "-D ANDROID_TOOLCHAIN=clang " + f"-D CMAKE_TOOLCHAIN_FILE={args.ndk}/build/cmake/android.toolchain.cmake " + f"-D ANDROID_ABI={args.abi} " + # f"-D ANDROID_PLATFORM=android-$MINSDKVERSION" + ) + return cmake_cmd + + +def generate_ios(args: Namespace): + raise NotImplementedError + + def cmake_generate(args: Namespace): src_dir = Path(args.src).absolute() - cmake = "cmake " - match args.os: + cmake = "" + match args.platform: case "windows": - arch = "x64" if args.arch == "x64" else "Win32" - cmake += ( - # f"-D CMAKE_TOOLCHAIN_FILE={args.dst / 'conan_toolchain.cmake'} " - # '-G "Visual Studio 16 2019" ' - "-D BUILD_WITH_STATIC_CRT=OFF " - f"-D CMAKE_GENERATOR_PLATFORM={arch} " - ) + cmake = generate_windows(args) case "linux": - flags = ( - "-D CMAKE_C_FLAGS=-m32 -D CMAKE_CXX_FLAGS=-m32" - if args.arch == "x86" - else "" - ) - cmake += f'-G "Ninja" -D OPENCV_DART_ARCH={args.arch} {flags} ' + cmake = generate_linux(args) case "android": - if not args.ndk.exists(): - raise FileNotFoundError(f"Android NDK not found at {args.ndk}") - cmake += ( - '-G "Ninja" ' - "-D ANDROID_STL=c++_static " - f"-D ANDROID_NDK={args.ndk} " - "-D ANDROID_TOOLCHAIN=clang " - f"-D CMAKE_TOOLCHAIN_FILE={args.ndk}/build/cmake/android.toolchain.cmake " - f"-D ANDROID_ABI={args.abi} " - # f"-D ANDROID_PLATFORM=android-$MINSDKVERSION" - ) + cmake = generate_android(args) case "macos": - cmake += '-G "Ninja" ' + cmake = generate_macos(args) case "ios": - cmake += '-G "Unix Makefiles" ' + cmake = generate_ios(args) raise NotImplementedError case _: raise NotImplementedError @@ -117,52 +147,13 @@ def cmake_build(args: Namespace): os.system(cmd) -# def copy_dlls(args, install_dir, lib_name_suffix, lib_copy_to_dir): -# lib_name_prefix: str = "lib" if args.os == "windows" else "" -# if args.copy_dlls: -# dependencies = pyldd.parse_to_list( -# pyldd.Args( -# format_="json", -# path=install_dir / f"{LIB_NAME}{lib_name_suffix}", -# sort_by="soname", -# recursive=True, -# unused=True, -# ) -# ) -# for dep in dependencies: -# skip = ( -# dep["soname"] is None -# # skip system dlls -# or str(Path(dep["path"]).absolute()).startswith("C:\WINDOWS") -# or not Path(dep["path"]).is_absolute() # skip existed -# or not isinstance(dep["path"], str) -# ) - -# if skip: -# print(f"skip {dep['soname']}: {dep['path']}") -# continue -# dep_path = Path(dep["path"]) -# shutil.copyfile(dep["path"], lib_copy_to_dir / dep_path.name) - -# if str(Path(dep["path"])).startswith(str(install_dir)): -# print(f"skip {dep['soname']}: {dep['path']}") -# continue - -# dst = install_dir / f"{lib_name_prefix}{dep_path.name}" - -# shutil.copyfile(dep["path"], dst) -# print(f"{dep['path']} -> {dst}") - - def main(args: Namespace): if args.opencv: args.src = args.src / "opencv" build_sub = "opencv_dart" if args.dart else "opencv" - if args.os == "android": - args.arch = args.abi args.extra_modules = Path(args.extra_modules).absolute() - args.dst = args.dst / build_sub / f"{args.os}" / f"{args.arch}" + args.dst = args.dst / build_sub / f"{args.platform}" / f"{args.arch}" if not args.dst.exists(): args.dst.mkdir(parents=True) os.chdir(args.dst) @@ -176,25 +167,25 @@ def main(args: Namespace): if not args.dart: return - + # copy built dlls to platform directory # i.e., windows/; linux/; macos/; android/src/main/jniLibs/ lib_copy_to_dir: Path lib_name_suffix: str = "" - match args.os: + match args.platform: case "windows": - lib_copy_to_dir = args.work_dir / args.os + lib_copy_to_dir = args.work_dir / args.platform lib_name_suffix = ".dll" case "android": lib_copy_to_dir = ( - args.work_dir / args.os / "src" / "main" / "jniLibs" / args.abi + args.work_dir / args.platform / "src" / "main" / "jniLibs" / args.abi ) lib_name_suffix = ".so" case "linux": - lib_copy_to_dir = args.work_dir / args.os + lib_copy_to_dir = args.work_dir / args.platform lib_name_suffix = ".so" case "macos" | "ios": - lib_copy_to_dir = args.work_dir / args.os + lib_copy_to_dir = args.work_dir / args.platform lib_name_suffix = ".dylib" case _: raise NotImplementedError @@ -206,13 +197,13 @@ def main(args: Namespace): publish_dir.mkdir(parents=True) install_dir = Path(args.dst) / "install" - _prefix: str = "" if args.os == "windows" else "lib" + _prefix: str = "" if args.platform == "windows" else "lib" shutil.copy(install_dir / f"{_prefix}{LIB_NAME}{lib_name_suffix}", lib_copy_to_dir) # copy_dlls() # archive - fname = publish_dir / f"lib{LIB_NAME}-{args.os}-{args.arch}.tar.gz" + fname = publish_dir / f"lib{LIB_NAME}-{args.platform}-{args.arch}.tar.gz" with tarfile.open(fname, mode="w:gz") as tar: for file in install_dir.glob("*"): if file.is_file(): @@ -238,63 +229,84 @@ def main(args: Namespace): default=False, ) parser.add_argument( - "--copy-dlls", - dest="copy_dlls", - action="store_true", - default=False, + "--src", + dest="src", + type=str, + default="src", ) - parser.add_argument( - "--os", - dest="os", + "--build-dir", + dest="build_dir", type=str, - default="windows", - choices=["windows", "linux", "android", "macos", "ios"], + default="build", ) parser.add_argument( + "--extra-modules", + dest="extra_modules", + type=str, + default=str((work_dir / "src" / "opencv_contrib" / "modules").absolute()), + ) + + sub_parsers = parser.add_subparsers(title="platform", dest="platform") + # macOS + sub_macos = sub_parsers.add_parser("macos") + sub_macos.add_argument( "--arch", dest="arch", type=str, default="x64", - choices=["x64", "x86", "arm64", "arm"], + choices=["x64", "arm64"], ) - parser.add_argument( - "--src", - dest="src", + # Windows + sub_windows = sub_parsers.add_parser("windows") + sub_windows.add_argument( + "--arch", + dest="arch", type=str, - default=str((work_dir / "src").absolute()), + default="x64", + choices=["x64", "x86"], ) - parser.add_argument( - "--build-dir", - dest="build_dir", + + # linux + sub_linux = sub_parsers.add_parser("linux") + sub_linux.add_argument( + "--arch", + dest="arch", type=str, - default=str((work_dir / "build").absolute()), + default="x64", + choices=["x64", "x86"], ) - parser.add_argument( - "--extra-modules", - dest="extra_modules", + + # android + sub_android = sub_parsers.add_parser("android") + sub_android.add_argument( + "--arch", + dest="arch", type=str, - default=str((work_dir / "src" / "opencv_contrib" / "modules").absolute()), + default="arm64-v8a", + choices=["arm64-v8a", "armeabi-v7a", "x86", "x86_64"], + help="i.e., android abi", ) - parser.add_argument( + sub_android.add_argument( "--android-ndk", dest="ndk", type=str, default=os.environ.get("ANDROID_NDK_HOME", ""), ) - parser.add_argument( - "--android-abi", - dest="abi", - type=str, - default="arm64-v8a", - choices=["arm64-v8a", "armeabi-v7a", "x86", "x86_64"], - ) + + # ios + sub_ios = sub_parsers.add_parser("ios") args = parser.parse_args() + + print(args) assert not all([args.opencv, args.dart]) + args.work_dir = work_dir args.src = Path(args.src).absolute() - args.ndk = Path(args.ndk).absolute() args.dst = Path(args.build_dir).absolute() + if args.platform == "android": + args.ndk = Path(args.ndk).absolute() + main(args)