我正致力于在超级构建中构建Boost,但是Boost坚持使用-arch arm
进行编译(并且必须手动添加所有其他架构),其中包含armv4t
二进制文件。因此,在构建后我想浏览库并使用lipo来删除无效的体系结构。在CMake中没有办法在CMake中做到这一点?
似乎我必须add_custom_command
并致电cmake -P
这使得这更加丑陋,尤其是因为我想要包含x86并将其扩展到Android。是否可以在ExternalProject_Add
之后运行cmake脚本而不使用cmake -P
?
include( ExternalProject )
set( NCPU 8 )
set( MIN_IOS_VERSION 8.0 )
set( BOOST_VERSION 1.63.0 )
set( BOOST_SHA_CHECKSUM 9f1dd4fa364a3e3156a77dc17aa562ef06404ff6 )
set( BOOST_COMPILE_LIBRARIES filesystem system date_time )
set( COMPILE_ARCHITECTURES armv6 armv7 armv7s arm64 )
set( ENABLE_BITCODE true )
string( REPLACE "." "_" BOOST_FILENAME "boost_${BOOST_VERSION}" )
set( boost_URL "http://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/${BOOST_FILENAME}.tar.bz2" )
set( boost_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/third_party/boost )
set( boost_INCLUDE_DIR ${boost_INSTALL}/include )
set( boost_LIB_DIR ${boost_INSTALL}/lib )
execute_process( COMMAND xcrun --sdk iphoneos --show-sdk-platform-path
COMMAND tr -d '\r\n'
OUTPUT_VARIABLE XCODE_ROOT )
execute_process( COMMAND xcrun --sdk iphoneos --find clang++
COMMAND tr -d '\r\n'
OUTPUT_VARIABLE CLANG_PATH )
execute_process( COMMAND xcrun --sdk iphoneos --show-sdk-path
COMMAND tr -d '\r\n'
OUTPUT_VARIABLE XCODE_SYSROOT )
execute_process( COMMAND xcodebuild -showsdks
COMMAND grep iphoneos
COMMAND egrep "[[:digit:]]+\.[[:digit:]]+" -o
COMMAND tail -1
COMMAND tr -d '\r\n'
OUTPUT_VARIABLE IOS_SDK_VERSION )
message( STATUS "IOS SDK Version ${IOS_SDK_VERSION}" )
string( REPLACE ";" "," BOOST_WITH_LIBRARIES "${BOOST_COMPILE_LIBRARIES}" )
message( STATUS "Compile Boost libraries ${BOOST_WITH_LIBRARIES}" )
set( COMPILEFLAGS )
foreach( COMPILE_ARCHITECTURE ${COMPILE_ARCHITECTURES} )
set( COMPILEFLAG "<compileflags>\"-arch ${COMPILE_ARCHITECTURE}\"" )
list( APPEND COMPILEFLAGS ${COMPILEFLAG} )
endforeach( COMPILE_ARCHITECTURE )
if( ENABLE_BITCODE )
list( APPEND COMPILEFLAGS "<compileflags>-fembed-bitcode" )
endif( ENABLE_BITCODE )
string( REPLACE ";" "\n" COMPILEFLAGS_FINAL "${COMPILEFLAGS}" )
set( USER_CONFIG_JAM
"using darwin : ${IOS_SDK_VERSION}~iphone :
${CLANG_PATH} :
<striper>
<root>${XCODE_ROOT}/Developer
<compileflags>-mios-version-min=${MIN_IOS_VERSION}
<compileflags>-std=c++11
<compileflags>-stdlib=libc++
<compileflags>-fvisibility-inlines-hidden
<compileflags>--sysroot=${XCODE_SYSROOT}
${COMPILEFLAGS_FINAL}
\;
" )
file( WRITE ${CMAKE_BINARY_DIR}/user-config.jam ${USER_CONFIG_JAM} )
ExternalProject_Add( external_boost
PREFIX boost
URL ${boost_URL}
URL_HASH SHA1=${BOOST_SHA_CHECKSUM}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./bootstrap.sh
--with-libraries=${BOOST_WITH_LIBRARIES}
--prefix=<INSTALL_DIR>
COMMAND ${CMAKE_COMMAND} -E remove <SOURCE_DIR>/tools/build/src/user-config.jam
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/user-config.jam <SOURCE_DIR>/tools/build/src/user-config.jam
BUILD_COMMAND ./b2
-d+2
-j${NCPU}
--reconfigure
architecture=arm
address-model=32_64
toolset=darwin
target-os=iphone
macosx-version=iphone-${IOS_SDK_VERSION}
define=_LITTLE_ENDIAN
link=static
variant=release
install
INSTALL_COMMAND ""
INSTALL_DIR ${boost_INSTALL} )
set( BOOST_LIBRARY_SUFFIX .a )
# Expected output filenames for the boost libraries
set( BOOST_RESULT_LIBRARIES )
foreach( BOOST_COMPILE_LIBRARY ${BOOST_COMPILE_LIBRARIES} )
set( LIBRARY_NAME libboost_${BOOST_COMPILE_LIBRARY}${BOOST_LIBRARY_SUFFIX} )
list( APPEND BOOST_RESULT_LIBRARIES ${LIBRARY_NAME} )
endforeach( BOOST_COMPILE_LIBRARY )
add_dependencies( BOOST_COMPILE_LIBRARY external_boost )
# Check each static library for the included architectures and toss anything that shouldn't be included
foreach( BOOST_RESULT_LIBRARY ${BOOST_RESULT_LIBRARIES} )
execute_process( COMMAND lipo -info ${boost_LIB_DIR}/${BOOST_RESULT_LIBRARY}
COMMAND egrep "armv?[[:digit:]]+[[:lower:]]*" -o
OUTPUT_VARIABLE ARCHIVE_LIBRARY_ARCHITECTURES )
string(REGEX REPLACE "[\r\n]+" ";" ARCHIVE_LIBRARY_ARCHITECTURES ${ARCHIVE_LIBRARY_ARCHITECTURES} )
set( REMOVE_ARCHITECTURES )
foreach( ARCHIVE_LIBRARY_ARCHITECTURE ${ARCHIVE_LIBRARY_ARCHITECTURES} )
list( FIND COMPILE_ARCHITECTURES ${ARCHIVE_LIBRARY_ARCHITECTURE} CONTAINS_ARCHITECTURE )
if( NOT CONTAINS_ARCHITECTURE )
list( APPEND REMOVE_ARCHITECTURES ${ARCHIVE_LIBRARY_ARCHITECTURE} )
endif( NOT CONTAINS_ARCHITECTURE )
endforeach( ARCHIVE_LIBRARY_ARCHITECTURE )
foreach( REMOVE_ARCHITECTURE ${REMOVE_ARCHITECTURES} )
execute_process( COMMAND lipo -remove ${REMOVE_ARCHITECTURE} -output ${BOOST_RESULT_LIBRARY} )
endforeach( REMOVE_ARCHITECTURE )
endforeach( BOOST_RESULT_LIBRARY )
message( STATUS "${LIBRARY_ARCHITECTURES}" )
答案 0 :(得分:0)
基本上,无论你喜欢什么,Boost总会注入-arch arm
。最后我转而使用shell脚本来构建Boost并将其清理干净。鉴于Boost有自己的构建系统,这可能就像它一样好。
以下代码使用cmake下载并启动Boost编译脚本。
include( ExternalProject )
set_property( DIRECTORY PROPERTY EP_BASE third_party )
set( BOOST_URL "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.bz2" )
set( BOOST_SHA1 "9f1dd4fa364a3e3156a77dc17aa562ef06404ff6" )
set( BOOST_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/boost )
set( BOOST_INCLUDE_DIR ${BOOST_INSTALL}/include )
set( BOOST_LIB_DIR ${BOOST_INSTALL}/lib )
list( APPEND DEPENDENCIES external_boost )
set( DEPENDENCIES "${DEPENDENCIES}" PARENT_SCOPE )
ExternalProject_Add( external_boost
PREFIX boost
URL ${BOOST_URL}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/cmake/lipo-library.sh <SOURCE_DIR>
BUILD_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cmake/boost-compile.sh <SOURCE_DIR> <INSTALL_DIR>
INSTALL_COMMAND ""
INSTALL_DIR ${BOOST_INSTALL} )
list( APPEND EXTRA_CMAKE_ARGS
-DBOOST_ROOT=${BOOST_INSTALL}
-DBoost_NO_SYSTEM_PATHS=ON )
set( EXTRA_CMAKE_ARGS "${EXTRA_CMAKE_ARGS}" PARENT_SCOPE )
#!/bin/bash
SOURCE_DIR="$1"
INSTALL_DIR="$2"
BOOST_MODULES=( "date_time" "system" "filesystem" )
VERBOSE_LOGGING=false
FORCE_REBUILD=true
NCPU=8
MIN_IOS_VERSION="8.0"
ENABLE_BITCODE=true
ARCHITECTURE_FAMILIES=( "arm" "x86" )
X86_COMPILE_ARCHITECTURES=( "i386" "x86_64" )
ARM_COMPILE_ARCHITECTURES=( "armv7" "armv7s" "arm64" )
ALL_ARCHITECTURES=( "${X86_COMPILE_ARCHITECTURES[@]}" "${ARM_COMPILE_ARCHITECTURES[@]}" )
echo "Building Boost libraries ${BOOST_MODULES[*]}"
RESULTS_DIRECTORIES=()
for ARCHITECTURE_FAMILY in "${ARCHITECTURE_FAMILIES[@]}"; do
SDK=""
TARGET_OS="iphone"
if [[ "${ARCHITECTURE_FAMILY}" == "arm" ]]; then
SDK="iphoneos"
SDK_SHORT="iphone"
elif [[ "${ARCHITECTURE_FAMILY}" == "x86" ]]; then
SDK="iphonesimulator"
SDK_SHORT="iphonesim"
fi
XCODE_PLATFORM_PATH="$(xcrun --sdk ${SDK} --show-sdk-platform-path )"
XCODE_IOS_CLANG_PATH="$( xcrun --sdk ${SDK} -f clang++ )"
XCODE_SDK_VERSION="$( xcrun --sdk ${SDK} --show-sdk-version )"
PLATFORM_NAME="darwin"
TOOLSET_PREFIX="${PLATFORM_NAME}"
TOOLSET_SUFFIX="${XCODE_SDK_VERSION}~${SDK_SHORT}"
TOOLSET="${TOOLSET_PREFIX}-${TOOLSET_SUFFIX}"
MACOSX_VERSION="${SDK_SHORT}-${XCODE_SDK_VERSION}"
if [[ "${ARCHITECTURE_FAMILY}" == "arm" ]]; then
SDK_LONG="iPhoneOS${XCODE_SDK_VERSION}.sdk"
# TOOLSET="${TOOLSET_PREFIX}"
elif [[ "${ARCHITECTURE_FAMILY}" == "x86" ]]; then
SDK_LONG="iPhoneSimulator${XCODE_SDK_VERSION}.sdk"
fi
echo "Using toolset ${TOOLSET}"
RESULTS_DIRECTORY="${INSTALL_DIR}/${SDK_LONG}-${ARCHITECTURE_FAMILY}"
mkdir -p "${RESULTS_DIRECTORY}"
CXXFLAGS=()
if [[ "${ARCHITECTURE_FAMILY}" == "arm" ]]; then
for ARM_COMPILE_ARCHITECTURE in "${ARM_COMPILE_ARCHITECTURES[@]}"; do
CXXFLAGS+=( "-arch ${ARM_COMPILE_ARCHITECTURE}" )
done
fi
USER_CONFIG_JAM=()
USER_CONFIG_JAM+=( "using ${TOOLSET_PREFIX} : ${TOOLSET_SUFFIX} :" )
USER_CONFIG_JAM+=( "${XCODE_IOS_CLANG_PATH} :" )
USER_CONFIG_JAM+=( "<striper>" )
USER_CONFIG_JAM+=( "<root>${XCODE_PLATFORM_PATH}/Developer" )
USER_CONFIG_JAM+=( "<compileflags>-std=c++11" )
USER_CONFIG_JAM+=( "<compileflags>-stdlib=libc++" )
USER_CONFIG_JAM+=( "<compileflags>-fvisibility-inlines-hidden" )
USER_CONFIG_JAM+=( "<compileflags>-mios-version-min=${MIN_IOS_VERSION}" )
if [[ "${ENABLE_BITCODE}" ]]; then
USER_CONFIG_JAM+=( "<compileflags>-fembed-bitcode" )
fi
USER_CONFIG_JAM+=( ": <architecture>${ARCHITECTURE_FAMILY} <target-os>${TARGET_OS}" )
USER_CONFIG_JAM+=( ";" )
USER_CONFIG_STRING=$( IFS=$'\n'; echo "${USER_CONFIG_JAM[*]}" )
echo "Creating ${SOURCE_DIR}/tools/build/src/user-config.jam"
echo "${USER_CONFIG_STRING}" > "${SOURCE_DIR}/tools/build/src/user-config.jam"
WITH_LIBRARIES=$( IFS=$','; echo "${BOOST_MODULES[*]}" )
echo "Boostrap Boost"
BOOTSTRAP_OPTIONS=()
BOOTSTRAP_OPTIONS+=( "--with-libraries=${WITH_LIBRARIES}" )
BOOTSTRAP_OPTIONS+=( "--prefix=${RESULTS_DIRECTORY}" )
./bootstrap.sh "${BOOTSTRAP_OPTIONS[@]}"
./b2 --clean-all
echo "B2 Boost"
B2_OPTIONS=()
if [[ "${VERBOSE_LOGGING}" ]]; then
B2_OPTIONS+=( "-d+2" )
fi
if [[ "${FORCE_REBUILD}" ]]; then
B2_OPTIONS+=( "-a" )
fi
B2_OPTIONS+=( "-j${NCPU}" )
B2_OPTIONS+=( "--reconfigure" )
B2_OPTIONS+=( "architecture=${ARCHITECTURE_FAMILY}" )
B2_OPTIONS+=( "address-model=32_64" )
B2_OPTIONS+=( "toolset=${TOOLSET}" )
B2_OPTIONS+=( "target-os=${TARGET_OS}" )
if [[ "${#CXXFLAGS[@]}" -gt 0 ]]; then
B2_OPTIONS+=( "cxxflags=${CXXFLAGS[*]}" )
fi
B2_OPTIONS+=( "macosx-version=${MACOSX_VERSION}" )
if [[ "${ARCHITECTURE_FAMILY}" == "arm" ]]; then
B2_OPTIONS+=( "define=_LITTLE_ENDIAN" )
fi
B2_OPTIONS+=( "link=static" )
B2_OPTIONS+=( "threading=single" )
B2_OPTIONS+=( "variant=release" )
B2_OPTIONS+=( "install" )
echo "./b2 ${B2_OPTIONS[*]}"
./b2 "${B2_OPTIONS[@]}"
RESULTS_DIRECTORIES+=( "${RESULTS_DIRECTORY}" )
done
echo "Create FAT Boost libraries"
FAT_INSTALL_INCLUDE_DIR="${INSTALL_DIR}/include"
FAT_INSTALL_LIBARY_DIR="${INSTALL_DIR}/lib"
mkdir -p "${FAT_INSTALL_INCLUDE_DIR}" "${FAT_INSTALL_LIBARY_DIR}"
BOOST_LIBRARIES=()
for BOOST_MODULE in "${BOOST_MODULES[@]}"; do
BOOST_LIBRARIES+=( "libboost_${BOOST_MODULE}.a" )
done
FAT_LIBBOOST_MODULE_INSTALL_PATHS=()
for BOOST_LIBRARY in "${BOOST_LIBRARIES[@]}"; do
FAT_LIBBOOST_MODULE_INSTALL_PATH="${FAT_INSTALL_LIBARY_DIR}/${BOOST_LIBRARY}"
rm -rf "${FAT_LIBBOOST_MODULE_INSTALL_PATH}"
FAT_LIBBOOST_MODULE_INSTALL_PATHS=( "${FAT_LIBBOOST_MODULE_INSTALL_PATH}" )
INCLUDES_DIRS=()
INTERMEDIATES=()
for RESULTS_DIRECTORY in "${RESULTS_DIRECTORIES[@]}"; do
INCLUDES_DIRS+=( "${RESULTS_DIRECTORY}/include/" )
INTERMEDIATES+=( "${RESULTS_DIRECTORY}/lib/${BOOST_LIBRARY}" )
done
for INCLUDES_DIR in "${INCLUDES_DIRS[@]}"; do
cp -R "${INCLUDES_DIR}" "${FAT_INSTALL_INCLUDE_DIR}"
done
if [[ "${#INTERMEDIATES[@]}" -gt 0 ]]; then
lipo -output "${FAT_LIBBOOST_MODULE_INSTALL_PATH}" -create "${INTERMEDIATES[@]}"
fi
done
echo "Cleaning up Boost build intermediates ${RESULTS_DIRECTORIES[*]}"
rm -rf "${RESULTS_DIRECTORIES[@]}"
echo "Validate Boost libraries contain desired architectures ${ALL_ARCHITECTURES[*]}"
SUCCESS=1
for FAT_LIBBOOST_MODULE_INSTALL_PATH in "${FAT_LIBBOOST_MODULE_INSTALL_PATHS[@]}"; do
"${SOURCE_DIR}/lipo-library.sh" "${FAT_LIBBOOST_MODULE_INSTALL_PATH}" "${ALL_ARCHITECTURES[@]}"
SUCCESS=$?
if [[ ${SUCCESS} -ne 0 ]]; then
break
fi
done
exit "${SUCCESS}"
#!/bin/bash
contains() {
local match="$1"
shift
local list=( "${@}" )
for item in "${list[@]}"; do
if [[ "${item}" == "${match}" ]]; then
echo true
return 1
fi
done
echo false
return 0
}
library="$1"
shift
valid_architectures=( "${@}" )
if [ -z "${library}" ] || [ ! "${#valid_architectures[@]}" -gt 0 ]; then
echo "Usage: $0 <library> <architecture ...>"
exit 1
fi
echo "Library to check ${library}"
echo "Required architectures ${valid_architectures[*]}"
# Check static library for the included architectures and toss anything that shouldn't be included
declare -a archive_library_architectures=()
# Handle finding the architectures in a static library, fat or not.
read -r -a archive_library_architectures <<< "$( lipo -detailed_info "${library}" |
grep architecture |
sed -e 's/.*architecture:\{0,1\} \{0,1\}//' |
tr '\r\n' ' ' |
xargs echo -n )"
echo "${library} contains ${archive_library_architectures[*]}"
missing_architectures=()
for valid_architecture in "${valid_architectures[@]}"; do
has_architecture=$( contains "${valid_architecture}" "${archive_library_architectures[@]}" )
if [[ "${has_architecture}" = false ]]; then
missing_architectures+=( "${valid_architecture}" )
fi
done
if [ "${#missing_architectures[@]}" -gt 0 ]; then
echo "${library} missing ${missing_architectures[*]}"
fi
invalid_architectures=()
for archive_library_architecture in "${archive_library_architectures[@]}"; do
has_architecture=$( contains "${archive_library_architecture}" "${valid_architectures[@]}" )
if [[ "${has_architecture}" = false ]]; then
invalid_architectures+=( "${archive_library_architecture}" )
fi
done
if [ "${#invalid_architectures[@]}" -gt 0 ]; then
echo "${library} invalid ${invalid_architectures[*]}"
fi
for invalid_architecture in "${invalid_architectures[@]}"; do
echo "lipo -remove ${invalid_architecture} -output ${library} $library"
lipo -remove "${invalid_architecture}" -output "${library}" "$library"
done
lipo "${library}" -verify_arch "${valid_architectures[@]}"
result=$?
if [ "${result}" = 0 ]; then
echo "Successfully built ${library} with desired architectures"
else
echo "Failed to build ${library} with desired architectures"
fi
exit "${result}"