Martijn Courteaux
Martijn Courteaux

Reputation: 68887

Android makefile links twice

I've set up a makefile for my game in SDL. The template of the Application.mk file included in SDL has three architectures:

APP_ABI := armeabi armeabi-v7a x86

Everything compiles just fine for armeabi, but for armeabi-v7a it fails. To me, it looks like compilation completes, but the linker has all obj files of two certain folders twice. While this does not happen for armeabi. The linker (ld) gives me an error of this kind:

/path/to/bin/ld: error: /path/to/myObjFile.obj: multiple definition of 'foo(int, int)'
/path/to/bin/ld: /path/to/myObjFile.obj: previous definition here

The path is exactly the same, so this makes me assume that the linker uses every file twice. A full example of such an error is here:

/Users/martijncourteaux/Development/android-ndk-r10c/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: /Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/obj/local/armeabi-v7a/objs/main//Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/jni/src/__/ThirdParty/Box2D/Collision/b2Distance.o: multiple definition of 'b2Distance(b2DistanceOutput*, b2SimplexCache*, b2DistanceInput const*)'
/Users/martijncourteaux/Development/android-ndk-r10c/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: /Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/obj/local/armeabi-v7a/objs/main//Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/jni/src/__/ThirdParty/Box2D/Collision/b2Distance.o: previous definition here

However, the object files that are linked double also generate this warning when I launch ndk-build:

/Users/martijncourteaux/Development/android-ndk-r10c/build/core/build-binary.mk:449: warning: ignoring old commands for target `/Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/obj/local/armeabi-v7a/objs/main//Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/jni/src/__/ThirdParty/Collision/b2Distance.o'
/Users/martijncourteaux/Development/android-ndk-r10c/build/core/build-binary.mk:449: warning: overriding commands for target `/Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/obj/local/armeabi-v7a/objs/main//Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/jni/src/__/ThirdParty/Collision/b2Distance.o'

Note that I have the impression that all these obj-files that have these multiple definition errors generate also generate this warning.

This is my Application.mk:

APP_STL := gnustl_static
APP_ABI := armeabi armeabi-v7a x86
NDK_TOOLCHAIN_VERSION := clang
APP_CPPFLAGS += -std=c++11
APP_PLATFORM := android-10

And here is my Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := main

SDL_PATH := ../SDL
THIRD_PARTY_FOLDER := $(LOCAL_PATH)/../ThirdParty

LOCAL_CPPFLAGS += -frtti
LOCAL_CPPFLAGS += -fexceptions
LOCAL_CPPFLAGS += -funwind-tables

PCH_FILE := $(LOCAL_PATH)/Gump/Gump-Prefix.pch
#PCH_FILE := Gump/Gump-Prefix.pch
LOCAL_CPPFLAGS += -include $(PCH_FILE) 

#LOCAL_PCH := $(PCH_FILE)
#LOCAL_CPPFLAGS += -DPCH

LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include \
                    $(LOCAL_PATH)/$(SDL_PATH)_mixer/ \
                    $(LOCAL_PATH)/$(SDL_PATH)_image/ \
                    $(LOCAL_PATH)/$(SDL_PATH)_net/ \
                    $(LOCAL_PATH)/../ThirdParty/ \
                    $(LOCAL_PATH)/Gump/

# Add your application source files here...
GUMP_SRC_FILES := $(wildcard $(LOCAL_PATH)/Gump/*.cpp)
THIRD_PARTY_SRC_FILES += $(wildcard $(THIRD_PARTY_FOLDER)/tinyxml2/tinyxml2.cpp)

THIRD_PARTY_SRC_FILES += $(wildcard $(THIRD_PARTY_FOLDER)/Box2D/*/*.cpp)
THIRD_PARTY_SRC_FILES += $(wildcard $(THIRD_PARTY_FOLDER)/Box2D/*/*/*.cpp)

THIRD_PARTY_SRC_FILES += $(wildcard $(THIRD_PARTY_FOLDER)/poly2tri/**/*.cc)

LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c $(THIRD_PARTY_SRC_FILES) $(GUMP_SRC_FILES)

LOCAL_SHARED_LIBRARIES := SDL2_image SDL2_mixer SDL2_net SDL2 

LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog

include $(BUILD_SHARED_LIBRARY)

My Guess (turns out false):

After writing this question and looking closely to provide you guys the most accurate information as possible about my problem, I noticed that the obj-files that are giving errors are those were I've used a wildcard on folder level as well. Eg: $(ROOT)/*/*.cpp. While these wildcards give no problem: $(ROOT)/Gump/*.cpp. I don't know for sure, but I guess that the wildcards work different on when linking for these different architectures...

Update:

I've tested it again not using wildcards for folders, and the same error about multiple definition appears.

Upvotes: 1

Views: 805

Answers (2)

Alex Cohn
Alex Cohn

Reputation: 57183

Your list of files is appended every time a new ABI is being built. LOCAL_SRC_FILES is erased through include $(CLEAR_VARS); GUMP_SRC_FILES is redefined each time. But THIRD_PARTY_SRC_FILES only grows longer and longer. This has nothing to do with the wildcards, as you noticed. Simply add line

THIRD_PARTY_SRC_FILES :=

after include $(CLEAR_VARS), and your build will be fine.

Upvotes: 1

Martijn Courteaux
Martijn Courteaux

Reputation: 68887

Running ndk-build V=1 shows the build commands executed during the process. There I could see the .o files being linked twice. I'm not sure what the reason for that is. I guess it might have been due to the fact that the android makefile in the src/ folder used sources from his parent directory: ../ThirdParty/[morehere].

I fixed it by creating extra makefiles for these third party libraries, so now every library creates a shared library in a .so file. Which gets linked at compile-time. I think this is neater, because changing a makefile requires only that subproject to be recompiled.

Upvotes: 0

Related Questions