go-flutter-desktop / go-flutter

Flutter on Windows, MacOS and Linux - based on Flutter Embedding, Go and GLFW.
https://hover.build/
BSD 3-Clause "New" or "Revised" License
5.86k stars 282 forks source link

Unable to package darwin-dmg when using CGo in a go-flutter-desktop plugin #499

Open Aurora12 opened 4 years ago

Aurora12 commented 4 years ago

Hover doctor

hover: Hover version v0.42.0 running on darwin
hover: Sharing flutter version
Flutter 1.20.0-7.3.pre • channel beta • https://github.com/flutter/flutter.git
Framework • revision e606910f28 (2 days ago) • 2020-07-28 16:06:37 -0700
Engine • revision ac95267aef
Tools • Dart 2.9.0 (build 2.9.0-21.10.beta)
hover: Flutter engine commit: https://github.com/flutter/engine/commit/ac95267aef5175b3f6c3387d502070c68f588ad5
hover: Finding out the C compiler version
clang version 10.0.0
Target: x86_64-apple-darwin19.5.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin

Preamble

The following does work.

I use CGo to compile xeodou/go-sqlcipher.

I use a modified version of go-flutter-plugin-sqlite to be able to use go-sqlcipher for transparent database encryption over SQLite.

~/go/bin/hover run and ~/go/bin/hover build darwin work as expected: the Flutter app runs and uses encrypted SQLite. I have env vars CGO_ENABLED, LIBRARY_PATH and CGO_CPPFLAGS set appropriately to make the compilation possible.

$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix

I also have OpenSSL installed as a dependency of SQLCipher.

Error output

I'm not able to package the app on macOS Catalina 10.15.5.

Using ~/go/bin/hover build --docker darwin-dmg to build my application, I get the following error once the compilation reaches go-sqlcipher:

hover: Compiling go binary using docker container
Running this docker command: /usr/local/bin/docker run --rm --mount type=bind,source=/Users/nox/Documents/workspace/worldr/client/desktop,target=/app --mount type=bind,source=/Users/nox/Library/Caches/hover/engine,target=/root/.cache/hover/engine --mount type=bind,source=/Users/nox/Library/Caches/hover/docker-go-cache,target=/go-cache --env GOCACHE=/go-cache --env HOVER_SAFE_CHOWN_UID=501 --env HOVER_SAFE_CHOWN_GID=20 --env GOPROXY=https://proxy.golang.org,direct
 --env GOPRIVATE=
 goflutter/hover:v0.42.0 hover-safe.sh build darwin-dmg --skip-flutter-build-bundle --skip-engine-download

<...>

docker container: github.com/xeodou/go-sqlcipher
docker container: # github.com/xeodou/go-sqlcipher
docker container: sqlite3-binding.c:24508:10: error: invalid argument type 'void' to unary expression
docker container: sqlite3-binding.c:24511:10: error: invalid argument type 'void' to unary expression
docker container: sqlite3-binding.c:24514:10: error: invalid argument type 'void' to unary expression
docker container: sqlite3-binding.c:24520:6: error: invalid argument type 'void' to unary expression
docker container: sqlite3-binding.c:24522:8: error: invalid argument type 'void' to unary expression
docker container: sqlite3-binding.c:24524:6: error: invalid argument type 'void' to unary expression
docker container: sqlite3-binding.c:24539:11: warning: implicit declaration of function 'PKCS5_PBKDF2_HMAC' is invalid in C99 [-Wimplicit-function-declaration]
docker container: hover: Go build failed: exit status 2
hover: Docker run failed: exit status 1

Attempts to fix

I figured the compiler may not know we are using CGo, so I set ENV CGO_ENABLED=1 in Hover's DockerFile to see if this changes the error. I also figured, this may be a problem with the version of GCC, so I tried building the Hover docker image with gcc:latest as a parent image instead of original ubuntu:bionic.

Nothing I did made any difference: the error remains the same, the compiler refuses the sqlite3-binding.c syntax. I can see Hover is using my local docker image by the way it complains on the CGO_CPPFLAGS.

Any ideas?

Any hints or directions are greatly appreciated!

ghost commented 4 years ago

In addition, shouldn't the following work?

$ hover build darwin-dmg
hover: Packaging darwin-bundle is not supported on darwin
hover: To still package darwin-bundle on darwin you need to run hover with the `--docker` flag.
$ hover build darwin-bundle
hover: Packaging darwin-bundle is not supported on darwin
hover: To still package darwin-bundle on darwin you need to run hover with the `--docker` flag.
$ hover build darwin-pkg
hover: Packaging darwin-bundle is not supported on darwin
hover: To still package darwin-bundle on darwin you need to run hover with the `--docker` flag.
provokateurin commented 4 years ago

There is no support currently, because I don't have a Mac and working in a VM is a pain. If you want you can add support. It should be fairly easy

Aurora12 commented 4 years ago

I ended up packaging with a series of commands to Xcode command-line tools.

What I added:

  1. a template folder structure:
    
    ./osx/bundle/     # becomes the root folder of .app
    /Contents/
    /Frameworks   # bundled dlls
    /MacOS        # build files generated by `hover build darwin` command
    /Resources    # icons and such
    Info.plist   # main package descriptor

./osx/hardened_runtime_entitlements.plist # the list of entitlements used by codesign tool


2. two `.plist` declarations: one for the `.app` and another for signing with entitlements for [hardened runtime](https://wiki.lazarus.freepascal.org/Hardened_runtime_for_macOS).
3. a bash script that copies the build files and the template folder around, packs and signs them.

These are the steps the build script takes:

1.  Copy the template folder from `./osx/bundle` to `./go/build/outputs/osx-package/YourAppPackage/YourApp.app`
2.  Copy the build files from `./go/build/outputs/darwin` to `osx-package/YourAppPackage/YourApp.app/Contents/MacOS`
3.  If you have any dlls (dylibs) bundled, use `install_name_tool` to change the target of dll loader so it points to the bundled library files instead of the system ones. 
4.  Use `codesign` tool to sign the YourApp.app folder with the `Developer ID Application` certificate that should be present on the local keychain. The important options to use are: `--options=runtime`, `--timestamp` and `--entitlements ./osx/hardened_runtime_entitlements.plist` to be able to [notarise the app with Apple](https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow).
5.  Use `hdiutil` tool to create a `.dmg` image file from the `YourAppPackage` folder.
6.  Use `codesign` tool again to sign the `.dmg` package with the same certificate as previously.
7.  Use `altool` to [notarise the app with Apple](https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow). This requires an [app-specific password](https://support.apple.com/en-us/HT204397) to be present on the keychain with `AC_PASSWORD` as the name of keychain item. You can still use the `.dmg` package without this, but you will have to go to the system security preferences and allow it to run.