Overview

  1. 定义一个工具链配置,配置名为"gcc"
1
toolchain("gcc") {
  1. 工具链中工具配置(tool)
1
  tool("cc") {
  1. Compiler tools所支持头文件依赖(编译依赖.ddeps)
1
2
    depfile = "{{output}}.d"
    depsformat = "gcc"
  1. 编译选项(command: cc/cxx)
1
    command = "gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
  1. 工具链显示(description)
1
    description = "CC {{output}}"
  1. 库文件输出路径(outputs)
1
2
    outputs =
        [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]

next:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
  }

  tool("cxx") {
    depfile = "{{output}}.d"
    depsformat = "gcc"
    command = "g++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
    description = "CXX {{output}}"
    outputs =
        [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
  }

  tool("alink") {
  1. 关联文件(rsp)
1
2
    rspfile = "{{output}}.rsp"
    rspfile_content = "{{inputs}}"
  1. 编译选项(command: a)
1
    command = "rm -f {{output}} && ar rcs {{output}} @$rspfile"

next:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    description = "AR {{target_output_name}}{{output_extension}}"

    outputs =
        [ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ]
    default_output_extension = ".a"
    output_prefix = "lib"
  }

  tool("solink") {
    soname = "{{target_output_name}}{{output_extension}}"  # e.g. "libfoo.so".
    sofile = "{{output_dir}}/$soname"
    rspfile = soname + ".rsp"
  1. 编译选项(command: so)
1
2
    command = "g++ -shared {{ldflags}} -o $sofile -Wl,-soname=$soname @$rspfile"
    rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"

next:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    description = "SOLINK $soname"

    # Use this for {{output_extension}} expansions unless a target manually
    # overrides it (in which case {{output_extension}} will be what the target
    # specifies).
    default_output_extension = ".so"

    # Use this for {{output_dir}} expansions unless a target manually overrides
    # it (in which case {{output_dir}} will be what the target specifies).
    default_output_dir = "{{root_out_dir}}"

    outputs = [ sofile ]
  1. 连接依赖(link_depend)
1
2
    link_output = sofile
    depend_output = sofile

next:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    output_prefix = "lib"
  }

  tool("link") {
    outfile = "{{target_output_name}}{{output_extension}}"
    rspfile = "$outfile.rsp"
    command = "g++ {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}"
    description = "LINK $outfile"
    default_output_dir = "{{root_out_dir}}"
    rspfile_content = "{{inputs}}"
    outputs = [ outfile ]
  }

  tool("stamp") {
    command = "touch {{output}}"
    description = "STAMP {{output}}"
  }

  tool("copy") {
    command = "cp -af {{source}} {{output}}"
    description = "COPY {{source}} {{output}}"
  }
}

Key Word

tool(“tool_name”)

gn reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   Compiler tools:
     "cc": C compiler
     "cxx": C++ compiler
     "objc": Objective C compiler
     "objcxx": Objective C++ compiler
     "rc": Resource compiler (Windows .rc files)
     "asm": Assembler

   Linker tools:
     "alink": Linker for static libraries (archives)
     "solink": Linker for shared libraries
     "link": Linker for executables

   Other tools:
     "stamp": Tool for creating stamp files
     "copy": Tool to copy files.
     "action": Defaults for actions

   Platform specific tools:
     "copy_bundle_data": [iOS, macOS] Tool to copy files in a bundle.
     "compile_xcassets": [iOS, macOS] Tool to compile asset catalogs.

   Rust tools:
     "rust_bin": Tool for compiling Rust binaries
     "rust_cdylib": Tool for compiling C-compatible dynamic libraries.
     "rust_dylib": Tool for compiling Rust dynamic libraries.
     "rust_macro": Tool for compiling Rust procedural macros.
     "rust_rlib": Tool for compiling Rust libraries.
     "rust_staticlib": Tool for compiling Rust static libraries.

depfile/depsformat

gn reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    depfile  [string with substitutions]
        Valid for: compiler tools (optional)

        If the tool can write ".d" files, this specifies the name of the
        resulting file. These files are used to list header file dependencies
        (or other implicit input dependencies) that are discovered at build
        time. See also "depsformat".

        Example: depfile = "{{output}}.d"

    depsformat  [string]
        Valid for: compiler tools (when depfile is specified)

        Format for the deps outputs. This is either "gcc" or "msvc". See the
        ninja documentation for "deps" for more information.

        Example: depsformat = "gcc"

gcc –help

-MD Write a depfile containing user and system headers -MF Write depfile output from -MMD, -MD, -MM, or -M to -MG Add missing headers to depfile -MJ Write a compilation database entry per input -MMD Write a depfile containing user headers -MM Like -MMD, but also implies -E and writes to stdout by default -MP Create phony target for each dependency (other than main file) -MQ Specify name of main file output to quote in depfile -MT Specify name of main file output in depfile -MV Use NMake/Jom format for the depfile -M Like -MD, but also implies -E and writes to stdout by default

紧随其后的command,包含编译选项-MMD -MF $depfile,即生成包含依赖用户头文件的{{output}}.d文件。

方舟编译器中的编译选项为-MD -MT {{output}} -MF $depfile,即生成包含依赖用户和系统头文件的{{output}}.d文件,同时-MT指定{{output}}.d中的主文件名为{{output}},取代{{output}}.o

command: cc/cxx

gn reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
  Compiler tools have the notion of a single input and a single output, along
  with a set of compiler-specific flags. The following expansions are
  available:

    {{asmflags}}
    {{cflags}}
    {{cflags_c}}
    {{cflags_cc}}
    {{cflags_objc}}
    {{cflags_objcc}}
    {{defines}}
    {{include_dirs}}
        Strings correspond that to the processed flags/defines/include
        directories specified for the target.
        Example: "--enable-foo --enable-bar"

        Defines will be prefixed by "-D" and include directories will be
        prefixed by "-I" (these work with Posix tools as well as Microsoft
        ones).

gn reference

1
2
3
4
5
6
7
8
    {{output}}
        The relative path and name of the output(s) of the current build step.
        If there is more than one output, this will expand to a list of all of
        them. Example: "out/base/my_file.o"

    {{source}}
        The relative path and name of the current input file.
        Example: "../../base/my_file.cc"

gcc –help

-c Only run preprocess, compile, and assemble steps -D = Define to (or 1 if omitted) -I

Add directory to include search path

description

gn reference

1
2
3
4
5
6
    description  [string with substitutions, optional]
        Valid for: all tools

        What to print when the command is run.

        Example: description = "Compiling {{source}}"

outputs

** gn reference**

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
   outputs  [list of strings with substitutions]
       Valid for: Linker and compiler tools (required)

       An array of names for the output files the tool produces. These are
       relative to the build output directory. There must always be at least
       one output file. There can be more than one output (a linker might
       produce a library and an import library, for example).

       This array just declares to GN what files the tool will produce. It is
       your responsibility to specify the tool command that actually produces
       these files.

       If you specify more than one output for shared library links, you
       should consider setting link_output, depend_output, and
       runtime_outputs.

       Example for a compiler tool that produces .obj files:
         outputs = [
           "{{source_out_dir}}/{{source_name_part}}.obj"
         ]

       Example for a linker tool that produces a .dll and a .lib. The use of
       {{target_output_name}}, {{output_extension}} and {{output_dir}} allows
       the target to override these values.
         outputs = [
           "{{output_dir}}/{{target_output_name}}"
               "{{output_extension}}",
           "{{output_dir}}/{{target_output_name}}.lib",
         ]

   {{source_out_dir}}
       The directory in the generated file and output directories,
       respectively, for the current input file. If the source file is in the
       same directory as the target is declared in, they will will be the same
       as the "target" versions above. Example: "gen/base/test"

   {{source_name_part}}
       The filename part of the source file with no directory or extension. This
       will generally be used for specifying a transformation from a source file
       to a destination file with the same name but different extension.
         "//foo/bar/baz.txt" => "baz"

   {{target_output_name}}
       The short name of the current target with no path information, or the
       value of the "output_name" variable if one is specified in the target.
       This will include the "output_prefix" if any. See also {{label_name}}.

       Example: "libfoo" for the target named "foo" and an output prefix for
       the linker tool of "lib".

   {{output_extension}}
       The value of the "output_extension" variable in the target, or the
       value of the "default_output_extension" value in the tool if the target
       does not specify an output extension.
       Example: ".so"

rsp

gn reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    rspfile  [string with substitutions]
        Valid for: all tools except "action" (optional)

        Name of the response file. If empty, no response file will be
        used. See "rspfile_content".

    rspfile_content  [string with substitutions]
        Valid for: all tools except "action" (required when "rspfile" is used)

        The contents to be written to the response file. This may include all
        or part of the command to send to the tool which allows you to get
        around OS command-line length limits.

        This example adds the inputs and libraries to a response file, but
        passes the linker flags directly on the command line:
          tool("link") {
            command = "link -o {{output}} {{ldflags}} @{{output}}.rsp"
            rspfile = "{{output}}.rsp"
            rspfile_content = "{{inputs}} {{solibs}} {{libs}}"
          }

command: a

man ar

1
2
3
4
5
6
7
8
NAME
     ar -- create and maintain library archives

-c      Whenever an archive is created, an informational message to that effect is written to standard error. If the -c option is specified, ar creates the archive silently.

-r      Replace or add the specified files to the archive.  If the archive does not exist a new archive file is created.  Files that replace existing files do not change the order of the files within the archive.  New files are appended to the archive unless one of the options -a, -b or -i is specified.

-s      Write an object-file index into the archive, or update an existing one, even if no other change is made to the archive.  You may use this modifier flag either with any operation, or alone.  Running `ar s' on an archive is equivalent to running `ranlib' on it.

command: so

g++ –help

-shared Create a shared library. -Wl, Pass comma-separated on to the linker.

-Wl,-soname=$soname可参考Linux下动态链接库文件的realname、soname和linkname

-Wl,--whole-archive/--no-whole-archive可参考Linux C/C++ 链接选项之静态库–whole-archive,–no-whole-archive和–start-group, –end-group

gn reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    {{solibs}}
        Extra libraries from shared library dependencies not specified in the
        {{inputs}}. This is the list of link_output files from shared libraries
        (if the solink tool specifies a "link_output" variable separate from
        the "depend_output").

        These should generally be treated the same as libs by your tool.

        Example: "libfoo.so libbar.so"

    {{libs}}
        Expands to the list of system libraries to link to. Each will be
        prefixed by the "lib_switch".

        As a special case to support Mac, libraries with names ending in
        ".framework" will be added to the {{libs}} with "-framework" preceding
        it, and the lib prefix will be ignored.

        Example: "-lfoo -lbar"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
    link_output  [string with substitutions]
    depend_output  [string with substitutions]
        Valid for: "solink" only (optional)

        These two files specify which of the outputs from the solink tool
        should be used for linking and dependency tracking. These should match
        entries in the "outputs". If unspecified, the first item in the
        "outputs" array will be used for all. See "Separate linking and
        dependencies for shared libraries" below for more.

        On Windows, where the tools produce a .dll shared library and a .lib
        import library, you will want the first two to be the import library
        and the third one to be the .dll file. On Linux, if you're not doing
        the separate linking/dependency optimization, all of these should be
        the .so output.

@/$/${}/{{}}

@ gn reference

1
2
3
4
   - Response file: If the input starts with an "@", it will be interpreted as
     a path to a file containing a list of labels or file names, one per line.
     This allows us to handle long lists of inputs without worrying about
     command line limits.

$/${} gn language: Strings

{{}}猜测为表达式展开。

启用toolchain

build/BUILDCONFIG.gn中配置:

1
set_default_toolchain("//build/toolchain:gcc")

参考

[1] toolchain: Defines a toolchain.

https://gn.googlesource.com/gn/+/master/docs/reference.md#func_toolchain

[2] OpenArkCompiler

https://gitee.com/harmonyos/OpenArkCompiler