xref: /aosp_15_r20/build/soong/rust/builder.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 The Android Open Source Project
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage rust
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
19*333d2b36SAndroid Build Coastguard Worker	"strings"
20*333d2b36SAndroid Build Coastguard Worker
21*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
22*333d2b36SAndroid Build Coastguard Worker
23*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
24*333d2b36SAndroid Build Coastguard Worker	"android/soong/cc"
25*333d2b36SAndroid Build Coastguard Worker	"android/soong/rust/config"
26*333d2b36SAndroid Build Coastguard Worker)
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Workervar (
29*333d2b36SAndroid Build Coastguard Worker	_     = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc")
30*333d2b36SAndroid Build Coastguard Worker	rustc = pctx.AndroidStaticRule("rustc",
31*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
32*333d2b36SAndroid Build Coastguard Worker			Command: "$envVars $rustcCmd " +
33*333d2b36SAndroid Build Coastguard Worker				"-C linker=${config.RustLinker} " +
34*333d2b36SAndroid Build Coastguard Worker				"-C link-args=\"${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
35*333d2b36SAndroid Build Coastguard Worker				"--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
36*333d2b36SAndroid Build Coastguard Worker				" && grep ^$out: $out.d.raw > $out.d",
37*333d2b36SAndroid Build Coastguard Worker			CommandDeps: []string{"$rustcCmd"},
38*333d2b36SAndroid Build Coastguard Worker			// Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
39*333d2b36SAndroid Build Coastguard Worker			// Rustc emits unneeded dependency lines for the .d and input .rs files.
40*333d2b36SAndroid Build Coastguard Worker			// Those extra lines cause ninja warning:
41*333d2b36SAndroid Build Coastguard Worker			//     "warning: depfile has multiple output paths"
42*333d2b36SAndroid Build Coastguard Worker			// For ninja, we keep/grep only the dependency rule for the rust $out file.
43*333d2b36SAndroid Build Coastguard Worker			Deps:    blueprint.DepsGCC,
44*333d2b36SAndroid Build Coastguard Worker			Depfile: "$out.d",
45*333d2b36SAndroid Build Coastguard Worker		},
46*333d2b36SAndroid Build Coastguard Worker		"rustcFlags", "earlyLinkFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
47*333d2b36SAndroid Build Coastguard Worker
48*333d2b36SAndroid Build Coastguard Worker	_       = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
49*333d2b36SAndroid Build Coastguard Worker	rustdoc = pctx.AndroidStaticRule("rustdoc",
50*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
51*333d2b36SAndroid Build Coastguard Worker			Command: "$envVars $rustdocCmd $rustdocFlags $in -o $outDir && " +
52*333d2b36SAndroid Build Coastguard Worker				"touch $out",
53*333d2b36SAndroid Build Coastguard Worker			CommandDeps: []string{"$rustdocCmd"},
54*333d2b36SAndroid Build Coastguard Worker		},
55*333d2b36SAndroid Build Coastguard Worker		"rustdocFlags", "outDir", "envVars")
56*333d2b36SAndroid Build Coastguard Worker
57*333d2b36SAndroid Build Coastguard Worker	_            = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver")
58*333d2b36SAndroid Build Coastguard Worker	clippyDriver = pctx.AndroidStaticRule("clippy",
59*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
60*333d2b36SAndroid Build Coastguard Worker			Command: "$envVars $clippyCmd " +
61*333d2b36SAndroid Build Coastguard Worker				// Because clippy-driver uses rustc as backend, we need to have some output even during the linting.
62*333d2b36SAndroid Build Coastguard Worker				// Use the metadata output as it has the smallest footprint.
63*333d2b36SAndroid Build Coastguard Worker				"--emit metadata -o $out --emit dep-info=$out.d.raw $in ${libFlags} " +
64*333d2b36SAndroid Build Coastguard Worker				"$rustcFlags $clippyFlags" +
65*333d2b36SAndroid Build Coastguard Worker				" && grep ^$out: $out.d.raw > $out.d",
66*333d2b36SAndroid Build Coastguard Worker			CommandDeps: []string{"$clippyCmd"},
67*333d2b36SAndroid Build Coastguard Worker			Deps:        blueprint.DepsGCC,
68*333d2b36SAndroid Build Coastguard Worker			Depfile:     "$out.d",
69*333d2b36SAndroid Build Coastguard Worker		},
70*333d2b36SAndroid Build Coastguard Worker		"rustcFlags", "libFlags", "clippyFlags", "envVars")
71*333d2b36SAndroid Build Coastguard Worker
72*333d2b36SAndroid Build Coastguard Worker	zip = pctx.AndroidStaticRule("zip",
73*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
74*333d2b36SAndroid Build Coastguard Worker			Command:        "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp",
75*333d2b36SAndroid Build Coastguard Worker			CommandDeps:    []string{"${SoongZipCmd}"},
76*333d2b36SAndroid Build Coastguard Worker			Rspfile:        "$out.rsp",
77*333d2b36SAndroid Build Coastguard Worker			RspfileContent: "$in",
78*333d2b36SAndroid Build Coastguard Worker		})
79*333d2b36SAndroid Build Coastguard Worker
80*333d2b36SAndroid Build Coastguard Worker	cp = pctx.AndroidStaticRule("cp",
81*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
82*333d2b36SAndroid Build Coastguard Worker			Command:        "cp `cat $outDir.rsp` $outDir",
83*333d2b36SAndroid Build Coastguard Worker			Rspfile:        "${outDir}.rsp",
84*333d2b36SAndroid Build Coastguard Worker			RspfileContent: "$in",
85*333d2b36SAndroid Build Coastguard Worker		},
86*333d2b36SAndroid Build Coastguard Worker		"outDir")
87*333d2b36SAndroid Build Coastguard Worker
88*333d2b36SAndroid Build Coastguard Worker	// Cross-referencing:
89*333d2b36SAndroid Build Coastguard Worker	_ = pctx.SourcePathVariable("rustExtractor",
90*333d2b36SAndroid Build Coastguard Worker		"prebuilts/build-tools/${config.HostPrebuiltTag}/bin/rust_extractor")
91*333d2b36SAndroid Build Coastguard Worker	_ = pctx.VariableFunc("kytheCorpus",
92*333d2b36SAndroid Build Coastguard Worker		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
93*333d2b36SAndroid Build Coastguard Worker	_ = pctx.VariableFunc("kytheCuEncoding",
94*333d2b36SAndroid Build Coastguard Worker		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
95*333d2b36SAndroid Build Coastguard Worker	_            = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
96*333d2b36SAndroid Build Coastguard Worker	kytheExtract = pctx.AndroidStaticRule("kythe",
97*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
98*333d2b36SAndroid Build Coastguard Worker			Command: `KYTHE_CORPUS=${kytheCorpus} ` +
99*333d2b36SAndroid Build Coastguard Worker				`KYTHE_OUTPUT_FILE=$out ` +
100*333d2b36SAndroid Build Coastguard Worker				`KYTHE_VNAMES=$kytheVnames ` +
101*333d2b36SAndroid Build Coastguard Worker				`KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
102*333d2b36SAndroid Build Coastguard Worker				`KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
103*333d2b36SAndroid Build Coastguard Worker				`$rustExtractor $envVars ` +
104*333d2b36SAndroid Build Coastguard Worker				`$rustcCmd ` +
105*333d2b36SAndroid Build Coastguard Worker				`-C linker=${config.RustLinker} ` +
106*333d2b36SAndroid Build Coastguard Worker				`-C link-args="${crtBegin} ${linkFlags} ${crtEnd}" ` +
107*333d2b36SAndroid Build Coastguard Worker				`$in ${libFlags} $rustcFlags`,
108*333d2b36SAndroid Build Coastguard Worker			CommandDeps:    []string{"$rustExtractor", "$kytheVnames"},
109*333d2b36SAndroid Build Coastguard Worker			Rspfile:        "${out}.rsp",
110*333d2b36SAndroid Build Coastguard Worker			RspfileContent: "$in",
111*333d2b36SAndroid Build Coastguard Worker		},
112*333d2b36SAndroid Build Coastguard Worker		"rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
113*333d2b36SAndroid Build Coastguard Worker)
114*333d2b36SAndroid Build Coastguard Worker
115*333d2b36SAndroid Build Coastguard Workertype buildOutput struct {
116*333d2b36SAndroid Build Coastguard Worker	outputFile android.Path
117*333d2b36SAndroid Build Coastguard Worker	kytheFile  android.Path
118*333d2b36SAndroid Build Coastguard Worker}
119*333d2b36SAndroid Build Coastguard Worker
120*333d2b36SAndroid Build Coastguard Workerfunc init() {
121*333d2b36SAndroid Build Coastguard Worker	pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
122*333d2b36SAndroid Build Coastguard Worker	cc.TransformRlibstoStaticlib = TransformRlibstoStaticlib
123*333d2b36SAndroid Build Coastguard Worker}
124*333d2b36SAndroid Build Coastguard Worker
125*333d2b36SAndroid Build Coastguard Workertype transformProperties struct {
126*333d2b36SAndroid Build Coastguard Worker	crateName       string
127*333d2b36SAndroid Build Coastguard Worker	targetTriple    string
128*333d2b36SAndroid Build Coastguard Worker	is64Bit         bool
129*333d2b36SAndroid Build Coastguard Worker	bootstrap       bool
130*333d2b36SAndroid Build Coastguard Worker	inRecovery      bool
131*333d2b36SAndroid Build Coastguard Worker	inRamdisk       bool
132*333d2b36SAndroid Build Coastguard Worker	inVendorRamdisk bool
133*333d2b36SAndroid Build Coastguard Worker	cargoOutDir     android.OptionalPath
134*333d2b36SAndroid Build Coastguard Worker	synthetic       bool
135*333d2b36SAndroid Build Coastguard Worker	crateType       string
136*333d2b36SAndroid Build Coastguard Worker}
137*333d2b36SAndroid Build Coastguard Worker
138*333d2b36SAndroid Build Coastguard Worker// Populates a standard transformProperties struct for Rust modules
139*333d2b36SAndroid Build Coastguard Workerfunc getTransformProperties(ctx ModuleContext, crateType string) transformProperties {
140*333d2b36SAndroid Build Coastguard Worker	module := ctx.RustModule()
141*333d2b36SAndroid Build Coastguard Worker	return transformProperties{
142*333d2b36SAndroid Build Coastguard Worker		crateName:       module.CrateName(),
143*333d2b36SAndroid Build Coastguard Worker		is64Bit:         ctx.toolchain().Is64Bit(),
144*333d2b36SAndroid Build Coastguard Worker		targetTriple:    ctx.toolchain().RustTriple(),
145*333d2b36SAndroid Build Coastguard Worker		bootstrap:       module.Bootstrap(),
146*333d2b36SAndroid Build Coastguard Worker		inRecovery:      module.InRecovery(),
147*333d2b36SAndroid Build Coastguard Worker		inRamdisk:       module.InRamdisk(),
148*333d2b36SAndroid Build Coastguard Worker		inVendorRamdisk: module.InVendorRamdisk(),
149*333d2b36SAndroid Build Coastguard Worker		cargoOutDir:     module.compiler.cargoOutDir(),
150*333d2b36SAndroid Build Coastguard Worker
151*333d2b36SAndroid Build Coastguard Worker		// crateType indicates what type of crate to build
152*333d2b36SAndroid Build Coastguard Worker		crateType: crateType,
153*333d2b36SAndroid Build Coastguard Worker
154*333d2b36SAndroid Build Coastguard Worker		// synthetic indicates whether this is an actual Rust module or not
155*333d2b36SAndroid Build Coastguard Worker		synthetic: false,
156*333d2b36SAndroid Build Coastguard Worker	}
157*333d2b36SAndroid Build Coastguard Worker}
158*333d2b36SAndroid Build Coastguard Worker
159*333d2b36SAndroid Build Coastguard Workerfunc TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
160*333d2b36SAndroid Build Coastguard Worker	outputFile android.WritablePath) buildOutput {
161*333d2b36SAndroid Build Coastguard Worker	if ctx.RustModule().compiler.Thinlto() {
162*333d2b36SAndroid Build Coastguard Worker		flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
163*333d2b36SAndroid Build Coastguard Worker	}
164*333d2b36SAndroid Build Coastguard Worker
165*333d2b36SAndroid Build Coastguard Worker	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "bin"))
166*333d2b36SAndroid Build Coastguard Worker}
167*333d2b36SAndroid Build Coastguard Worker
168*333d2b36SAndroid Build Coastguard Workerfunc TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
169*333d2b36SAndroid Build Coastguard Worker	outputFile android.WritablePath) buildOutput {
170*333d2b36SAndroid Build Coastguard Worker	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
171*333d2b36SAndroid Build Coastguard Worker}
172*333d2b36SAndroid Build Coastguard Worker
173*333d2b36SAndroid Build Coastguard Worker// TransformRlibstoStaticlib is assumed to be called from the cc module, and
174*333d2b36SAndroid Build Coastguard Worker// thus needs to reconstruct the common set of flags which need to be passed
175*333d2b36SAndroid Build Coastguard Worker// to the rustc compiler.
176*333d2b36SAndroid Build Coastguard Workerfunc TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
177*333d2b36SAndroid Build Coastguard Worker	outputFile android.WritablePath) android.Path {
178*333d2b36SAndroid Build Coastguard Worker
179*333d2b36SAndroid Build Coastguard Worker	var rustPathDeps PathDeps
180*333d2b36SAndroid Build Coastguard Worker	var rustFlags Flags
181*333d2b36SAndroid Build Coastguard Worker
182*333d2b36SAndroid Build Coastguard Worker	for _, rlibDep := range deps {
183*333d2b36SAndroid Build Coastguard Worker		rustPathDeps.RLibs = append(rustPathDeps.RLibs, RustLibrary{Path: rlibDep.LibPath, CrateName: rlibDep.CrateName})
184*333d2b36SAndroid Build Coastguard Worker		rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
185*333d2b36SAndroid Build Coastguard Worker	}
186*333d2b36SAndroid Build Coastguard Worker
187*333d2b36SAndroid Build Coastguard Worker	ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
188*333d2b36SAndroid Build Coastguard Worker	toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
189*333d2b36SAndroid Build Coastguard Worker	t := transformProperties{
190*333d2b36SAndroid Build Coastguard Worker		// Crate name can be a predefined value as this is a staticlib and
191*333d2b36SAndroid Build Coastguard Worker		// it does not need to be unique. The crate name is used for name
192*333d2b36SAndroid Build Coastguard Worker		// mangling, but it is mixed with the metadata for that purpose, which we
193*333d2b36SAndroid Build Coastguard Worker		// already set to the module name.
194*333d2b36SAndroid Build Coastguard Worker		crateName:       "generated_rust_staticlib",
195*333d2b36SAndroid Build Coastguard Worker		is64Bit:         toolchain.Is64Bit(),
196*333d2b36SAndroid Build Coastguard Worker		targetTriple:    toolchain.RustTriple(),
197*333d2b36SAndroid Build Coastguard Worker		bootstrap:       ccModule.Bootstrap(),
198*333d2b36SAndroid Build Coastguard Worker		inRecovery:      ccModule.InRecovery(),
199*333d2b36SAndroid Build Coastguard Worker		inRamdisk:       ccModule.InRamdisk(),
200*333d2b36SAndroid Build Coastguard Worker		inVendorRamdisk: ccModule.InVendorRamdisk(),
201*333d2b36SAndroid Build Coastguard Worker
202*333d2b36SAndroid Build Coastguard Worker		// crateType indicates what type of crate to build
203*333d2b36SAndroid Build Coastguard Worker		crateType: "staticlib",
204*333d2b36SAndroid Build Coastguard Worker
205*333d2b36SAndroid Build Coastguard Worker		// synthetic indicates whether this is an actual Rust module or not
206*333d2b36SAndroid Build Coastguard Worker		synthetic: true,
207*333d2b36SAndroid Build Coastguard Worker	}
208*333d2b36SAndroid Build Coastguard Worker
209*333d2b36SAndroid Build Coastguard Worker	rustFlags = CommonDefaultFlags(ctx, toolchain, rustFlags)
210*333d2b36SAndroid Build Coastguard Worker	rustFlags = CommonLibraryCompilerFlags(ctx, rustFlags)
211*333d2b36SAndroid Build Coastguard Worker	rustFlags.GlobalRustFlags = append(rustFlags.GlobalRustFlags, "-C lto=thin")
212*333d2b36SAndroid Build Coastguard Worker
213*333d2b36SAndroid Build Coastguard Worker	rustFlags.EmitXrefs = false
214*333d2b36SAndroid Build Coastguard Worker
215*333d2b36SAndroid Build Coastguard Worker	return transformSrctoCrate(ctx, mainSrc, rustPathDeps, rustFlags, outputFile, t).outputFile
216*333d2b36SAndroid Build Coastguard Worker}
217*333d2b36SAndroid Build Coastguard Worker
218*333d2b36SAndroid Build Coastguard Workerfunc TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
219*333d2b36SAndroid Build Coastguard Worker	outputFile android.WritablePath) buildOutput {
220*333d2b36SAndroid Build Coastguard Worker	if ctx.RustModule().compiler.Thinlto() {
221*333d2b36SAndroid Build Coastguard Worker		flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
222*333d2b36SAndroid Build Coastguard Worker	}
223*333d2b36SAndroid Build Coastguard Worker
224*333d2b36SAndroid Build Coastguard Worker	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "dylib"))
225*333d2b36SAndroid Build Coastguard Worker}
226*333d2b36SAndroid Build Coastguard Worker
227*333d2b36SAndroid Build Coastguard Workerfunc TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
228*333d2b36SAndroid Build Coastguard Worker	outputFile android.WritablePath) buildOutput {
229*333d2b36SAndroid Build Coastguard Worker	if ctx.RustModule().compiler.Thinlto() {
230*333d2b36SAndroid Build Coastguard Worker		flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
231*333d2b36SAndroid Build Coastguard Worker	}
232*333d2b36SAndroid Build Coastguard Worker
233*333d2b36SAndroid Build Coastguard Worker	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "staticlib"))
234*333d2b36SAndroid Build Coastguard Worker}
235*333d2b36SAndroid Build Coastguard Worker
236*333d2b36SAndroid Build Coastguard Workerfunc TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
237*333d2b36SAndroid Build Coastguard Worker	outputFile android.WritablePath) buildOutput {
238*333d2b36SAndroid Build Coastguard Worker	if ctx.RustModule().compiler.Thinlto() {
239*333d2b36SAndroid Build Coastguard Worker		flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
240*333d2b36SAndroid Build Coastguard Worker	}
241*333d2b36SAndroid Build Coastguard Worker
242*333d2b36SAndroid Build Coastguard Worker	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "cdylib"))
243*333d2b36SAndroid Build Coastguard Worker}
244*333d2b36SAndroid Build Coastguard Worker
245*333d2b36SAndroid Build Coastguard Workerfunc TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
246*333d2b36SAndroid Build Coastguard Worker	flags Flags, outputFile android.WritablePath) buildOutput {
247*333d2b36SAndroid Build Coastguard Worker	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "proc-macro"))
248*333d2b36SAndroid Build Coastguard Worker}
249*333d2b36SAndroid Build Coastguard Worker
250*333d2b36SAndroid Build Coastguard Workerfunc rustLibsToPaths(libs RustLibraries) android.Paths {
251*333d2b36SAndroid Build Coastguard Worker	var paths android.Paths
252*333d2b36SAndroid Build Coastguard Worker	for _, lib := range libs {
253*333d2b36SAndroid Build Coastguard Worker		paths = append(paths, lib.Path)
254*333d2b36SAndroid Build Coastguard Worker	}
255*333d2b36SAndroid Build Coastguard Worker	return paths
256*333d2b36SAndroid Build Coastguard Worker}
257*333d2b36SAndroid Build Coastguard Worker
258*333d2b36SAndroid Build Coastguard Workerfunc makeLibFlags(deps PathDeps) []string {
259*333d2b36SAndroid Build Coastguard Worker	var libFlags []string
260*333d2b36SAndroid Build Coastguard Worker
261*333d2b36SAndroid Build Coastguard Worker	// Collect library/crate flags
262*333d2b36SAndroid Build Coastguard Worker	for _, lib := range deps.RLibs {
263*333d2b36SAndroid Build Coastguard Worker		libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
264*333d2b36SAndroid Build Coastguard Worker	}
265*333d2b36SAndroid Build Coastguard Worker	for _, lib := range deps.DyLibs {
266*333d2b36SAndroid Build Coastguard Worker		libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
267*333d2b36SAndroid Build Coastguard Worker	}
268*333d2b36SAndroid Build Coastguard Worker	for _, proc_macro := range deps.ProcMacros {
269*333d2b36SAndroid Build Coastguard Worker		libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
270*333d2b36SAndroid Build Coastguard Worker	}
271*333d2b36SAndroid Build Coastguard Worker
272*333d2b36SAndroid Build Coastguard Worker	for _, path := range deps.linkDirs {
273*333d2b36SAndroid Build Coastguard Worker		libFlags = append(libFlags, "-L "+path)
274*333d2b36SAndroid Build Coastguard Worker	}
275*333d2b36SAndroid Build Coastguard Worker
276*333d2b36SAndroid Build Coastguard Worker	return libFlags
277*333d2b36SAndroid Build Coastguard Worker}
278*333d2b36SAndroid Build Coastguard Worker
279*333d2b36SAndroid Build Coastguard Workerfunc rustEnvVars(ctx android.ModuleContext, deps PathDeps, crateName string, cargoOutDir android.OptionalPath) []string {
280*333d2b36SAndroid Build Coastguard Worker	var envVars []string
281*333d2b36SAndroid Build Coastguard Worker
282*333d2b36SAndroid Build Coastguard Worker	// libstd requires a specific environment variable to be set. This is
283*333d2b36SAndroid Build Coastguard Worker	// not officially documented and may be removed in the future. See
284*333d2b36SAndroid Build Coastguard Worker	// https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
285*333d2b36SAndroid Build Coastguard Worker	if crateName == "std" {
286*333d2b36SAndroid Build Coastguard Worker		envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.Arch().ArchType])
287*333d2b36SAndroid Build Coastguard Worker	}
288*333d2b36SAndroid Build Coastguard Worker
289*333d2b36SAndroid Build Coastguard Worker	if len(deps.SrcDeps) > 0 && cargoOutDir.Valid() {
290*333d2b36SAndroid Build Coastguard Worker		moduleGenDir := cargoOutDir
291*333d2b36SAndroid Build Coastguard Worker		// We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
292*333d2b36SAndroid Build Coastguard Worker		// assumes that paths are relative to the source file.
293*333d2b36SAndroid Build Coastguard Worker		var outDirPrefix string
294*333d2b36SAndroid Build Coastguard Worker		if !filepath.IsAbs(moduleGenDir.String()) {
295*333d2b36SAndroid Build Coastguard Worker			// If OUT_DIR is not absolute, we use $$PWD to generate an absolute path (os.Getwd() returns '/')
296*333d2b36SAndroid Build Coastguard Worker			outDirPrefix = "$$PWD/"
297*333d2b36SAndroid Build Coastguard Worker		} else {
298*333d2b36SAndroid Build Coastguard Worker			// If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything.
299*333d2b36SAndroid Build Coastguard Worker			outDirPrefix = ""
300*333d2b36SAndroid Build Coastguard Worker		}
301*333d2b36SAndroid Build Coastguard Worker		envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
302*333d2b36SAndroid Build Coastguard Worker	} else {
303*333d2b36SAndroid Build Coastguard Worker		// TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value.
304*333d2b36SAndroid Build Coastguard Worker		envVars = append(envVars, "OUT_DIR=out")
305*333d2b36SAndroid Build Coastguard Worker	}
306*333d2b36SAndroid Build Coastguard Worker
307*333d2b36SAndroid Build Coastguard Worker	envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx))
308*333d2b36SAndroid Build Coastguard Worker
309*333d2b36SAndroid Build Coastguard Worker	if rustMod, ok := ctx.Module().(*Module); ok && rustMod.compiler.cargoEnvCompat() {
310*333d2b36SAndroid Build Coastguard Worker		// We only emulate cargo environment variables for 3p code, which is only ever built
311*333d2b36SAndroid Build Coastguard Worker		// by defining a Rust module, so we only need to set these for true Rust modules.
312*333d2b36SAndroid Build Coastguard Worker		if bin, ok := rustMod.compiler.(*binaryDecorator); ok {
313*333d2b36SAndroid Build Coastguard Worker			envVars = append(envVars, "CARGO_BIN_NAME="+bin.getStem(ctx))
314*333d2b36SAndroid Build Coastguard Worker		}
315*333d2b36SAndroid Build Coastguard Worker		envVars = append(envVars, "CARGO_CRATE_NAME="+crateName)
316*333d2b36SAndroid Build Coastguard Worker		envVars = append(envVars, "CARGO_PKG_NAME="+crateName)
317*333d2b36SAndroid Build Coastguard Worker		pkgVersion := rustMod.compiler.cargoPkgVersion()
318*333d2b36SAndroid Build Coastguard Worker		if pkgVersion != "" {
319*333d2b36SAndroid Build Coastguard Worker			envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
320*333d2b36SAndroid Build Coastguard Worker
321*333d2b36SAndroid Build Coastguard Worker			// Ensure the version is in the form of "x.y.z" (approximately semver compliant).
322*333d2b36SAndroid Build Coastguard Worker			//
323*333d2b36SAndroid Build Coastguard Worker			// For our purposes, we don't care to enforce that these are integers since they may
324*333d2b36SAndroid Build Coastguard Worker			// include other characters at times (e.g. sometimes the patch version is more than an integer).
325*333d2b36SAndroid Build Coastguard Worker			if strings.Count(pkgVersion, ".") == 2 {
326*333d2b36SAndroid Build Coastguard Worker				var semver_parts = strings.Split(pkgVersion, ".")
327*333d2b36SAndroid Build Coastguard Worker				envVars = append(envVars, "CARGO_PKG_VERSION_MAJOR="+semver_parts[0])
328*333d2b36SAndroid Build Coastguard Worker				envVars = append(envVars, "CARGO_PKG_VERSION_MINOR="+semver_parts[1])
329*333d2b36SAndroid Build Coastguard Worker				envVars = append(envVars, "CARGO_PKG_VERSION_PATCH="+semver_parts[2])
330*333d2b36SAndroid Build Coastguard Worker			}
331*333d2b36SAndroid Build Coastguard Worker		}
332*333d2b36SAndroid Build Coastguard Worker	}
333*333d2b36SAndroid Build Coastguard Worker
334*333d2b36SAndroid Build Coastguard Worker	if ctx.Darwin() {
335*333d2b36SAndroid Build Coastguard Worker		envVars = append(envVars, "ANDROID_RUST_DARWIN=true")
336*333d2b36SAndroid Build Coastguard Worker	}
337*333d2b36SAndroid Build Coastguard Worker
338*333d2b36SAndroid Build Coastguard Worker	return envVars
339*333d2b36SAndroid Build Coastguard Worker}
340*333d2b36SAndroid Build Coastguard Worker
341*333d2b36SAndroid Build Coastguard Workerfunc transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps PathDeps, flags Flags,
342*333d2b36SAndroid Build Coastguard Worker	outputFile android.WritablePath, t transformProperties) buildOutput {
343*333d2b36SAndroid Build Coastguard Worker
344*333d2b36SAndroid Build Coastguard Worker	var inputs android.Paths
345*333d2b36SAndroid Build Coastguard Worker	var implicits android.Paths
346*333d2b36SAndroid Build Coastguard Worker	var orderOnly android.Paths
347*333d2b36SAndroid Build Coastguard Worker	var output buildOutput
348*333d2b36SAndroid Build Coastguard Worker	var rustcFlags, linkFlags []string
349*333d2b36SAndroid Build Coastguard Worker	var earlyLinkFlags string
350*333d2b36SAndroid Build Coastguard Worker
351*333d2b36SAndroid Build Coastguard Worker	output.outputFile = outputFile
352*333d2b36SAndroid Build Coastguard Worker
353*333d2b36SAndroid Build Coastguard Worker	envVars := rustEnvVars(ctx, deps, t.crateName, t.cargoOutDir)
354*333d2b36SAndroid Build Coastguard Worker
355*333d2b36SAndroid Build Coastguard Worker	inputs = append(inputs, main)
356*333d2b36SAndroid Build Coastguard Worker
357*333d2b36SAndroid Build Coastguard Worker	// Collect rustc flags
358*333d2b36SAndroid Build Coastguard Worker	rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
359*333d2b36SAndroid Build Coastguard Worker	rustcFlags = append(rustcFlags, flags.RustFlags...)
360*333d2b36SAndroid Build Coastguard Worker	rustcFlags = append(rustcFlags, "--crate-type="+t.crateType)
361*333d2b36SAndroid Build Coastguard Worker	if t.crateName != "" {
362*333d2b36SAndroid Build Coastguard Worker		rustcFlags = append(rustcFlags, "--crate-name="+t.crateName)
363*333d2b36SAndroid Build Coastguard Worker	}
364*333d2b36SAndroid Build Coastguard Worker	if t.targetTriple != "" {
365*333d2b36SAndroid Build Coastguard Worker		rustcFlags = append(rustcFlags, "--target="+t.targetTriple)
366*333d2b36SAndroid Build Coastguard Worker		linkFlags = append(linkFlags, "-target "+t.targetTriple)
367*333d2b36SAndroid Build Coastguard Worker	}
368*333d2b36SAndroid Build Coastguard Worker
369*333d2b36SAndroid Build Coastguard Worker	// Suppress an implicit sysroot
370*333d2b36SAndroid Build Coastguard Worker	rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
371*333d2b36SAndroid Build Coastguard Worker
372*333d2b36SAndroid Build Coastguard Worker	// Enable incremental compilation if requested by user
373*333d2b36SAndroid Build Coastguard Worker	if ctx.Config().IsEnvTrue("SOONG_RUSTC_INCREMENTAL") {
374*333d2b36SAndroid Build Coastguard Worker		incrementalPath := android.PathForOutput(ctx, "rustc").String()
375*333d2b36SAndroid Build Coastguard Worker
376*333d2b36SAndroid Build Coastguard Worker		rustcFlags = append(rustcFlags, "-C incremental="+incrementalPath)
377*333d2b36SAndroid Build Coastguard Worker	} else {
378*333d2b36SAndroid Build Coastguard Worker		rustcFlags = append(rustcFlags, "-C codegen-units=1")
379*333d2b36SAndroid Build Coastguard Worker	}
380*333d2b36SAndroid Build Coastguard Worker
381*333d2b36SAndroid Build Coastguard Worker	// Disallow experimental features
382*333d2b36SAndroid Build Coastguard Worker	modulePath := ctx.ModuleDir()
383*333d2b36SAndroid Build Coastguard Worker	if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
384*333d2b36SAndroid Build Coastguard Worker		rustcFlags = append(rustcFlags, "-Zallow-features=\"\"")
385*333d2b36SAndroid Build Coastguard Worker	}
386*333d2b36SAndroid Build Coastguard Worker
387*333d2b36SAndroid Build Coastguard Worker	// Collect linker flags
388*333d2b36SAndroid Build Coastguard Worker	if !ctx.Darwin() {
389*333d2b36SAndroid Build Coastguard Worker		earlyLinkFlags = "-Wl,--as-needed"
390*333d2b36SAndroid Build Coastguard Worker	}
391*333d2b36SAndroid Build Coastguard Worker
392*333d2b36SAndroid Build Coastguard Worker	linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
393*333d2b36SAndroid Build Coastguard Worker	linkFlags = append(linkFlags, flags.LinkFlags...)
394*333d2b36SAndroid Build Coastguard Worker
395*333d2b36SAndroid Build Coastguard Worker	// Check if this module needs to use the bootstrap linker
396*333d2b36SAndroid Build Coastguard Worker	if t.bootstrap && !t.inRecovery && !t.inRamdisk && !t.inVendorRamdisk {
397*333d2b36SAndroid Build Coastguard Worker		dynamicLinker := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker"
398*333d2b36SAndroid Build Coastguard Worker		if t.is64Bit {
399*333d2b36SAndroid Build Coastguard Worker			dynamicLinker += "64"
400*333d2b36SAndroid Build Coastguard Worker		}
401*333d2b36SAndroid Build Coastguard Worker		linkFlags = append(linkFlags, dynamicLinker)
402*333d2b36SAndroid Build Coastguard Worker	}
403*333d2b36SAndroid Build Coastguard Worker
404*333d2b36SAndroid Build Coastguard Worker	libFlags := makeLibFlags(deps)
405*333d2b36SAndroid Build Coastguard Worker
406*333d2b36SAndroid Build Coastguard Worker	// Collect dependencies
407*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
408*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
409*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
410*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, deps.StaticLibs...)
411*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, deps.SharedLibDeps...)
412*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, deps.srcProviderFiles...)
413*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, deps.AfdoProfiles...)
414*333d2b36SAndroid Build Coastguard Worker
415*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, deps.CrtBegin...)
416*333d2b36SAndroid Build Coastguard Worker	implicits = append(implicits, deps.CrtEnd...)
417*333d2b36SAndroid Build Coastguard Worker
418*333d2b36SAndroid Build Coastguard Worker	orderOnly = append(orderOnly, deps.SharedLibs...)
419*333d2b36SAndroid Build Coastguard Worker
420*333d2b36SAndroid Build Coastguard Worker	if !t.synthetic {
421*333d2b36SAndroid Build Coastguard Worker		// Only worry about OUT_DIR for actual Rust modules.
422*333d2b36SAndroid Build Coastguard Worker		// Libraries built from cc use generated source, and do not utilize OUT_DIR.
423*333d2b36SAndroid Build Coastguard Worker		if len(deps.SrcDeps) > 0 {
424*333d2b36SAndroid Build Coastguard Worker			var outputs android.WritablePaths
425*333d2b36SAndroid Build Coastguard Worker
426*333d2b36SAndroid Build Coastguard Worker			for _, genSrc := range deps.SrcDeps {
427*333d2b36SAndroid Build Coastguard Worker				if android.SuffixInList(outputs.Strings(), genSubDir+genSrc.Base()) {
428*333d2b36SAndroid Build Coastguard Worker					ctx.PropertyErrorf("srcs",
429*333d2b36SAndroid Build Coastguard Worker						"multiple source providers generate the same filename output: "+genSrc.Base())
430*333d2b36SAndroid Build Coastguard Worker				}
431*333d2b36SAndroid Build Coastguard Worker				outputs = append(outputs, android.PathForModuleOut(ctx, genSubDir+genSrc.Base()))
432*333d2b36SAndroid Build Coastguard Worker			}
433*333d2b36SAndroid Build Coastguard Worker
434*333d2b36SAndroid Build Coastguard Worker			ctx.Build(pctx, android.BuildParams{
435*333d2b36SAndroid Build Coastguard Worker				Rule:        cp,
436*333d2b36SAndroid Build Coastguard Worker				Description: "cp " + t.cargoOutDir.Path().Rel(),
437*333d2b36SAndroid Build Coastguard Worker				Outputs:     outputs,
438*333d2b36SAndroid Build Coastguard Worker				Inputs:      deps.SrcDeps,
439*333d2b36SAndroid Build Coastguard Worker				Args: map[string]string{
440*333d2b36SAndroid Build Coastguard Worker					"outDir": t.cargoOutDir.String(),
441*333d2b36SAndroid Build Coastguard Worker				},
442*333d2b36SAndroid Build Coastguard Worker			})
443*333d2b36SAndroid Build Coastguard Worker			implicits = append(implicits, outputs.Paths()...)
444*333d2b36SAndroid Build Coastguard Worker		}
445*333d2b36SAndroid Build Coastguard Worker	}
446*333d2b36SAndroid Build Coastguard Worker
447*333d2b36SAndroid Build Coastguard Worker	if !t.synthetic {
448*333d2b36SAndroid Build Coastguard Worker		// Only worry about clippy for actual Rust modules.
449*333d2b36SAndroid Build Coastguard Worker		// Libraries built from cc use generated source, and don't need to run clippy.
450*333d2b36SAndroid Build Coastguard Worker		if flags.Clippy {
451*333d2b36SAndroid Build Coastguard Worker			clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
452*333d2b36SAndroid Build Coastguard Worker			ctx.Build(pctx, android.BuildParams{
453*333d2b36SAndroid Build Coastguard Worker				Rule:            clippyDriver,
454*333d2b36SAndroid Build Coastguard Worker				Description:     "clippy " + main.Rel(),
455*333d2b36SAndroid Build Coastguard Worker				Output:          clippyFile,
456*333d2b36SAndroid Build Coastguard Worker				ImplicitOutputs: nil,
457*333d2b36SAndroid Build Coastguard Worker				Inputs:          inputs,
458*333d2b36SAndroid Build Coastguard Worker				Implicits:       implicits,
459*333d2b36SAndroid Build Coastguard Worker				OrderOnly:       orderOnly,
460*333d2b36SAndroid Build Coastguard Worker				Args: map[string]string{
461*333d2b36SAndroid Build Coastguard Worker					"rustcFlags":  strings.Join(rustcFlags, " "),
462*333d2b36SAndroid Build Coastguard Worker					"libFlags":    strings.Join(libFlags, " "),
463*333d2b36SAndroid Build Coastguard Worker					"clippyFlags": strings.Join(flags.ClippyFlags, " "),
464*333d2b36SAndroid Build Coastguard Worker					"envVars":     strings.Join(envVars, " "),
465*333d2b36SAndroid Build Coastguard Worker				},
466*333d2b36SAndroid Build Coastguard Worker			})
467*333d2b36SAndroid Build Coastguard Worker			// Declare the clippy build as an implicit dependency of the original crate.
468*333d2b36SAndroid Build Coastguard Worker			implicits = append(implicits, clippyFile)
469*333d2b36SAndroid Build Coastguard Worker		}
470*333d2b36SAndroid Build Coastguard Worker	}
471*333d2b36SAndroid Build Coastguard Worker
472*333d2b36SAndroid Build Coastguard Worker	ctx.Build(pctx, android.BuildParams{
473*333d2b36SAndroid Build Coastguard Worker		Rule:        rustc,
474*333d2b36SAndroid Build Coastguard Worker		Description: "rustc " + main.Rel(),
475*333d2b36SAndroid Build Coastguard Worker		Output:      outputFile,
476*333d2b36SAndroid Build Coastguard Worker		Inputs:      inputs,
477*333d2b36SAndroid Build Coastguard Worker		Implicits:   implicits,
478*333d2b36SAndroid Build Coastguard Worker		OrderOnly:   orderOnly,
479*333d2b36SAndroid Build Coastguard Worker		Args: map[string]string{
480*333d2b36SAndroid Build Coastguard Worker			"rustcFlags":     strings.Join(rustcFlags, " "),
481*333d2b36SAndroid Build Coastguard Worker			"earlyLinkFlags": earlyLinkFlags,
482*333d2b36SAndroid Build Coastguard Worker			"linkFlags":      strings.Join(linkFlags, " "),
483*333d2b36SAndroid Build Coastguard Worker			"libFlags":       strings.Join(libFlags, " "),
484*333d2b36SAndroid Build Coastguard Worker			"crtBegin":       strings.Join(deps.CrtBegin.Strings(), " "),
485*333d2b36SAndroid Build Coastguard Worker			"crtEnd":         strings.Join(deps.CrtEnd.Strings(), " "),
486*333d2b36SAndroid Build Coastguard Worker			"envVars":        strings.Join(envVars, " "),
487*333d2b36SAndroid Build Coastguard Worker		},
488*333d2b36SAndroid Build Coastguard Worker	})
489*333d2b36SAndroid Build Coastguard Worker
490*333d2b36SAndroid Build Coastguard Worker	if !t.synthetic {
491*333d2b36SAndroid Build Coastguard Worker		// Only emit xrefs for true Rust modules.
492*333d2b36SAndroid Build Coastguard Worker		if flags.EmitXrefs {
493*333d2b36SAndroid Build Coastguard Worker			kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
494*333d2b36SAndroid Build Coastguard Worker			ctx.Build(pctx, android.BuildParams{
495*333d2b36SAndroid Build Coastguard Worker				Rule:        kytheExtract,
496*333d2b36SAndroid Build Coastguard Worker				Description: "Xref Rust extractor " + main.Rel(),
497*333d2b36SAndroid Build Coastguard Worker				Output:      kytheFile,
498*333d2b36SAndroid Build Coastguard Worker				Inputs:      inputs,
499*333d2b36SAndroid Build Coastguard Worker				Implicits:   implicits,
500*333d2b36SAndroid Build Coastguard Worker				OrderOnly:   orderOnly,
501*333d2b36SAndroid Build Coastguard Worker				Args: map[string]string{
502*333d2b36SAndroid Build Coastguard Worker					"rustcFlags": strings.Join(rustcFlags, " "),
503*333d2b36SAndroid Build Coastguard Worker					"linkFlags":  strings.Join(linkFlags, " "),
504*333d2b36SAndroid Build Coastguard Worker					"libFlags":   strings.Join(libFlags, " "),
505*333d2b36SAndroid Build Coastguard Worker					"crtBegin":   strings.Join(deps.CrtBegin.Strings(), " "),
506*333d2b36SAndroid Build Coastguard Worker					"crtEnd":     strings.Join(deps.CrtEnd.Strings(), " "),
507*333d2b36SAndroid Build Coastguard Worker					"envVars":    strings.Join(envVars, " "),
508*333d2b36SAndroid Build Coastguard Worker				},
509*333d2b36SAndroid Build Coastguard Worker			})
510*333d2b36SAndroid Build Coastguard Worker			output.kytheFile = kytheFile
511*333d2b36SAndroid Build Coastguard Worker		}
512*333d2b36SAndroid Build Coastguard Worker	}
513*333d2b36SAndroid Build Coastguard Worker	return output
514*333d2b36SAndroid Build Coastguard Worker}
515*333d2b36SAndroid Build Coastguard Worker
516*333d2b36SAndroid Build Coastguard Workerfunc Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps,
517*333d2b36SAndroid Build Coastguard Worker	flags Flags) android.ModuleOutPath {
518*333d2b36SAndroid Build Coastguard Worker
519*333d2b36SAndroid Build Coastguard Worker	rustdocFlags := append([]string{}, flags.RustdocFlags...)
520*333d2b36SAndroid Build Coastguard Worker	rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null")
521*333d2b36SAndroid Build Coastguard Worker
522*333d2b36SAndroid Build Coastguard Worker	// Build an index for all our crates. -Z unstable options is required to use
523*333d2b36SAndroid Build Coastguard Worker	// this flag.
524*333d2b36SAndroid Build Coastguard Worker	rustdocFlags = append(rustdocFlags, "-Z", "unstable-options", "--enable-index-page")
525*333d2b36SAndroid Build Coastguard Worker
526*333d2b36SAndroid Build Coastguard Worker	// Ensure we use any special-case code-paths for Soong.
527*333d2b36SAndroid Build Coastguard Worker	rustdocFlags = append(rustdocFlags, "--cfg", "soong")
528*333d2b36SAndroid Build Coastguard Worker
529*333d2b36SAndroid Build Coastguard Worker	targetTriple := ctx.toolchain().RustTriple()
530*333d2b36SAndroid Build Coastguard Worker
531*333d2b36SAndroid Build Coastguard Worker	// Collect rustc flags
532*333d2b36SAndroid Build Coastguard Worker	if targetTriple != "" {
533*333d2b36SAndroid Build Coastguard Worker		rustdocFlags = append(rustdocFlags, "--target="+targetTriple)
534*333d2b36SAndroid Build Coastguard Worker	}
535*333d2b36SAndroid Build Coastguard Worker
536*333d2b36SAndroid Build Coastguard Worker	crateName := ctx.RustModule().CrateName()
537*333d2b36SAndroid Build Coastguard Worker	rustdocFlags = append(rustdocFlags, "--crate-name "+crateName)
538*333d2b36SAndroid Build Coastguard Worker
539*333d2b36SAndroid Build Coastguard Worker	rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...)
540*333d2b36SAndroid Build Coastguard Worker	docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
541*333d2b36SAndroid Build Coastguard Worker
542*333d2b36SAndroid Build Coastguard Worker	// Silence warnings about renamed lints for third-party crates
543*333d2b36SAndroid Build Coastguard Worker	modulePath := ctx.ModuleDir()
544*333d2b36SAndroid Build Coastguard Worker	if android.IsThirdPartyPath(modulePath) {
545*333d2b36SAndroid Build Coastguard Worker		rustdocFlags = append(rustdocFlags, " -A warnings")
546*333d2b36SAndroid Build Coastguard Worker	}
547*333d2b36SAndroid Build Coastguard Worker
548*333d2b36SAndroid Build Coastguard Worker	// Yes, the same out directory is used simultaneously by all rustdoc builds.
549*333d2b36SAndroid Build Coastguard Worker	// This is what cargo does. The docs for individual crates get generated to
550*333d2b36SAndroid Build Coastguard Worker	// a subdirectory named for the crate, and rustdoc synchronizes writes to
551*333d2b36SAndroid Build Coastguard Worker	// shared pieces like the index and search data itself.
552*333d2b36SAndroid Build Coastguard Worker	// https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146
553*333d2b36SAndroid Build Coastguard Worker	docDir := android.PathForOutput(ctx, "rustdoc")
554*333d2b36SAndroid Build Coastguard Worker
555*333d2b36SAndroid Build Coastguard Worker	ctx.Build(pctx, android.BuildParams{
556*333d2b36SAndroid Build Coastguard Worker		Rule:        rustdoc,
557*333d2b36SAndroid Build Coastguard Worker		Description: "rustdoc " + main.Rel(),
558*333d2b36SAndroid Build Coastguard Worker		Output:      docTimestampFile,
559*333d2b36SAndroid Build Coastguard Worker		Input:       main,
560*333d2b36SAndroid Build Coastguard Worker		Implicit:    ctx.RustModule().UnstrippedOutputFile(),
561*333d2b36SAndroid Build Coastguard Worker		Args: map[string]string{
562*333d2b36SAndroid Build Coastguard Worker			"rustdocFlags": strings.Join(rustdocFlags, " "),
563*333d2b36SAndroid Build Coastguard Worker			"outDir":       docDir.String(),
564*333d2b36SAndroid Build Coastguard Worker			"envVars":      strings.Join(rustEnvVars(ctx, deps, crateName, ctx.RustModule().compiler.cargoOutDir()), " "),
565*333d2b36SAndroid Build Coastguard Worker		},
566*333d2b36SAndroid Build Coastguard Worker	})
567*333d2b36SAndroid Build Coastguard Worker
568*333d2b36SAndroid Build Coastguard Worker	return docTimestampFile
569*333d2b36SAndroid Build Coastguard Worker}
570