1# Copyright 2019 The Hafnium Authors.
2#
3# Use of this source code is governed by a BSD-style
4# license that can be found in the LICENSE file or at
5# https://opensource.org/licenses/BSD-3-Clause.
6
7# This template auto-generate a C header file with "#define" constants, e.g.
8# struct sizes and member offsets.
9#
10# It uses a trick similar to other projects, e.g. Linux, where the integer
11# constant is used as an immediate in an inline assembly block. The source file
12# is compiled and the constant extracted by a script which generates the header
13# file. For easy grep-ing, the constant is compiled into a '.ascii' string,
14# surrounded by magic strings, and extracted using the 'strings' binutils tool.
15#
16# To guarantee correctness, the same source file is compiled again as part
17# of the parent target but this time the declarations are converted to
18# static_asserts to check the values at its compile-time.
19template("offset_size_header") {
20  target_lib = "${target_name}__lib"
21  target_header = "${target_name}__header"
22
23  # Compile source files into binaries that contain strings with definitions
24  # of constants.
25  static_library(target_lib) {
26    forward_variables_from(invoker,
27                           [
28                             "sources",
29                             "deps",
30                             "test_only",
31                           ])
32    defines = [ "GENERATE_BINARY" ]
33
34    # Disable LTO to force emitting assembly.
35    cflags = [ "-fno-lto" ]
36  }
37
38  # Extract strings from the static library, parse definitions and generate
39  # a header file.
40  action(target_header) {
41    forward_variables_from(invoker, [ "test_only" ])
42    lib_file = "${target_out_dir}/${target_lib}.a"
43    out_file = "${root_gen_dir}/offset_size_header/${invoker.path}"
44
45    script = "//build/toolchain/gen_offset_size_header.py"
46    args = [
47      rebase_path(lib_file, root_build_dir),
48      rebase_path(out_file, root_build_dir),
49    ]
50    deps = [
51      ":$target_lib",
52    ]
53    outputs = [
54      out_file,
55    ]
56  }
57
58  # This source_set will be compiled into the target that depends on this one.
59  # This generates static_asserts which check the constants in the generated
60  # header against compile-time structs.
61  source_set(target_name) {
62    forward_variables_from(invoker,
63                           [
64                             "sources",
65                             "test_only",
66                           ])
67    cflags = [
68      "-include",
69      invoker.path,
70    ]
71    defines = [ "VERIFY_HEADER" ]
72    deps = [
73      ":$target_header",
74    ]
75  }
76}
77