【问题标题】:Android makefile links twiceAndroid makefile 链接两次
【发布时间】:2014-11-12 22:14:44
【问题描述】:

我在 SDL 中为我的游戏设置了一个生成文件。 SDL中包含的Application.mk文件的模板有三种架构:

APP_ABI := armeabi armeabi-v7a x86

对于armeabi,一切都编译得很好,但对于armeabi-v7a,它失败了。对我来说,看起来编译完成了,但是链接器两次拥有两个特定文件夹的所有 obj 文件。虽然 armeabi 不会发生这种情况。链接器 (ld) 给了我这样的错误:

/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

路径完全相同,所以这让我假设链接器使用每个文件两次。此类错误的完整示例如下:

/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

但是,当我启动 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'

请注意,我的印象是,所有这些 obj 文件生成这些 multiple definition 错误也会生成此警告。

这是我的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

这是我的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)

我的猜测(结果是错误的):

在写完这个问题并仔细研究为你们提供关于我的问题的最准确信息之后,我注意到给出错误的 obj 文件是我在文件夹级别使用通配符的那些文件。例如:$(ROOT)/*/*.cpp。虽然这些通配符没有问题:$(ROOT)/Gump/*.cpp。我不确定,但我猜在链接这些不同架构时通配符的工作方式不同......

更新:

我又测试了一遍,文件夹不使用通配符,出现同样的多定义错误。

【问题讨论】:

    标签: android c++ makefile android-ndk linker


    【解决方案1】:

    每次构建新的 ABI 时都会附加您的文件列表。 LOCAL_SRC_FILESinclude $(CLEAR_VARS) 擦除; GUMP_SRC_FILES 每次都重新定义。但是THIRD_PARTY_SRC_FILES 只会越来越长。正如您所注意到的,这与通配符无关。只需添加一行

    THIRD_PARTY_SRC_FILES :=
    

    include $(CLEAR_VARS) 之后,你的构建就可以了。

    【讨论】:

    • 天才!我会记住的:)
    【解决方案2】:

    Running ndk-build V=1 显示了在此过程中执行的构建命令。在那里我可以看到.o 文件被链接了两次。我不确定这是什么原因。我想这可能是因为src/ 文件夹中的android makefile 使用了他的父目录中的源:../ThirdParty/[morehere]

    我通过为这些第三方库创建额外的 makefile 来修复它,所以现在每个库都在 .so 文件中创建一个共享库。在编译时链接。我认为这更简洁,因为更改 makefile 只需要重新编译该子项目。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      相关资源
      最近更新 更多