Einführung in die Verwendung von mit Google gn kompilierten Dateien

Was ist Gn?

Es handelt sich um ein Kompilierungstool, das von Google zur Pflege von Chrom-Projekten verwendet wird. Verwandte Open-Source-Projekte basieren jetzt auf gn für die Kompilierungsverwaltung. Derzeit verwenden einige große Systeme GN, beispielsweise Google und Hongmeng.

Gn ist ein Build-Skript-Generator, eine aktualisierte Version des vorherigen Gyp.

Und gn basiert auf C++ und ist fast 20-mal effizienter als gyp auf Python-Basis.

Bild

Für weitere technische Artikel wird das öffentliche Konto „ Moyu IT “ zum ersten Mal im gesamten Netzwerk gestartet. Ich hoffe, dass jeder darauf achtet, es weiterleitet und es mag! Einführung in die Verwendung von mit Google gn kompilierten Dateien

Offizielle Website-Dokumentreferenz: https://gn.googlesource.com/gn/+/master/docs

Referenzdokumente: Analyse des Hongmeng-Kernel-Quellcodes (GN-Anwendung) | GN-Syntax und Verwendung in Hongmeng | Hunderte von Blogs, die den OpenHarmony-Quellcode analysieren | v60.02 – Nuggets

Die Rolle von GN-Dateien 

Für eine Reihe von Kompilierungstools sind zum Kompilieren des Quellcodes in eine endgültige ausführbare Datei drei Teilkomponentensysteme erforderlich: GN, Ninja und GCC (es können hier auch andere Compiler sein).

GN dient als Kompilierungslogikteil. Das gesamte Projekt wird über gn miteinander verbunden, um die Datei build.ninja zu generieren.

Als mittlerer Teil des Builds verwendet Ninja die einfachste und schnellste Methode, um die Kompilierungsparameter der kompilierten Datei an das Kompilierungssystem zu übergeben, und Ninja ist für die Ausführung des Kompilierungsprozesses verantwortlich.

Als Kompilierungsteil ändert sich GCC normalerweise mit dem Kompilierungssystem.

Als nächstes stellen wir einige wichtige Teile und die Syntax der GN-Datei vor:

Angebot | Importieren 

.gn ist die Quelldatei; .gni ist die Header-Datei, ähnlich der Header-Datei .h in C++, auf die durch Import verwiesen wird

import("//build/lite/config/hap_pack.gni")

Zielobjekte | Ziele 

Das Ziel besteht darin, einen Knoten im Diagramm zu konstruieren. Dies bedeutet normalerweise, dass eine Art ausführbare Datei oder Bibliotheksdatei generiert wird. Der gesamte Build besteht nacheinander aus Zielen.

Hier sind einige häufig verwendete integrierte Ziele:

Aktion: Führen Sie ein Skript aus, um eine Datei zu generieren

ausführbar: Ausführbare Datei generieren

shared_library: dynamische Bibliothek, eine .dll oder .so

static_library: statische Bibliothek, eine .lib-Datei oder .a

App: ausführbares Programm

android_apk: Generieren Sie eine APK

shared_library("cameraApp") #生成一个cameraApp的动态库

Konfigurationselemente | Konfigurationen 

Zeichnen Sie die Konfigurationsinformationen auf, die zum Abschließen des Zielprojekts erforderlich sind. Die Konfigurationsinformationen können Flags, Definitionen, Include-Verzeichnisse usw. umfassen, umfassen jedoch keine Abhängigkeitsdateien wie Quellen und Deps/Public_Deps. Zum Beispiel:

configs = [
    ":config_json_creator_test",
    "$ace_root:ace_test_config",
]

Quelldateien | Quellen 

Dieses Etikett bedeutet, die Quelldateien aufzulisten, die kompiliert werden müssen. Natürlich können bedingte Anweisungen für die bedingte Kompilierung verwendet werden.

sources = [ #需要编译的源码
    "cameraApp/src/main/cpp/camera_ability.cpp",
    "cameraApp/src/main/cpp/camera_ability_slice.cpp",
    "cameraApp/src/main/cpp/camera_manager.cpp",
 ]

Abhängigkeiten | Abt 

Das heißt, die zum Kompilieren von Zielen verwendeten Abhängigkeiten sollten in alphabetischer Reihenfolge angeordnet sein.

Deps in der aktuellen Datei sollten zuerst geschrieben werden und können nicht mit Dateinamen qualifiziert werden.

Andere Deps sollten immer vollständig qualifizierte Pfadnamen verwenden, es sei denn, aus irgendeinem Grund sind relative Pfadnamen erforderlich. ​​​​​​

deps = [
    "${aafwk_lite_path}/frameworks/ability_lite:aafwk_abilitykit_lite",
    "${appexecfwk_lite_path}/frameworks/bundle_lite:bundle",
    "//foundation/distributeddatamgr/kv_store/interfaces/inner_api/kv_store:kv_store",
    "//foundation/graphic/surface",
    "//foundation/graphic/ui:lite_ui",
    "//foundation/graphic/utils:lite_graphic_utils",
    "//foundation/multimedia/camera_lite/frameworks:camera_lite",
    "//foundation/multimedia/media_lite/frameworks/recorder_lite:recorder_lite",
    "//foundation/systemabilitymgr/samgr_lite/samgr:samgr",
]

Ersetzen Sie $ 

Die Verwendung von $ unterstützt die einfache Variablenersetzung, bei der das Wort nach dem Dollarzeichen durch den Wert der Variablen ersetzt wird. Wenn keine nicht variablen Namenszeichen zum Abschluss des Variablennamens vorhanden sind, können Sie den Namen mit {} umgeben. Komplexere Ausdrücke werden nicht unterstützt, nur die Ersetzung von Variablennamen wird unterstützt.

a = "moyupath"
b = "$a/king.cc"   #b -> "moyupath/king.cc"
c = "king${a}bar.cc"  #c -> "kingmoyupathbar.cc"

Liste[ ] 

Es gibt keine Möglichkeit, die Länge einer Liste zu ermitteln. Wenn Sie feststellen, dass Sie so etwas tun möchten, versuchen Sie, zu viel Arbeit in Ihren Build zu investieren.

Die Liste unterstützt das Anhängen von:​​​​​​

a = [ "first" ]
a += [ "second" ]  # [ "first", "second" ]
a += [ "third", "fourth" ]  # [ "first", "second", "third", "fourth" ]
b = a + [ "fifth" ]  # [ "first", "second", "third", "fourth", "fifth" ]
a = [ "first" ]a += [ "second" ]  # [ "first", "second" ]a += [ "third", "fourth" ]  # [ "first", "second", "third", "fourth" ]b = a + [ "fifth" ]  # [ "first", "second", "third", "fourth", "fifth" ]

Codebeispiel

#目的是要得到项目各个模块的编译入口

group("ohos") {

  deps = []

  if (ohos_build_target == "") {

    # Step 1: Read product configuration profile.

    # 第一步:读取配置文件product_path的值来源于根目录的ohos_config.json,如下,内容由 hb set 命令生成

    # {

    #  "root_path": "/home/openharmony",

    #  "board": "hispark_aries",

    #  "kernel": "liteos_a",

    #  "product": "ipcamera_hispark_aries",

    #  "product_path": "/home/openharmony/vendor/hisilicon/hispark_aries",

    #  "device_path": "/home/openharmony/device/hisilicon/hispark_aries/sdk_liteos",

    #  "patch_cache": null

    #}

    product_cfg = read_file("${product_path}/config.json", "json")



    # Step 2: Loop subsystems configured by product.

    # 第二步:循环处理各自子系统,config.json中子系统部分格式如下hb

    #"subsystems": [

    #  {

    #    "subsystem": "aafwk",

    #    "components": [

    #      { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = false" ] }

    #    ]

    #  },

    #  ...

    #  {

    #    "subsystem": "distributed_schedule",

    #    "components": [

    #    { "component": "system_ability_manager", "features":[] },

    #    { "component": "foundation", "features":[] },

    #    { "component": "distributed_schedule", "features":[] }

    #    ]

    #  },

    #  {

    #      "subsystem": "kernel",

    #      "components": [

    #        { "component": "liteos_a", "features":[] }

    #      ]

    #   },

    #]

    foreach(product_configed_subsystem, product_cfg.subsystems) {#对子系统数组遍历操作

      subsystem_name = product_configed_subsystem.subsystem    #读取一个子系统 aafwk,hiviewdfx,security ==

      subsystem_info = {

      }



      # Step 3: Read OS subsystems profile.

           # 第三步: 读取各个子系统的配置文件

      subsystem_info =

          read_file("//build/lite/components/${subsystem_name}.json", "json")



      # Step 4: Loop components configured by product.

      # 第四步: 循环读取子系统内各控件的配置信息

      # 此处以内核为例://build/lite/components/kernel.json"

      # "components": [

      #   {

      #     "component": "liteos_a",              # 组件名称

      #     "description": "liteos-a kernel",     # 组件一句话功能描述

      #     "optional": "false",                  # 组件是否为最小系统必选

      #     "dirs": [                             # 组件源码路径

      #       "kernel/liteos_a"

      #     ],

      #     "targets": [                          # 组件编译入口

      #       "//kernel/liteos_a:kernel"

      #     ],

      #     "rom": "1.98MB",                      # 组件ROM值

      #     "ram": "",                            # 组件RAM估值

      #     "output": [                           # 组件编译输出

      #       "liteos.bin"

      #     ],

      #     "adapted_board": [                    # 组件已适配的主板

      #       "hispark_aries",

      #       "hispark_taurus",

      #       "hi3518ev300",

      #          "hi3516dv300",

      #     ],

      #     "adapted_kernel": [ "liteos_a" ],     # 组件已适配的内核

      #     "features": [],                       # 组件可配置的特性

      #     "deps": {

      #       "components": [],                   # 组件依赖的其他组件

      #       "third_party": [                    # 组件依赖的三方开源软件

      #         "FreeBSD",

      #         "musl",

      #         "zlib",

      #         "FatFs",

      #         "Linux_Kernel",

      #         "lwip",

      #         "NuttX",

      #         "mtd-utils"

      #       ]

      #     }

      #   },

      # ]

      foreach(product_configed_component,

              product_configed_subsystem.components) { #遍历项目控件数组

        # Step 5: Check whether the component configured by product is exist.

                  # 第五步: 检查控件配置信息是否存在

        component_found = false #初始为不存在

        foreach(system_component, subsystem_info.components) {#项目控件和子系统中的控件遍历对比

          if (product_configed_component.component ==

              system_component.component) { #找到了liteos_a

            component_found = true

          }

        }

                  #如果没找到的信息,则打印项目控件查找失败日志

        assert(

            component_found,

            "Component \"${product_configed_component.component}\" not found" +

                ", please check your product configuration.")

             

        # Step 6: Loop OS components and check validity of product configuration.

              # 第六步: 检查子系统控件的有效性并遍历控件组,处理各个控件

        foreach(component, subsystem_info.components) {

          kernel_valid = false   #检查内核

          board_valid = false   #检查开发板



          # Step 6.1: Skip component which not configured by product.

          if (component.component == product_configed_component.component) {

            # Step 6.1.1: Loop OS components adapted kernel type.

            foreach(component_adapted_kernel, component.adapted_kernel) {

              if (component_adapted_kernel == product_cfg.kernel_type &&

                  kernel_valid == false) { #内核检测是否已适配

                kernel_valid = true

              }

            }

                     # 如果内核未适配,则打印未适配日志

            assert(

                kernel_valid,

                "Invalid component configed, ${subsystem_name}:${product_configed_component.component} " + "not available for kernel: ${product_cfg.kernel_type}!")



            # Step 6.1.2: Add valid component for compiling.

                     # 添加有效组件进行编译

            foreach(component_target, component.targets) {//遍历组件的编译入口

              deps += [ component_target ] #添加到编译列表中

            }

          }

        }

      }

    }



    # Step 7: Add device and product target by default.

    # 第七步: 添加设备和项目的编译单元

    # "product_path": "/home/openharmony/vendor/hisilicon/hispark_aries",

    # "device_path": "/home/openharmony/device/hisilicon/hispark_aries/sdk_liteos",

      deps += [

      "${device_path}/../", #添加 //device/hisilicon/hispark_aries 进入编译项

      "${product_path}"            #添加 //vendor/hisilicon/hispark_aries 进入编译项

    ]

  } else {#编译指定的组件,例如 hb build -T targetA&&targetB

    deps += string_split(ohos_build_target, "&&")

  }

}

BUILD.gn-Datei unter openharmony\applications\sample\camera\cameraApp:

import("//build/lite/config/hap_pack.gni")



#编的库名称

shared_library("cameraApp") {

  sources = [ #需要编译的源码

    "cameraApp/src/main/cpp/camera_ability.cpp",

    "cameraApp/src/main/cpp/camera_ability_slice.cpp",

    "cameraApp/src/main/cpp/camera_manager.cpp",

  ]



  deps = [#引用三方组件库

    "${aafwk_lite_path}/frameworks/ability_lite:aafwk_abilitykit_lite",

    "${appexecfwk_lite_path}/frameworks/bundle_lite:bundle",

    "//foundation/distributeddatamgr/kv_store/interfaces/inner_api/kv_store:kv_store",

    "//foundation/graphic/surface",

    "//foundation/graphic/ui:lite_ui",

    "//foundation/graphic/utils:lite_graphic_utils",

    "//foundation/multimedia/camera_lite/frameworks:camera_lite",

    "//foundation/multimedia/media_lite/frameworks/recorder_lite:recorder_lite",

    "//foundation/systemabilitymgr/samgr_lite/samgr:samgr",

  ]



  include_dirs = [#需要的头文件

    "cameraApp/src/main/cpp",

    "${aafwk_lite_path}/interfaces/kits/ability_lite",

    "${appexecfwk_lite_path}/interfaces/kits/bundle_lite",

    "${aafwk_lite_path}/interfaces/kits/want_lite",

    "//foundation/multimedia/camera_lite/interfaces/kits",

    "//foundation/multimedia/camera_lite/interfaces/kits",

  ]

  ldflags = [

    "-L$ohos_root_path/sysroot/usr/lib",

    "-Wl,-rpath-link=$ohos_root_path/sysroot/usr/lib",

    "-lstdc++",

    "-lcamera_lite",

    "-lsurface",

    "-lrecorder_lite",

  ]

  defines = [

    "ENABLE_WINDOW=1",

    "ABILITY_WINDOW_SUPPORT",

  ]

}



hap_pack("cameraApp_hap") {

  deps = [ ":cameraApp" ]

  mode = "hap"

  json_path = "cameraApp/src/main/config.json"

  ability_so_path = "$root_out_dir/libcameraApp.so"

  force = "true"

  cert_profile = "cert/camera_AppProvision_Release.p7b"

  resources_path = "cameraApp/src/main/resources"

  hap_name = "cameraApp"

  privatekey = "HOS Application Provision Release"

}

Das Obige ist eine kurze Einführung in die grundlegende Verwendung von GN-Dateien. Freunde, lernt schnell, sie zu verwenden!

おすすめ

転載: blog.csdn.net/qrx941017/article/details/132907603