Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Taming the NDK Dragon for Cross-Platform develo...

Taming the NDK Dragon for Cross-Platform development

Talk about how PSPDFKit uses C++ shared code to do cross-platform development between Android, iOS, OS X, Linux and Windows.

Avatar for Jernej Virag

Jernej Virag

June 16, 2016
Tweet

More Decks by Jernej Virag

Other Decks in Technology

Transcript

  1. Jernej Virag / PSPDFKit Taming the NDK dragon So much

    choice… j2objc Xamarin RoboVM LUA ObjC Apportable Swift JavaScript Appcelerator Titanium C / C++
  2. Jernej Virag / PSPDFKit Taming the NDK dragon So much

    choice… C / C++ Supported on pretty much ALL platforms with first party compilers.
  3. Jernej Virag / PSPDFKit Taming the NDK dragon Benefits •

    No duplication for important bussiness logic. • Several sets of eyes on the same code. • Platform independence “for free” - compiles on iOS, Android, Linux, OS X and Windows. • Significant time savings in the development process.
  4. Jernej Virag / PSPDFKit Taming the NDK dragon Project setup

    C++ main logic Android glue Android UI
 Java APIs Linux CLI Windows CLI ObjC APIs iOS Mac
  5. Jernej Virag / PSPDFKit Taming the NDK dragon . ʮʒʒ

    README.md ʮʒʒ android ʔ ʮʒʒ build ʔ ʮʒʒ build.gradle ʔ ʮʒʒ CHANGELOG.md ʔ ʮʒʒ checkstyle ʔ ʮʒʒ documentation ʔ ʮʒʒ gradle ʔ ʮʒʒ gradle.properties ʔ ʮʒʒ gradlew ʔ ʮʒʒ gradlew.bat ʔ ʮʒʒ local.properties ʔ ʮʒʒ local.properties.sample ʔ ʮʒʒ pretty-gradle ʔ ʮʒʒ pspdfcatalog ʔ ʮʒʒ pspdfkit ʔ ʮʒʒ pspdfkit-tests ʔ ʮʒʒ README.md ʔ ʦʒʒ settings.gradle ʮʒʒ assets ʔ ʮʒʒ ... test pdf assets ... ʮʒʒ cli ʔ ʮʒʒ CMakeLists.txt ʔ ʮʒʒ README.md ʔ ʮʒʒ Vendor ʔ ʮʒʒ build ʔ ʦʒʒ src ʔ ʮʒʒ tools ʔ ʮʒʒ README.md ʔ ʦʒʒ … misc tools … ʮʒʒ core ʔ ʮʒʒ Android.mk ʔ ʮʒʒ AndroidTestHost ʔ ʮʒʒ CHANGELOG.md ʔ ʮʒʒ CMakeLists.txt ʔ ʮʒʒ PSPDFCore ʔ ʮʒʒ PSPDFCoreTestHost ʔ ʮʒʒ PSPDFCoreTests ʔ ʮʒʒ README.md ʔ ʮʒʒ Rakefile ʔ ʮʒʒ Vendor ʔ ʮʒʒ build ʔ ʮʒʒ libs ʮʒʒʒ iOS ʔ ʮʒʒ CHANGELOG.md ʔ ʮʒʒ PSPDFKit ʔ ʮʒʒ PSPDFKit\ KIF\ Tests ʔ ʮʒʒ PSPDFKit\ KIF-TestHost ʔ ʮʒʒ README.md ʔ ʮʒʒ PSPDFKit-Tests ʔ ʮʒʒ PSPDFKit-Tests.xcodeproj ʔ ʮʒʒ PSPDFKit.xcworkspace ʔ ʮʒʒ PSPDFKitSnapshotTests ʔ ʮʒʒ README.md ʔ ʮʒʒ Resources ʦʒʒʒʒ Samples PSPDFKit Monorepo
  6. Jernej Virag / PSPDFKit Taming the NDK dragon NDK •

    LLVM / Clang 3.8 or GCC 4.9 • C++ STL libraries: stdc++, gabi++, stlport, gnustl and libc++ • Access to: • OpenGL ES 1.0 - 3.1 • OpenSL ES • OpenMAX AL • zlib • logcat • sensors • configuration • APK assets • OBB files
  7. Jernej Virag / PSPDFKit Taming the NDK dragon NDK -

    Compiling • ndk-build with custom .mk configuration • Gradle Experimental Plugin • Standalone toolchain with standard tools 
 (CMake, etc.) } lib/<arch>/libname.so
  8. Jernej Virag / PSPDFKit Taming the NDK dragon NDK C++

    STL libraries: libstdc++, gabi++, stlport, gnustl, libc++ None of them fully featured. ¯\_(ϑ)_/¯
  9. Jernej Virag / PSPDFKit Taming the NDK dragon Architectures CPU

    TYPE ARM5/6** ARM7 ARM8 X86 X86_64 MIPS*** armeabi ✓ ✓ ✓ ✓ ✓ armeabi-v7a ✓ ✓ ✓* ✓ arm64-v8a ✓ x86 ✓ ✓ x86_64 ✓ mips ✓ * via libhoudini, slower and potentially buggy ** obsolete architecture, not used anymore
 *** no known consumer devices
  10. Jernej Virag / PSPDFKit Taming the NDK dragon JNI JVM

    DalvikVM ART libmyndklib.so Java Native Interface
  11. Jernej Virag / PSPDFKit Taming the NDK dragon JNI JNI

    is slow. Moving data from managed to unmanaged environment requires copying.
  12. Jernej Virag / PSPDFKit Taming the NDK dragon Djinni 


    
 https://github.com/dropbox/djinni
  13. Jernej Virag / PSPDFKit Taming the NDK dragon Djinni Page

    = interface +c { const get_text(): string; const get_page_info(): PageInfo; get_text_rect(coord: Point, tolerance: f32): optional<Rect>; close(); } Implementation in C++, interface in Java and ObjC
  14. Jernej Virag / PSPDFKit Taming the NDK dragon Java public

    class Page { public String getText() { .. }; public PageInfo getPageInfo() { .. }; public RectF getTextRect(Point coord, float tolerance) { .. }; public void close() { .. }; } C++ class Page { virtual std::string get_text() = 0; virtual PageInfo get_page_info() = 0; virtual std::optional<Rect> get_text_rect(Point coord, float tolerance) = 0; virtual void close() = 0; }
  15. Jernej Virag / PSPDFKit Taming the NDK dragon Djinni page.djinni

    NativePage.java
 Java API NativePage.cpp JNI glue Page.cpp
 Portable implementation PSPDFPage.mm Objective C API } }Android / other Java iOS / Mac
  16. Jernej Virag / PSPDFKit Taming the NDK dragon Djinni Page

    = interface +j +o { const get_text(): string; const get_page_info(): PageInfo; get_text_rect(coord: Point, tolerance: f32): optional<Rect>; close(); } Implementation in Java and/or Obj-C, interface in C++.
  17. Jernej Virag / PSPDFKit Taming the NDK dragon Debugging and

    testing Run tests on development machine.
  18. Jernej Virag / PSPDFKit Taming the NDK dragon Debugging and

    testing GTest https://github.com/google/googletest
  19. Jernej Virag / PSPDFKit Taming the NDK dragon GTest on

    Android device Android.mk, build binary Jenkins / TC JUnit output compatible script
  20. Jernej Virag / PSPDFKit Taming the NDK dragon Project setup

    C++ main logic Android glue Android UI
 Java APIs Linux CLI Windows CLI ObjC APIs iOS Mac
  21. Jernej Virag / PSPDFKit Taming the NDK dragon Project setup

    C++ main logic Android glue Android UI
 Java APIs Linux CLI Windows CLI ObjC APIs iOS Mac Unit tests Instrumentation tests iOS tests C++ GTest unit tests
  22. Jernej Virag / PSPDFKit Taming the NDK dragon Profiling •

    No good support at all - XCode Instruments still the best tool. • nVidia Tegra Profiler is the only working one - needs a (rooted) Tegra device. https://developer.nvidia.com/tegra-system-profiler
  23. Jernej Virag / PSPDFKit Taming the NDK dragon Dos and

    don’ts! • DO minimize cross-language calls. • DO use modern C++14 and use it wisely.
  24. Jernej Virag / PSPDFKit Taming the NDK dragon Dos and

    don’ts! • DON’T link against system libraries. • DON’T rely on C++ UTF implementation - use miniUTF or platform APIs. • DO offload heavy dependencies (regex, charsets, crypto) to platform libraries. • DO be conservative with dependencies - “smart” libraries will break. • DO link everyting in a single static .so library. Dynamic linking is full of issues on Android.