cmake-一次针对多个架构,无需在构建之间进行手动清理

Boš*_*ber 5 c++ android cmake android-ndk

我正在为Android和iOS开发一个跨平台的C ++库,并且正在使用cmake来准备构建脚本。

项目结构如下所示:

somelib
|
?? .gitignore
|
??? src
?   ??? CMakeLists.txt
?   ??? Doxyfile.in
|   ??? include (Public headers)
?       ??? somelib
?           ??? somelib.hpp
?   ??? somelib
?       ??? CMakeLists.txt
?       ??? somelib.cpp
?       ??? ....hpp, ....cpp
?       ??? test
?           ??? test_classname.cpp
?   ??? libs (source of 3rd party libs)
?       ??? 3rd_party_lib_1
?           ??? CMakeLists.txt
?           ??? ...
?       ??? ...
?           ??? CMakeLists.txt
?           ??? ...
?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
??? toolchains
?   ??? andoid
?       ??? android.toolchain.cmake
?       ??? ...
?   ??? ios
?       ??? ios.toolchain.cmake
?       ??? ...
?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
?
??? build
?   ??? build.sh
?   ??? Doxyfile
?   ??? ...
?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
??? dist (distribute)
?   ??? docs
?       ??? index.html
?       ??? ...
|   ??? include (Public headers)
?       ??? somelib.hpp
?   ??? local
|       ??? somelibtest (executable tests)
?   ??? android
?       ??? Debug
?           ??? armeabi
?           ??? armeabi-v7a
?           ??? ...
?       ??? Release
?           ??? armeabi
?           ??? armeabi-v7a
?           ??? ...
?   ??? ios
?       ??? Debug
?           ??? armv
?           ??? armv7
?           ??? ...
?       ??? Release
?           ??? armv
?           ??? armv7
?           ??? ...
|
Run Code Online (Sandbox Code Playgroud)

我通过执行build.sh从./build/路径运行cmake,在为Android构建的情况下,它看起来像这样:

build.sh:

...

TARGETS="armeabi-v7a armeabi x86 mips arm64-v8a mips64"

mkdir -p "$BUILD_PATH"

for TARGET in $TARGETS
do

    cmake -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} -DCMAKE_TOOLCHAIN_FILE=${ANDROID_TOOLCHAIN} -DANDROID_NDK=${ANDROID_NDK} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DANDROID_ABI=${TARGET} -DPROJ_HOME=${PROJ_HOME} ../src

    make -j32

  done

fi
...
Run Code Online (Sandbox Code Playgroud)

如果我要针对一种特定的体系结构进行构建,例如仅将TARGETS设置为“ arm64-v8a”,则该库的构建良好。如果我想一次为多个架构构建一个库,那么它就不能很好地工作,因为cmake专门为每个平台/架构准备了构建脚本。我在生成期间遇到链接器错误,例如“目标不兼容”。

构建针对多个平台和多体系结构的库的最佳实践是什么?

在准备为其他体系结构进行构建之前,如何避免清除构建脚本文件?

感谢您的任何建议!


PS:这是来自src / CmakeLists.txt主文件的几行:

cmake_minimum_required(VERSION 3.6.0 FATAL_ERROR)

include(GNUInstallDirs)

# Set default build type
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release")
endif()

## Output directories

if (IOS)
  set(REL_OUTPUT_DIR "ios/${CMAKE_BUILD_TYPE}/${IOS_ARCH}")
elseif (ANDROID)
  set(REL_OUTPUT_DIR "android/${CMAKE_BUILD_TYPE}/${ANDROID_ABI}")
else()
  set(REL_OUTPUT_DIR "local")
endif()
set(OUTPUT_DIR ${CMAKE_BINARY_DIR}/../dist/${REL_OUTPUT_DIR})
set(DESTDIR ${CMAKE_BINARY_DIR}/../dist/${REL_OUTPUT_DIR})

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${OUTPUT_DIR}") # Static libraries
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_DIR}") # Dynamic libraries
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") # Executables

# Include libraries
add_subdirectory(libs/3rd_party_lib_1)
add_subdirectory(libs/3rd_party_lib_n)
Run Code Online (Sandbox Code Playgroud)

Ste*_*mer 6

正如我在评论中所忽略的,一种选择是每个目标体系结构使用一个构建目录

...

TARGETS="armeabi-v7a armeabi x86 mips arm64-v8a mips64"

for TARGET in ${TARGETS}
do    
    # create one build dir per target architecture
    mkdir -p ${BUILD_PATH}/${TARGET}
    cd ${BUILD_PATH}/${TARGET}

    cmake -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} -DCMAKE_TOOLCHAIN_FILE=${ANDROID_TOOLCHAIN} -DANDROID_NDK=${ANDROID_NDK} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DANDROID_ABI=${TARGET} -DPROJ_HOME=${PROJ_HOME} ../../src

    make -j32

    cd -    
done

...
Run Code Online (Sandbox Code Playgroud)

这将导致一棵树看起来像下面的样子

project/
+--- src/
+--- build/
     +--- armeabi-v7a/
     +--- armeabi/
     +--- x86/
     +--- mips/
     +--- arm64-v8a/
     +--- mips64/
Run Code Online (Sandbox Code Playgroud)