美文网首页
BUCK - 使用BUCK编译iOS项目(4)

BUCK - 使用BUCK编译iOS项目(4)

作者: 西西的一天 | 来源:发表于2020-01-12 14:40 被阅读0次

    这一节中,将把React Native集成入之前的项目中,集成React Native有两种方式:1. 为每一个RN的子pod编写一个BUCK文件;2. 将React Native编译成Framework,使用集成mars的方式进行集成。比较一下,方法一的工作量巨大,因为整个ReactNative项目被拆分为了多个pod,尽管官方提供部分pod的BUCK文件,但数量还是有点大,所以采用了方法二。

    Build Framework

    这里采用了Cocoapods的一个插件:cocoapods-packager,只需提供一个podspec文件即可通过该插件生成Framework,这个插件的使用方式网上有很多文章。插件的安装方式:gem install cocoapods-packager
    这里使用podspec文件源于之前的一个项目,如何将RN作为一个Framework的方式引入。podspec文件如下所示,其中的这些依赖源自一个私有Cocoapods仓库

    Pod::Spec.new do |s|
      s.name             = 'RNContainer'
      s.version          = '0.1.0'
      s.summary          = 'React Native Container'
      s.description      = 'Description of RNContainer'
    
      s.homepage         = 'https://github.com/iossocket/RNContainer'
      s.license          = { :type => 'MIT', :file => 'LICENSE' }
      s.author           = { 'iossocket' => 'avx302@gmail.com' }
      s.source           = { :git => 'https://github.com/iossocket/RNContainer.git', :tag => s.version.to_s }
    
      s.ios.deployment_target = '10.0'
      s.source_files = 'RNContainer/Classes/**/*.{h,m,mm}'
      s.public_header_files = 'RNContainer/Classes/RNContainer.h'
      s.static_framework = true
      s.libraries = 'stdc++'
      s.frameworks = 'Accelerate', 'AudioToolbox', 'CoreTelephony', 'JavaScriptCore', 'MobileCoreServices', 'SystemConfiguration'
      
      s.dependency 'FBLazyVector'
      s.dependency 'FBReactNativeSpec'
      s.dependency 'RCTRequired'
      s.dependency 'RCTTypeSafety'
      s.dependency 'React'
      s.dependency 'React-Core'
      s.dependency 'React-CoreModules'
      s.dependency 'React-Core/DevSupport'
      s.dependency 'React-RCTActionSheet'
      s.dependency 'React-RCTAnimation'
      s.dependency 'React-RCTBlob'
      s.dependency 'React-RCTImage'
      s.dependency 'React-RCTLinking'
      s.dependency 'React-RCTNetwork'
      s.dependency 'React-RCTSettings'
      s.dependency 'React-RCTText'
      s.dependency 'React-RCTVibration'
      s.dependency 'React-Core/RCTWebSocket'
    
      s.dependency 'React-cxxreact'
      s.dependency 'React-jsi'
      s.dependency 'React-jsiexecutor'
      s.dependency 'React-jsinspector'
      s.dependency 'ReactCommon/jscallinvoker'
      s.dependency 'ReactCommon/turbomodule/core'
      s.dependency 'Yoga'
    
      s.dependency 'DoubleConversion'
      s.dependency 'glog'
      s.dependency 'Folly'
    end
    

    准备就绪,便可使用插件进行编译打包了,在podspec的同级目录下执行如下命令:

    pod package RNContainer.podspec --force --embedded --no-mangle --spec-sources=https://github.com/iossocket/ReactNativeLib.git,https://github.com/CocoaPods/Specs.git
    

    注意,这里的sources指定了两个,一个是私有仓库,一个官方仓库。force:强制覆盖之前的build产物;embedded:指明要生成的Framework为static;no-mangle可以详解文档。

    运行成功后,会在该目录下生成一个目录RNContainer-0.1.00.1.0是podspec中声明的版本号,在这个目录中便可看到生成Framework。

    集成进入BUCK

    MyBuckSample-iOS的Libraries目录下创建两个Target,一个是刚刚生成好的Framework,创建一个目录rncontainer,把RNContainer.framewrok拷贝到该目录,并创建一个BUCK文件:

    load("//Config:buck_rule_macros.bzl", "apple_lib")
    prebuilt_apple_framework(
        name = "RNContainer",
        framework = "RNContainer.framework",
        preferred_linkage = "shared",
        visibility = ["PUBLIC"],
    )
    
    # Every BUCK file needs at least one library with source.
    apple_lib(
        name = "PreBuildProjectGeneratorHackRN",
        srcs = glob([
            "BuckSupportFiles/**/*.swift",
        ]),
    )
    

    其中PreBuildProjectGeneratorHackRN的目的,可详见之前集成mars的文章。

    另一个Target用于放置资源文件js.bundle

    react-native init App --version 0.61.2
    # 修改一下index.js,简单起见没有引入其他图片资源
    react-native bundle --platform='ios' --entry-file='index.js' --dev=false --minify=true --bundle-output="./build/ios/main.jsbundle" --assets-dest="./build/ios"
    

    在Libraries目录下为这个资源target创建目录rnapp,将js.bundle拷贝进入,同时创建一个BUCK文件:

    apple_resource(
        name = "RNResource",
        visibility = ["//App:"],
        files = glob(["**/*.jsbundle"]),
    )
    

    到此为止两个Target已经创建完毕,检验一下所有的target是否都可以正常被引用:make targets

    buck targets //...
    Action graph will be rebuilt because files have been added or removed.
    //App:Assets
    //App:MyBuckSampleApp
    //App:MyBuckSampleAppBinary
    //App:MyBuckSampleAppPackage
    //App:Resource
    //App:workspace
    //Libraries/ObjcLib:ObjcLib
    //Libraries/mars:PreBuildProjectGeneratorHack
    //Libraries/mars:mars
    //Libraries/rnapp:RNResource
    //Libraries/rncontainer:PreBuildProjectGeneratorHackRN
    //Libraries/rncontainer:RNContainer
    //Libraries/xlog:xlog
    //Pods:Alamofire
    

    在主App中使用RNContainer

    为了让主App可以使用这新加入的target,需要修改主App的依赖,同时由于React Native的需要,加入了一下系统库的依赖:

    ...
        deps = [
            ":Resource",
            ":Assets",
            "//Pods:Alamofire",
            "//Libraries/ObjcLib:ObjcLib",
            "//Libraries/xlog:xlog",
            "//Libraries/mars:PreBuildProjectGeneratorHack",
            "//Libraries/rnapp:RNResource",
            "//Libraries/rncontainer:PreBuildProjectGeneratorHackRN",
            "//Libraries/rncontainer:RNContainer"
        ],
        frameworks = [
            "$SDKROOT/System/Library/Frameworks/SystemConfiguration.framework",
            "$SDKROOT/System/Library/Frameworks/CoreTelephony.framework",
            "$SDKROOT/System/Library/Frameworks/Accelerate.framework",
            "$SDKROOT/System/Library/Frameworks/AudioToolbox.framework",
            "$SDKROOT/System/Library/Frameworks/JavaScriptCore.framework",
            "$SDKROOT/System/Library/Frameworks/MobileCoreServices.framework",
        ]
    ...
    

    修改ViewController,让它来弹出刚添加的一个RN页面

    ...
    import RNContainer
    ...
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            let vc = RNContainer().viewController(byRoute: "App")
            present(vc, animated: true, completion: nil)
        }
    ...
    

    大功告成!

    相关文章

      网友评论

          本文标题:BUCK - 使用BUCK编译iOS项目(4)

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