为什么 NDK 在构建时抛出未定义引用错误?
Why is NDK throwing Undefined Reference error on Build?
我在尝试使用 ndk 构建库时遇到此错误:
$ /cygdrive/d/android-ndk-r10d/ndk-build.cmd
[armeabi] SharedLibrary : libgame.so
jni/core/src/coreApplication.cpp:9: error: undefined reference to 'CCoreMessaging::CCoreMessaging()'
jni/core/src/coreApplication.cpp:11: error: undefined reference to 'CCoreScreenContainer::CCoreScreenContainer()'
jni/core/src/coreReference.h:75: error: undefined reference to 'CCoreRefClass::_RemoveRef(void*, bool)'
jni/core/src/coreReference.h:76: error: undefined reference to 'CCoreRefClass::_AddRef(void*, bool)'
jni/core/src/coreReference.h:58: error: undefined reference to 'CCoreRefClass::_RemoveRef(void*, bool)'
jni/core/src/coreReference.h:58: error: undefined reference to 'CCoreRefClass::_RemoveRef(void*, bool)'
jni/core/src/coreApplication.h:12: error: undefined reference to 'CCoreMessaging::~CCoreMessaging()'
jni/core/src/coreReference.h:58: error: undefined reference to CCoreRefClass::_RemoveRef(void*, bool)'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [obj/local/armeabi/libgame.so] Error 1
coreApplication.h:
<other includes>
#include "coreResources.h"
#include "coreMessaging.h"
class CCoreApplication
{
public:
CCoreApplication(CCoreContext& a_context);
virtual ~CCoreApplication() {}
CCoreScreenContainer& GetScreenContainer() { return *m_screenContainer; }
CCoreMessaging& GetMessages() { return m_messages; }
<other functions and properties>
CCoreMessaging m_messages;
};
coreApplication.cpp
#include "coreApplication.h"
#include "coreMessaging.h"
#include "coreScreenContainer.h"
<other includes>
CCoreApplication::CCoreApplication(CCoreContext& a_context):
m_context(a_context)
{
m_screenContainer = new CCoreScreenContainer;
GetScreenContainer().SetBounds(CRectangle(0,0, a_context.GetPlatformHandler()->GetResolutionWidth(), a_context.GetPlatformHandler()->GetResolutionHeight()));
}
coreMessaging.h:
class CCoreMessaging
{
public:
CCoreMessaging();
~CCoreMessaging();
void SendMessage(int a_messageID, void* argument0=0, void* argument1=0);
void AddMessageHandler(CCoreMessageHandle& handle, CCoreMessageDelegate handler);
void RemoveMessageHandler(CCoreMessageHandle& handle);
protected:
typedef std::map<int, CCoreMessageDelegate> Map;
Map m_Delegates;
int m_AutoIncrement;
int m_SelfID;
static int m_SelfIDIncrement;
};
coreMessaging.cpp
#include "coreMessaging.h"
<other functions>
CCoreMessaging::CCoreMessaging() : m_AutoIncrement(1)
{
m_SelfID = m_SelfIDIncrement++;
gMessaging[m_SelfID] = this;
if(m_SelfID > 127)
throw std::runtime_error("too many messaging instances");
}
coreReference.h
class MFAPI CCoreRefClass
{
public:
virtual void Delete() { delete this; }
void _AddRef(void* cls, bool strong);
void _RemoveRef(void* cls, bool strong);
void _IncRef();
bool _DecRef(); // returns true if reference decrease has lead to destruction. false if object is still valid
protected:
CCoreRefClass();
virtual ~CCoreRefClass();
typedef CCoreRefPtr<CCoreRefClass,false> RefType;
std::vector<RefType*> m_refData;
int m_refCount;
};
coreReference.cpp
#include "coreReference.h"
<other functions>
void CCoreRefClass::_RemoveRef( void* cls, bool strong )
{
RefType* refCls = (RefType*)cls;
int lastIdx=(int)m_refData.size()-1;
int refIdx = refCls->m_arrayIndex;
refCls->m_arrayIndex = -1;
// swap erase reference
m_refData[refIdx] = m_refData[lastIdx];
m_refData[refIdx]->m_arrayIndex = refIdx;
m_refData.pop_back();
if(strong)
_DecRef();
}
void CCoreRefClass::_AddRef( void* cls, bool strong )
{
if(strong)
_IncRef();
RefType* refCls = (RefType*)cls;
m_refData.push_back(refCls);
refCls->m_arrayIndex = (int)m_refData.size()-1;
}
这些错误中的大部分似乎是由打字错误产生的,但这段代码确实在 visual studio 中作为 lib 完全编译。
我希望这只是我错过或没见过的东西。
如果需要,请随时提出更多要求。
编辑:
application.mk
APP_STL := gnustl_static
APP_CPPFLAGS += -std=c++11
NDK_TOOLCHAIN_VERSION := 4.8
APP_PLATFORM := android-14
android.mk
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := game
LOCAL_SRC_FILES := coreBridge.cpp core/game.cpp core/src/coreApplication.cpp
LOCAL_LDLIBS := -llog -lGLESv2
include $(BUILD_SHARED_LIBRARY)
#include $(BUILD_EXECUTABLE)
您没有将定义这些符号的文件添加到构建中:
coreMessaging.cpp
coreReference.cpp
大概
coreScreen.cpp (that i don't see here).
包括 headers 意味着只添加声明。您需要编译源代码以获得 object 个文件,其中包含 link 时间用户使用的实际符号。
感谢 Bogdan V。我发现我需要包含所有源文件。
但是,与其 link 将它们全部分开,它们都可以同时 link:
Android.mk:
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := libgame
LOCAL_SRC_FILES := coreBridge.cpp core/game.cpp
FILE_LIST := $(wildcard $(LOCAL_PATH)/../../../core/src/*.cpp)
LOCAL_SRC_FILES += $(FILE_LIST:$(LOCAL_PATH)/%=%) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../core/include
LOCAL_LDLIBS := -llog -lGLESv2
LOCAL_CPP_FEATURES += exceptions
LOCAL_SHARED_LIBRARIES := libgame.so
include $(BUILD_SHARED_LIBRARY)
#include $(BUILD_EXECUTABLE)
其中:
FILE_LIST := $(wildcard $(LOCAL_PATH)/../../../core/src/*.cpp)
LOCAL_SRC_FILES += $(FILE_LIST:$(LOCAL_PATH)/%=%) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../core/include
是 link 全部的重要部分。
毕竟,这让我能够创建 .so。
我在尝试使用 ndk 构建库时遇到此错误:
$ /cygdrive/d/android-ndk-r10d/ndk-build.cmd [armeabi] SharedLibrary : libgame.so
jni/core/src/coreApplication.cpp:9: error: undefined reference to 'CCoreMessaging::CCoreMessaging()'
jni/core/src/coreApplication.cpp:11: error: undefined reference to 'CCoreScreenContainer::CCoreScreenContainer()'
jni/core/src/coreReference.h:75: error: undefined reference to 'CCoreRefClass::_RemoveRef(void*, bool)'
jni/core/src/coreReference.h:76: error: undefined reference to 'CCoreRefClass::_AddRef(void*, bool)'
jni/core/src/coreReference.h:58: error: undefined reference to 'CCoreRefClass::_RemoveRef(void*, bool)'
jni/core/src/coreReference.h:58: error: undefined reference to 'CCoreRefClass::_RemoveRef(void*, bool)'
jni/core/src/coreApplication.h:12: error: undefined reference to 'CCoreMessaging::~CCoreMessaging()'
jni/core/src/coreReference.h:58: error: undefined reference to CCoreRefClass::_RemoveRef(void*, bool)'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [obj/local/armeabi/libgame.so] Error 1
coreApplication.h:
<other includes>
#include "coreResources.h"
#include "coreMessaging.h"
class CCoreApplication
{
public:
CCoreApplication(CCoreContext& a_context);
virtual ~CCoreApplication() {}
CCoreScreenContainer& GetScreenContainer() { return *m_screenContainer; }
CCoreMessaging& GetMessages() { return m_messages; }
<other functions and properties>
CCoreMessaging m_messages;
};
coreApplication.cpp
#include "coreApplication.h"
#include "coreMessaging.h"
#include "coreScreenContainer.h"
<other includes>
CCoreApplication::CCoreApplication(CCoreContext& a_context):
m_context(a_context)
{
m_screenContainer = new CCoreScreenContainer;
GetScreenContainer().SetBounds(CRectangle(0,0, a_context.GetPlatformHandler()->GetResolutionWidth(), a_context.GetPlatformHandler()->GetResolutionHeight()));
}
coreMessaging.h:
class CCoreMessaging
{
public:
CCoreMessaging();
~CCoreMessaging();
void SendMessage(int a_messageID, void* argument0=0, void* argument1=0);
void AddMessageHandler(CCoreMessageHandle& handle, CCoreMessageDelegate handler);
void RemoveMessageHandler(CCoreMessageHandle& handle);
protected:
typedef std::map<int, CCoreMessageDelegate> Map;
Map m_Delegates;
int m_AutoIncrement;
int m_SelfID;
static int m_SelfIDIncrement;
};
coreMessaging.cpp
#include "coreMessaging.h"
<other functions>
CCoreMessaging::CCoreMessaging() : m_AutoIncrement(1)
{
m_SelfID = m_SelfIDIncrement++;
gMessaging[m_SelfID] = this;
if(m_SelfID > 127)
throw std::runtime_error("too many messaging instances");
}
coreReference.h
class MFAPI CCoreRefClass
{
public:
virtual void Delete() { delete this; }
void _AddRef(void* cls, bool strong);
void _RemoveRef(void* cls, bool strong);
void _IncRef();
bool _DecRef(); // returns true if reference decrease has lead to destruction. false if object is still valid
protected:
CCoreRefClass();
virtual ~CCoreRefClass();
typedef CCoreRefPtr<CCoreRefClass,false> RefType;
std::vector<RefType*> m_refData;
int m_refCount;
};
coreReference.cpp
#include "coreReference.h"
<other functions>
void CCoreRefClass::_RemoveRef( void* cls, bool strong )
{
RefType* refCls = (RefType*)cls;
int lastIdx=(int)m_refData.size()-1;
int refIdx = refCls->m_arrayIndex;
refCls->m_arrayIndex = -1;
// swap erase reference
m_refData[refIdx] = m_refData[lastIdx];
m_refData[refIdx]->m_arrayIndex = refIdx;
m_refData.pop_back();
if(strong)
_DecRef();
}
void CCoreRefClass::_AddRef( void* cls, bool strong )
{
if(strong)
_IncRef();
RefType* refCls = (RefType*)cls;
m_refData.push_back(refCls);
refCls->m_arrayIndex = (int)m_refData.size()-1;
}
这些错误中的大部分似乎是由打字错误产生的,但这段代码确实在 visual studio 中作为 lib 完全编译。 我希望这只是我错过或没见过的东西。 如果需要,请随时提出更多要求。
编辑: application.mk
APP_STL := gnustl_static
APP_CPPFLAGS += -std=c++11
NDK_TOOLCHAIN_VERSION := 4.8
APP_PLATFORM := android-14
android.mk
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := game
LOCAL_SRC_FILES := coreBridge.cpp core/game.cpp core/src/coreApplication.cpp
LOCAL_LDLIBS := -llog -lGLESv2
include $(BUILD_SHARED_LIBRARY)
#include $(BUILD_EXECUTABLE)
您没有将定义这些符号的文件添加到构建中:
coreMessaging.cpp
coreReference.cpp
大概
coreScreen.cpp (that i don't see here).
包括 headers 意味着只添加声明。您需要编译源代码以获得 object 个文件,其中包含 link 时间用户使用的实际符号。
感谢 Bogdan V。我发现我需要包含所有源文件。 但是,与其 link 将它们全部分开,它们都可以同时 link:
Android.mk:
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := libgame
LOCAL_SRC_FILES := coreBridge.cpp core/game.cpp
FILE_LIST := $(wildcard $(LOCAL_PATH)/../../../core/src/*.cpp)
LOCAL_SRC_FILES += $(FILE_LIST:$(LOCAL_PATH)/%=%) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../core/include
LOCAL_LDLIBS := -llog -lGLESv2
LOCAL_CPP_FEATURES += exceptions
LOCAL_SHARED_LIBRARIES := libgame.so
include $(BUILD_SHARED_LIBRARY)
#include $(BUILD_EXECUTABLE)
其中:
FILE_LIST := $(wildcard $(LOCAL_PATH)/../../../core/src/*.cpp)
LOCAL_SRC_FILES += $(FILE_LIST:$(LOCAL_PATH)/%=%) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../core/include
是 link 全部的重要部分。 毕竟,这让我能够创建 .so。