鸿蒙进阶——CMakelist、GN语法简介及三方库通用移植指南

news2025/5/23 14:56:04

文章大纲

  • 引言
  • 一、GN常用的内置变量
  • 二、GN常用的内置函数
  • 三、CMake 重要语法
    • 1、生成动态库
    • 2、生成静态库
    • 3、生成OBJECT 库
    • 4、重要的函数和模块
      • 4.1、add_definitions
      • 4.2、execute_process
      • 4.3、add_dependencies
      • 4.4、install
      • 4.5、FetchContent
  • 四、GN 重要语法
    • 1、编译Target
    • 2、预构建Target
    • 3、group
    • 4、external_deps 和 deps
  • 五、编写bundle.json 配置模块信息
    • 1、inner_kits声明对外开放的动态库(可选)
    • 2、使用inner_kits

引言

BUILD.gn 是 Google 开发的一种构建脚本语言,用于描述项目依赖关系、编译规则等信息,以便由 ninja 构建系统生成构建文件并进行编译。华为基于gn进行了一些扩展并把其作为主要的构建系统,换句话说无论是完全全采用gn来构建还是通过gn间接触发cmake等其他构建系统也好,OpenHarmony中都是要先改成gn的,移植主要有以下步骤:

  • GN 方式进行构建
  • 编写bundle.json 配置Module及其部件信息
  • 注册Module 到指定的subsystem

一、GN常用的内置变量

名称描述
current_cpu当前工具链的处理器架构
current_os当前工具链的操作系统类型
current_toolchain表示当前使用的工具链
default_toolchain表示默认使用的工具链
target_cpu表示目标平台的CPU类型
target_os表示目标平台的操作系统类型
root_build_dir表示根目录的构建目录
root_gen_dir表示根目录的生成目录
root_out_dir表示根目录的输出目录
target_out_dir表示目标文件的输出目录
target_gen_dir表示中间文件的生成目录
defines表示当前目标的预定义宏列表
include_dirs表示当前目标的头文件搜索路径列表
cflags表示当前目标的C语言编译选项列表
cxxflags表示当前目标的C++语言编译选项列表
ldflags表示当前目标的链接选项列表
asmflags表示当前目标的汇编语言编译选项列表
libs表示当前目标依赖的库文件列表

二、GN常用的内置函数

名称描述
assert()断言函数,如果条件不成立,则会抛出一个异常
defined()判断变量是否已经定义
exec_script()执行一个Python脚本
get_label_info()获取标签信息,例如标签的名称、路径、类型等等
get_path_info()获取路径信息,例如路径是否存在、是否是目录、是否是文件等等
group()将一组目标文件组合成一个库文件
import()导入其他GN构建文件
read_file()读取文件内容
read_json()读取JSON格式的文件
read_path()读取路径中的内容,返回一个字符串列表
rebase_path()重新定位路径,将路径中的某个部分替换为新的值
write_file()写入文件内容
template()处理字符串模板,将模板中的变量替换为实际的值,其功能类似与函数
action()定义一个自定义的构建动作,通过action调用python脚本完成期望动作
action_foreach()针对每个元素执行一个自定义的构建动作
executable()定义一个可执行文件
shared_library()定义一个动态库
static_library()定义一个静态库

三、CMake 重要语法

在 CMake 中,add_library 命令用于创建库目标,可以是静态库(Static Library)、动态库(Shared Library)或目标对象(Object Library)。

1、生成动态库

  • 使用 add_library(${target_name} SHARED ${ARGN}) 创建动态库,它会生成一个共享对象文件,如 libexample.so
  • 动态库在运行时被可执行文件加载,而不是在链接时复制到可执行文件中。
  • 静态库和动态库可以直接被可执行文件或其他库目标链接
  • 动态库是一个共享对象文件,用于在运行时共享,适用于当你想要运行时共享代码,节省内存占用,或在不重启应用程序的情况下更新功能。
  • 动态库需要在编译对象文件后进行额外的生成共享对象。
    function(onnxruntime_add_shared_library target_name)
    add_library(${target_name} SHARED A R G N ) o n n x r u n t i m e c o n f i g u r e t a r g e t ( {ARGN}) onnxruntime_configure_target( ARGN)onnxruntimeconfiguretarget({target_name})
    endfunction()

2、生成静态库

  • 使用 add_library(${target_name} STATIC ${ARGN}) 创建静态库,它会将对象文件存档成一个单一的文件,如 libexample.a
  • 静态库在链接时会被复制到最终的可执行文件中。
  • 静态库和动态库可以直接被可执行文件或其他库目标链接。
  • 静态库是一个存档文件,包含所有成员对象文件,适用于当你想要分发包含所有依赖的单一文件,便于部署。
  • 静态库需要在编译对象文件后进行额外的存档步骤
    function(onnxruntime_add_static_library target_name)
    add_library(${target_name} STATIC A R G N ) o n n x r u n t i m e c o n f i g u r e t a r g e t ( {ARGN}) onnxruntime_configure_target( ARGN)onnxruntimeconfiguretarget({target_name})
    endfunction()

3、生成OBJECT 库

  • 使用 add_library(${target_name} OBJECT ${ARGN}) 创建的是目标对象库,它是一个包含编译后对象文件的集合。
  • 这些对象文件不会自动被存档成库文件(.a.so),而是可以直接被其他库或可执行文件目标链接。
  • 对象库不能直接被链接,它的对象文件需要被其他库或可执行文件显式链接。
  • 对象库实际上是不存档的,它只是一组编译后的对象文件,适用于当你想要在多个目标之间共享编译结果,避免重复编译相同的代码。
  • 对象库不涉及额外的编译步骤来创建库文件。
    创建目标对象库的示例
    add_library(${target_name} OBJECT ${ARGN})

${target_name} 是库目标的名称,${ARGN} 是传递给 add_library 命令的所有额外参数,通常是源文件列表。这样创建的对象库可以被其他目标通过 target_sources 命令添加到它们的源文件列表中。
依赖头文件和库

include_directories(
  ${ONNXRUNTIME_INCLUDE_DIR}
  ${REPO_ROOT}/include/onnxruntime/core/session
)

4、重要的函数和模块

4.1、add_definitions

add_definitions 函数用于向项目中添加编译器定义。这些定义会被转换为预处理器宏,可以在源代码中使用 #ifdef、#ifndef、#define 等预处理器指令来控制条件编译。比如说add_definitions(-DOPENVINO_CONFIG_NPU=1) 相当于是-DOPENVINO_CONFIG_NPU=1在编译过程中,对于所有的源文件,都定义一个名为 OPENVINO_CONFIG_NPU 的宏,并将其值设置为 1。在 C++ 源代码中,你可以使用 #ifdef OPENVINO_CONFIG_NPU 或 #if defined(OPENVINO_CONFIG_NPU) 来检查这个宏是否被定义。

#ifdef OPENVINO_CONFIG_NPU
    // 这部分代码只有在 OPENVINO_CONFIG_NPU 宏被定义时才会被编译
    // 实现与 NPU 相关的功能
#endif

4.2、execute_process

用于执行一个外部进程,并可以捕获其输出。它允许 CMake 脚本与系统上的其他命令行工具交互。

execute_process(
    COMMAND <cmd> [args1 [args2 ...]]
    [WORKING_DIRECTORY <dir>]
    [TIMEOUT <seconds>]
    [RESULT_VARIABLE <variable>]
    [OUTPUT_VARIABLE <variable>]
    [ERROR_VARIABLE <variable>]
    [OUTPUT_STRIP_TRAILING_WHITESPACE]
    [ERROR_STRIP_TRAILING_WHITESPACE]
    [ENCODING <encoding>]
    [ECHO [STDOUT|STDERR]]
    [RESULT_ERROR_VARIABLE <variable>]
    [OUTPUT_FILE <file>]
    [ERROR_FILE <file>]
    [USE_RESULT_VARIABLE]
    [RESULT_CODE <variable>]
    [OUTPUT_QUIET]
    [ERROR_QUIET]
    [COMMAND_ERROR_IS_FATAL]
)

execute_process 执行了 ls -l 命令,并将输出和错误分别存储在 output 和 error 变量中。然后使用 message 函数打印输出结果。

# 执行一个命令并捕获输出
execute_process(
    COMMAND ls -l
    OUTPUT_VARIABLE output
    ERROR_VARIABLE error
    OUTPUT_STRIP_TRAILING_WHITESPACE
)
# 打印输出结果
message(STATUS "Command Output:\n${output}")
if(error)
    message(STATUS "Command Error:\n${error}")
endif()

4.3、add_dependencies

是 CMake 中的一个指令,用于定义目标(通常是可执行程序或库)之间的依赖关系。当你使用 add_dependencies 命令时,你告诉 CMake 在构建某个目标之前需要先构建其他的目标。

add_dependencies(onnxruntime_flatbuffers flatc)

onnxruntime_flatbuffers 这个目标在构建之前需要先构建 flatc 目标。如果你还没有定义 onnxruntime_flatbuffers 和 flatc,你需要先定义它们:

add_executable(flatc src/flatc.cpp)
# 假设 onnxruntime_flatbuffers 依赖于由 flatc 生成的源代码
add_library(onnxruntime_flatbuffers STATIC
    src/onnxruntime_generated.cpp
    # 其他源文件
)
# 设置 onnxruntime_flatbuffers 对 flatc 的依赖
add_dependencies(onnxruntime_flatbuffers flatc)

4.4、install

用于指定在安装目标(可执行文件、库、头文件等)时应采取的操作。这个函数定义了如何将构建的文件和目录复制到系统的标准安装位置,或者用户指定的任何位置。

  • ${CMAKE_INSTALL_LIBDIR} 共享库、静态库或者库相关的其他文件的标准目录。
  • ${CMAKE_INSTALL_BINDIR} 可执行文件的标准目录。
    除了可以通过CMake脚本配置还可以在命令行配置 -DCMAKE_INSTALL_LIBDIR=some/path 或 -DCMAKE_INSTALL_BINDIR=some/path 来指定自定义的安装路径。
  • 安装可执行文件到默认的 bin 目录
    install(TARGETS my_executable RUNTIME DESTINATION bin)
  • 安装库文件到默认的 lib 目录
    install(TARGETS my_library LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
  • 安装头文件到特定目录
    install(FILES my_header.h DESTINATION include)
  • 安装数据文件到特定目录
    install(FILES my_header.h DESTINATION include)
  • 设置文件权限
    install(FILES my_file.txt DESTINATION /etc/my_project PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)

4.5、FetchContent

include(FetchContent) 是一个命令,用于包含 FetchContent 模块。FetchContent 是 CMake 的一个内置模块,它提供了一种机制来下载、缓存和包含外部项目或依赖项,这些项目或依赖项可以是源代码仓库或二进制文件。使用 FetchContent 模块,你可以将第三方库或项目作为依赖项集成到你的 CMake 项目中,而无需手动下载和集成这些依赖项。这个模块会自动处理依赖项的下载和配置

  • 自动下载:如果指定的依赖项不在缓存中,FetchContent 会自动从指定的 URL 下载依赖项。
  • 缓存机制:下载的依赖项会被缓存,以避免未来的重新下载,提高构建效率。
  • 可配置性:你可以配置下载的源代码的子模块、分支、标签或提交,以确保获取正确的依赖项版本。
  • 依赖项包含:下载的依赖项可以作为子目录包含在项目中,或者作为独立的外部项目使用。
  • 兼容性:FetchContent 模块兼容 CMake 3.11 及以上版本。
    使用步骤
  • include(FetchContent)
  • FetchContent_Declare(子模块名) 获取项目。
  • FetchContent_MakeAvailable(子模块),再引入我们的项目中
  • target_link_libraries(主项目 PRIVATE 子模块::子模块)

四、GN 重要语法

GN 是以target 为基础对象构建组织的,所以CMake中的动态库、静态库在GN中映射为对应的Target,而华为为每一种Target定义了一套对应的模板,直接按照相应语法配置即可。
/build/templates/cxx/cxx.gni
GN中通用的规则

  • .gn 文件所在的目录是构建根目录。
  • 路径以“//” 开头的表示绝对路径,以“/“或者则表示相对路径
    //path/to/proprietary_library:libproprietary 冒号前部分是库所在的目录绝对路径,冒号后部分是该库在 BUILD.gn 文件中定义的Target名称
  • gn中不支持以通配符的形式把相应的源文件打包起来,gn中的源文件需要逐条列出,头文件可以只配置对应目录
  • declare_args 定义变量,这个变量疑似是全局唯一的所有在同一个系统内部名称不能重复
declare_args() {
  allow_sanitize_debug = false
}

1、编译Target

  • ohos_shared_library 编译动态库
    在这里插入图片描述

  • ohos_static_library编译静态库

  • ohos_executable 编译可以执行文件
    ohos_source_set配置源集

2、预构建Target

/build/templates/cxx/prebuilt.gni
所谓prebuilt 从某种程度上来说就是把现有的产物复制到对应的路径下,复制过程中根据需要进行相关的依赖关系处理。

  • ohos_prebuilt_executable 不额外配置路径的话会保存到${install_images}/bin目录下
  • ohos_prebuilt_shared_library 不额外配置路径的话会保存到${install_images}/lib 或者lib64目录下
  • ohos_prebuilt_static_library 不额外配置路径的话会保存到${install_images}/lib 或者lib64目录下
  • ohos_prebuilt_etc 不额外配置路径的话会保存到${install_images}/etc目录下
    ohos_prebuilt_etc(“mnist.onnx”) {
    source = “//third_party/onnxrt/test/demo/mnist.onnx”
    subsystem_name = “third_party”
    part_name = “onnx_runtime”
    install_images = [ chipset_base_dir ] #会保存到 vendor/etc下
    install_enable = true
    }

3、group

group作用就是把所有的Target 的编译入口整合到一个group Target里,在bundle.json里就不需要逐条去声明了,只需要声明一个group就会触发。

group("onnx_runtime") {
    deps = [
        ":onnxrt_providers_shared",
        ":onnxrt_1.18.0",
        ":onnxrt_link",
    ]
    if(enable_demo){
      deps += [ 
        ":onnxrt_demo",
        ":mnist.onnx",
      ]
    }
}

4、external_deps 和 deps

external_deps 节点用于指定项目所依赖的外部(非本Module内部)库或模块。而deps 属性用于指定一个构建目标(如 executable、shared_library、static_library 等)所依赖的其他目标。这些依赖可以是同一项目内的其他构建目标,也可以是通过 external_deps 声明的外部库。
在添加一个模块的时候,需要在BUILD.gn中声明它的依赖,部件内依赖deps和部件间依赖external_deps。
在这里插入图片描述

  • 部件内依赖: 现有模块module1属于部件part1,要添加一个属于部件part1的模块module2,module2依赖于module1,这种情况就属于部件内依赖。
    import(“//build/ohos.gni”)
ohos_shared_library("module1") {
  ……
  part_name = "part1"   # 必选,所属部件名称
  ……
}

import("//build/ohos.gni")
ohos_shared_library("module2") {
  ……
  deps = [
    "module1的gn target",
  ……
 ]                        # 部件内模块依赖
part_name = "part1"       # 必选,所属部件名称
}
  • 部件间依赖: 现有模块module1属于部件part1,要添加一个模块module2,module2依赖于module1,module2属于部件part2。模块module2与模块module1分属于两个不同的部件,这种情况就属于部件间依赖。
import("//build/ohos.gni")
ohos_shared_library("module1") {
  ……
  part_name = "part1"   # 必选,所属部件名称
  ……
}

import("//build/ohos.gni")
ohos_shared_library("module2") {
  ……
  external_deps = [
    "part1:module1",
  ……
  ]                      # 部件间模块依赖,这里依赖的模块必须是依赖的部件声明在inner_kits中的模块
  part_name = "part2"    # 必选,所属部件名称
}

五、编写bundle.json 配置模块信息

OpenHarmony中以模块Module 进行组织,其配置文件为bundle.json。

{
    #HPM部件英文名称,格式"@组织/部件名称"
    "name": "@ohos/alsa-lib",
     # 部件功能一句话描述
    "description": "The alsa-lib is a library to interface with ALSA in the Linux kernel and virtual devices using a plugin system.",
    # 版本号,版本号与OpenHarmony版本号一致
    "version": "3.1",
    # 部件License
    "license": "GNU Lesser General Public License v2.1",
     # HPM包的发布方式,当前默认都为code-segment
    "publishAs": "code-segment",
    # 发布类型为code-segment时为必填项,定义发布类型code-segment的代码还原路径(源码路径)
    "segment": {
        "destPath": "third_party/alsa-lib"
    },
    # HPM包的目录结构,字段必填内容可以留空
    "dirs": {},
    # HPM包定义需要执行的脚本,字段必填,值非必填
    "scripts": {},
    # 部件License路径,字段和值非必填
    "licensePath": "COPYING",
    # 部件说明路径,字段和值非必填
    "readmePath": {
        "en": "README.md",
        "zh": "README_zh.md"
    },
    # 部件属性
    "component": {
        # 部件名称
        "name": "alsa-lib",
        # 部件所属子系统,字段必填,值非必填
        "subsystem": "thirdparty",
        # 部件为应用提供的系统能力,在component下加入关键字syscap,对内部配置相应的系统能力。系统能力若无赋值,则默认为true,若有赋值,则按实际值为准。若值为true,则表示该部件默认开启此系统能力,若值为false,则表明该部件默认关闭此系统能力。WIFI的STA、AP、和HotspotExt三个系统能力是打开的,而P2P和Core是关闭的。
        "syscap": [
         "SystemCapability.Communication.WiFi.STA = true",
            "SystemCapability.Communication.WiFi.AP = true",
            "SystemCapability.Communication.WiFi.P2P = false",
            "SystemCapability.Communication.WiFi.Core = false",
            "SystemCapability.Communication.WiFi.HotspotExt"
            ],
         # 部件对外的可配置特性列表,一般与build中的sub_component对应,可供产品配置
        "features": [],
        # 轻量(mini)小型(small)和标准(standard),可以是多个比如:["standard", "small"],
        "adapted_system_type": [ "standard" ],
        # 部件ROM值
        "rom": "950KB",
        # 部件RAM估值
        "ram": "988KB",
        "deps": {
            "components": [],    # 部件依赖的其他部件
            "third_party": []    # 部件依赖的其他部件
        },
        # 编译相关配置
        "build": {
            # 部件编译入口,模块在此处配置组件产物的so、静态库的BUILD.gn,可执行文件不能在这里配置
            "sub_component": [ "//third_party/alsa-lib:libasound" ],
            # 对外开放的模块在此处配置
            "inner_kits": [],
            # 部件测试用例编译入口
            "test": []
        }
    }
}

1、inner_kits声明对外开放的动态库(可选)

似乎目前OpenHarmony只支持以so的形式对外提供,也就是external_deps 部分中所依赖到的外部库,本质上都是其他模块对外提供的bundle.json中的inner_kits部分的。
在这里插入图片描述

2、使用inner_kits

这样子声明之后就可以在external_deps里像 c_utils:c_utils这样直接形如”模块名:inner_kits “即 onnx_runtime:onnxrt_1.18.0
在这里插入图片描述

  • 使用这个inner_kits模块的bundle.json 下的 “component” 下的"deps"里"components"中配置上inner_kits所在Component的name
    在这里插入图片描述

根据具体情况再不同的子节点中配置即可,有些可能需要配置在third_party下的。

  • 在使用这个inner_kits模块的BUILD.gn下配置需要引入的inner_kits的头文件和库Target
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2383965.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS-5.1 Transition 过渡

本系列可作为前端学习系列的笔记&#xff0c;代码的运行环境是在HBuilder中&#xff0c;小编会将代码复制下来&#xff0c;大家复制下来就可以练习了&#xff0c;方便大家学习。 HTML系列文章 已经收录在前端专栏&#xff0c;有需要的宝宝们可以点击前端专栏查看&#xff01; 点…

从虚拟仿真到行业实训再到具身智能--华清远见嵌入式物联网人工智能全链路教学方案

2025年5月23-25日&#xff0c;第63届中国高等教育博览会&#xff08;高博会&#xff09;将在长春中铁东北亚国际博览中心举办。作为国内高等教育领域规模大、影响力广的综合性展会&#xff0c;高博会始终聚焦教育科技前沿&#xff0c;吸引全国高校管理者、一线教师、教育科技企…

告别手动绘图!2分钟用 AI 生成波士顿矩阵

波士顿矩阵作为经典工具&#xff0c;始终是企业定位产品组合、制定竞争策略的核心方法论。然而&#xff0c;传统手动绘制矩阵的方式&#xff0c;往往面临数据处理繁琐、图表调整耗时、团队协作低效等痛点。 随着AI技术的发展&#xff0c;这一现状正在被彻底改变。boardmix博思白…

GraphPad Prism工作表的管理

《2025新书现货 GraphPad Prism图表可视化与统计数据分析&#xff08;视频教学版&#xff09;雍杨 康巧昆 清华大学出版社教材书籍 9787302686460 GraphPadPrism图表可视化 无规格》【摘要 书评 试读】- 京东图书 GraphPad Prism统计数据分析_夏天又到了的博客-CSDN博客 工作…

告别静态UI!Guineration用AI打造用户专属动态界面

摘 要 作为智能原生操作系统 DingOS 的核心技术之一&#xff0c;Guineration 生成式 UI 体系深刻践行了 DingOS“服务定义软件”的核心理念。DingOS 以“一切皆服务、服务按需而取、按用付费”为设计宗旨&#xff0c;致力于通过智能原生能力与粒子服务架构&#xff0c;实现资源…

第六届电子通讯与人工智能国际学术会议(ICECAI 2025)

在数字化浪潮中&#xff0c;电子通讯与人工智能的融合正悄然重塑世界的运行逻辑。技术基础的共生关系是这场变革的核心——电子通讯如同“信息高速公路”&#xff0c;通过5G等高速传输技术&#xff0c;将海量数据实时输送至AI系统&#xff0c;使其能够像人类神经系统般快速响应…

解决vscode在任务栏显示白色图标

长久不用&#xff0c;不知道怎么着就显示成白色图标&#xff0c;虽然不影响使用&#xff0c;但是看起来不爽 问了豆包&#xff0c;给了个解决方法&#xff1a; 1、打开隐藏文件&#xff0c; 由于图标缓存文件是隐藏文件&#xff0c;首先点击资源管理器中的 “查看” 菜单&am…

架构思维:构建高并发扣减服务_分布式无主架构

文章目录 Pre无主架构的任务简单实现分布式无主架构 设计和实现扣减中的返还什么是扣减的返还返还实现原则原则一&#xff1a;扣减完成才能返还原则二&#xff1a;一次扣减可以多次返还原则三&#xff1a;返还的总数量要小于等于原始扣减的数量原则四&#xff1a;返还要保证幂等…

uni-app学习笔记九-vue3 v-for指令

v-for 指令基于一个数组来渲染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法&#xff0c;其中 items 是源数据的数组&#xff0c;而 item 是迭代项的别名&#xff1a; <template><view v-for"(item,index) in 10" :key"index"…

MAC电脑中右键后复制和拷贝的区别

在Mac电脑中&#xff0c;右键菜单中的“复制”和“拷贝”操作在功能上有所不同&#xff1a; 复制 功能&#xff1a;在选定的位置创建一个与原始文件相同的副本。快捷键&#xff1a;CommandD用于在当前位置快速复制文件&#xff0c;CommandC用于将内容复制到剪贴板。效果&…

华为2025年校招笔试手撕真题教程(二)

一、题目 大湾区某城市地铁线路非常密集&#xff0c;乘客很难一眼看出选择哪条线路乘坐比较合适&#xff0c;为了解决这个问题&#xff0c;地铁公司希望你开发一个程序帮助乘客挑选合适的乘坐线路&#xff0c;使得乘坐时间最短&#xff0c;地铁公司可以提供的数据是各相邻站点…

征程 6 J6E/M linear 双int16量化支持替代方案

1.背景简介 当发现使用 plugin 精度 debug 工具定位到是某个 linear 敏感时&#xff0c;示例如下&#xff1a; op_name sensitive_type op_type L1 quant_dty…

深度学习模块缝合拼接方法套路+即插即用模块分享

前言 在深度学习中&#xff0c;模型的设计往往不是从头开始&#xff0c;而是通过组合不同的模块来构建。这种“模块缝合”技术&#xff0c;就像搭积木一样&#xff0c;把不同的功能模块拼在一起&#xff0c;形成一个强大的模型。今天&#xff0c;我们就来聊聊四种常见的模块缝…

改写视频生产流程!快手SketchVideo开源:通过线稿精准控制动态分镜的AI视频生成方案

Sketch Video 的核心特点 Sketch Video 通过手绘生成动画的形式&#xff0c;将复杂的信息以简洁、有趣的方式展现出来。其核心特点包括&#xff1a; 超强吸引力 Sketch Video 的手绘风格赋予了视频一种质朴而真实的质感&#xff0c;与常见的精致特效视频形成鲜明对比。这种独…

04-Web后端基础(基础知识)

而像HTML、CSS、JS 以及图片、音频、视频等这些资源&#xff0c;我们都称为静态资源。 所谓静态资源&#xff0c;就是指在服务器上存储的不会改变的数据&#xff0c;通常不会根据用户的请求而变化。 那与静态资源对应的还有一类资源&#xff0c;就是动态资源。那所谓动态资源&…

Spring Cloud生态与技术选型指南:如何构建高可用的微服务系统?

引言&#xff1a;为什么选择Spring Cloud&#xff1f; 作为全球开发者首选的微服务框架&#xff0c;Spring Cloud凭借其开箱即用的组件、与Spring Boot的无缝集成&#xff0c;以及活跃的社区生态&#xff0c;成为企业级微服务架构的基石。但在实际项目中&#xff0c;如何从众多…

手写简单的tomcat

首先&#xff0c;Tomcat是一个软件&#xff0c;所有的项目都能在Tomcat上加载运行&#xff0c;Tomcat最核心的就是Servlet集合&#xff0c;本身就是HashMap。Tomcat需要支持Servlet&#xff0c;所以有servlet底层的资源&#xff1a;HttpServlet抽象类、HttpRequest和HttpRespon…

高等数学-积分

一、不定积分 定理&#xff1a;如果函数f(x)在区间I上连续&#xff0c;那么f(x)在区间I上一定有原函数&#xff0c;即一定存在区间I上的可导函数F(x)&#xff0c;使得F(x)f(x) &#xff0c;x∈I 简单地说&#xff1a;连续函数必有原函数。 极限lim*0->x {[∫*0^x sin(t^2)…

IOS平台Unity3D AOT全局模块结构分析

分析背景 由于IOS平台中不允许执行动态代码&#xff0c;Unity 4.6之前的版本在IOS平台中采用了AOT的处理方式&#xff0c;提前将C#代码静态编译为机器识别的二进制机器码。Unity引擎4.6之前的版本中IOS框架采用了Mono的AOT机制实现静态编译和处理&#xff0c;本文针对全局AOT模…