ios-cmake 生成framework 在Headers/保留项目目录结构

前言

公司有个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
cmake --build . --config Debug
#cmake --build . --config Release

解释:最终编译出来的文件都在build-ios目录下,cmake的编译选项在leetal/ios-cmake中有详细介绍。按照上述例子中类似的结构,直接运行“sh build.sh”即可编译生成framework,最终生成的framework应该是在Debug-iphoneos或Release-iphoneos目录下。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值