Come configurare CMake per creare un'app per iPhone
Domanda
Questo è strettamente correlato al mio domanda precedente , che riguardava l'utilizzo di CMake per creare una libreria statica su iPhone. Ho capito che funziona impostando il CMAKE_OSX_SYSROOT
.
Tuttavia, questo non funziona per creare un'app. Il mio CMakeLists.txt
è simile a:
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})
Alcune note:
- Fornisco esplicitamente l'opzione di collegamento
-framework
perchéfind_library
non ha funzionato per tutti i framework (ne ha trovati la maggior parte, ma nonOpenGLES
). Non capisco perché, poiché sono tutti nella stessa cartella$ {SDK} / Sistema / Libreria / Frameworks
. Questo mi porta a credere che stavo facendo qualcosa di sbagliato, ma non so cosa. - Ho aggiunto
MACOSX_BUNDLE
al comandoadd_executable
in modo che il tipo di prodotto generato siacom.apple.product-type.application
invece dicom.apple.product-type.tool
, che apparentemente non esiste su iPhone.
In ogni caso, l'app si compila e si collega correttamente, ma quando la eseguo nel simulatore, ottengo il temuto
Failed to launch simulated application: Unknown error.
Esistono molte istanze segnalate di questo problema su Google e StackOverflow, ma tutte le soluzioni prevedono la pulizia o la creazione di un nuovo progetto e lo spostamento dei file; ma sto compilando una nuova copia dopo che CMake ha fatto il suo lavoro, quindi nulla di tutto ciò si applica.
Ho trovato questa discussione nella mailing list di CMake , ma segnala solo un successo nella costruzione di una biblioteca e quindi si protesta.
Soluzione
Alla fine ho capito come fare. Ecco come appare il mio file 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")
Ovviamente, cambia mycompany
nel nome della tua azienda e cambia My Name
nel tuo nome. Ho trovato molto utile aggiungere la directory dei collegamenti \ $ {HOME} / \ $ {SDKROOT} / lib
come sopra, in modo che se l'app si collega a una libreria statica (in particolare un generico (non- iPhone)), puoi creare librerie iPhoneOS e iPhoneSimulator separate e collegarti facilmente a quella giusta, invece di preoccuparti di un binario universale.
Inoltre, Xcode non sembra aggiungere correttamente le risorse quando costruisci il progetto usando CMake, quindi ho aggiunto questo pezzo al file CMakeLists.txt
. Copia l'intera cartella / data
nella mia cartella delle risorse (come se avessi aggiunto un link alla cartella "blu" in 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}
)
Altri suggerimenti
Per i framework, ho trovato questo messaggio http: //www.mail -archive.com/cmake@cmake.org/msg24659.html Ho preso abbastanza informazioni per questo:
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)
Invece di impostare CMAKE_EXE_LINKER_FLAGS, ora lo faccio:
ADD_FRAMEWORK(AudioToolbox MyApp)
ADD_FRAMEWORK(CoreGraphics MyApp)
ADD_FRAMEWORK(QuartzCore MyApp)
ADD_FRAMEWORK(UIKit MyApp)
Questo funziona anche con OpenGLES.
Le versioni recenti di CMake passano i file .m e .mm al compilatore C ++, che rileva la lingua attraverso l'estensione, quindi non è necessario aggiungere " -x goal-c ++ " alle bandiere esplicitamente.