Как настроить CMake для создания приложения для iPhone
Вопрос
Это тесно связано с моим предыдущий вопрос, в котором говорилось об использовании CMake для создания статической библиотеки на iPhone.Я заставил это сработать, установив CMAKE_OSX_SYSROOT
.
Однако это не работает для создания приложения.Мой CMakeLists.txt
выглядит как:
project(TEST)
set(CMAKE_OSX_SYSROOT iphoneos2.2.1)
set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_BIT)")
set(CMAKE_EXE_LINKER_FLAGS
"-framework Foundation -framework OpenGLES -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit -framework OpenAL"
)
set(SRC --my files--)
add_executable(iphone-test MACOSX_BUNDLE ${SRC})
Несколько заметок:
- Я недвусмысленно даю
-framework
вариант связывания, потому чтоfind_library
не работал для всех фреймворков (он нашел большинство из них, но неOpenGLES
).Я не понимаю почему, поскольку все они находятся в одной папке${SDK}/System/Library/Frameworks
.Это наводит меня на мысль, что я делал что-то не так, но я не знаю, что именно. - Я добавил
MACOSX_BUNDLE
к томуadd_executable
команда, чтобы сгенерированный тип продукта былcom.apple.product-type.application
вместо того , чтобыcom.apple.product-type.tool
, который, по-видимому, не существует на iPhone.
В любом случае, приложение компилируется и связывается корректно, но когда я запускаю его в симуляторе, я получаю страшное
Failed to launch simulated application: Unknown error.
В Google и stackoverflow зарегистрировано множество случаев этой проблемы, но все решения включают очистку или создание нового проекта и перемещение файлов;но я компилирую новую копию после того, как CMake выполнит свою работу, так что все это неприменимо.
Я нашел этот поток в списке рассылки CMake, но он сообщает только об успехе в создании библиотеки, а затем исчезает.
Решение
Я наконец-то понял, как это сделать.Вот что мой CMakeLists.txt
файл выглядит следующим образом:
project(test)
set(NAME test)
file(GLOB headers *.h)
file(GLOB sources *.cpp)
set(CMAKE_OSX_SYSROOT iphoneos2.2.1)
set(CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_32_BIT))
set(CMAKE_CXX_FLAGS "-x objective-c++")
set(CMAKE_EXE_LINKER_FLAGS
"-framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit"
)
link_directories(\${HOME}/\${SDKROOT}/lib)
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.mycompany.\${PRODUCT_NAME:identifier}")
set(APP_TYPE MACOSX_BUNDLE)
add_executable(${NAME}
${APP_TYPE}
${headers}
${sources}
)
target_link_libraries(${NAME}
# other libraries to link
)
# code signing
set_target_properties(${NAME} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer: My Name")
Очевидно, что изменить mycompany
к названию вашей компании и измените My Name
на твое имя.Я обнаружил, что очень полезно добавить каталог ссылок \${HOME}/\${SDKROOT}/lib
как указано выше, так что, если ваше приложение ссылается на статическую библиотеку (особенно на универсальную библиотеку (не для iPhone)), вы можете создавать отдельные библиотеки iPhoneOS и iPhoneSimulator и легко ссылаться на нужную, вместо того чтобы беспокоиться об универсальном двоичном коде.
Кроме того, Xcode, похоже, неправильно добавляет ресурсы при сборке проекта с использованием CMake, поэтому я добавил эту часть в CMakeLists.txt
файл.Он копирует всю папку целиком /data
в мою папку ресурсов (как если бы я добавил ссылку на "синюю" папку в Xcode).
# copy resource phase
set(APP_NAME \${TARGET_BUILD_DIR}/\${FULL_PRODUCT_NAME})
set(RES_DIR ${test_SOURCE_DIR}/data)
add_custom_command(
TARGET ${NAME}
POST_BUILD
COMMAND /Developer/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp -exclude .DS_Store -exclude CVS -exclude .svn -resolve-src-symlinks ${RES_DIR} ${APP_NAME}
)
Другие советы
Что касается фреймворков, я нашел это сообщение http://www.mail-archive.com/cmake@cmake.org/msg24659.html Я собрал достаточно информации для этого:
SET(TARGETSDK iPhoneOS3.1.2.sdk)
SET(CMAKE_OSX_SYSROOT /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/${TARGETSDK})
macro(ADD_FRAMEWORK fwname appname)
find_library(FRAMEWORK_${fwname}
NAMES ${fwname}
PATHS ${CMAKE_OSX_SYSROOT}/System/Library
PATH_SUFFIXES Frameworks
NO_DEFAULT_PATH)
if( ${FRAMEWORK_${fwname}} STREQUAL FRAMEWORK_${fwname}-NOTFOUND)
MESSAGE(ERROR ": Framework ${fwname} not found")
else()
TARGET_LINK_LIBRARIES(${appname} ${FRAMEWORK_${fwname}})
MESSAGE(STATUS "Framework ${fwname} found at ${FRAMEWORK_${fwname}}")
endif()
endmacro(ADD_FRAMEWORK)
Вместо того, чтобы устанавливать CMAKE_EXE_LINKER_FLAGS, теперь я делаю:
ADD_FRAMEWORK(AudioToolbox MyApp)
ADD_FRAMEWORK(CoreGraphics MyApp)
ADD_FRAMEWORK(QuartzCore MyApp)
ADD_FRAMEWORK(UIKit MyApp)
Это работает и для OpenGLES.
Последние версии CMake передают файлы .m и .mm компилятору C ++, который определяет язык по расширению, поэтому вам не нужно явно добавлять "-x objective-c ++" к флагам.