Tauri 解析

 

本文简介

本文简介

commands代码解析

条件编译

#![cfg_attr(
  all(not(debug_assertions), target_os = "windows"),
  windows_subsystem = "windows"
)]

当没有定义debug_assertions,并且目标是windows时,展开成

#[windows_subsystem="windows"]

主函数

fn main() {
  tauri::Builder::default()
    .manage(MyState { // 将MyState添加到tauri的app中 
      value: 0,
      label: "Tauri!".into(),
    })
    .invoke_handler(tauri::generate_handler![
      borrow_cmd,
      borrow_cmd_async,
      window_label,
      force_async,
      force_async_with_result,
      commands::simple_command,
      commands::stateful_command,
      cmd,
      invoke,
      message,
      resolver,
      async_simple_command,
      future_simple_command,
      async_stateful_command,
      command_arguments_wild,
      command_arguments_struct,
      simple_command_with_result,
      stateful_command_with_result,
      command_arguments_tuple_struct,
      async_simple_command_with_result,
      future_simple_command_with_return,
      future_simple_command_with_result,
      async_stateful_command_with_result,
    ])
    .run(tauri::generate_context!(
      "../../examples/commands/src-tauri/tauri.conf.json"
    ))
    .expect("error while running tauri application");
}

附录

属性

句法

InnerAttribute :
   # ! [ Attr ]

OuterAttribute :
   # [ Attr ]

Attr :
   SimplePath AttrInput?

AttrInput :
      DelimTokenTree
   | = LiteralExpression不带后缀
  • 属性是一种通用的、格式自由的元数据(free-form metadatum)
    • 这种元数据会(被编译器/解释器)依据名称、约定、语言和编译器版本进行解释
    • 内部属性(Inner attributes)#! 开头
      • 应用于程序项
    • 外部属性(Outer attributes)# 开头
      • 应用于属性后面的内容
  • 举例
    • 应用于当前模块或 crate 的一般性元数据

        #![crate_type = "lib"]
      
    • 标记为单元测试的函数

        #[test]
        fn test_foo() {
            /* ... */
        }
      
    • 一个条件编译模块

      #[cfg(target_os = "linux")]
      mod bar {
          /* ... */
      }
      
    • 适用于整个函数的内部属性

      fn some_unused_variables() {
        #![allow(unused_variables)]
      
        let x = ();
        let y = ();
        let z = ();
      }
      

活跃属性和惰性属性

  • 在属性处理过程中
    • 活跃属性将自己从它们所在的对象上移除
      • cfg 和 cfg_attr 属性是活跃的
      • 宏属性是活跃的
    • 惰性属性依然保持原位置不变
      • test属性在为测试所做的编译形式中是惰性的,在其他编译形式中是活跃的
      • 所有其他属性都是惰性的

外部工具属性

条件编译

  • 根据某些条件, 条件性编译的源代码(Conditionally compiled source code)可以被选择编译进 crate 源代码的一部分。类似C语言的#ifdef
  • 可以使用属性 cfg 和 cfg_attr 以及内置的 cfg macro 来有条件地对源代码进行编译。
  • 每种形式的编译条件都有一个计算结果为真或假的配置谓词

句法

格式

配置谓词:
  配置选项 | 配置all | 配置any | 配置not
  • 配置选项:标识符
    • 如果设置了该选项,则为真,如果未设置则为假
    • 配置选项可以是名称,也可以是键值对,它们可以设置,也可以不设置
      • 名称以单个标识符形式写入,例如unix
      • 键值对被写为标识符后跟 =,然后再跟一个字符串。
        • 例如,target_arch=“x86_64” 就是一个配置选项
        • feature = “std” and feature = “serde” 可以同时设置。
    • 字符串字面量
      • 字符串字面量是位于两个双引号”(U+0022)字符内的任意 Unicode 字符序列
      • 允许换行书写
        • 换行可用换行符(U+000A)表示
          • \n的unicode码是\u000a,\r的unicode码是\u000d
        • 也可以用一对回车符换行符(U+000D, U+000A)的字节序列,但它会被转换为U+000A,下述示例中,a 和 b 是一样的:

          let a = "foobar";
          let b = "foo\
                    bar";
          
    • 原生字符串字面量
      • 原生字符串字面量不做任何转义
      • 它以r后跟0+#,以及"组合开始
      • 中间跟任意Unicode 字符序列
      • 后面跟"结束
      • 字符串字面量示例

        "foo"; r"foo;         // foo
        "\\x52"; r"\x52";     // \x52
        
        "foo #\"# bar";       // foo #"# bar
        r##"foo #"# bar"##;   // foo #"# bar
        
  • all() 配置谓词列表
    • 列表内的配置谓词以逗号分隔
    • 列表中所有配置谓词都为真时为真
  • any() 配置谓词列表
    • 列表内的配置谓词以逗号分隔
    • 列表中有一个配置谓词都为真时为真
  • not() 模式
    • 对此配置谓词取反

设置配置选项

  • 配置选项分类
    • 编译器设置集(compiler-set),
      • 这部分选项是在源代码中配置的
    • 任意设置集(arbitrarily-set)
      • 从代码之外传参给编译器来设置
      • 对于 rustc,任意配置集的配置选项要使用命令行参数 –cfg 来设置
  • 键名为 feature 的配置选项一般被 Cargo 约定用于指定编译期(用到的各种编译)选项和可选依赖项
  • 键值对选项
    • target_arch
      • 设置编译目标的 CPU 架构
      • atrget_arch=x86
    • target_os
      • 设置编译目标的操作系统类型
      • 类似于平台目标三元组中的第二和第三个元素
      • target_os=linux
  • 标识符配置选项
    • test
      • 在编译测试套件时启用
      • 通过在 rustc 里使用 –test 命令行参数来完成此启用
    • debug_assertions
      • 在进行非优化编译时默认启用
      • 在开发中启用额外的代码调试功能
      • 它控制着标准库的 debug_assert!宏(是否可用)

条件编译的形式

cfg 属性

句法

cfg属性:
  cfg(配置谓词)
  • 类似C的#ifdef
  • 如果谓词为真,则重写该部分代码,使其上没有 cfg 属性,也就是删除上面的cfg(...)这一行
  • 如果谓词为假,则从源代码中删除该cfg修饰的代码内容。
  • 举例
    • 函数只有在编译目标的os为macOs时才会保留

      #[cfg(target_os = "macos")]
      fn macos_only() {
        // ...
      }
      
    • 函数只有在定义了foo或bar才保留

      #[cfg(any(foo, bar))]
      fn needs_foo_or_bar() {
        // ...
      }
      
    • 函数仅在编译目标是32位体系架构且是类unix系统时才会保留

      #[cfg(all(unix, target_pointer_width = "32"))]
      fn on_32bit_unix() {
        // ...
      }
      
    • 函数仅在没有定义 foo 时才会保留

      #[cfg(not(foo))]
      fn needs_not_foo() {
        // ...
      }
      

cfg_attr属性

句法

cfg_attr属性:
  cfg_attr(ConfigurationPredicate , CfgAttrs?)

CfgAttrs :
   Attr (, Attr)* ,?

说明

  • cfg_attr属性根据配置谓词有条件地包含属性
  • 当配置谓词为真时,此属性展开为谓词后列出的属性

      #[cfg_attr(feature = "magic", sparkles, crackles)]
      fn bewitched() {}
    

    当启用了 magic 特性时, 上面的代码将会被展开为:

      #[sparkles]
      #[crackles]
      fn bewitched() {}
    
  • cfg_attr 能展开为另一个 cfg_attr。比如:

      #[cfg_attr(target_os = "linux", 
          cfg_attr(feature = "multithreaded", some_other_attribute))]
    

    相当于

      #[cfg_attr(
          all(target_os = "linux", feature ="multithreaded"), 
          some_other_attribute)]
    

目标三元组

  • 目标三元组可以理解为我们常说的平台信息,包含这些信息:
    • 第一项元素:CPU 架构;
    • 第二项元素:供应商;
    • 第三项元素:操作系统;
    • 第四项元素:ABI。
  • Rust 下查看当前平台的三元组属性可以用 rustc –version –verbose 命令行
    • host: x86_64-unknown-linux-gnu
      • CPU 架构为 x86_64
      • 供应商为 unknown
      • 操作系统为 linux
      • ABI 为 gnu 。
    • host: x86_64-pc-windows-msvc
      • CPU 架构为 x86_64
      • 供应商为 pc
      • 操作系统为 windows
      • ABI 为 msvc 。
  • Rust 官方对一些平台提供了默认的目标三元组
    • 我们可以通过 rustc –print target-list 命令来查看完整列表
    • rustc --print target-list|grep riscv查看riscv的目标三元组