進階使用CMake編譯程式碼

Note of Using CMake for Compilation in Advance

Posted by imprld01 on Saturday, July 23, 2022

目錄


一則故事

  1. 寫程式一般透過gccg++等編譯器 (Compiler),將程式碼 (Code) 轉為可執行檔 (Program)

  2. 隨著系統越加龐大,程式碼檔案數量也隨之增加,程式碼間的關聯性錯綜複雜,為了處理複雜的程式碼編譯,並降低開發與維護程式碼的困難度,make工具便被開發出來。make工具算是批次處理工具,它參照makefile內的規則與相依性,依次編譯程式碼,直到最終目標文件被生成。而這個makefile並非憑空出生,它仍然需要被工程師們撰寫出來。

  3. 然而,編寫一個makefile有時十分麻煩,尤其在一個複雜系統內。或者,在更換目標平台時,makefile內的編譯器或路徑等資訊也需要被修改。因此,cmake工具就被開發出來,這是一個能夠自動化生成各式makefile的工具,它根據CMakeList.txt內的規則、函式庫關聯生成適用於目標平台的makefile。當然,CMakeList.txt也非憑空而來,它仍然需要被工程師們撰寫出來。

以Ne10為範例認識cmake跟cmakelists.txt

  1. 只要透過cmake與make就能完成Ne10的編譯,Ne10的交叉編譯筆記可以參考這裡

  2. 這裡節錄一些Ne10開頭的cmakelists.txt

    cmake_minimum_required(VERSION 2.6)
    
    project(NE10 C CXX ASM)
    
    option(NE10_BUILD_SHARED "Build NE10 shared libraries" OFF)
    option(NE10_BUILD_STATIC "Build NE10 static libraries" ON)
    option(NE10_BUILD_EXAMPLES "Build NE10 examples" ON)
    
    #hard float abi
    option(NE10_ARM_HARD_FLOAT "Build NE10 for hard float abi" ON)
    
    #unit test options
    option(NE10_BUILD_UNIT_TEST "Build NE10 unit test" OFF)
    
    ......(省略)......
    
    # Add NE10 library sub-directory.
    add_subdirectory(modules)
    
    if(NE10_BUILD_EXAMPLES AND NE10_ENABLE_MATH)
        add_subdirectory(samples)
    endif()
    
    if(NE10_BUILD_UNIT_TEST)
        add_subdirectory(test)
    endif()
    
    ......(省略)......
    

    Ne10的子資料夾下還有其他關聯的cmakelists.txt,例如modules/CMakeLists.txt

    ......(省略)......
    
    if(NE10_ENABLE_MATH)
        #enable NE10_init_math
        add_definitions(-DNE10_ENABLE_MATH)
        # Add math C files.
        set(NE10_MATH_C_SRCS
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_abs.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_addc.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_add.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_divc.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_div.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_len.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_mlac.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_mla.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_mulc.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_mul.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_normalize.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_rsbc.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_setc.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_subc.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_sub.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_dot.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_cross.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_addmat.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_submat.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_mulmat.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_mulcmatvec.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_detmat.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_invmat.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_transmat.c
            ${PROJECT_SOURCE_DIR}/modules/math/NE10_identitymat.c
        )
    
    ......(省略)......
    
    if(NE10_BUILD_SHARED)
    
        add_library( NE10_shared SHARED
            ${NE10_C_SRCS}
            ${NE10_INTRINSIC_SRCS}
            ${NE10_NEON_SRCS}
            ${NE10_INIT_SRCS}
        )
    
        target_link_libraries(NE10_shared m)
    
        set_target_properties(NE10_shared PROPERTIES
            OUTPUT_NAME "NE10"
            CLEAN_DIRECT_OUTPUT 1
            VERSION ${NE10_VERSION}
            LINKER_LANGUAGE C
        )
    
        add_library( NE10_test SHARED
            ${NE10_C_SRCS}
            ${NE10_INTRINSIC_SRCS}
            ${NE10_NEON_SRCS}
            ${NE10_INIT_SRCS}
        )
    
        set_target_properties(NE10_test PROPERTIES
            OUTPUT_NAME "NE10_test"
            CLEAN_DIRECT_OUTPUT 1
            VERSION ${NE10_VERSION}
        )
    
        target_link_libraries(NE10_test m)
    
    endif()
    
  3. 另外,Ne10裡面還有一個檔案GNUlinux_config.cmake,這是cmake預留的接口,只要cmake時透過CMAKE_TOOLCHAIN_FILE指定.cmake結尾的設定檔,就能方便置換交叉編譯的工具鏈 (toolchain)。下面是N10GNUlinux_config.cmake節錄:

    set(GNULINUX_PLATFORM ON)
    set(CMAKE_SYSTEM_NAME "Linux")
    set(CMAKE_SYSTEM_PROCESSOR "arm")
    
    if(NOT DEFINED ENV{NE10_LINUX_TARGET_ARCH})
       set(NE10_LINUX_TARGET_ARCH "armv7")
    else()
       set(NE10_LINUX_TARGET_ARCH $ENV{NE10_LINUX_TARGET_ARCH})
    endif()
    
    if(NE10_LINUX_TARGET_ARCH STREQUAL "armv7")
       set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
       set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
       set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as)
       find_program(CMAKE_AR NAMES "arm-linux-gnueabihf-ar")
       find_program(CMAKE_RANLIB NAMES "arm-linux-gnueabihf-ranlib")
    elseif(NE10_LINUX_TARGET_ARCH STREQUAL "aarch64")
       set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
       set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
       set(CMAKE_ASM_COMPILER aarch64-linux-gnu-as)
       find_program(CMAKE_AR NAMES "aarch64-linux-gnu-ar")
       find_program(CMAKE_RANLIB NAMES "aarch64-linux-gnu-ranlib")
    endif()
    
    mark_as_advanced(CMAKE_AR)
    mark_as_advanced(CMAKE_RANLIB)
    

Reference

  1. 5分钟理解make/makefile/cmake/nmake
  2. cmake交叉编译配置_bytxl的博客-CSDN博客_cmake_toolchain_file
  3. CMAKE missing sysroot when cross compiling

comments powered by Disqus