blob: a1e17fc3fd5c3960cc4d88c190a93fc54e43097b [file] [log] [blame]
Ivan Lozanoffee3342019-08-27 12:03:00 -07001// Copyright 2019 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package rust
16
17import (
Ivan Lozano1776a2a2020-11-11 10:59:52 -050018 "path/filepath"
Ivan Lozanoffee3342019-08-27 12:03:00 -070019 "strings"
20
21 "github.com/google/blueprint"
22
23 "android/soong/android"
Ivan Lozano0a468a42024-05-13 21:03:34 -040024 "android/soong/cc"
ThiƩbaud Weksteen71512f32020-11-03 15:17:51 +010025 "android/soong/rust/config"
Ivan Lozanoffee3342019-08-27 12:03:00 -070026)
27
28var (
Wen-yi Chu41326c12023-09-22 03:58:59 +000029 _ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc")
Wen-yi Chu41326c12023-09-22 03:58:59 +000030 rustc = pctx.AndroidStaticRule("rustc",
31 blueprint.RuleParams{
32 Command: "$envVars $rustcCmd " +
Colin Cross004bd3f2023-10-02 11:39:17 -070033 "-C linker=${config.RustLinker} " +
34 "-C link-args=\"${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
Wen-yi Chu41326c12023-09-22 03:58:59 +000035 "--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
Ivan Lozanocfeec1c2024-03-28 19:27:24 +000036 " && grep ^$out: $out.d.raw > $out.d",
Colin Cross004bd3f2023-10-02 11:39:17 -070037 CommandDeps: []string{"$rustcCmd"},
Wen-yi Chu41326c12023-09-22 03:58:59 +000038 // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
39 // Rustc emits unneeded dependency lines for the .d and input .rs files.
40 // Those extra lines cause ninja warning:
41 // "warning: depfile has multiple output paths"
42 // For ninja, we keep/grep only the dependency rule for the rust $out file.
43 Deps: blueprint.DepsGCC,
44 Depfile: "$out.d",
45 },
Colin Cross004bd3f2023-10-02 11:39:17 -070046 "rustcFlags", "earlyLinkFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
Wen-yi Chu41326c12023-09-22 03:58:59 +000047
48 _ = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
49 rustdoc = pctx.AndroidStaticRule("rustdoc",
50 blueprint.RuleParams{
51 Command: "$envVars $rustdocCmd $rustdocFlags $in -o $outDir && " +
52 "touch $out",
53 CommandDeps: []string{"$rustdocCmd"},
54 },
55 "rustdocFlags", "outDir", "envVars")
56
57 _ = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver")
58 clippyDriver = pctx.AndroidStaticRule("clippy",
59 blueprint.RuleParams{
60 Command: "$envVars $clippyCmd " +
61 // Because clippy-driver uses rustc as backend, we need to have some output even during the linting.
62 // Use the metadata output as it has the smallest footprint.
63 "--emit metadata -o $out --emit dep-info=$out.d.raw $in ${libFlags} " +
64 "$rustcFlags $clippyFlags" +
Alex91c74762024-04-11 17:30:27 +020065 " && grep ^$out: $out.d.raw > $out.d",
Wen-yi Chu41326c12023-09-22 03:58:59 +000066 CommandDeps: []string{"$clippyCmd"},
67 Deps: blueprint.DepsGCC,
68 Depfile: "$out.d",
69 },
70 "rustcFlags", "libFlags", "clippyFlags", "envVars")
71
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -040072 zip = pctx.AndroidStaticRule("zip",
73 blueprint.RuleParams{
74 Command: "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp",
75 CommandDeps: []string{"${SoongZipCmd}"},
76 Rspfile: "$out.rsp",
77 RspfileContent: "$in",
78 })
Ivan Lozano43845682020-07-09 21:03:28 -040079
Wen-yi Chu41326c12023-09-22 03:58:59 +000080 cp = pctx.AndroidStaticRule("cp",
Ivan Lozano43845682020-07-09 21:03:28 -040081 blueprint.RuleParams{
82 Command: "cp `cat $outDir.rsp` $outDir",
83 Rspfile: "${outDir}.rsp",
84 RspfileContent: "$in",
85 },
86 "outDir")
Sasha Smundaka76acba2022-04-18 20:12:56 -070087
88 // Cross-referencing:
89 _ = pctx.SourcePathVariable("rustExtractor",
90 "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/rust_extractor")
91 _ = pctx.VariableFunc("kytheCorpus",
92 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
93 _ = pctx.VariableFunc("kytheCuEncoding",
94 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
Wen-yi Chu41326c12023-09-22 03:58:59 +000095 _ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
96 kytheExtract = pctx.AndroidStaticRule("kythe",
97 blueprint.RuleParams{
98 Command: `KYTHE_CORPUS=${kytheCorpus} ` +
99 `KYTHE_OUTPUT_FILE=$out ` +
100 `KYTHE_VNAMES=$kytheVnames ` +
101 `KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
102 `KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
103 `$rustExtractor $envVars ` +
104 `$rustcCmd ` +
Colin Cross004bd3f2023-10-02 11:39:17 -0700105 `-C linker=${config.RustLinker} ` +
106 `-C link-args="${crtBegin} ${linkFlags} ${crtEnd}" ` +
Wen-yi Chu41326c12023-09-22 03:58:59 +0000107 `$in ${libFlags} $rustcFlags`,
108 CommandDeps: []string{"$rustExtractor", "$kytheVnames"},
109 Rspfile: "${out}.rsp",
110 RspfileContent: "$in",
111 },
Colin Cross004bd3f2023-10-02 11:39:17 -0700112 "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
Ivan Lozanoffee3342019-08-27 12:03:00 -0700113)
114
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400115type buildOutput struct {
Joel Galensonfa049382021-01-14 16:03:18 -0800116 outputFile android.Path
Sasha Smundaka76acba2022-04-18 20:12:56 -0700117 kytheFile android.Path
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400118}
Ivan Lozanoffee3342019-08-27 12:03:00 -0700119
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400120func init() {
121 pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
Ivan Lozano0a468a42024-05-13 21:03:34 -0400122 cc.TransformRlibstoStaticlib = TransformRlibstoStaticlib
Ivan Lozanoffee3342019-08-27 12:03:00 -0700123}
124
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400125type transformProperties struct {
126 crateName string
127 targetTriple string
128 is64Bit bool
129 bootstrap bool
130 inRecovery bool
131 inRamdisk bool
132 inVendorRamdisk bool
133 cargoOutDir android.OptionalPath
134 synthetic bool
135 crateType string
136}
137
138// Populates a standard transformProperties struct for Rust modules
139func getTransformProperties(ctx ModuleContext, crateType string) transformProperties {
140 module := ctx.RustModule()
141 return transformProperties{
142 crateName: module.CrateName(),
143 is64Bit: ctx.toolchain().Is64Bit(),
144 targetTriple: ctx.toolchain().RustTriple(),
145 bootstrap: module.Bootstrap(),
146 inRecovery: module.InRecovery(),
147 inRamdisk: module.InRamdisk(),
148 inVendorRamdisk: module.InVendorRamdisk(),
149 cargoOutDir: module.compiler.cargoOutDir(),
150
151 // crateType indicates what type of crate to build
152 crateType: crateType,
153
154 // synthetic indicates whether this is an actual Rust module or not
155 synthetic: false,
156 }
157}
158
Wen-yi Chu41326c12023-09-22 03:58:59 +0000159func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700160 outputFile android.WritablePath) buildOutput {
Ivan Lozanoab586472024-05-15 10:59:47 -0400161 if ctx.RustModule().compiler.Thinlto() {
162 flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
163 }
Chris Wailes99180c22024-02-20 21:39:40 +0000164
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400165 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "bin"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700166}
167
Wen-yi Chu41326c12023-09-22 03:58:59 +0000168func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700169 outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400170 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700171}
172
Ivan Lozano872e8462024-10-30 19:30:48 +0000173// TransformRlibstoStaticlib is assumed to be called from the cc module, and
174// thus needs to reconstruct the common set of flags which need to be passed
175// to the rustc compiler.
Ivan Lozano0a468a42024-05-13 21:03:34 -0400176func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
177 outputFile android.WritablePath) android.Path {
178
179 var rustPathDeps PathDeps
180 var rustFlags Flags
181
182 for _, rlibDep := range deps {
183 rustPathDeps.RLibs = append(rustPathDeps.RLibs, RustLibrary{Path: rlibDep.LibPath, CrateName: rlibDep.CrateName})
184 rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
185 }
186
187 ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
188 toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
189 t := transformProperties{
190 // Crate name can be a predefined value as this is a staticlib and
191 // it does not need to be unique. The crate name is used for name
192 // mangling, but it is mixed with the metadata for that purpose, which we
193 // already set to the module name.
194 crateName: "generated_rust_staticlib",
195 is64Bit: toolchain.Is64Bit(),
196 targetTriple: toolchain.RustTriple(),
197 bootstrap: ccModule.Bootstrap(),
198 inRecovery: ccModule.InRecovery(),
199 inRamdisk: ccModule.InRamdisk(),
200 inVendorRamdisk: ccModule.InVendorRamdisk(),
201
202 // crateType indicates what type of crate to build
203 crateType: "staticlib",
204
205 // synthetic indicates whether this is an actual Rust module or not
206 synthetic: true,
207 }
208
209 rustFlags = CommonDefaultFlags(ctx, toolchain, rustFlags)
210 rustFlags = CommonLibraryCompilerFlags(ctx, rustFlags)
211 rustFlags.GlobalRustFlags = append(rustFlags.GlobalRustFlags, "-C lto=thin")
212
213 rustFlags.EmitXrefs = false
214
215 return transformSrctoCrate(ctx, mainSrc, rustPathDeps, rustFlags, outputFile, t).outputFile
216}
217
Wen-yi Chu41326c12023-09-22 03:58:59 +0000218func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700219 outputFile android.WritablePath) buildOutput {
Ivan Lozanoab586472024-05-15 10:59:47 -0400220 if ctx.RustModule().compiler.Thinlto() {
221 flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
222 }
Chris Wailes99180c22024-02-20 21:39:40 +0000223
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400224 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "dylib"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700225}
226
Wen-yi Chu41326c12023-09-22 03:58:59 +0000227func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700228 outputFile android.WritablePath) buildOutput {
Ivan Lozanoab586472024-05-15 10:59:47 -0400229 if ctx.RustModule().compiler.Thinlto() {
230 flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
231 }
232
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400233 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "staticlib"))
Ivan Lozano52767be2019-10-18 14:49:46 -0700234}
235
Wen-yi Chu41326c12023-09-22 03:58:59 +0000236func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700237 outputFile android.WritablePath) buildOutput {
Ivan Lozanoab586472024-05-15 10:59:47 -0400238 if ctx.RustModule().compiler.Thinlto() {
239 flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
240 }
241
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400242 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "cdylib"))
Ivan Lozano52767be2019-10-18 14:49:46 -0700243}
244
Wen-yi Chu41326c12023-09-22 03:58:59 +0000245func TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
Dan Albert06feee92021-03-19 15:06:02 -0700246 flags Flags, outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400247 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "proc-macro"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700248}
249
250func rustLibsToPaths(libs RustLibraries) android.Paths {
251 var paths android.Paths
252 for _, lib := range libs {
253 paths = append(paths, lib.Path)
254 }
255 return paths
256}
257
Wen-yi Chu41326c12023-09-22 03:58:59 +0000258func makeLibFlags(deps PathDeps) []string {
Dan Albert06feee92021-03-19 15:06:02 -0700259 var libFlags []string
260
261 // Collect library/crate flags
Wen-yi Chu41326c12023-09-22 03:58:59 +0000262 for _, lib := range deps.RLibs {
263 libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700264 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000265 for _, lib := range deps.DyLibs {
266 libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700267 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000268 for _, proc_macro := range deps.ProcMacros {
269 libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700270 }
271
272 for _, path := range deps.linkDirs {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000273 libFlags = append(libFlags, "-L "+path)
Dan Albert06feee92021-03-19 15:06:02 -0700274 }
275
276 return libFlags
277}
278
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400279func rustEnvVars(ctx android.ModuleContext, deps PathDeps, crateName string, cargoOutDir android.OptionalPath) []string {
Dan Albert06feee92021-03-19 15:06:02 -0700280 var envVars []string
281
282 // libstd requires a specific environment variable to be set. This is
283 // not officially documented and may be removed in the future. See
284 // https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400285 if crateName == "std" {
286 envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.Arch().ArchType])
Dan Albert06feee92021-03-19 15:06:02 -0700287 }
288
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400289 if len(deps.SrcDeps) > 0 && cargoOutDir.Valid() {
290 moduleGenDir := cargoOutDir
Dan Albert06feee92021-03-19 15:06:02 -0700291 // We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
292 // assumes that paths are relative to the source file.
Wen-yi Chu41326c12023-09-22 03:58:59 +0000293 var outDirPrefix string
294 if !filepath.IsAbs(moduleGenDir.String()) {
Sam Delmericoa588d152023-06-16 10:28:04 -0400295 // If OUT_DIR is not absolute, we use $$PWD to generate an absolute path (os.Getwd() returns '/')
Wen-yi Chu41326c12023-09-22 03:58:59 +0000296 outDirPrefix = "$$PWD/"
Sam Delmericoa588d152023-06-16 10:28:04 -0400297 } else {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000298 // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything.
299 outDirPrefix = ""
Dan Albert06feee92021-03-19 15:06:02 -0700300 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000301 envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
Peter Collingbourne0dcd62e2023-03-31 23:05:16 -0700302 } else {
303 // TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value.
304 envVars = append(envVars, "OUT_DIR=out")
Dan Albert06feee92021-03-19 15:06:02 -0700305 }
306
Matthew Maurer34609fa2023-06-26 21:10:13 +0000307 envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx))
308
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400309 if rustMod, ok := ctx.Module().(*Module); ok && rustMod.compiler.cargoEnvCompat() {
310 // We only emulate cargo environment variables for 3p code, which is only ever built
311 // by defining a Rust module, so we only need to set these for true Rust modules.
312 if bin, ok := rustMod.compiler.(*binaryDecorator); ok {
Matthew Maurer34609fa2023-06-26 21:10:13 +0000313 envVars = append(envVars, "CARGO_BIN_NAME="+bin.getStem(ctx))
314 }
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400315 envVars = append(envVars, "CARGO_CRATE_NAME="+crateName)
316 envVars = append(envVars, "CARGO_PKG_NAME="+crateName)
317 pkgVersion := rustMod.compiler.cargoPkgVersion()
Matthew Maurer34609fa2023-06-26 21:10:13 +0000318 if pkgVersion != "" {
319 envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
Ivan Lozanof4455622023-07-28 12:42:20 -0400320
321 // Ensure the version is in the form of "x.y.z" (approximately semver compliant).
322 //
323 // For our purposes, we don't care to enforce that these are integers since they may
324 // include other characters at times (e.g. sometimes the patch version is more than an integer).
325 if strings.Count(pkgVersion, ".") == 2 {
326 var semver_parts = strings.Split(pkgVersion, ".")
327 envVars = append(envVars, "CARGO_PKG_VERSION_MAJOR="+semver_parts[0])
328 envVars = append(envVars, "CARGO_PKG_VERSION_MINOR="+semver_parts[1])
329 envVars = append(envVars, "CARGO_PKG_VERSION_PATCH="+semver_parts[2])
330 }
Matthew Maurer34609fa2023-06-26 21:10:13 +0000331 }
332 }
333
Sam Delmericoc5cf9902023-10-23 21:40:13 +0000334 if ctx.Darwin() {
335 envVars = append(envVars, "ANDROID_RUST_DARWIN=true")
336 }
337
Dan Albert06feee92021-03-19 15:06:02 -0700338 return envVars
339}
340
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400341func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps PathDeps, flags Flags,
342 outputFile android.WritablePath, t transformProperties) buildOutput {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700343
344 var inputs android.Paths
Colin Cross004bd3f2023-10-02 11:39:17 -0700345 var implicits android.Paths
346 var orderOnly android.Paths
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400347 var output buildOutput
Dan Albert06feee92021-03-19 15:06:02 -0700348 var rustcFlags, linkFlags []string
Wen-yi Chu41326c12023-09-22 03:58:59 +0000349 var earlyLinkFlags string
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400350
351 output.outputFile = outputFile
Ivan Lozanoffee3342019-08-27 12:03:00 -0700352
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400353 envVars := rustEnvVars(ctx, deps, t.crateName, t.cargoOutDir)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000354
Ivan Lozanoffee3342019-08-27 12:03:00 -0700355 inputs = append(inputs, main)
356
357 // Collect rustc flags
Ivan Lozanof1c84332019-09-20 11:00:37 -0700358 rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700359 rustcFlags = append(rustcFlags, flags.RustFlags...)
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400360 rustcFlags = append(rustcFlags, "--crate-type="+t.crateType)
361 if t.crateName != "" {
362 rustcFlags = append(rustcFlags, "--crate-name="+t.crateName)
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700363 }
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400364 if t.targetTriple != "" {
365 rustcFlags = append(rustcFlags, "--target="+t.targetTriple)
366 linkFlags = append(linkFlags, "-target "+t.targetTriple)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700367 }
Matthew Maurerbb3add12020-06-25 09:34:12 -0700368
369 // Suppress an implicit sysroot
370 rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
371
Chris Wailes99180c22024-02-20 21:39:40 +0000372 // Enable incremental compilation if requested by user
373 if ctx.Config().IsEnvTrue("SOONG_RUSTC_INCREMENTAL") {
374 incrementalPath := android.PathForOutput(ctx, "rustc").String()
375
376 rustcFlags = append(rustcFlags, "-C incremental="+incrementalPath)
377 } else {
378 rustcFlags = append(rustcFlags, "-C codegen-units=1")
379 }
380
Chris Wailes6d12db42023-02-24 16:58:18 -0800381 // Disallow experimental features
Colin Crossf96b0012023-10-26 14:01:51 -0700382 modulePath := ctx.ModuleDir()
Chris Wailes6d12db42023-02-24 16:58:18 -0800383 if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
Chris Wailes547bfdd2023-05-31 11:53:44 -0700384 rustcFlags = append(rustcFlags, "-Zallow-features=\"\"")
Chris Wailesd9781fd2021-12-03 17:17:28 -0800385 }
386
Ivan Lozanof1c84332019-09-20 11:00:37 -0700387 // Collect linker flags
A. Cody Schuffelenf29ca582023-07-13 19:03:39 -0700388 if !ctx.Darwin() {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000389 earlyLinkFlags = "-Wl,--as-needed"
A. Cody Schuffelenf29ca582023-07-13 19:03:39 -0700390 }
391
Wen-yi Chu41326c12023-09-22 03:58:59 +0000392 linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
393 linkFlags = append(linkFlags, flags.LinkFlags...)
394
395 // Check if this module needs to use the bootstrap linker
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400396 if t.bootstrap && !t.inRecovery && !t.inRamdisk && !t.inVendorRamdisk {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000397 dynamicLinker := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker"
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400398 if t.is64Bit {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000399 dynamicLinker += "64"
400 }
401 linkFlags = append(linkFlags, dynamicLinker)
402 }
403
404 libFlags := makeLibFlags(deps)
405
Ivan Lozanoffee3342019-08-27 12:03:00 -0700406 // Collect dependencies
Wen-yi Chu41326c12023-09-22 03:58:59 +0000407 implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
408 implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
409 implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
Colin Cross004bd3f2023-10-02 11:39:17 -0700410 implicits = append(implicits, deps.StaticLibs...)
411 implicits = append(implicits, deps.SharedLibDeps...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000412 implicits = append(implicits, deps.srcProviderFiles...)
Colin Cross004bd3f2023-10-02 11:39:17 -0700413 implicits = append(implicits, deps.AfdoProfiles...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000414
Colin Cross004bd3f2023-10-02 11:39:17 -0700415 implicits = append(implicits, deps.CrtBegin...)
416 implicits = append(implicits, deps.CrtEnd...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000417
Colin Cross004bd3f2023-10-02 11:39:17 -0700418 orderOnly = append(orderOnly, deps.SharedLibs...)
Sam Delmerico51d6d1c2023-03-28 16:54:00 -0400419
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400420 if !t.synthetic {
421 // Only worry about OUT_DIR for actual Rust modules.
422 // Libraries built from cc use generated source, and do not utilize OUT_DIR.
423 if len(deps.SrcDeps) > 0 {
424 var outputs android.WritablePaths
Ivan Lozano43845682020-07-09 21:03:28 -0400425
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400426 for _, genSrc := range deps.SrcDeps {
427 if android.SuffixInList(outputs.Strings(), genSubDir+genSrc.Base()) {
428 ctx.PropertyErrorf("srcs",
429 "multiple source providers generate the same filename output: "+genSrc.Base())
430 }
431 outputs = append(outputs, android.PathForModuleOut(ctx, genSubDir+genSrc.Base()))
Ivan Lozano43845682020-07-09 21:03:28 -0400432 }
Ivan Lozano43845682020-07-09 21:03:28 -0400433
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400434 ctx.Build(pctx, android.BuildParams{
435 Rule: cp,
436 Description: "cp " + t.cargoOutDir.Path().Rel(),
437 Outputs: outputs,
438 Inputs: deps.SrcDeps,
439 Args: map[string]string{
440 "outDir": t.cargoOutDir.String(),
441 },
442 })
443 implicits = append(implicits, outputs.Paths()...)
444 }
Ivan Lozano43845682020-07-09 21:03:28 -0400445 }
446
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400447 if !t.synthetic {
448 // Only worry about clippy for actual Rust modules.
449 // Libraries built from cc use generated source, and don't need to run clippy.
450 if flags.Clippy {
451 clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
452 ctx.Build(pctx, android.BuildParams{
453 Rule: clippyDriver,
454 Description: "clippy " + main.Rel(),
455 Output: clippyFile,
456 ImplicitOutputs: nil,
457 Inputs: inputs,
458 Implicits: implicits,
459 OrderOnly: orderOnly,
460 Args: map[string]string{
461 "rustcFlags": strings.Join(rustcFlags, " "),
462 "libFlags": strings.Join(libFlags, " "),
463 "clippyFlags": strings.Join(flags.ClippyFlags, " "),
464 "envVars": strings.Join(envVars, " "),
465 },
466 })
467 // Declare the clippy build as an implicit dependency of the original crate.
468 implicits = append(implicits, clippyFile)
469 }
Ivan Lozanobae62be2020-07-21 13:28:27 -0400470 }
471
Wen-yi Chu41326c12023-09-22 03:58:59 +0000472 ctx.Build(pctx, android.BuildParams{
Colin Cross004bd3f2023-10-02 11:39:17 -0700473 Rule: rustc,
474 Description: "rustc " + main.Rel(),
475 Output: outputFile,
476 Inputs: inputs,
477 Implicits: implicits,
478 OrderOnly: orderOnly,
Wen-yi Chu41326c12023-09-22 03:58:59 +0000479 Args: map[string]string{
Colin Cross004bd3f2023-10-02 11:39:17 -0700480 "rustcFlags": strings.Join(rustcFlags, " "),
481 "earlyLinkFlags": earlyLinkFlags,
482 "linkFlags": strings.Join(linkFlags, " "),
483 "libFlags": strings.Join(libFlags, " "),
484 "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
485 "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
486 "envVars": strings.Join(envVars, " "),
Wen-yi Chu41326c12023-09-22 03:58:59 +0000487 },
488 })
Ivan Lozanoffee3342019-08-27 12:03:00 -0700489
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400490 if !t.synthetic {
491 // Only emit xrefs for true Rust modules.
492 if flags.EmitXrefs {
493 kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
494 ctx.Build(pctx, android.BuildParams{
495 Rule: kytheExtract,
496 Description: "Xref Rust extractor " + main.Rel(),
497 Output: kytheFile,
498 Inputs: inputs,
499 Implicits: implicits,
500 OrderOnly: orderOnly,
501 Args: map[string]string{
502 "rustcFlags": strings.Join(rustcFlags, " "),
503 "linkFlags": strings.Join(linkFlags, " "),
504 "libFlags": strings.Join(libFlags, " "),
505 "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
506 "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
507 "envVars": strings.Join(envVars, " "),
508 },
509 })
510 output.kytheFile = kytheFile
511 }
Sasha Smundaka76acba2022-04-18 20:12:56 -0700512 }
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400513 return output
514}
Dan Albert06feee92021-03-19 15:06:02 -0700515
Wen-yi Chu41326c12023-09-22 03:58:59 +0000516func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps,
517 flags Flags) android.ModuleOutPath {
Dan Albert06feee92021-03-19 15:06:02 -0700518
519 rustdocFlags := append([]string{}, flags.RustdocFlags...)
520 rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null")
521
Dan Albertb433bf72021-04-27 17:12:02 -0700522 // Build an index for all our crates. -Z unstable options is required to use
523 // this flag.
524 rustdocFlags = append(rustdocFlags, "-Z", "unstable-options", "--enable-index-page")
525
Chris Wailes3d211a02024-07-11 11:31:14 -0700526 // Ensure we use any special-case code-paths for Soong.
527 rustdocFlags = append(rustdocFlags, "--cfg", "soong")
528
Dan Albert06feee92021-03-19 15:06:02 -0700529 targetTriple := ctx.toolchain().RustTriple()
530
531 // Collect rustc flags
532 if targetTriple != "" {
533 rustdocFlags = append(rustdocFlags, "--target="+targetTriple)
534 }
535
536 crateName := ctx.RustModule().CrateName()
Dan Albertb433bf72021-04-27 17:12:02 -0700537 rustdocFlags = append(rustdocFlags, "--crate-name "+crateName)
Dan Albert06feee92021-03-19 15:06:02 -0700538
Wen-yi Chu41326c12023-09-22 03:58:59 +0000539 rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...)
Dan Albert06feee92021-03-19 15:06:02 -0700540 docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
Dan Albertb433bf72021-04-27 17:12:02 -0700541
Chris Wailesb2703ad2021-07-30 13:25:42 -0700542 // Silence warnings about renamed lints for third-party crates
Colin Crossf96b0012023-10-26 14:01:51 -0700543 modulePath := ctx.ModuleDir()
Chris Wailesb2703ad2021-07-30 13:25:42 -0700544 if android.IsThirdPartyPath(modulePath) {
Chris Wailes7b3eb242023-02-14 16:09:49 -0800545 rustdocFlags = append(rustdocFlags, " -A warnings")
Chris Wailesb2703ad2021-07-30 13:25:42 -0700546 }
Chris Wailes9953a192021-07-28 12:07:16 -0700547
Dan Albertb433bf72021-04-27 17:12:02 -0700548 // Yes, the same out directory is used simultaneously by all rustdoc builds.
549 // This is what cargo does. The docs for individual crates get generated to
550 // a subdirectory named for the crate, and rustdoc synchronizes writes to
551 // shared pieces like the index and search data itself.
552 // https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146
553 docDir := android.PathForOutput(ctx, "rustdoc")
Dan Albert06feee92021-03-19 15:06:02 -0700554
Wen-yi Chu41326c12023-09-22 03:58:59 +0000555 ctx.Build(pctx, android.BuildParams{
556 Rule: rustdoc,
557 Description: "rustdoc " + main.Rel(),
558 Output: docTimestampFile,
559 Input: main,
560 Implicit: ctx.RustModule().UnstrippedOutputFile(),
561 Args: map[string]string{
562 "rustdocFlags": strings.Join(rustdocFlags, " "),
563 "outDir": docDir.String(),
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400564 "envVars": strings.Join(rustEnvVars(ctx, deps, crateName, ctx.RustModule().compiler.cargoOutDir()), " "),
Wen-yi Chu41326c12023-09-22 03:58:59 +0000565 },
566 })
Dan Albert06feee92021-03-19 15:06:02 -0700567
568 return docTimestampFile
569}