Introjucer: No Android Studio support for Import Shared/Static Libraries

Hi all,

I could be wrong about this, especially because I'm new to Android, but it appears that in the Introjucer, nothing happens when you populate the entries for "Import Static Libraries" or "Import Shared Libraries" of an AndroidStudio exporter. My understanding is that an Android.mk (makefile) should be created, in which there are scripts to link these libraries (which apparenlty should be located in the path to your environment variable NDK_MODULE_PATH).

But there appears to be no files/lines of code in my generated android project that correspond to whatever I put in the "Import Static Libraries" or "Import Shared Libraries" entries in my AndroidStudio config settings. Am I missing something here?

I also checked the Introjucer source code (jucer_ProjectExport_AndroidStudio.h), but there seems to be no mention of static libararies/shared libraries in that file. jucer_ProjectExport_Android.h does seem to handle shared/static libraries; they are used when writing the Android.mk file. This makes me think that something similar should be happening for an AndroidStudio export.

Let me know if this is a problem or if I missed something. Also, any advice about how to link an existing shared-object library (lib<X>.so) to my AndroidStudio build would be great (and maybe could be nice to have in a tutorial in the future?). Also I'd like to know if my understanding about the NDK_MODULE_PATH is correct, and why they decided to go for an environment variable instead of a config option.

Hi,

Are you referring to the two fields "Import static library modules" and "Import shared library modules"?

If yes, then you're right, nothing happens for Android Studio when you populate them. They seem to be a leftover from the Android Ant exporter that we forgot to remove.

In Android Studio, there is no "Android.mk" (makefile) and that whole old system where you'd specify those imports doesn't exist. Instead, they have to be added with a different syntax to the build.gradle file (which is the analogue of the makefile in the old Android Ant world).

You can use the fields "Extra linker flags" and "External libraries to link" though. They will work for Android Studio and add the correct linker options to the build.gradle file.

Would that work for you?

Thanks for the reply!

Yes, I did mean "Import static library modules" and "Import shared library modules". I figured it might be something like you said.

Still, "Extra linker flags" also appears to do nothing...and I can't seem to figure out to correctly load the library.

What I'm currently doing:
1. Add the library search path using the "Extra library search paths" field under the Debug or Release config. (Right now I'm using an absolute path, but i'd like for this to eventually be a relative path, and I don't think that'll be a problem.)
2. Add the name of the library (of course excluding the 'lib' prefix and the file extension) using the "External libraries to link" field.

I'm doing this because these fields generate corresponding code in the build.gradle file. One thing I noticed is that in the generated build.gradle file, the ldlibs.addAll() call (where my library linking flag is being added) is inside the android.ndk, juce_jni module block, but the "Extra library search paths" puts the -L flag to the library search path under the android.buildTypes block. I wonder if that's correct or not (I have no idea myself)?

I get the link error:

"<PATH_TO_ANDROID_NDK>/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9/../../../../i686-linux-android/bin/ld: error: cannot find -lGUIDOEngine-android

Where my library name is libGUIDOEngine-android.so. Any suggestions?
 

Still, "Extra linker flags" also appears to do nothing...

Yes, what you are describing is another bug that I fixed today. It's not pushed yet though—this whole Android Studio exporter turned out to be quite messy and full of bugs so I decided to refactor it and clean it up. I should be able to push the new (and hopefully bug-free) version tomorrow, please be patient.

Sounds good! Thanks for this, I know it is a pain and of course takes time.

Hi,

I just pushed a massive re-factoring of the Android Studio exporter which should get rid of all the Introjucer bugs in that area.

Please update to the newest tip and check out whether "Extra linker flags" and all the other options now finally work as they should.

1. I get a compile error when building the Introjucer in the Release Scheme. It works under the Debug Scheme for me, though.
Log:

CompileC /Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/Objects-normal/x86_64/jucer_ProjectExporter.o /Users/me/Documents/JUCE/extras/Introjucer/Source/Project\ Saving/jucer_ProjectExporter.cpp normal x86_64 c++ com.apple.compilers.llvm.clang.1_0.compiler

    cd /Users/me/Documents/JUCE/extras/Introjucer/Builds/MacOSX

    export LANG=en_US.US-ASCII

    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x c++ -arch x86_64 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=c++11 -Wno-trigraphs -fpascal-strings -O3 -Wno-missing-field-initializers -Wno-missing-prototypes -Wnon-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wno-shorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -D_NDEBUG=1 -DNDEBUG=1 -DJUCER_XCODE_MAC_F6D2F4CF=1 -DJUCE_APP_VERSION=4.1.0 -DJUCE_APP_VERSION_HEX=0x40100 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -fasm-blocks -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -mmacosx-version-min=10.5 -fvisibility=hidden -fvisibility-inlines-hidden -Wno-sign-conversion -iquote /Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/Introjucer-generated-files.hmap -I/Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/Introjucer-own-target-headers.hmap -I/Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/Introjucer-all-target-headers.hmap -iquote /Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/Introjucer-project-headers.hmap -I/Users/me/Documents/JUCE/extras/Introjucer/Builds/MacOSX/build/Release/include -I../../JuceLibraryCode -I../../../../modules -I/Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/DerivedSources/x86_64 -I/Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/DerivedSources -Wreorder -F/Users/me/Documents/JUCE/extras/Introjucer/Builds/MacOSX/build/Release -Wall -Wshadow -Wno-missing-field-initializers -Wshadow -Wshorten-64-to-32 -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wconversion -Wsign-compare -Wint-conversion -Woverloaded-virtual -Wreorder -Wconstant-conversion -Wsign-conversion -MMD -MT dependencies -MF /Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/Objects-normal/x86_64/jucer_ProjectExporter.d --serialize-diagnostics /Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/Objects-normal/x86_64/jucer_ProjectExporter.dia -c /Users/me/Documents/JUCE/extras/Introjucer/Source/Project\ Saving/jucer_ProjectExporter.cpp -o /Users/me/Library/Developer/Xcode/DerivedData/The_Introjucer-gawtwmzqfjvcotaixocbfsjveqct/Build/Intermediates/The\ Introjucer.build/Release/The\ Introjucer.build/Objects-normal/x86_64/jucer_ProjectExporter.o

 

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp:33:

/Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_AndroidStudio.h:432:48: error: no member named 'forward' in namespace 'std'

            children.add (new GradleType (std::forward<Args> (args)...));

                                          ~~~~~^

/Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_AndroidStudio.h:432:56: error: 'Args' does not refer to a value

            children.add (new GradleType (std::forward<Args> (args)...));

                                                       ^

/Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_AndroidStudio.h:429:52: note: declared here

        template <typename GradleType, typename... Args>

                                                   ^

/Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_AndroidStudio.h:607:21: error: no matching constructor for initialization of 'juce::StringArray'

        StringArray cppFlags { "-fsigned-char", "-fexceptions", "-frtti", "-std=c++11" };

                    ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp:25:

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/../jucer_Headers.h:33:

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/../../JuceLibraryCode/JuceHeader.h:17:

In file included from ../../JuceLibraryCode/modules/juce_core/juce_core.h:4:

In file included from ../../JuceLibraryCode/modules/juce_graphics/../../../../../modules/juce_graphics/../juce_core/juce_core.h:210:

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:60:5: note: candidate constructor not viable: requires 2 arguments, but 4 were provided

    StringArray (const String* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:67:5: note: candidate constructor not viable: requires 2 arguments, but 4 were provided

    StringArray (const char* const* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:87:5: note: candidate constructor not viable: requires 2 arguments, but 4 were provided

    StringArray (const wchar_t* const* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:47:5: note: candidate constructor not viable: requires 1 argument, but 4 were provided

    StringArray (const StringArray&);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:50:5: note: candidate constructor not viable: requires 1 argument, but 4 were provided

    StringArray (StringArray&&) noexcept;

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:54:14: note: candidate constructor not viable: requires single argument 'firstValue', but 4 arguments were provided

    explicit StringArray (const String& firstValue);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:74:14: note: candidate constructor not viable: requires single argument 'strings', but 4 arguments were provided

    explicit StringArray (const char* const* strings);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:80:14: note: candidate constructor not viable: requires single argument 'strings', but 4 arguments were provided

    explicit StringArray (const wchar_t* const* strings);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:44:5: note: candidate constructor not viable: requires 0 arguments, but 4 were provided

    StringArray() noexcept;

    ^

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp:33:

/Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_AndroidStudio.h:625:21: error: no matching constructor for initialization of 'juce::StringArray'

        StringArray includePaths { "${project.rootDir}/app", "${ext.juceRootDir}", "${ext.juceModuleDir}" };

                    ^            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp:25:

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/../jucer_Headers.h:33:

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/../../JuceLibraryCode/JuceHeader.h:17:

In file included from ../../JuceLibraryCode/modules/juce_core/juce_core.h:4:

In file included from ../../JuceLibraryCode/modules/juce_graphics/../../../../../modules/juce_graphics/../juce_core/juce_core.h:210:

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:60:5: note: candidate constructor not viable: requires 2 arguments, but 3 were provided

    StringArray (const String* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:67:5: note: candidate constructor not viable: requires 2 arguments, but 3 were provided

    StringArray (const char* const* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:87:5: note: candidate constructor not viable: requires 2 arguments, but 3 were provided

    StringArray (const wchar_t* const* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:47:5: note: candidate constructor not viable: requires 1 argument, but 3 were provided

    StringArray (const StringArray&);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:50:5: note: candidate constructor not viable: requires 1 argument, but 3 were provided

    StringArray (StringArray&&) noexcept;

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:54:14: note: candidate constructor not viable: requires single argument 'firstValue', but 3 arguments were provided

    explicit StringArray (const String& firstValue);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:74:14: note: candidate constructor not viable: requires single argument 'strings', but 3 arguments were provided

    explicit StringArray (const char* const* strings);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:80:14: note: candidate constructor not viable: requires single argument 'strings', but 3 arguments were provided

    explicit StringArray (const wchar_t* const* strings);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:44:5: note: candidate constructor not viable: requires 0 arguments, but 3 were provided

    StringArray() noexcept;

    ^

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp:33:

/Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExport_AndroidStudio.h:667:21: error: no matching constructor for initialization of 'juce::StringArray'

        StringArray libs {"android", "EGL", "GLESv2", "log"};

                    ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp:25:

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/../jucer_Headers.h:33:

In file included from /Users/me/Documents/JUCE/extras/Introjucer/Source/Project Saving/../../JuceLibraryCode/JuceHeader.h:17:

In file included from ../../JuceLibraryCode/modules/juce_core/juce_core.h:4:

In file included from ../../JuceLibraryCode/modules/juce_graphics/../../../../../modules/juce_graphics/../juce_core/juce_core.h:210:

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:60:5: note: candidate constructor not viable: requires 2 arguments, but 4 were provided

    StringArray (const String* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:67:5: note: candidate constructor not viable: requires 2 arguments, but 4 were provided

    StringArray (const char* const* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:87:5: note: candidate constructor not viable: requires 2 arguments, but 4 were provided

    StringArray (const wchar_t* const* strings, int numberOfStrings);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:47:5: note: candidate constructor not viable: requires 1 argument, but 4 were provided

    StringArray (const StringArray&);

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:50:5: note: candidate constructor not viable: requires 1 argument, but 4 were provided

    StringArray (StringArray&&) noexcept;

    ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:54:14: note: candidate constructor not viable: requires single argument 'firstValue', but 4 arguments were provided

    explicit StringArray (const String& firstValue);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:74:14: note: candidate constructor not viable: requires single argument 'strings', but 4 arguments were provided

    explicit StringArray (const char* const* strings);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:80:14: note: candidate constructor not viable: requires single argument 'strings', but 4 arguments were provided

    explicit StringArray (const wchar_t* const* strings);

             ^

../../JuceLibraryCode/modules/juce_core/../../../../../modules/juce_core/text/juce_StringArray.h:44:5: note: candidate constructor not viable: requires 0 arguments, but 4 were provided

    StringArray() noexcept;

    ^

5 errors generated.



2. The build.gradle code generated from the "Extra linker flags" field includes an extra quote at the end, as for example:

ldFlags.add("-L../../Libraries/Binaries/Guido/Android/Debug"")

3. Should the "Header search paths" and "Extra library search paths" fileds in the configuration add ldFlags instead cppFlags?

eg.
cppFlags.add("-L../../Libraries/Binaries/Guido/Android/Debug")

should be

ldFlags.add("-L../../Libraries/Binaries/Guido/Android/Debug")

Should be fixed now, please update to the newest tip.

Hello everybody,

I’m new in JUCE, have been working with it only for 1 and a half month now. I want to create an Android build of my project. The project has to be linked with two external libraries, GUIDO Engine and musicxml2, specifically. I compiled both .so files using the ndk-build command, but was only able to link them to the Android build by manually changing the experimental Gradle (version 0.7.2), project folders and by using commands that Projucer doesn’t currently support. Here is a snippet:

> repositories {
>       libs(PrebuiltLibraries){
>             guido {
>                 headers.srcDir "${project.rootDir}/app/src/main/jniLibs/Guido/include"
>                 binaries.withType(SharedLibraryBinary) {
>                     sharedLibraryFile = file("${project.rootDir}/app/src/main/jniLibs/${targetPlatform.getName()}/libGUIDOEngine.so")
>                 }
>             }
>       }
> }

Of course, this is not a durable solution since Projucer overwrites the build folder. I tried several configurations using Projucer fields, none of them led to an executable application. Sometimes it wouldn’t compile because of undefined references to methods I call from those libraries, others gave UnsatisfiedLinkError because the .so libraries wouldn’t be found by Android Studio, just like with cplaguna.

I’m wondering if anybody has managed to successfully link shared libraries to Android builds with Projucer, and could assist me? Any help will be appreciated.

PS: As cplaguna pointed out, the Extra Linker Flags is still leading to an extra quote at the end of the string.