CMake cross-compile problem with CXX_FLAGS in linker
I have following toolchain for iPhone crosscompilation on mac os x:
# Platform Info
SET (CMAKE_SYSTEM_VERSION 1)
SET (CMAKE_SYSTEM_PROCESSOR arm)
# SDK Info
SET (SDKVER "3.0")
SET (DEVROOT "/Developer/Platforms/iPhoneOS.platform/Developer")
SET (SDKROOT "${DEVROOT}/SDKs/iPhoneOS${SDKVER}.sdk")
SET (CMAKE_OSX_SYSROOT "${SDKROOT}")
SET (CMAKE_OSX_ARCHITECTURES "armv6")
SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
# C Compiler
SET (CMAKE_C_COMPILER "${DEVROOT}/usr/bin/arm-apple-darwin9-gcc-4.2.1")
#SET (LINK_FLAGS "-arch armv6 -arch armv7")
#SET (CMAKE_C_LINK_EXECUTABLE "${DEVROOT}/usr/bin/g++-4.2")
SET (CMAKE_C_FLAGS "-x objective-c")
SET (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -DDEBUG=1 -ggdb")
SET (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -DNDEBUG=1")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -DNDEBUG=1 -ggdb")
# CXX Compiler
SET (CMAKE_CXX_COMPILER "${DEVROOT}/usr/bin/arm-apple-darwin9-g++-4.2.1")
SET (CMAKE_CXX_FLAGS "-x objective-c++")
SET (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -DDEBUG=1 -ggdb")
SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -DNDEBUG=1")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS} -DNDEBUG=1 -ggdb")
# Definitions
#ADD_DEFINITIONS("-arch armv6")
#ADD_DEFINITIONS("-arch armv7")
ADD_DEFINITIONS("-pipe")
ADD_DEFINITIONS("-no-cpp-precomp")
ADD_DEFINITIONS("--sysroot=${SDKROOT}")
ADD_DEFINITIONS("-miphoneos-version-min=${SDKVER}")
# System Includes
INCLUDE_DIRECTORIES(SYSTEM "${SDKROOT}/usr/include")
INCLUDE_DIRECTORIES(SYSTEM "${SDKROOT}/usr/include/c++/4.2.1")
INCLUDE_DIRECTORIES(SYSTEM "${SDKROOT}/usr/include/c++/4.2.1/armv6-apple-darwin9")
INCLUDE_DIRECTORIES(SYSTEM "${SDKROOT}/opt/iphone-${SDKVER}/include")
INCLUDE_DIRECTORIES(SYSTEM "${SDKROOT}/usr/local/iphone-${SDKVER}/include")
# System Libraries
LINK_DIRECTORIES("${SDKROOT}/usr/lib")
LINK_DIRECTORIES("${SDKROOT}/usr/lib/gcc/arm-apple-darwin9/4.2.1/")
#LINK_DIRECTORIES("${SDKROOT}/opt/iphone-${SDKVER}/lib")
#LINK_DIRECTORIES("${SDKROOT}/usr/local/iphone-${SDKVER}/lib")
# Root Paths
SET (CMAKE_FIND_ROOT_PATH "${SDKROOT}" "/opt/iphone-${SDKVER}/" "/usr/local/iphone-${SDKVER}/")
SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
SET (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# CMake Parameters
SET (iPhone 1)
SET (iPhoneOS 1)
SET (iPhoneOS_VERSION ${SDKVER})
SET (CMAKE_CROSSCOMPILING 1)
#SET_TARGET_PROPERTIES(p3dm PROPERTIES LINK_FLAGS "-arch armv6 -arch armv7")
# HELPERS
#---------
MACRO(ADD_FRAMEWORK appname fwname)
find_library(FRAMEWORK_${fwname}
NAMES ${fwname}
PATHS ${SDKROOT}/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)
And i use following CMakeLists.txt:
# PROJECT PARAMETERS
#--------------------
SET(APP_NAME p3dm)
PROJECT(${APP_NAME})
# SOURCE CODE
#-------------
SET(CMAKE_CXX_FLAGS "-x objective-c++")
INCLUDE_DIRECTORIES(SYSTEM ../inc/ ../xsrc/)
FILE(GLOB headers ../src/*.h ../xsrc/*.h)
FILE(GLOB sources .开发者_JS百科./src/*.cpp ../xsrc/*.c ../xsrc/*.cpp)
#set_source_files_properties(${sources} PROPERTIES LANGUAGE C )
# EXECUTABLE
#------------
SET(MACOSX_BUNDLE_GUI_IDENTIFIER "org.reversity.${APPNAME}")
SET(APP_TYPE MACOSX_BUNDLE)
ADD_EXECUTABLE(${APP_NAME} ${APP_TYPE} ${headers} ${sources})
SET_TARGET_PROPERTIES(${APP_NAME} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer: Mario Hros")
# FRAMEWORKS
#------------
ADD_FRAMEWORK(${APP_NAME} UIKit)
I use following compilation bash script:
#!/bin/bash
unset CPATH
unset C_INCLUDE_PATH
unset CPLUS_INCLUDE_PATH
unset OBJC_INCLUDE_PATH
unset LIBS
unset DYLD_FALLBACK_LIBRARY_PATH
unset DYLD_FALLBACK_FRAMEWORK_PATH
export SDKVER="3.0"
export DEVROOT="/Developer/Platforms/iPhoneOS.platform/Developer"
export SDKROOT="$DEVROOT/SDKs/iPhoneOS$SDKVER.sdk"
export PKG_CONFIG_PATH="$SDROOT/usr/lib/pkgconfig":"/opt/iphone-$SDKVER/lib/pkgconfig":"/usr/local/iphone-$SDKVER/lib/pkgconfig"
export PKG_CONFIG_LIBDIR="$PKG_CONFIG_PATH"
export MAINFOLDER=`pwd`
cmake . \
-DCMAKE_TOOLCHAIN_FILE="$MAINFOLDER/cmake/iphone-$SDKVER.toolchain" \
-DCMAKE_INSTALL_PREFIX="/opt/iphone-$SDKVER" \
"$@"
The problem is, that it uses CMAKE_CXX_FLAGS also in linker. Compilation is fine. Linking looks fine, it adds correct -framework flags, but also adds CMAKE_CXX_FLAGS (which are -x objective-c++) so instead of linking object files compiled previously it behaves like compiling objective c++ (-x objective-c++) and it is impossible to link these objects.
I am getting errors like
ComponentManager.cpp.o:20: error: stray '\341' in program
Don't you know what I am doing wrong?
You can set the LINKER_LANGUAGE
to C
to force CMake to use the CMAKE_C_FLAGS
for the linker. Check it out here.
I've solved this problem by removing CMAKE_CXX_FLAGS and CMAKE_C_FLAGS from the toolchain file and adding ADD_DEFINITIONS("-x objective-c++") to CMakeLists.txt.
That way -x objective-c++ flags get passed only to the compiler (not linker) and only for my source code (not cmake test compilation which happens before building my target).
The link command line is set in Modules/CMake{C,CXX,Fortran}Information.cmake and defaults to using the compiler and its compilation flags (see source code). This can be changed by replacing the rule that builds the link command line, which lives in variables CMAKE_CXX_LINK_EXECUTABLE (and friends). That variable does not give the linker executable; it says how to link an executable!
One solution is to set a modified form of that rule that avoids the use of CXX flags, e.g.
cmake -DCMAKE_CXX_LINK_EXECUTABLE="<CMAKE_CXX_COMPILER> <FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
However, you can avoid the problem by not setting CMAKE_CXX_FLAGS in the first place, but rather adding COMPILE_FLAGS property to the target.
精彩评论