GN-base
https://github.com/jingjin666/GN-base.git
BUILD.gn
BUILD.gn是GN构建的核心配置文件,GN-base中只用到了一些基本语法,其他高级语法可参考goolge官方文档https://gn.googlesource.com/gn/进行扩展
GN最小系统
- .gn
- BUILD.gn
- build/config/BUILDCONFIG.gn
- build/toolchain/BUILD.gn
.gn
buildconfig = "//build/config/BUILDCONFIG.gn"
BUILD.gn
executable
executable为最后输出的可执行文件,依赖于os_modules,一个系统中可以根据需要生成多个可执行文件
os_config为生成可执行文件的配置文件,也就是ldflags
gcc下的ldflags参考https://sourceware.org/binutils/docs-2.38/ld/Options.html#Options
os_modules模块依赖于os下的BUILD.gn
import("//build/config/compiler.gni")
group("os_modules") {
deps = [
"//os",
]
}
config("os_config") {
defines = []
ld_script = rebase_path("//os/linker.lds")
ldflags = [
"-g",
"-T",
"$ld_script"
]
}
executable("os") {
configs = []
configs += [ ":os_config" ]
sources = []
deps = [
":os_modules",
]
}
target = "$root_out_dir/os.elf"
target_elf = "$root_out_dir/image/os.elf"
target_bin = "$root_out_dir/image/os.bin"
target_hex = "$root_out_dir/image/os.hex"
target_dump = "$root_out_dir/image/os.dump"
copy("copy_os") {
deps = [ ":os" ]
sources = [ "$target" ]
outputs = [ "$target_elf" ]
}
action("build_image") {
deps = [
":copy_os",
]
script = "//build/py_script/elf_format.py"
sources = [
"$target_elf",
]
outputs = [
"$target_bin",
"$target_hex",
"$target_dump",
]
args = [
"--format_tool",
"$crossdev",
"--elf",
rebase_path("$target_elf"),
"--bin",
rebase_path("$target_bin"),
"--hex",
rebase_path("$target_hex"),
"--dump",
rebase_path("$target_dump"),
"--dir",
rebase_path("$root_out_dir/image"),
"--flag",
"bd",
]
}
copy
copy为拷贝动作,定义在build/toolchain/BUILD.gn中
action
当生成可执行文件后,你还需要一些后续操作,这个时候你可以定义action,actoin实际上是通过python脚本来实现自定义操作
build/config/BUILDCONFIG.gn
配置GN使用的编译器,配置toolchain变量来配置使用gcc或者clang等编译器
toolchain = "gcc"
#toolchain = "clang"
target_toolchain = "//build/toolchain:${toolchain}"
set_default_toolchain(target_toolchain)
build/toolchain/BUILD.gn
配置gcc或者clang等其他编译的具体编译选项
gcc
gcc变量定义在build/config/compiler.gni头文件中
import("//build/config/compiler.gni")
toolchain("gcc") {
tool("asm") {
depfile = "{{output}}.d"
command = "${crossdev}gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
depsformat = "gcc"
description = "ASM {{output}}"
outputs =
[ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
}
tool("cc") {
depfile = "{{output}}.d"
command = "${crossdev}gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
depsformat = "gcc"
description = "CC {{output}}"
outputs =
[ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
}
tool("cxx") {
depfile = "{{output}}.d"
command = "${crossdev}g++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
depsformat = "gcc"
description = "CXX {{output}}"
outputs =
[ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
}
tool("link") {
outfile = "{{target_output_name}}{{output_extension}}"
rspfile = "$outfile.rsp"
command = "${crossdev}ld {{ldflags}} -o $outfile --start-group @$rspfile {{solibs}} --end-group {{libs}}"
description = "LINK $outfile"
default_output_dir = "{{root_out_dir}}"
rspfile_content = "{{inputs}}"
outputs = [ outfile ]
default_output_extension = ".elf"
}
tool("alink") {
outfile = "{{target_output_name}}{{output_extension}}"
rspfile = "$outfile.rsp"
command = "${crossdev}ar cr $outfile @$rspfile"
description = "AR $outfile"
default_output_dir = "{{root_out_dir}}"
rspfile_content = "{{inputs}}"
outputs = [ outfile ]
default_output_extension = ".a"
output_prefix = "lib"
}
tool("solink") {
outfile = "{{target_output_name}}{{output_extension}}"
rspfile = "$outfile.rsp"
command = "${crossdev}gcc --shared -fPIC -o $outfile @$rspfile"
description = "SOLINK $outfile"
default_output_dir = "{{root_out_dir}}"
rspfile_content = "{{inputs}}"
outputs = [ outfile ]
default_output_extension = ".so"
output_prefix = "lib"
}
tool("stamp") {
command = "touch {{output}}"
description = "STAMP {{output}}"
}
tool("copy") {
command = "cp -af {{source}} {{output}}"
description = "COPY {{source}} {{output}}"
}
}
toolchain("clang") {
}
clang
build/config/compiler.gni
gcc
gcc下通用的变量包括:
- crossdev:是否需要交叉编译
- defines:宏定义
- include_dirs:头文件目录
- asmflags:汇编编译选项
- cflags:目标编译选项
- cflags_c:C标准的编译选项
- cflags_cc:C++标准编译选项
arch_flags定义了所选编译器针对目标硬件的编译选项,包括不限于:
- arch_cpu
- arch_c
- debug
- cpu
- optimaztion
不同编译器对应不同cpu架构所支持的arch_flags是不一样的,这里的arch_flags只是gcc对应cpu的flags
gcc支持的flags参考https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html
arch_cpuflags = []
arch_cpuflags = [ "-mcpu=cortex-a53" ]
arch_cflags = []
arch_cflags = [ "-nostdlib",
"-nostdinc",
"-fno-builtin",
"-fno-common",
"-fno-stack-protector",
"-fno-strict-overflow",
"-fno-strict-aliasing" ]
debug_build_flags = []
debug_build_flags = [ "-g" ]
debug_build_flags += [ "-Wall",
"-Wstrict-prototypes",
"-Wshadow",
"-Wundef" ]
arch_optimaztion_flags = []
arch_flags = arch_cpuflags + arch_cflags + debug_build_flags + arch_optimaztion_flags
crossdev = "aarch64-none-elf-"
cflags_c = [ "-std=gnu99" ]
cflags_cc = [ "-std=gnu++17" ]
cflags = arch_flags
asmflags = cflags
asmflags += [ "-D__ASSEMBLY__" ]
defines = [ "GIT_VERSION=" ]
添加新代码到GN-base中
1、新增文件夹os/test
2、修改os/BUILD.gn
添加deps和configs
group("os") {
deps = []
deps += [
"arch",
"test",
]
}
config("kernel") {
configs = []
configs += [
"arch:kernel",
"test:kernel",
]
}
3、新增源文件和头文件os/test/test.c,os/test/include/test.h
4、新增os/test/BUILD.gn
如果需要把当前头文件目录导出到系统头文件目录,需要在config-kernel中加入include_dirs
如果当前源文件需要导入kernel系统头文件目录,需要在configs中加入//build/config:kernel
module_name = get_path_info(rebase_path("."), "name")
source_set(module_name) {
sources = [
"test.c",
]
# 导入的配置目录
configs = [
"//build/config:kernel",
]
}
# 导出的头文件
config("kernel") {
include_dirs = [ "./include" ]
}