Compiling android app using boost, undefined reference to 'mbtowc'
Asked Answered
S

2

6

I am trying to compile an android app using boost 1-49's serialization library. Specifically, this project had some convenient scripts to get the job done: https://github.com/MysticTreeGames/Boost-for-Android

Boost built without issue against the official ndk-r8, using gnu-libstdc++ 4.6 for armeabi-v7a.

At least, it was able to create libboost_serialization-gcc-mt-1_49.a without encountering any errors. Several warnings were thrown up during build, 'forbids zero-size array '_pad' [-pedantic]', 'does not support 'long long', 'does not permit named variadic macros', nothing that seemed serious, but I don't claim to be an expert on the gnu compiler.

Building boost also created libboost_wserialization-gcc-mt-1_49.a, which seemed odd, but is probably irrelevant. I did not include it in my makefiles.

In any case, when I now try to compile my code using this library, I get the following errors:

/Users/wespaugh/Development/android-ndk-r8d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/libboost_serialization-gcc-mt-1_49.a(xml_iarchive.o): in function boost::archive::xml_iarchive_impl<boost::archive::xml_iarchive>::load(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&):./boost/archive/impl/xml_iarchive_impl.ipp:71: error: undefined reference to 'mbtowc'
/Users/wespaugh/Development/android-ndk-r8d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/libboost_serialization-gcc-mt-1_49.a(xml_iarchive.o): in function boost::archive::xml_iarchive_impl<boost::archive::xml_iarchive>::load(wchar_t*):./boost/archive/impl/xml_iarchive_impl.ipp:101: error: undefined reference to 'mbtowc'
/Users/wespaugh/Development/android-ndk-r8d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/libboost_serialization-gcc-mt-1_49.a(xml_iarchive.o): in function boost::archive::xml_iarchive_impl<boost::archive::naked_xml_iarchive>::load(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&):./boost/archive/impl/xml_iarchive_impl.ipp:71: error: undefined reference to 'mbtowc'
/Users/wespaugh/Development/android-ndk-r8d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/libboost_serialization-gcc-mt-1_49.a(xml_iarchive.o): in function boost::archive::xml_iarchive_impl<boost::archive::naked_xml_iarchive>::load(wchar_t*):./boost/archive/impl/xml_iarchive_impl.ipp:101: error: undefined reference to 'mbtowc'
/Users/wespaugh/Development/android-ndk-r8d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/libboost_serialization-gcc-mt-1_49.a(xml_oarchive.o): in function boost::archive::iterators::ostream_iterator<char> std::__copy_move<false, false, std::input_iterator_tag>::__copy_m<boost::archive::iterators::mb_from_wchar<boost::archive::iterators::xml_escape<wchar_t const*> >, boost::archive::iterators::ostream_iterator<char> >(boost::archive::iterators::mb_from_wchar<boost::archive::iterators::xml_escape<wchar_t const*> >, boost::archive::iterators::mb_from_wchar<boost::archive::iterators::xml_escape<wchar_t const*> >, boost::archive::iterators::ostream_iterator<char>):./boost/archive/iterators/mb_from_wchar.hpp:91: error: undefined reference to 'wctomb'
collect2: ld returned 1 exit status

EDIT

OK, I've made some progress on this over lunch. By actually digging into those src files in boost, I found that mbtowc and its reciprocal are part of gnu-libstdc++. So, somehow when I build boost it must not be getting the right references. Can't give it any more time over lunch, but I've looked at how boost was compiled, and the flags used should have linked everything appropriately.

From the build log:

Building with TOOLSET=gcc-androidR8 CXXPATH=/Users/wespaugh/Development/android-ndk-r8d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/arm-linux-androideabi-g++ CXXFLAGS=-I/Users/wespaugh/Development/android-ndk-r8d/platforms/android-14/arch-arm/usr/include -I/Users/wespaugh/Development/android-ndk-r8d/sources/cxx-stl/gnu-libstdc++/4.6/include -I/Users/wespaugh/Development/android-ndk-r8d/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include

End edit

Given that I'm getting errors with the library, and that it's the only library that I use in code, I wouldn't think there could be a problem with makefiles. For the sake of thoroughness, though, here are there contents: Android.mk, included where I keep the compiled boost library:

# define module to include serialization static library
LOCAL_PATH:= $(call my-dir)

# serialization
include $(CLEAR_VARS)

LOCAL_CFLAGS += -I$(LOCAL_PATH)/include/boost-1_49

# -L$(LOCAL_PATH)/lib/ 
LOCAL_LDLIBS += -lboost_serialization \
        -L$(NDK_ROOT)/sources/cxx-stl/ gnu-libstdc++/4.6/libs/armeabi-v7a \
        -lgnustl_static

LOCAL_CPPFLAGS += -fexceptions
LOCAL_CPPFLAGS += -frtti

LOCAL_CPP_EXTENSION := .cpp .hpp

LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/boost-1_49 \
                    $(LOCAL_PATH)/include/boost-1_49/boost/archive \
                    $(LOCAL_PATH)/include/boost-1_49/boost/serialization

LOCAL_MODULE:= boost_serialization
LOCAL_SRC_FILES:= lib/libboost_serialization-gcc-mt-1_49.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../../Classes
include $(PREBUILT_STATIC_LIBRARY)

Android.mk, in proj.android/jni/

# compile the app
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LDFLAGS= -L$(NDK_ROOT)/sources/crystax/libs/armeabi-v7a/4.6.3 -Lcrystax 

LOCAL_CPPFLAGS += -fexceptions 

LOCAL_CPPFLAGS += -frtti

LOCAL_MODULE := game_shared

LOCAL_MODULE_FILENAME := libgame

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \
                   ../../Classes/HelloWorldScene.cpp 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \
        $(LOCAL_PATH)/../../../cocos2dx/platform/third_party/android/prebuilt/libboost/include/boost-1_49 \
        $(LOCAL_PATH)/../../../cocos2dx/platform/third_party/android/prebuilt/libboost/include/boost-1_49/boost/archive \
        $(LOCAL_PATH)/../../../cocos2dx/platform/third_party/android/prebuilt/libboost/include/boost-1_49/boost/serialization

LOCAL_WHOLE_STATIC_LIBRARIES := boost_serialization cocos2dx_static cocosdenshion_static cocos_extension_static

include $(BUILD_SHARED_LIBRARY)

$(call import-module,CocosDenshion/android) \
$(call import-module,cocos2dx)
$(call import-module,libboost)

My best guess is that I'm not building boost correctly, but can't say for sure. What could be causing those errors? I can't even seem to google the files that are allegedly referenced in the serialization library ('mbtowc' and permutations). Is it trying to reference the system or filesystem boost libraries, which I did not include via makefile?

Scrap answered 17/1, 2013 at 14:46 Comment(0)
S
1

Boost serialization isn't supported on android-ndk-r8. I will look into crystaX r7 and see how that goes. The key difference is support for wchar, it seems. Here's hoping.

EDIT: OK, maybe it does. I don't know anymore. Depending who you ask, you might hear that the official ndk does support wchars, and its just a matter of managing boost's config files to know enough about the platform you're building to.

Further, I'm also learning that apparently there are problems with boost crashing with crystaX's NDK.

Expect me back here next week saying, 'no no, actually I was right the second time, and half-right the fourth' /bitter

Scrap answered 18/1, 2013 at 4:33 Comment(3)
any luck? Just started hitting this issue myself.Fannie
It's impossible! The serialization library is incompatible with Android NDK. My solution: give up and write something myself to handle my saving and loading needs. 4 months of my life, over a hundred hours researching and testing and asking questions, trying different combinations of boost distributions, NDKs, versions of GCC, all of it for naught. Save yourself the headache and find another way to accomplish this. Maybe a better version of the NDK will come along and fix it, maybe not. Wait until someone proves it possible before trying.Scrap
good advice. spent several days on this myself, and I think I've found every comment you've made on the subject across the entire internet :). My hack: turns out our code uses the serialization library, but doesn't hit those particular functions, so we modified boost-for-android to #def out the bodies of the offending functions. It was only in two places I think.Fannie
S
0

I had the same problem. I was creating an android port for code that uses boost::serialization.

My code did not use std::wstring or wchar_t anywhere.

I compiled boost for android following the advice on this link: http://www.codexperiments.com/android/2011/05/tips-tricks-building-boost-with-ndk-r5/

I am using boost-1.55_0 and NDK r9c. And I had the same errors ->

error: undefined reference to 'mbtowc' / error: undefined reference to 'wctomb'

However I recompiled boost adding the following flag (via the jam configuration file):

<compileflags>-DBOOST_NO_STD_WSTRING

This time the resulting library did not use mbtowc and serialization works for me.

Snorkel answered 12/5, 2014 at 17:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.