VisualGDB and Android (.mk) static libraries not linking

Sysprogs forums Forums VisualGDB VisualGDB and Android (.mk) static libraries not linking

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #905
    Anonymous
    Participant

    VisualGDB Evalution expires in 9 days. Help here would be greatly appreciated and a strong recommendation to by a full license.

    This is about my experience of building an Android GoogleTest static library, a program with functionality that requires testing, and an Android UnitTest program to carry out the task of testing on the Android OS. This is much a record of my attempt to produce the above as it is to gain help or make others aware of problems in what should be a simple exercise. I wanted to build the programs for Android using Visual Studio 2013. I installed and set up the pre-requisites:

    Android SDK
    Android NDK
    Environment variables for the above SDK and NDK
    VisualGDB

    I downloaded GoogleTest, unzipped it and put it someplace which I could access from Visual Studio easily. It comes as a set of source files with examples and build projects for various operating systems, but not for Android. An example is given in a readme, but it got me only so far. The code for this exercise is simple enough, the problem I believe lies with creating the correct Android .mk files. I wanted the following setup to perform a test on one math function:

    GoogleTest static library
    SimpleMath executable
    UnitTestSimpleMath executable

    In a Visual Studio solution I had three projects; one for each of the above. To prove that the GoogleTest set up above worked, I first did this exercise for Windows. The code built and linked against the GoogleTest static library, forming an executable which ran in a console window. All things at this stage worked as hoped and expected.

    GoogleTestWindowsRan

    Ok, so now to do the same thing for Android. I created another solution, with three VisualGDB Android projects this time. I have not used VisualGDB before and so did not realise for a while that while there is a VisualGDB properties dialogue (which edits the .mk files) the editing of the standard project properties does not have any effect on how the Android code is built. Hence I could not build the following code because various include files could not be found. Once I realised this, I concentrated on the editing of just the .mk files. The code for this exercise is as follows.

    For the SimpleMath executable I had the following:

    
    Main.cpp:
    
    #include
    #include "SimpleMath.h"

    int main( int argc, char **argv ) {
    double stopDeadCodeStripping = cubic( 10.0 );
    printf( "The cubic of 10 is %fn", stopDeadCodeStripping );
    return 0;
    }

    For SimpleMath.c:

    include "SimpleMath.h"
    
    double cubic( double d ) {
    return d * d * d;
    } 

    For UnitTestSimpleMath, the project just has one file, UnitTestSimpleMath.cpp:

    #include
    #include"SimpleMath.c"
    #include

    TEST( testMath, myCubicTest ) {
    EXPECT_EQ( 1000, cubic( 10 ));
    }

    int main( int argc, char **argv ) {
    printf( "Running main() from UnitTestSimpleMath.cpp. Cubic of 10 is %fn", cubic( 10 ) );
    printf( "Running tests...n" );
    ::testing::InitGoogleTest( &argc, argv );
    return RUN_ALL_TESTS();
    }

    So, the only important settings when building Android projects are contained within the Android.mk and Application.mk files. These can be editing directly or by using the VisualGDB project properties. For the GoogleTest project the .mk files are as follows.

    For Android.mk:

    
    #VisualGDBAndroid: AutoUpdateSourcesInNextLine
    LOCAL_CPP_EXTENSION := .cc .cpp
    LOCAL_SRC_FILES := src/gtest-all.cc
    LOCAL_C_INCLUDES := jni/include
    LOCAL_EXPORT_C_INCLUDES := jni/include
    LOCAL_STATIC_LIBRARIES :=
    LOCAL_SHARED_LIBRARIES :=
    LOCAL_LDLIBS :=
    LOCAL_CFLAGS :=
    LOCAL_CPPFLAGS :=
    LOCAL_LDFLAGS :=
    COMMON_SRC_FILES :=
    include $(BUILD_STATIC_LIBRARY)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := GoogleTest-shared
    #VisualGDBAndroid: AutoUpdateSourcesInNextLine
    LOCAL_CPP_EXTENSION := .cc .cpp
    LOCAL_SRC_FILES := D:/Dev/gtest-1.7.0/src/gtest-all.cc
    LOCAL_C_INCLUDES := D:/Dev/MyFirstAndroidGoogleTest/GoogleTest/jni/include
    LOCAL_EXPORT_C_INCLUDES := D:/Dev/gtest-1.7.0/include
    LOCAL_EXPORT_C_INCLUDES += D:/Dev/gtest-1.7.0
    LOCAL_STATIC_LIBRARIES :=
    LOCAL_SHARED_LIBRARIES :=
    LOCAL_LDLIBS :=
    LOCAL_CFLAGS :=
    LOCAL_CPPFLAGS :=
    LOCAL_LDFLAGS :=
    COMMON_SRC_FILES :=
    include $(BUILD_SHARED_LIBRARY)
    

    As you can see, there are two approaches that I used to prove the GoogleTest libraries could be built. The first involved specifying directly that the files required could be found in the directory where I installed the GoogleTest code. The other references code copied to the source and includes directories in the project’s jni directory.

    For Application.mk:

    # Generated by VisualGDB
    APP_MODULES := GoogleTest-static GoogleTest-shared
    APP_ABI := all
    APP_STL := gnustl_shared
    

    This project builds and forms a shared library (.so) and a static library (.a), of 689KB and 2581KB respectively.

    For the SimpleMath executable project the .mk files are the following:

    For Android.mk:

    # Generated by VisualGDB
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := SimpleMath
    #VisualGDBAndroid: AutoUpdateSourcesInNextLine
    LOCAL_SRC_FILES := main.c SimpleMath.c
    LOCAL_C_INCLUDES :=
    LOCAL_EXPORT_C_INCLUDES := SimpleMath.h
    LOCAL_STATIC_LIBRARIES :=
    LOCAL_SHARED_LIBRARIES :=
    LOCAL_LDLIBS :=
    LOCAL_CFLAGS :=
    LOCAL_CPPFLAGS :=
    LOCAL_LDFLAGS :=
    COMMON_SRC_FILES := $(LOCAL_SRC_FILES)
    include $(BUILD_EXECUTABLE)
    

    For Application.mk:

    # Generated by VisualGDB
    APP_MODULES :=
    APP_ABI := all
    

    For the UnitTestSimpleMath executable project, the .mk files are the following:

    For Android.mk:

    # Generated by VisualGDB
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := GoogleTest-static
    LOCAL_SRC_FILES := ../../GoogleTest/obj/local/armeabi/libGoogleTest-static.a
    LOCAL_EXPORT_C_INCLUDES := D:/Dev/gtest-1.7.0/include D:/Dev/gtest-1.7.0
    include $(PREBUILT_STATIC_LIBRARY)
    
    include $(CLEAR_VARS)
    GTEST_DIR := D:/Dev/gtest-1.7.0
    LOCAL_MODULE := UnitTestSimpleMath
    #VisualGDBAndroid: AutoUpdateSourcesInNextLine
    LOCAL_SRC_FILES := UnitTestSimpleMath.cpp
    LOCAL_C_INCLUDES := ../SimpleMath/jni D:/Dev/gtest-1.7.0/include D:/Dev/gtest-1.7.0
    LOCAL_SHARED_LIBRARIES :=
    LOCAL_STATIC_LIBRARIES := GoogleTest-static
    LOCAL_STATIC_LIBRARIES += SimpleMath-static
    LOCAL_LDLIBS :=
    LOCAL_CFLAGS :=
    LOCAL_CPPFLAGS :=
    LOCAL_LDFLAGS :=
    LOCAL_LDFLAGS :=
    COMMON_SRC_FILES := $(LOCAL_SRC_FILES)
    include $(BUILD_EXECUTABLE)
    
    $(call import-module,third_party/googletest)
    

    For Application.mk:

    # Generated by VisualGDB
    APP_ABI := all
    APP_STL := gnustl_shared
    APP_OPTIM := debug
    

    The problem I have been having is that, while the GoogleTest and SimpleMath code builds fine, building the UnitTestSimpleMath project fails. This is because it is unable to find references to GoogleTest functions, giving errors such as: UnitTestSimpleMath.cpp:14: error: undefined reference to ‘testing::InitGoogleTest(int*, char**)’. After much Google searching, the .mk files above have formed into what they are now, but something is still missing to complete the build.

    I can add the following to the UnitTestSimpleMathTest’s .mk file: LOCAL_SRC_FILES += D:/Dev/gtest-1.7.0/src/gtest-all.cc. The project will then build and run on the Android OS. However, this should not be necessary. It voids the reason to have a GoogleTest static library, with the code contained nicely separated elsewhere, and not dragged in to this project. Also, in the many edits of the .mk files and NO errors reported as to why and what is happening, I discovered that removing or just entering bogus library names made no difference to the build outcome:

    LOCAL_STATIC_LIBRARIES := GooxxxxxgleTest-static
    LOCAL_STATIC_LIBRARIES += SimxxxxpleMath-static
    

    They appear to do nothing, yet every example of how to build an Android program and link in a static library has this LOCAL_STATIC_LIBRARIES entry. Also consider the following lines:

    include $(CLEAR_VARS)
    LOCAL_MODULE := GoogleTest-static
    LOCAL_SRC_FILES := ../../GoogleTest/obj/local/armeabi/libGoogleTest-static.a
    LOCAL_EXPORT_C_INCLUDES := D:/Dev/gtest-1.7.0/include D:/Dev/gtest-1.7.0
    include $(PREBUILT_STATIC_LIBRARY)
    

    These can be removed from the same .mk file without any errors or information, or changing the outcome of the build, apart from just not building. Though I have had a learning curve with using VisualGDB, and with the general concept of building an Android static linked program, I believe that the problem simply lies with the .mk file itself.

    #3377
    Illya
    Participant

    Though I believe the problem is likely to be with usage of the .mk file there is a possibility that VisualGDB is not handling the .mk file correctly. I would like this either confirmed or otherwise.

    #3376
    ket
    Participant

    Hi,

    Getting the linking syntax correct in Android makefiles can be tricky as different path syntax is expected for different variables. Some variable values only work with relative paths or paths relative to LOCAL_PATH. VisualGDB only passes the makefiles along to make, so the problem must lie within the makefiles.
    VisualGDB handles the library dependencies of projects inside the same solution automatically if you set project dependencies. With the logic VisualGDB uses for its library dependencies each library project is built separately when VS builds them, the projects dependent on other library projects do not rebuild them.
    Have you tried looking at our Android library tutorial for help?

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.