blob: ee24300c4bb586713ccde0c3dc8f0421bd62db6e [file] [log] [blame]
Mitch Phillipsda9a4632019-07-15 09:34:09 -07001// Copyright 2016 Google Inc. All rights reserved.
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 cc
16
17import (
Kris Alderf979ee32019-10-22 10:52:01 -070018 "encoding/json"
Mitch Phillips4de896e2019-08-28 16:04:36 -070019 "path/filepath"
Mitch Phillipse1ee1a12019-10-17 19:20:41 -070020 "sort"
Mitch Phillipsa0a5e192019-09-27 14:00:06 -070021 "strings"
Mitch Phillips4de896e2019-08-28 16:04:36 -070022
Mitch Phillipsda9a4632019-07-15 09:34:09 -070023 "android/soong/android"
24 "android/soong/cc/config"
25)
26
Kris Alderf979ee32019-10-22 10:52:01 -070027type FuzzConfig struct {
28 // Email address of people to CC on bugs or contact about this fuzz target.
29 Cc []string `json:"cc,omitempty"`
hamzeh3478a0d2019-12-16 16:25:50 -080030 // Specify whether to enable continuous fuzzing on devices. Defaults to true.
31 Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
32 // Specify whether to enable continuous fuzzing on host. Defaults to true.
33 Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"`
Kris Alderf979ee32019-10-22 10:52:01 -070034 // Component in Google's bug tracking system that bugs should be filed to.
35 Componentid *int64 `json:"componentid,omitempty"`
36 // Hotlists in Google's bug tracking system that bugs should be marked with.
37 Hotlists []string `json:"hotlists,omitempty"`
38}
39
40func (f *FuzzConfig) String() string {
41 b, err := json.Marshal(f)
42 if err != nil {
43 panic(err)
44 }
45
46 return string(b)
47}
48
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070049type FuzzProperties struct {
50 // Optional list of seed files to be installed to the fuzz target's output
51 // directory.
52 Corpus []string `android:"path"`
Tri Voad172d82019-11-27 13:45:45 -080053 // Optional list of data files to be installed to the fuzz target's output
54 // directory. Directory structure relative to the module is preserved.
55 Data []string `android:"path"`
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070056 // Optional dictionary to be installed to the fuzz target's output directory.
57 Dictionary *string `android:"path"`
Kris Alderf979ee32019-10-22 10:52:01 -070058 // Config for running the target on fuzzing infrastructure.
59 Fuzz_config *FuzzConfig
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070060}
61
Mitch Phillipsda9a4632019-07-15 09:34:09 -070062func init() {
63 android.RegisterModuleType("cc_fuzz", FuzzFactory)
Mitch Phillipsd3254b42019-09-24 13:03:28 -070064 android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070065}
66
67// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
68// $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on
69// your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
70func FuzzFactory() android.Module {
71 module := NewFuzz(android.HostAndDeviceSupported)
72 return module.Init()
73}
74
75func NewFuzzInstaller() *baseInstaller {
76 return NewBaseInstaller("fuzz", "fuzz", InstallInData)
77}
78
79type fuzzBinary struct {
80 *binaryDecorator
81 *baseCompiler
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070082
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -070083 Properties FuzzProperties
84 dictionary android.Path
85 corpus android.Paths
86 corpusIntermediateDir android.Path
Kris Alderf979ee32019-10-22 10:52:01 -070087 config android.Path
Tri Voad172d82019-11-27 13:45:45 -080088 data android.Paths
89 dataIntermediateDir android.Path
Mitch Phillipse1ee1a12019-10-17 19:20:41 -070090 installedSharedDeps []string
Mitch Phillipsda9a4632019-07-15 09:34:09 -070091}
92
93func (fuzz *fuzzBinary) linkerProps() []interface{} {
94 props := fuzz.binaryDecorator.linkerProps()
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070095 props = append(props, &fuzz.Properties)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070096 return props
97}
98
99func (fuzz *fuzzBinary) linkerInit(ctx BaseModuleContext) {
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700100 fuzz.binaryDecorator.linkerInit(ctx)
101}
102
103func (fuzz *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
104 deps.StaticLibs = append(deps.StaticLibs,
105 config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
106 deps = fuzz.binaryDecorator.linkerDeps(ctx, deps)
107 return deps
108}
109
110func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
111 flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800112 // RunPaths on devices isn't instantiated by the base linker. `../lib` for
113 // installed fuzz targets (both host and device), and `./lib` for fuzz
114 // target packages.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700115 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800116 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700117 return flags
118}
119
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700120// This function performs a breadth-first search over the provided module's
121// dependencies using `visitDirectDeps` to enumerate all shared library
122// dependencies. We require breadth-first expansion, as otherwise we may
123// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
124// from a dependency. This may cause issues when dependencies have explicit
125// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
Colin Crossdc809f92019-11-20 15:58:32 -0800126func collectAllSharedDependencies(ctx android.SingletonContext, module android.Module) android.Paths {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700127 var fringe []android.Module
128
Colin Crossdc809f92019-11-20 15:58:32 -0800129 seen := make(map[android.Module]bool)
130
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700131 // Enumerate the first level of dependencies, as we discard all non-library
132 // modules in the BFS loop below.
133 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800134 if isValidSharedDependency(dep) {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800135 fringe = append(fringe, dep)
136 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700137 })
138
Colin Crossdc809f92019-11-20 15:58:32 -0800139 var sharedLibraries android.Paths
140
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700141 for i := 0; i < len(fringe); i++ {
142 module := fringe[i]
Colin Crossdc809f92019-11-20 15:58:32 -0800143 if seen[module] {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700144 continue
145 }
Colin Crossdc809f92019-11-20 15:58:32 -0800146 seen[module] = true
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700147
148 ccModule := module.(*Module)
Colin Crossdc809f92019-11-20 15:58:32 -0800149 sharedLibraries = append(sharedLibraries, ccModule.UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700150 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800151 if isValidSharedDependency(dep) && !seen[dep] {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800152 fringe = append(fringe, dep)
153 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700154 })
155 }
Colin Crossdc809f92019-11-20 15:58:32 -0800156
157 return sharedLibraries
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700158}
159
160// This function takes a module and determines if it is a unique shared library
161// that should be installed in the fuzz target output directories. This function
162// returns true, unless:
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700163// - The module is not a shared library, or
164// - The module is a header, stub, or vendor-linked library.
Colin Crossdc809f92019-11-20 15:58:32 -0800165func isValidSharedDependency(dependency android.Module) bool {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700166 // TODO(b/144090547): We should be parsing these modules using
167 // ModuleDependencyTag instead of the current brute-force checking.
168
169 if linkable, ok := dependency.(LinkableInterface); !ok || // Discard non-linkables.
170 !linkable.CcLibraryInterface() || !linkable.Shared() || // Discard static libs.
171 linkable.UseVndk() || // Discard vendor linked libraries.
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800172 // Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
173 // be excluded on the basis of they're not CCLibrary()'s.
174 (linkable.CcLibrary() && linkable.BuildStubs()) {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700175 return false
176 }
177
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800178 // We discarded module stubs libraries above, but the LLNDK prebuilts stubs
179 // libraries must be handled differently - by looking for the stubDecorator.
180 // Discard LLNDK prebuilts stubs as well.
181 if ccLibrary, isCcLibrary := dependency.(*Module); isCcLibrary {
182 if _, isLLndkStubLibrary := ccLibrary.linker.(*stubDecorator); isLLndkStubLibrary {
183 return false
184 }
185 }
186
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700187 return true
188}
189
190func sharedLibraryInstallLocation(
191 libraryPath android.Path, isHost bool, archString string) string {
192 installLocation := "$(PRODUCT_OUT)/data"
193 if isHost {
194 installLocation = "$(HOST_OUT)"
195 }
196 installLocation = filepath.Join(
197 installLocation, "fuzz", archString, "lib", libraryPath.Base())
198 return installLocation
199}
200
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700201func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700202 fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
203 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
204 fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
205 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700206 fuzz.binaryDecorator.baseInstaller.install(ctx, file)
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700207
208 fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -0700209 builder := android.NewRuleBuilder()
210 intermediateDir := android.PathForModuleOut(ctx, "corpus")
211 for _, entry := range fuzz.corpus {
212 builder.Command().Text("cp").
213 Input(entry).
214 Output(intermediateDir.Join(ctx, entry.Base()))
215 }
216 builder.Build(pctx, ctx, "copy_corpus", "copy corpus")
217 fuzz.corpusIntermediateDir = intermediateDir
218
Tri Voad172d82019-11-27 13:45:45 -0800219 fuzz.data = android.PathsForModuleSrc(ctx, fuzz.Properties.Data)
220 builder = android.NewRuleBuilder()
221 intermediateDir = android.PathForModuleOut(ctx, "data")
222 for _, entry := range fuzz.data {
223 builder.Command().Text("cp").
224 Input(entry).
225 Output(intermediateDir.Join(ctx, entry.Rel()))
226 }
227 builder.Build(pctx, ctx, "copy_data", "copy data")
228 fuzz.dataIntermediateDir = intermediateDir
229
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700230 if fuzz.Properties.Dictionary != nil {
231 fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
232 if fuzz.dictionary.Ext() != ".dict" {
233 ctx.PropertyErrorf("dictionary",
234 "Fuzzer dictionary %q does not have '.dict' extension",
235 fuzz.dictionary.String())
236 }
237 }
Kris Alderf979ee32019-10-22 10:52:01 -0700238
239 if fuzz.Properties.Fuzz_config != nil {
Kris Alderdb97af42019-10-30 10:17:04 -0700240 configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
Kris Alderf979ee32019-10-22 10:52:01 -0700241 ctx.Build(pctx, android.BuildParams{
242 Rule: android.WriteFile,
243 Description: "fuzzer infrastructure configuration",
244 Output: configPath,
245 Args: map[string]string{
246 "content": fuzz.Properties.Fuzz_config.String(),
247 },
248 })
249 fuzz.config = configPath
250 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700251
252 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800253 seen := make(map[android.Module]bool)
254 var sharedLibraries android.Paths
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700255 ctx.WalkDeps(func(child, parent android.Module) bool {
Colin Crossdc809f92019-11-20 15:58:32 -0800256 if seen[child] {
257 return false
258 }
259 seen[child] = true
260
261 if isValidSharedDependency(child) {
262 sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700263 return true
264 }
265 return false
266 })
267
268 for _, lib := range sharedLibraries {
269 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
270 sharedLibraryInstallLocation(
271 lib, ctx.Host(), ctx.Arch().ArchType.String()))
272 }
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700273}
274
275func NewFuzz(hod android.HostOrDeviceSupported) *Module {
276 module, binary := NewBinary(hod)
277
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700278 binary.baseInstaller = NewFuzzInstaller()
279 module.sanitize.SetSanitizer(fuzzer, true)
280
281 fuzz := &fuzzBinary{
282 binaryDecorator: binary,
283 baseCompiler: NewBaseCompiler(),
284 }
285 module.compiler = fuzz
286 module.linker = fuzz
287 module.installer = fuzz
Colin Crosseec9b282019-07-18 16:20:52 -0700288
289 // The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin.
290 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
Alex Light71123ec2019-07-24 13:34:19 -0700291 disableDarwinAndLinuxBionic := struct {
Colin Crosseec9b282019-07-18 16:20:52 -0700292 Target struct {
293 Darwin struct {
294 Enabled *bool
295 }
Alex Light71123ec2019-07-24 13:34:19 -0700296 Linux_bionic struct {
297 Enabled *bool
298 }
Colin Crosseec9b282019-07-18 16:20:52 -0700299 }
300 }{}
Alex Light71123ec2019-07-24 13:34:19 -0700301 disableDarwinAndLinuxBionic.Target.Darwin.Enabled = BoolPtr(false)
302 disableDarwinAndLinuxBionic.Target.Linux_bionic.Enabled = BoolPtr(false)
303 ctx.AppendProperties(&disableDarwinAndLinuxBionic)
Colin Crosseec9b282019-07-18 16:20:52 -0700304 })
305
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700306 return module
307}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700308
309// Responsible for generating GNU Make rules that package fuzz targets into
310// their architecture & target/host specific zip file.
311type fuzzPackager struct {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700312 packages android.Paths
313 sharedLibInstallStrings []string
314 fuzzTargets map[string]bool
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700315}
316
317func fuzzPackagingFactory() android.Singleton {
318 return &fuzzPackager{}
319}
320
321type fileToZip struct {
322 SourceFilePath android.Path
323 DestinationPathPrefix string
324}
325
Colin Crossdc809f92019-11-20 15:58:32 -0800326type archOs struct {
327 hostOrTarget string
328 arch string
329 dir string
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700330}
331
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700332func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
333 // Map between each architecture + host/device combination, and the files that
334 // need to be packaged (in the tuple of {source file, destination folder in
335 // archive}).
Colin Crossdc809f92019-11-20 15:58:32 -0800336 archDirs := make(map[archOs][]fileToZip)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700337
Colin Crossdc809f92019-11-20 15:58:32 -0800338 // Map tracking whether each shared library has an install rule to avoid duplicate install rules from
339 // multiple fuzzers that depend on the same shared library.
340 sharedLibraryInstalled := make(map[string]bool)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700341
342 // List of individual fuzz targets, so that 'make fuzz' also installs the targets
343 // to the correct output directories as well.
344 s.fuzzTargets = make(map[string]bool)
345
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700346 ctx.VisitAllModules(func(module android.Module) {
347 // Discard non-fuzz targets.
348 ccModule, ok := module.(*Module)
349 if !ok {
350 return
351 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700352
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700353 fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
354 if !ok {
355 return
356 }
357
Yifan Hong1b3348d2020-01-21 15:53:22 -0800358 // Discard vendor-NDK-linked + ramdisk + recovery modules, they're duplicates of
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800359 // fuzz targets we're going to package anyway.
360 if !ccModule.Enabled() || ccModule.Properties.PreventInstall ||
Yifan Hong1b3348d2020-01-21 15:53:22 -0800361 ccModule.UseVndk() || ccModule.InRamdisk() || ccModule.InRecovery() {
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700362 return
363 }
364
Mitch Phillips6a9bf212019-12-05 07:36:11 -0800365 // Discard modules that are in an unavailable namespace.
366 if !ccModule.ExportedToMake() {
367 return
368 }
369
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700370 s.fuzzTargets[module.Name()] = true
371
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700372 hostOrTargetString := "target"
373 if ccModule.Host() {
374 hostOrTargetString = "host"
375 }
376
377 archString := ccModule.Arch().ArchType.String()
378 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800379 archOs := archOs{hostOrTarget: hostOrTargetString, arch: archString, dir: archDir.String()}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700380
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700381 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800382 sharedLibraries := collectAllSharedDependencies(ctx, module)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700383
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800384 var files []fileToZip
385 builder := android.NewRuleBuilder()
386
387 // Package the corpora into a zipfile.
388 if fuzzModule.corpus != nil {
389 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
390 command := builder.Command().BuiltTool(ctx, "soong_zip").
391 Flag("-j").
392 FlagWithOutput("-o ", corpusZip)
393 command.FlagWithRspFileInputList("-l ", fuzzModule.corpus)
394 files = append(files, fileToZip{corpusZip, ""})
395 }
396
Tri Voad172d82019-11-27 13:45:45 -0800397 // Package the data into a zipfile.
398 if fuzzModule.data != nil {
399 dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
400 command := builder.Command().BuiltTool(ctx, "soong_zip").
401 FlagWithOutput("-o ", dataZip)
402 for _, f := range fuzzModule.data {
403 intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
404 command.FlagWithArg("-C ", intermediateDir)
405 command.FlagWithInput("-f ", f)
406 }
407 files = append(files, fileToZip{dataZip, ""})
408 }
409
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800410 // Find and mark all the transiently-dependent shared libraries for
411 // packaging.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700412 for _, library := range sharedLibraries {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800413 files = append(files, fileToZip{library, "lib"})
Mitch Phillips13ed3f52019-11-12 11:12:10 -0800414
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700415 // For each architecture-specific shared library dependency, we need to
416 // install it to the output directory. Setup the install destination here,
417 // which will be used by $(copy-many-files) in the Make backend.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700418 installDestination := sharedLibraryInstallLocation(
419 library, ccModule.Host(), archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800420 if sharedLibraryInstalled[installDestination] {
421 continue
422 }
423 sharedLibraryInstalled[installDestination] = true
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700424 // Escape all the variables, as the install destination here will be called
425 // via. $(eval) in Make.
426 installDestination = strings.ReplaceAll(
427 installDestination, "$", "$$")
428 s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
429 library.String()+":"+installDestination)
430 }
431
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700432 // The executable.
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800433 files = append(files, fileToZip{ccModule.UnstrippedOutputFile(), ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700434
435 // The dictionary.
436 if fuzzModule.dictionary != nil {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800437 files = append(files, fileToZip{fuzzModule.dictionary, ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700438 }
Kris Alderf979ee32019-10-22 10:52:01 -0700439
440 // Additional fuzz config.
441 if fuzzModule.config != nil {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800442 files = append(files, fileToZip{fuzzModule.config, ""})
Kris Alderf979ee32019-10-22 10:52:01 -0700443 }
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800444
445 fuzzZip := archDir.Join(ctx, module.Name()+".zip")
446 command := builder.Command().BuiltTool(ctx, "soong_zip").
447 Flag("-j").
448 FlagWithOutput("-o ", fuzzZip)
449 for _, file := range files {
450 if file.DestinationPathPrefix != "" {
451 command.FlagWithArg("-P ", file.DestinationPathPrefix)
452 } else {
453 command.Flag("-P ''")
454 }
455 command.FlagWithInput("-f ", file.SourceFilePath)
456 }
457
458 builder.Build(pctx, ctx, "create-"+fuzzZip.String(),
459 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
460
Colin Crossdc809f92019-11-20 15:58:32 -0800461 archDirs[archOs] = append(archDirs[archOs], fileToZip{fuzzZip, ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700462 })
463
Colin Crossdc809f92019-11-20 15:58:32 -0800464 var archOsList []archOs
465 for archOs := range archDirs {
466 archOsList = append(archOsList, archOs)
467 }
468 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].dir < archOsList[j].dir })
469
470 for _, archOs := range archOsList {
471 filesToZip := archDirs[archOs]
472 arch := archOs.arch
473 hostOrTarget := archOs.hostOrTarget
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700474 builder := android.NewRuleBuilder()
475 outputFile := android.PathForOutput(ctx, "fuzz-"+hostOrTarget+"-"+arch+".zip")
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700476 s.packages = append(s.packages, outputFile)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700477
478 command := builder.Command().BuiltTool(ctx, "soong_zip").
479 Flag("-j").
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800480 FlagWithOutput("-o ", outputFile).
481 Flag("-L 0") // No need to try and re-compress the zipfiles.
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700482
483 for _, fileToZip := range filesToZip {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800484 if fileToZip.DestinationPathPrefix != "" {
485 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
486 } else {
487 command.Flag("-P ''")
488 }
489 command.FlagWithInput("-f ", fileToZip.SourceFilePath)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700490 }
491
492 builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
493 "Create fuzz target packages for "+arch+"-"+hostOrTarget)
494 }
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700495}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700496
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700497func (s *fuzzPackager) MakeVars(ctx android.MakeVarsContext) {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700498 packages := s.packages.Strings()
499 sort.Strings(packages)
500 sort.Strings(s.sharedLibInstallStrings)
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700501 // TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
502 // ready to handle phony targets created in Soong. In the meantime, this
503 // exports the phony 'fuzz' target and dependencies on packages to
504 // core/main.mk so that we can use dist-for-goals.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700505 ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
506 ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
507 strings.Join(s.sharedLibInstallStrings, " "))
508
509 // Preallocate the slice of fuzz targets to minimise memory allocations.
510 fuzzTargets := make([]string, 0, len(s.fuzzTargets))
511 for target, _ := range s.fuzzTargets {
512 fuzzTargets = append(fuzzTargets, target)
513 }
514 sort.Strings(fuzzTargets)
515 ctx.Strict("ALL_FUZZ_TARGETS", strings.Join(fuzzTargets, " "))
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700516}