File: rust_static_library.gni

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (227 lines) | stat: -rw-r--r-- 9,509 bytes parent folder | download | duplicates (10)
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//build/rust/rust_target.gni")

# Defines a Rust static library which can be used by downstream Rust or C++
# targets. This is a single Rust compilation unit consisting of potentially
# multiple .rs files.
#
# We term this 'rust_static_library' because it is used most analogously
# to a C++ 'static_library' in Chromium. Like the C++ one, it can be compiled
# independently into an intermediate linking target. The output contains the
# object file(s) of the GN target's sources, and not its dependencies.
#
# Parameters
#
#   sources
#     List of source files which this crate is allowed to compile, which is
#     used to determine the impact of source code changes on other GN targets.
#     This is not used by the Rust compiler, as it discovers source files by
#     following `mod` declarations starting at the `crate_root`. The
#     discovered source files must match this list. (This is not yet enforced,
#     but will be.)
#
#   edition (optional)
#     Edition of the Rust language to be used.
#     Options are "2015", "2018" and "2021". Defaults to "2021".
#
#   allow_unsafe (optional)
#     Set to true to allow unsafe code in this target. Defaults to false.
#
#   configs (optional)
#     A list of config labels (in the GN meaning) applying to this target.
#
#   rustflags (optional)
#     Explicit flags for rustc command line. (Use 'edition' or 'features'
#     where possible).
#
#   deps (optional)
#     List of GN targets on which this crate depends. These may be Rust
#     or non-Rust targets.
#
#   public_deps (optional)
#     List of GN targets on which this crate depends, and which are exported
#     into the dependency list of any crate that depends on it. Dependency
#     crates that appear in the public API should be included here.
#
#   test_deps (optional)
#     List of GN targets on which this crate's tests depend, in addition
#     to deps.
#
#   is_gtest_unittests (optional)
#     Should only be set to true for rlibs of gtest unit tests. This ensures
#     all objects in the rlib are linked into the final target, rather than
#     pruning dead code, so that the tests themselves are not discarded by the
#     linker.
#
#   mutually_dependent_target (optional)
#   mutually_dependent_public_deps (optional)
#     These is for use by the mixed_target() template.
#
#     If this Rust code is intrinsically paired with some C/C++ code,
#     with bidirectional calls between the two, then this would
#     be a circular dependency. GN does not allow circular dependencies,
#     (other than for header files per allow_circular_includes_from).
#     But this is common for a 'component' which has both Rust and C++
#     code. You should structure things such that the C++ code depends
#     on the Rust code in the normal way:
#        static_library("cpp_stuff") {
#          deps = [ "rust_stuff" ]
#          # ..
#        }
#     but that the Rust target also notes the C++ target using this
#     'mutually_dependent_target' parameter.
#        rust_static_library("rust_stuff") {
#          mutually_dependent_target = "cpp_stuff"
#          mutually_dependent_public_deps = _cpp_stuff_public_deps
#          # ..
#        }
#
#     This causes the Rust unit tests, if generated, to depend on the mutually
#     dependent target, since depending on the Rust code only would be
#     insufficient. And it allows any C++ bindings generated from the Rust code
#     to include headers from the mutually_dependent_target by depending on its
#     public_deps.
#
#   build_native_rust_unit_tests (optional)
#     Builds native unit tests (under #[cfg(test)]) written inside the Rust
#     crate. This will create a `<name>_unittests` executable in the output
#     directory when set to true.
#
#   unit_test_target (optional)
#     Overrides the default name for the unit tests target
#
#   crate_root (optional)
#     Location of the crate root.
#     This defaults to `./src/lib.rs` and should only be changed when
#     absolutely necessary (such as in the case of generated code).
#
#   features (optional)
#     A list of conditional compilation flags to enable. This can be used
#     to set features for crates built in-tree which are also published to
#     crates.io. Each feature in the list will be passed to rustc as
#     '--cfg feature=XXX'
#
#   cxx_bindings (optional)
#     A list of Rust files which contain #[cxx::bridge] mods and should
#     therefore have C++ bindings generated. See https://cxx.rs.
#     This will automatically add appropriate dependencies: there's no
#     need to depend on the cxx crate or any generated bindings.
#
#   data, testonly, visibility (optional)
#     Same meaning as in other GN targets.
#
#   crate_name (optional)
#     Discouraged - first-party code should prefer to use the auto-generated,
#     target-based crate name which is guaranteed to be globally unique (and
#     still ergonomic to import and use via the `chromium::import!` macro).
#
#   inputs (optional)
#     Additional input files needed for compilation (such as `include!`ed files)
#
#   test_inputs (optional)
#     Same as above but for the unit tests target
#
#   rustc_metadata (optional)
#     Override the metadata identifying the target's version. This allows e.g.
#     linking otherwise conflicting versions of the same Rust library. The
#     metadata string will also be appended to the output library names.
#     Should be used sparingly, since generally we should have one version and
#     build of each target.
#
# Example of usage:
#
#   rust_static_library("foo_bar") {
#     deps = [
#       "//boo/public/rust/bar",
#       "//third_party/rust/crates:argh",
#       "//third_party/rust/crates:serde",
#       "//third_party/rust/crates:slab",
#     ]
#     sources = [ "src/lib.rs" ]
#   }
#
# This template is intended to serve the same purpose as 'rustc_library'
# in Fuchsia.
template("rust_static_library") {
  _target_name = target_name

  _configs = []
  _all_dependent_configs = []

  if (defined(invoker.configs)) {
    _configs += invoker.configs
  }

  # TODO(dcheng): Is there any value in allowing rust_shared_library() to also
  # set `is_gtest_unittest` to true?
  if (defined(invoker.is_gtest_unittests) && invoker.is_gtest_unittests) {
    _output_dir = rebase_path(target_out_dir, root_build_dir)

    config("${_target_name}_alwayslink") {
      # Targets using the #[gtest(...)] proc macro register their tests with
      # static initializers. A rust library target generates a .rlib, which is
      # a regular static library with extra metadata. However, if nothing
      # outside the .rlib references functions in the .rlib—as is often the
      # case with a target containing only tests—the linker will not pull in
      # the .rlib into the final test binary at all, so the tests won't run.
      #
      # C++ works around this by using source sets and directly pass the .o
      # files to the linker, but Rust does not have a parallel to this. Instead,
      # force the linker to always include the whole archive.

      # NOTE: TargetName=>CrateName mangling algorithm should be updated
      # simultaneously in 3 places: here, //build/rust/rust_target.gni,
      # //build/rust/chromium_prelude/import_attribute.rs
      if (defined(invoker.crate_name)) {
        _crate_name = invoker.crate_name
      } else {
        # Not using `get_label_info(..., "label_no_toolchain")` to consistently
        # use `//foo/bar:baz` instead of the alternative shorter `//foo/bar` form.
        _dir = get_label_info(":${_target_name}", "dir")
        _dir = string_replace(_dir, "//", "")
        _crate_name = "${_dir}:${_target_name}"

        # The `string_replace` calls below replicate the escaping algorithm
        # from the `escape_non_identifier_chars` function in
        # //build/rust/chromium_prelude/import_attribute.rs.  Note that the
        # ordering of `match` branches within the Rust function doesn't matter,
        # but the ordering of `string_replace` calls *does* matter - the escape
        # character `_` needs to be handled first to meet the injectivity
        # requirement (otherwise we would get `/` => `_s` => `_us` and the same
        # result for `_s` => `_us`).
        _crate_name = string_replace(_crate_name, "_", "_u")
        _crate_name = string_replace(_crate_name, "/", "_s")
        _crate_name = string_replace(_crate_name, ":", "_c")
        _crate_name = string_replace(_crate_name, "-", "_d")
      }

      _rlib_path = "${_output_dir}/lib${_crate_name}.rlib"
      if (current_os == "aix") {
        # The AIX linker does not implement an option for this.
      } else if (is_win) {
        ldflags = [ "/WHOLEARCHIVE:${_rlib_path}" ]
      } else {
        ldflags = [ "-LinkWrapper,add-whole-archive=${_rlib_path}" ]
      }
    }
    _all_dependent_configs += [ ":${target_name}_alwayslink" ]
    _configs += [ "//build/rust:is_gtest_unittests" ]
  }

  rust_target(_target_name) {
    forward_variables_from(invoker,
                           "*",
                           TESTONLY_AND_VISIBILITY + [ "configs" ])
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    library_configs = _configs
    all_dependent_configs = _all_dependent_configs
    target_type = "rust_library"
  }
}

set_defaults("rust_static_library") {
  configs = default_compiler_configs
}