初识Blade-基本概念及安装测试

1. Blade简介

██████╗ ██╗      █████╗ ██████╗ ███████╗
██╔══██╗██║     ██╔══██╗██╔══██╗██╔════╝
██████╔╝██║     ███████║██║  ██║█████╗
██╔══██╗██║     ██╔══██║██║  ██║██╔══╝
██████╔╝███████╗██║  ██║██████╔╝███████╗
╚═════╝ ╚══════╝╚═╝  ╚═╝╚═════╝ ╚══════╝

项目地址: blade-build
官方文档: 英文, 中文

什么是Blade

Blade是一个方便易用高性能的现代化代码构建系统,特别适合公司内的大规模代码库的敏捷构建,内置了对多种编程语言及单元测试框架的直接支持。

Blade is an easy-to-use, fast and modern build system for trunk based development in large scale monorepo codebase. It supports building mulitiple programming languages.

为什么要用Blade

Blade 是一个现代构建系统,期望的目标是强大而好用,把程序员从构建的繁琐中解放出来。

Blade主要定位于linux下的大型C++项目,密切配合研发流程,比如单元测试,持续集成,覆盖率统计等。 但像unix下的文本过滤程序一样,保持相对的独立性,可以单独运行。目前重点支持i386/x86_64 Linux,未来可以考虑支持其他的类Unix系统。

  1. Blade自动维护库与库、程序与库之间的依赖关系,自动分析头文件依赖关系
  2. 增量构建,即只编译因改动而需要重新构建的代码
  3. 保证多层间依赖的库能被重新构建
  4. 简化编译和单测的流程

借用文档中的例子

cc_library(
    name = 'foo', // 库名
    srcs = ...,
    hdrs = ...,
    deps = ':common' // 依赖库
)
cc_binary(
    name = 'my_app', // 程序名
    srcs = ...,
    deps = ':foo' // 依赖库
)

例子各个字段的意义会在下文展开

此处想说明的是Blade在分析依赖时的特性。

当构建my_app时,Blade会自动检查其直接依赖的foo库是否需要更新,以及foo库依赖的common库是否需要更新,以此类推。保证了完整更新构建的同时高效构建。


2. Blade安装

依赖安装

Blade 运行时需要以下依赖:

  • Linux 或 Mac 操作系统
  • Python v2.7+
  • Ninja v1.8+

需要注意的是保证本地有python2的环境,如果仅有python3是不够的

Blade 支持 Python 2.7.x,对 python 3.x 的支持还在准备中

同时可以顺带检验一下gcc的版本

$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0

ninja的安装有两种方式

  1. GitHub官方项目:地址
  2. 用包管理工具安装ninja-build
$ sudo apt-get install ninja-build

安装后验证ninja的版本

$ ninja --version
1.10.0

Blade安装

拉取Blade仓库

$ git clone git@github.com:chen3feng/blade-build.git && cd blade-build

切换到v2.0并运行install

$ git checkout v2.0
$ ./install

安装:

$ ./install 
Installing vim scripts..., Done.
Installing blade auxiliary tools..., Done.
Installing blade..., Done.
Install success, please relogin or run 'source /home/parallels/.profile' manually to apply

按照提示运行:

$ source /home/parallels/.profile

安装成功:

$ blade -h
usage: blade [-h] [--version] {build,run,test,clean,query,dump} ...

blade <subcommand> [options...] [targets...]

positional arguments:
  {build,run,test,clean,query,dump}
                        Available subcommands
    build               Build specified targets
    run                 Build and runs a single target
    test                Build the specified targets and runs tests
    clean               Remove all blade-created output
    query               Execute a dependency graph query
    dump                Dump specified internal information

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit


快速测试

根据官方文档的 快速测试部分 创建一个快速测试的项目

也可以直接拉取项目 example 中的 quick-start 进行测试

创建测试目录

$ mkdir quick-start && cd quick-start
$ touch BLADE_ROOT

定义实现 say 库

创建头文件say.h

#pragma once
#include <string>

// Say a message
void Say(const std::string& msg);

创建实现文件say.cpp

#include "say.h"
#include <iostream>

void Say(const std::string& msg) {
    std::cout << msg << "!\n";
}

创建BUILD文件,描述上述文件为’say’库

cc_library(
    name = 'say',
    hdrs = ['say.h'],
    srcs = ['say.cpp'],
)

定义实现 hello 库

创建头文件 hello.h

#pragma once
#include <string>

// Say hello to `to`
void Hello(const std::string& to);

创建实现文件 hello.cpp

#include "say.h"

void Hello(const std::string& to) {
    Say("Hello, " + to);
}

需要注意的是文档中《定义实现 hello 库》下的表述有一定问题

创建 BUILD 文件,把上述文件描述为一个 hello 库

这里并非创建一个新的BUILD文件,而是在上一步的BUILD文件中追加

cc_library(
    name = 'hello',
    hdrs = ['hello.h'],
    srcs = ['hello.cpp'],
    deps = [':say'], // 表示依赖 say 库, ':'前缀表示目标在同一个 BUILD 文件里
)

实现 hello-world 程序

创建 hello-world.cpp 文件:

#include "hello.h"

int main() {
    Hello("World");
    return 0;
}

BUILD 文件中增加编译 hello-world 的规则调用:

cc_binary( 
    name = 'hello-world',
    srcs = ['hello-world.cpp'],
    deps = [':hello'],
)

注意规则名是 cc_binary 了,deps 里需要加入对 hello 库的依赖,但是不需要加入对 say 库的依赖,因为这是 hello 的实现细节,hello-world 目标不需要了解,编译和链接时,Blade 会正确处理依赖关系的传递。

测试

创建完后文件目录应该如下:

$ tree
.
├── BLADE_ROOT
├── BUILD
├── hello.cpp
├── hello.h
├── hello-world.cpp
├── say.cpp
└── say.h

测试构建和运行
在这里插入图片描述

至此Blade测试成功


3. BUILD文件简述

BUILD语言

Blade 的 DSL 是受限制的 Python 语言

关于Blade的语法,官方文档有比较详细的介绍可以参考:DSL 和 API 模块

拓展阅读:什么是领域专用语言 (DSL)

通用属性

以下内容主要围绕C/C++构建展开,其他类型的功能可以参考文档,这里不一一展开

示例代码

cc_library(
    name = 'string',
    srcs = [
        'algorithm.cpp',
        'format.cpp',
        'concat.cpp',
    ],
    hdrs = [
        'algorithm.h',
        'format.h',
        'concat.h',
    ]
    deps = ['//common/base:int'],
)

每个 BUILD文件通过一组目标描述函数描述了一个目标的源文件,所依赖的其他目标,以及其他一些属性。

  • name: 目标的名称,和路径一起组成了target的唯一标识和输出名

  • srcs: source,构建target需要的源文件,官方文档建议一般是存放在当前目录或子目录的文件,同样可以使用通配符glob来筛选文件名(glob介绍

  • hdrs: 声明库的公开接口头文件

  • deps: 该对象依赖的其它 targets路径

    允许的路径格式:

    • “//path/to/dir:name” 其他目录下的target,path为从BLADE_ROOT出发的路径,name为被依赖的目标名。看见就知道在哪里。
    • “:name” 当前BUILD文件内的target, path可以省略。
    • “#name” 系统库。直接写#跟名字即可,比如#pthread,#z分别相当于链接命令行上的-lpthread和-lz,但是会被传递给依赖这个库的其他目标。
  • cc_library: 同时用于构建静态和动态库,默认只构建静态库

    cc_library生成的动态链接库里不包含其依赖的代码,而是包含了对所依赖的库的路径。这些库主要是为了开发环境本地使用(比如运行测试),并不适合部署到生产环境。 如果你需要生成需要在运行时动态加载或者在其他语言中作为扩展调用的动态库,应该使用 cc_plugin 构建规则,这样生成的动态库已经以静态链接的方式包含了其依赖。

  • cc_binary: 定义C++可执行文件目标

以下两个详细信息应该参照官方文档,这里仅作简单补充 文档地址

  • proto_library : 用于定义 protobuf 目标 deps 为 import 所涉及的其他 proto_library 自动依赖 protobuf 运行库,使用者不需要再显式指定。
  • thrift_library: 用于定义thrift库目标 deps 为import所涉及的其他thrift_library 自动依赖thrift,使用者不需要再显式指定。 构建时自动调用thrift命令生成cpp和h,并且编译成对应的cc_library

4. Blade命令行

基本语法

blade <subcommand> [options...] [targets...]

subcommand :

  • build 构建指定的目标
  • test 构建并且运行指定的测试
  • clean 清除指定目标的构建结果
  • dump 输出一些内部信息
  • query 查询目标的依赖项与被依赖项
  • run 构建并运行单个可执行的目标

targets: 对应BUILD中的name,支持单选和多选目标,语法如下:

  • path:name 表示 path 中的某个 target,这种形式称为直接目标。
  • path:* 表示 path 中所有目标,但不包含其子目录
  • path 是 path:* 的简写形式
  • path/… 表示path中所有目标,并递归包括所有子目录 (Blade 会递归搜索 BUILD 文件,如果需要排除某些目录,在其中放一个空的 .bladeskip 文件即可)
  • :name 表示当前目录下的某个目标

如果 path 以 // 开始,则表示从工作空间的根目录开始。name 部分不是通配符的称为“直接目标”。

如果没有指定目标模式,则默认为当前目录下的所有目标(不包含子目录),如果当前目录下没有 BUILD 文件,就会失败。 当指定 … 作为结尾目标时,如果其路径存在,即使展开为空,也总不会失败。

注意:

如果你安装了 ohmyzsh,裸的 … 会被其自动展开为 …,需要写成 ./…

### Python 基础语法概述 Python 是一种解释型高级编程语言,以其简洁清晰的语法著称。对于初学者来说,理解其基本结构和语法规则是非常重要的。 #### 代码组织与缩进 Python 使用缩进来表示代码块之间的关系,而不是像其他一些编程语言那样使用大括号或其他分隔符。每一级缩进通常由四个空格组成[^2]。例如: ```python def my_function(): print("This is inside the function") # 这里有一个缩进级别 print("This line is outside of the function") ``` #### 控制流语句 Python 提供了几种常见的控制流工具来管理程序执行路径,包括条件判断 `if` 和循环 `for`, `while` 等。下面是一个简单的例子展示了如何使用这些语句: ```python number = 10 if number > 5: print(f"{number} is greater than five.") else: print(f"{number} is not greater than five.") for i in range(3): print(i) counter = 0 while counter < 3: print(counter) counter += 1 ``` #### 注释 为了提高代码可读性和维护性,在编写过程中添加适当注释是非常有益的做法。单行注释可以通过井号(`#`)实现;而多行注释则可以采用三重引号(无论是三个单引号还是双引号都可以)[^4]: ```python # This is a single-line comment. ''' This is a multi-line comment. It spans multiple lines. ''' """ Another way to write multi-line comments, using triple double quotes instead. """ ``` #### 变量定义 在 Python 中声明变量不需要指定数据类型,直接赋值即可创建新变量。支持多种内置的数据类型如整数(int), 浮点数(float),字符串(str)等: ```python integer_example = 42 # Integer variable floating_point_example = 3.14 # Float variable string_example = "Hello, world!" # String variable ``` 通过上述内容的学习,能够帮助建立起对 Python 编程的基础认识,并为进一步深入学习打下良好基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值