Skip to content

Swift Package Manager [WIP]#18925

Draft
chrisballinger wants to merge 33 commits intoopencv:4.xfrom
Rightpoint:swift-package
Draft

Swift Package Manager [WIP]#18925
chrisballinger wants to merge 33 commits intoopencv:4.xfrom
Rightpoint:swift-package

Conversation

@chrisballinger
Copy link
Copy Markdown
Contributor

@chrisballinger chrisballinger commented Nov 25, 2020

Here is preliminary support for Swift Package Manager (resolves #18398) utilizing the new binaryTarget feature in conjunction with xcframeworks, building upon @colejd's work in #18826. Additionally this PR includes support for GitHub Actions to build and store both static and dynamic xcframework artifacts, as seen here in the Rightpoint fork: https://github.com/Rightpoint/opencv/actions/runs/383938322

Screen Shot 2020-11-25 at 2 53 49 PM

There are still some additional problems to solve, namely:

  • Run swift test using a locally compiled binary xcframework
  • Provide guidance on updating the remote xcframework URL and checksum
  • Ensure existing tests are not broken

This PR also changes a few things to get around a symbol conflict issue for Rect, Size and Point, as they conflict with existing symbols present in the Darwin package. I provided typealiases for backward compatibility. I may have also broken the existing tests during my process of migrating them to working via swift test, so I expect some follow up work there before this is mergeable.

I think the trickiest bit will be figuring out a workflow that helps keep the binaryTarget URL and checksum in Package.swift up to date. Although you can grab the artifacts and checksum from the GitHub Actions jobs, there isn't a way to keep these URLs up to date automatically through the CI system, so every time there is a release someone will need to update these items:

        .binaryTarget(
            name: "opencv2",
            url: "https://github.com/Rightpoint/opencv/releases/download/4.5.1/opencv2-4.5.1-dynamic.xcframework.zip",
            checksum: "48273710fe03eb6d6a77ca57f96ef7917db395e6c3bc62e2b495df3dc8f1a0a9"
        ),

Where this becomes extra tricky, is that attaching a release to a tag creates sort of a chicken and the egg scenario. A tag needs to be created for a binary xcframework build to be made and checksum computed, but although the URL can be known in advance the checksum cannot. So when creating a new release tag, someone first should ensure they are using the latest xcframework and have recomputed the checksum and committed it to Package.swift before tagging. I've attempted to make this process slightly less annoying by computing the checksum on CI, so you can grab the latest checksum and xcframework binaries from master. Then you just need to make sure Package.swift is updated with the latest checksum and URL before creating the new release tag.

Screen Shot 2020-11-25 at 2 55 54 PM

The other part that is a bit tricky, is that running the tests via swift test requires uncommenting the local xcframework section of the Package.swift file, and then commenting out the remote xcframework:

        // Recompute checksum via `swift package --package-path /path/to/opencv compute-checksum /path/to/opencv2.xcframework.zip`
//        .binaryTarget(
//            name: "opencv2",
//            url: "https://github.com/Rightpoint/opencv/releases/download/4.5.1/opencv2-4.5.1-dynamic.xcframework.zip",
//            checksum: "48273710fe03eb6d6a77ca57f96ef7917db395e6c3bc62e2b495df3dc8f1a0a9"
//        ),
        // If you are compiling OpenCV locally, you can uncomment the below block to use a custom copy
        // e.g. `$ python platforms/apple/build_xcframework.py --dynamic build/dynamic-xcframework`
        .binaryTarget(
            name: "opencv2",
            path: "build/dynamic-xcframework/opencv2.xcframework"
        ),

There may be a way to modify Rocket which has support for hide_dev_dependencies/unhide_dev_dependencies to include something like hide_prod_dependencies so we can temporarily comment out the remote binaryTarget when running tests on CI.

I'll probably not respond much over the next few days, but wanted to get this out there for people to start testing.

Cheers! 🦃

Pull Request Readiness Checklist

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
  • The PR is proposed to proper branch
  • There is reference to original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake
force_builders_only=docs,ios,Custom Mac
buildworker:Mac=macosx-1
buildworker:iOS=macosx-2
build_image:Custom Mac=osx_framework-test
buildworker:Custom Mac=macosx-2

@asmorkalov
Copy link
Copy Markdown
Contributor

@chrisballinger Please take a look on CI status. BuildBot report trailing white spaces issue: https://pullrequest.opencv.org/buildbot/builders/precommit_docs/builds/27965


import PackageDescription

let package = Package(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really necessary to put this file into repository root?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packages are Git repositories, tagged with semantic versions, containing a Package.swift file at their root.

From here: https://github.com/apple/swift-package-manager/blob/main/Documentation/Usage.md

@alalek Unfortunately it's not possible to put the Package.swift file elsewhere. Alternatively, we could create another repository like opencv/opencv-swift or opencv/opencv-swift-package for the Swift Package that is periodically kept up to date with the parent repo. That might also solve the "chicken and the egg" xcframework checksum problem as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually do not store package-specific information in the root of this repository.

we could create another repository like opencv/opencv-swift or opencv/opencv-swift-package for the Swift Package

I believe this should work.

There is an example for "opencv-python" PyPi packages: https://github.com/skvark/opencv-python
It is not the same (it is not the package itself), just contains build scripts / dependencies settings / other package manager requirements.


BTW, Do you have a simple demo example "project" which uses the package? (besides of builtin tests). It is possible to put it into samples/swift?

@alalek
Copy link
Copy Markdown
Member

alalek commented Nov 26, 2020

latest checksum and xcframework binaries from master

OpenCV release binaries are built from release tag

need to make sure Package.swift is updated with the latest checksum and URL before creating the new release tag

The chicken and egg problem ...


@chrisballinger Could you please add into PR description some links on documentation about package manager requirements?

@chrisballinger
Copy link
Copy Markdown
Contributor Author

@asmorkalov I took another look at the diff and don't see any obvious whitespace issues. Is there a way to view the logs for the whitespace issue? When I click into the CI job, it says "No logs" so I'm not exactly sure where to look: https://pullrequest.opencv.org/buildbot/builders/precommit_docs/builds/27965/steps/whitespace%20opencv

@alalek If we split off the Package.swift portion into a separate repository, I think the GitHub Action xcframework builds should still be merged as part of this repo (and the Rect/Size/Point symbol collision fixes). I believe it requires some action on your end to enable Actions for this repository: https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/disabling-or-limiting-github-actions-for-a-repository

@alalek
Copy link
Copy Markdown
Member

alalek commented Nov 30, 2020

We lost log details (due to builds artifacts limit). I restarted the Docs builder.

Logs:

.github/workflows/apple-build-checks.yml:3: trailing whitespace.
+on:  
platforms/ios/build_framework.py:104: trailing whitespace.
+                target_flag = "-target %s-apple-ios13.0-macabi" % target[0]  # e.g. x86_64-apple-ios13.0-macabi 
platforms/ios/build_framework.py:106: trailing whitespace, tab in indent.
+					target_flag,     

.testTarget(
name: "OpenCVTests",
dependencies: ["OpenCV"],
path: "modules/core/misc/objc/test/swift",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several tests besides of "core" module which are not mentioned here.
Full set of tests is prepared during the build.

If we are moving to dedicated repository for the package it make sense to adapt build scripts to prepare additional folder with:

  • Package.swift file based on template from platforms/apple/Package.swift.template (or .in suffix) with correct checksum and adjusted tests path
  • copy of test files from build directory
  • misc files, like readme.md (copy content from platforms/apple/opencv-swift)

This folder should be uploaded as artifact (.zip archive should be OK).
This artifact can be used later to prepare an update (commit/PR) in dedicated "opencv-swift" repository.


Note1: All names/paths above are just examples for now.
Note2: Prefer to keep code in Python scripts instead of workflows (it is very hard to debug "workflows" or other CI's scripts)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I wasn't aware of how the OpenCV test process works, I'll take a closer look. I'm going to break this PR into smaller functional components, because it seems like the right path forward.

  • GitHub Actions for building xcframework artifacts
  • Fix Size/Point/Rect symbol conflict issue
  • Package.swift in separate repository


#import <XCTest/XCTest.h>
#import <OpenCV/OpenCV.h>
#import <opencv2/opencv2.h>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an idea to rename "opencv2" => "OpenCV" framework.
Currently it is postponed for OpenCV 4.x. Should be changed with next major release OpenCV 5.0+ .
Need to check if we can change this for Swift in OpenCV 4.5.x (do we break existed user Swift code?)

BTW, this name change is handled by this code in "build" directory.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I was aware but when integrated via SPM, I can't use #import <OpenCV/OpenCV.h> because it doesn't exist in Obj-C land. I saw there's a script to do a find/replace for this, but it doesn't execute before swift test. I'll see if there's another workaround.

As an aside - I do like the idea to rename to OpenCV in 5.x. But that raises an interesting point about what will happen in the Package.swift after the transition, as underlying binaryTarget name (currently opencv2) might conflict with the parent/wrapper package name OpenCV.

@chrisballinger
Copy link
Copy Markdown
Contributor Author

Alrighty, I made a couple smaller PRs #18976, #18977, and #18978 based on this PR, and started work on a standalone Swift Package repo here: https://github.com/Rightpoint/opencv-swift

Right now it contains the Package.swift manifest and opencv added as a git submodule, currently pointed to this branch. Once things get merged and other issues ironed out, it would be ideal if the long term plan would be to move that repo under the OpenCV GitHub org to facilitate ongoing maintenance and automated release processes.

@alalek
Copy link
Copy Markdown
Member

alalek commented Dec 4, 2020

Hi @chrisballinger

I looked on content in proposed Swift package repository ( https://github.com/Rightpoint/opencv-swift ).
Some thoughts:

  • there are several paths using "opencv/modules/core/misc/objc" which points to "core" module only.
    It is not enough because OpenCV contains several modules besides of "core".
  • tests and bindings sources are prepared in build directory (look at <build>/modules/objc_bindings_generator/{ios/osx}) by build_*.py scripts
    Looks like, tests content is the same between ios/osx, so it is not a problem to pick only one (or use common tests only).
  • these generated files can be prepared with proper framework name - build_*.py scripts handles that
    There are plans to rename opencv2 => OpenCV in OpenCV 5.0 or even in OpenCV 4.x for Swift package.
  • we should reuse these files from build directory instead of <opencv>/modules/core/misc/objc from source code
  • other package-related files like Package.swift (with hashes), *.podspec (?) can be generated (from templates) by platforms/apple/build_xcframework.py script too
  • this build_xcframework.py script can gather necessary generated test files, *.swift source files (if needed), package-related files (Package.swift) and put all of them into a directory with layout similar to opencv-swift repo content.
  • GitHub workflow can upload the directory of "swift-package" repository content as an artifact
  • release engineer after validation will push new update commit to opencv-swift package repo with new content from prepared artifact.
  • perhaps "opencv" submodule with source code is not really needed after that in this opencv-swift repo

Meantime it would be nice to have some simple "hello-world" sample which uses OpenCV Swift package and some "how to" instructions. It will be used for validation, so command-line instructions is preferable to perform automatic validation.
Can we put sample into <opencv>/samples/swift/ or do we need another one repository?
Refs: https://github.com/apple/example-package-dealer (example from https://swift.org/package-manager/ )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swift Package Manager Support

4 participants