美文网首页iOS
ios-cmake 生成framework并在Headers/保

ios-cmake 生成framework并在Headers/保

作者: 叶一帆6 | 来源:发表于2019-09-28 14:48 被阅读0次

    前言

    公司有个C/C++/ObjC的底层算法库需要在IOS上使用,做了一番调查之后决定将其编成framework的形式(至于IOS上静态库、动态库和framework的区别,网上已经有很多文章了,这里就不再累述了)。

    提醒:底下的大部分链接都需要翻墙访问。

    正文

    ios-cmake生成framework

    由于项目一直是用CMake来管理,所以找到了ios-cmake生成framework的方法,在Github上就有:用cmake生成ios framework库。我使用的是其中的第二种方法,也就是使用这里的ios.toolchain.cmake进行编译。

    其中困扰了很久的问题就是如何在framework/Headers中保留原有项目的目录结构,找了很久,提出这个问题的人不少,但解决方案不合适,比如这里的:iOS框架标题不保留文件夹层次结构
    一开始我采用了shell脚本手动移动文件的方法来达成需求,但这样对于一个大型项目来说显然是很low的,一旦文件目录更改,就得同时修改CMakeLists.txt和shell脚本,改的越多,出错就越容易。所以还是得找到一个可以在CMake里面实现的方法,最终被我找到了,如果急着解决,可以看这里:一个2010年的帖子。不着急的话,就看一下我在底下写的一个小例子吧。

    项目结构和初步的CMakeLists.txt

    如图所示,源文件和头文件按功能模块分目录,都在src底下,src/CMakeLists.txt负责编译这些文件,顶层目录有三个文件:

    • build.sh: 编译用的脚本
    • CMakeLists.txt:顶层CMakeLists.txt,可以用来编译外部的文件,这里只用来add_subdirectory(src)
    • ios.toolchain.cmake:直接从上面所说的网址上clone下来的
    在这里插入图片描述

    src/CMakeLists.txt

    主要部分是“用cmake生成ios framework库”这里提到的,而在framework/Headers保留目录结构的关键则是:MACOSX_PACKAGE_LOCATION

    src/CMakeLists.txt内容如下所示,备注应该挺清楚的了的吧。

    cmake_minimum_required(VERSION 3.0)
    set(CMAKE_CXX_STANDARD 11)
    
    # 在这里所指示的目录将会成为最终framework/Headers底下的目录
    set(dir1 dir1/test.cc dir1/test.h)
    set(dir1_ios dir1/ios/test_ios.cc dir1/ios/test_ios.h)
    set(dir2_1 dir2/subDir1/test2.cc dir2/subDir1/test2.h)
    set(dir2_2 dir2/subDir2/test3.cc dir2/subDir2/test3.h)
    set(dir3 dir3/test.cc dir3/test.h)
    
    add_library(testFramework
        ${dir1}
        ${dir1_ios}
        ${dir2_1}
        ${dir2_2}
        ${dir3}
        )  
    
    # 这里链接了第三方库:opencv.framework和几个系统库
    set_target_properties(testFramework PROPERTIES
        #-F后面接着的是opencv2.framework所在目录
        LINK_FLAGS "-W1,-F${CMAKE_CURRENT_SOURCE_DIR}/3party/opencv/ios"
        )
    target_link_libraries(testFramework 
            "-framework opencv2"
            "-framework Foundation" 
            "-framework CoreVideo"
            "-framework coreml"
            )
    
    # 列出要编译的所有源文件和头文件
    set(SRC_FILES
        ${dir1}
        ${dir1_ios}
        ${dir2_1}
        ${dir2_2}
        ${dir3}
        )
    
    # 从SRC_FILES列表中找出所有头文件,并放入INCLUDE_FILES变量中
    set(INCLUDE_FILES "")
    foreach(file ${SRC_FILES})
        # 通过识别".h"子字符串的方式得出一个文件是否是头文件,所以.h和.hpp文件都会被找到
        string(FIND ${file} ".h" pos REVERSE)  
        if(NOT ${pos} MATCHES "-1")
            message(STATUS "header file: ${file}")
            list(APPEND INCLUDE_FILES ${file})
        endif()
    endforeach(file)
    set(INCLUDE_FILES ${INCLUDE_FILES} CACHE INTERNAL "List of include files" FORCE)
    
    set_xcode_property(testFramework GCC_GENERATE_DEBUGGING_SYMBOLS YES "ALL")
    set_target_properties(testFramework PROPERTIES
        FRAMEWORK TRUE
        FRAMEWORK_VERSION A
        MACOSX_FRAMEWORK_IDENTIFIER cn.yrh.test
        VERSION 1.0.0
        SOVERSION 1.0.0
        #PUBLIC_HEADER ${INCLUDE_FILES} # 使用另一种方法生成Headers/,所以PUBLIC_HEADER就不用了
        )
    
    # 将INCLUDE_FILES变量中的所有文件按其路径名放入testFramework.framework/Headers中
    foreach(hfile ${INCLUDE_FILES})
        # 截取出hfile变量中的路径
        string(FIND ${hfile} "/" pos REVERSE)  # 得出最后一个"/"的位置pos
        string(SUBSTRING ${hfile} 0 ${pos} dir)
        message(STATUS "subDir: ${dir}")
        # MACOSX_PACKAGE_LOCATION关键字可以将文件复制到特定的路径中,在IOS framework中,
        # 就是<name>.framework/
        set_property(SOURCE ${hfile} PROPERTY 
                    MACOSX_PACKAGE_LOCATION Headers/${dir})
    endforeach(hfile)
    
    include_directories(
        .
        ${CMAKE_CURRENT_SOURCE_DIR}/3party/opencv/ios/opencv2.framework
        )
    

    build.sh

    #!/bin/bash
    rm -r build-ios
    mkdir build-ios
    cd build-ios
    cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../ios.toolchain.cmake -DPLATFORM=OS64 -DARCHS=arm64 -DDEPLOYMENT_TARGET=12.2 -DENABLE_STRICT_TRY_COMPILE=TRUE -DENABLE_VISIBILITY=TRUE -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=UBX9CH9GDX
    cmake --build . --config Debug
    #cmake --build . --config Release
    

    解释:最终编译出来的文件都在build-ios目录下,cmake的编译选项在leetal/ios-cmake中有详细介绍。
    最终生成的framework应该是在Debug-iphoneos或Release-iphoneos目录下。

    对了,这个也是我:


    yeRuiHuan

    相关文章

      网友评论

        本文标题:ios-cmake 生成framework并在Headers/保

        本文链接:https://www.haomeiwen.com/subject/bvftpctx.html