Компилировать / связывать FreeImage для iOS 5.0

Недавно я решил попробовать запустить часть своего графического кода на устройстве iOS, но я использую FreeImage для загрузки текстур. В результате мне нужно собрать его для iOS 5.0.

В настоящее время я получаю ошибки ссылок при попытке использовать библиотеку FreeImage. Все ошибки ссылок связаны со стандартной библиотекой C ++. Например…

Undefined symbols for architecture i386:
"std::basic_string<char, std::char_traits<char>, std::allocator<char>>::~basic_string()", referenced from:
_FreeImage_GetMetadata in libfreeimage-iphonesimulator.a(BitmapAccess.o-i386)
_FreeImage_SetMetadata in libfreeimage-iphonesimulator.a(BitmapAccess.o-i386)
_FreeImage_CloneMetadata in libfreeimage-iphonesimulator.a(BitmapAccess.o-i386)
_FreeImage_Clone in libfreeimage-iphonesimulator.a(BitmapAccess.o-i386)
std::pair<std::string const, FITAG*>::~pair() in libfreeimage-iphonesimulator.a(BitmapAccess.o-i386)
Load(FreeImageIO*, void*, int, int, void*) in libfreeimage-iphonesimulator.a(PluginEXR.o-i386)
C_OStream::write(char const*, int) in libfreeimage-iphonesimulator.a(PluginEXR.o-i386)
...

К сожалению, поставляемый make-файл для сборки FreeImage для iOS немного устарел, поэтому я был вынужден обновить его. Кроме того, в моем проекте XCode я переключил компилятор для поддержки функций C ++ 11 и использования libc ++ (как описано здесь Могу ли я использовать C ++ 11 с Xcode?)

Поэтому я попытался отразить эти изменения в make-файле для FreeImage, но я все еще получаю эти ошибки.

Мой make-файл выглядит так (я нашел этот пост несколько полезным http://sourceforge.net/p/freeimage/discussion/36110/thread/51445acc)

# Configuration for iPhone OS, making static libs
# this will generate both iPhone (arm) and iPhoneSimulator (i686) libs

include Makefile.srcs

CFLAGS =  -g -O2 -Wall -Wmissing-prototypes -std=c99 -ffast-math -fno-strict-aliasing
CXXFLAGS = -g -O2 -Wall -fno-strict-aliasing -std=c++0x -stdlib=libc++

GCC_VERSION = 4.2
IPHONEOS_DEPLOYMENT_TARGET = 5.0
MACOSX_DEPLOYMENT_TARGET = 10.6

PLATFORM_SIM = iPhoneSimulator
PLATFORM_PHONE = iPhoneOS

ARCH_SIM = i386
ARCH_PHONE = armv7

PLATFORM_SIM_DEVELOPER_BIN_DIR = /Developer/Platforms/$(PLATFORM_SIM).platform/Developer/usr/bin
PLATFORM_PHONE_DEVELOPER_BIN_DIR = /Developer/Platforms/$(PLATFORM_PHONE).platform/Developer/usr/bin

SDKROOT_SIM = /Developer/Platforms/$(PLATFORM_SIM).platform/Developer/SDKs/$(PLATFORM_SIM)$(IPHONEOS_DEPLOYMENT_TARGET).sdk
SDKROOT_PHONE = /Developer/Platforms/$(PLATFORM_PHONE).platform/Developer/SDKs/$(PLATFORM_PHONE)$(IPHONEOS_DEPLOYMENT_TARGET).sdk

EXTRA_CFLAGS_SIM += -arch $(ARCH_SIM) -pipe -mdynamic-no-pic -fvisibility=hidden $(INCLUDE) -isysroot $(SDKROOT_SIM)
EXTRA_LDFLAGS_SIM += -arch $(ARCH_SIM) -isysroot $(SDKROOT_SIM) -Wl,-dead_strip
EXTRA_CFLAGS_SIM += -D__IPHONE_OS_VERSION_MIN_REQUIRED=20000 -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET)
EXTRA_LDFLAGS_SIM += -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET)

EXTRA_CFLAGS_PHONE += -arch $(ARCH_PHONE) -pipe -mdynamic-no-pic -fvisibility=hidden $(INCLUDE) -isysroot $(SDKROOT_PHONE)
EXTRA_LDFLAGS_PHONE += -arch $(ARCH_PHONE) -isysroot $(SDKROOT_PHONE) -Wl,-dead_strip
EXTRA_CFLAGS_PHONE += -miphoneos-version-min=$(IPHONEOS_DEPLOYMENT_TARGET)
EXTRA_LDFLAGS_PHONE += -miphoneos-version-min=$(IPHONEOS_DEPLOYMENT_TARGET)

AR_SIM = $(PLATFORM_SIM_DEVELOPER_BIN_DIR)/ar
AR_PHONE = $(PLATFORM_PHONE_DEVELOPER_BIN_DIR)/ar

CC_SIM = $(PLATFORM_SIM_DEVELOPER_BIN_DIR)/llvm-gcc-$(GCC_VERSION)
CC_PHONE = $(PLATFORM_PHONE_DEVELOPER_BIN_DIR)/llvm-gcc-$(GCC_VERSION)

CFLAGS_SIM = $(CFLAGS) $(EXTRA_CFLAGS_SIM)
LDFLAGS_SIM = $(EXTRA_LDFLAGS_SIM)
CXX_SIM = $(PLATFORM_SIM_DEVELOPER_BIN_DIR)/clang++
CXXFLAGS_SIM += $(EXTRA_CFLAGS_SIM) -fvisibility-inlines-hidden
LIBTOOL_SIM = /Developer/Platforms/$(PLATFORM_SIM).platform/Developer/usr/bin/libtool

CFLAGS_PHONE = $(CFLAGS) $(EXTRA_CFLAGS_PHONE)
LDFLAGS_PHONE += $(EXTRA_LDFLAGS_PHONE)
CXX_PHONE = $(PLATFORM_PHONE_DEVELOPER_BIN_DIR)/clang++
CXXFLAGS_PHONE += $(EXTRA_CFLAGS_PHONE) -fvisibility-inlines-hidden
LIBTOOL_PHONE = /Developer/Platforms/$(PLATFORM_PHONE).platform/Developer/usr/bin/libtool

TARGET = freeimage
STATICLIB_SIM = lib$(TARGET)-iphonesimulator.a
STATICLIB_PHONE = lib$(TARGET)-iphone.a
HEADER = Source/FreeImage.h

.SUFFIXES: .o-i386 .o-arm
MODULES_ARM = $(SRCS:.c=.o-arm)
MODULES_ARM := $(MODULES_ARM:.cpp=.o-arm)
MODULES_i386 = $(SRCS:.c=.o-i386)
MODULES_i386 := $(MODULES_i386:.cpp=.o-i386)

default: all

all: dist

dist: FreeImage
cp *.a Dist
cp Source/FreeImage.h Dist

FreeImage: $(STATICLIB_SIM) $(STATICLIB_PHONE)

$(STATICLIB_SIM): $(MODULES_i386)
$(LIBTOOL_SIM) -arch_only $(ARCH_SIM) -o $@ $(MODULES_i386)

.c.o-i386:
$(CC_SIM) $(CFLAGS_SIM) -c $< -o $@

.cpp.o-i386:
$(CXX_SIM) $(CXXFLAGS_SIM) -c $< -o $@

$(STATICLIB_PHONE): $(MODULES_ARM)
$(LIBTOOL_PHONE) -arch_only $(ARCH_PHONE) -o $@ $(MODULES_ARM)

.c.o-arm:
$(CC_PHONE) $(CFLAGS_PHONE) -c $< -o $@

.cpp.o-arm:
$(CXX_PHONE) $(CXXFLAGS_PHONE) -c $< -o $@

clean:
rm -f core Dist/*.* u2dtmp* $(MODULES_i386) $(MODULES_ARM) $(STATICLIB_SIM) $(STATICLIB_PHONE)

Возможно, кто-то может указать, где я иду не так

Редактировать:
Я исправил проблему, когда он не восстанавливал объектные файлы i386, надеясь, что это будет решением, однако он все еще имеет те же ошибки связи.

Редактировать:
Я настроил свой make-файл для использования clang ++

Я также добавил libc ++ в связанные фреймворки

введите описание изображения здесь

А вот мои настройки для проекта XCode в отношении C ++

введите описание изображения здесь

У меня также есть файлы .cpp в моем проекте XCode. Ошибки, однако, все еще сохраняются.

Edit3:

Результаты по запрашиваемому запросу:

nm libfreeimage-iphonesimulator.a | c++filt | grep '~basic_string()' | sort -u
nm: no name list
nm: no name list
U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()

Полный вывод ошибок компоновщика можно найти здесь: http://pastebin.com/wjbWgE4S

3

Решение

Проекты Цель C используют clang компилятор (вы все еще можете использовать gcc), который (технически говоря) C компилятор, а не C++ компилятор. Он достаточно умен, чтобы использовать расширения файлов, чтобы определить, компилировать ли код как C, Objective C или же C++,

Когда вы связываете проект Objective C, он связывается, используя clang, который не является ссылкой в C++ во время выполнения. Вам нужно сделать ссылку во время выполнения.

Если вы строите свою библиотеку, используя libc++ библиотека, то вам нужно будет добавить libc++ к списку библиотек, которые связаны с проектом в Build Phases -> Link Binary With Libraries, Если вы строите с libstdc++ библиотека, то вам нужно будет добавить libstdc++ к списку библиотек, которые связаны в.

Xcode достаточно умен, чтобы связать, используя clang++ если есть хотя бы один C++ файл в проекте, устраняя необходимость явной ссылки в C++ время выполнения в этой ситуации.

ТЛ; др — похоже, вы не компилируете C++ код для симулятора с теми же флагами, что и при создании основного приложения. Линия:

CXXFLAGS_SIM += $(EXTRA_CFLAGS_SIM) -fvisibility-inlines-hidden

на самом деле отсутствует база $(CXXFLAGS) пункт и должен читать:

CXXFLAGS_SIM += $(CXXFLAGS) $(EXTRA_CFLAGS_SIM) -fvisibility-inlines-hidden

аналогично для CXXFLAGS_PHONE линия

в результате вы смешиваете libc++ а также libstdc++ скомпилированный код, который приводит к ошибке ссылки. Это должен был быть намек на то, что CXXFLAGS линия не использовалась, так как c++ в начале строки компиляции, которая вызвала бы ошибку компиляции, если бы она использовалась в любом коде.

Есть и другие проблемы, например, использовать libc++ Ваша цель развертывания iPhone должна быть iOS 5 или более поздней (так __IPHONE_OS_VERSION_MIN_REQUIRED=50000 необходим для компиляции симулятора), и вам нужно исправить некоторые файлы из-за проблем с расширением знака, например,

Source/LibRawLite/./internal/dcraw_common.cpp:3926:19: error: constant expression evaluates to 128 which cannot be narrowed to type 'signed char' [-Wc++11-narrowing]

Если вы хотите проверить, C++ код был скомпилирован с -stdlib=libc++ или же -stdlib=libstdc++Вы можете сделать nm любого из результирующего скомпилированного кода, передавая его через c++filt, Если вы видите пространство имен std::__1::Затем код был скомпилирован с -stdlib=libc++иначе он был скомпилирован с -stdlib=libstdc++

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]