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

Taming the NDK Dragon for Cross-Platform development

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.

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.