blob: bb89bb4953936b8ce0d79bef3f8de29790454962 [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"`
30 // Boolean specifying whether to disable the fuzz target from running
31 // automatically in continuous fuzzing infrastructure.
32 Disable *bool `json:"disable,omitempty"`
33 // Component in Google's bug tracking system that bugs should be filed to.
34 Componentid *int64 `json:"componentid,omitempty"`
35 // Hotlists in Google's bug tracking system that bugs should be marked with.
36 Hotlists []string `json:"hotlists,omitempty"`
37}
38
39func (f *FuzzConfig) String() string {
40 b, err := json.Marshal(f)
41 if err != nil {
42 panic(err)
43 }
44
45 return string(b)
46}
47
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070048type FuzzProperties struct {
49 // Optional list of seed files to be installed to the fuzz target's output
50 // directory.
51 Corpus []string `android:"path"`
52 // Optional dictionary to be installed to the fuzz target's output directory.
53 Dictionary *string `android:"path"`
Kris Alderf979ee32019-10-22 10:52:01 -070054 // Config for running the target on fuzzing infrastructure.
55 Fuzz_config *FuzzConfig
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070056}
57
Mitch Phillipsda9a4632019-07-15 09:34:09 -070058func init() {
59 android.RegisterModuleType("cc_fuzz", FuzzFactory)
Mitch Phillipsd3254b42019-09-24 13:03:28 -070060 android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070061}
62
63// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
64// $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on
65// your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
66func FuzzFactory() android.Module {
67 module := NewFuzz(android.HostAndDeviceSupported)
68 return module.Init()
69}
70
71func NewFuzzInstaller() *baseInstaller {
72 return NewBaseInstaller("fuzz", "fuzz", InstallInData)
73}
74
75type fuzzBinary struct {
76 *binaryDecorator
77 *baseCompiler
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070078
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -070079 Properties FuzzProperties
80 dictionary android.Path
81 corpus android.Paths
82 corpusIntermediateDir android.Path
Kris Alderf979ee32019-10-22 10:52:01 -070083 config android.Path
Mitch Phillipse1ee1a12019-10-17 19:20:41 -070084 installedSharedDeps []string
Mitch Phillipsda9a4632019-07-15 09:34:09 -070085}
86
87func (fuzz *fuzzBinary) linkerProps() []interface{} {
88 props := fuzz.binaryDecorator.linkerProps()
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070089 props = append(props, &fuzz.Properties)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070090 return props
91}
92
93func (fuzz *fuzzBinary) linkerInit(ctx BaseModuleContext) {
Mitch Phillipsda9a4632019-07-15 09:34:09 -070094 fuzz.binaryDecorator.linkerInit(ctx)
95}
96
97func (fuzz *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
98 deps.StaticLibs = append(deps.StaticLibs,
99 config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
100 deps = fuzz.binaryDecorator.linkerDeps(ctx, deps)
101 return deps
102}
103
104func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
105 flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800106 // RunPaths on devices isn't instantiated by the base linker. `../lib` for
107 // installed fuzz targets (both host and device), and `./lib` for fuzz
108 // target packages.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700109 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800110 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700111 return flags
112}
113
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700114// This function performs a breadth-first search over the provided module's
115// dependencies using `visitDirectDeps` to enumerate all shared library
116// dependencies. We require breadth-first expansion, as otherwise we may
117// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
118// from a dependency. This may cause issues when dependencies have explicit
119// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
Colin Crossdc809f92019-11-20 15:58:32 -0800120func collectAllSharedDependencies(ctx android.SingletonContext, module android.Module) android.Paths {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700121 var fringe []android.Module
122
Colin Crossdc809f92019-11-20 15:58:32 -0800123 seen := make(map[android.Module]bool)
124
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700125 // Enumerate the first level of dependencies, as we discard all non-library
126 // modules in the BFS loop below.
127 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800128 if isValidSharedDependency(dep) {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800129 fringe = append(fringe, dep)
130 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700131 })
132
Colin Crossdc809f92019-11-20 15:58:32 -0800133 var sharedLibraries android.Paths
134
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700135 for i := 0; i < len(fringe); i++ {
136 module := fringe[i]
Colin Crossdc809f92019-11-20 15:58:32 -0800137 if seen[module] {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700138 continue
139 }
Colin Crossdc809f92019-11-20 15:58:32 -0800140 seen[module] = true
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700141
142 ccModule := module.(*Module)
Colin Crossdc809f92019-11-20 15:58:32 -0800143 sharedLibraries = append(sharedLibraries, ccModule.UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700144 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800145 if isValidSharedDependency(dep) && !seen[dep] {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800146 fringe = append(fringe, dep)
147 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700148 })
149 }
Colin Crossdc809f92019-11-20 15:58:32 -0800150
151 return sharedLibraries
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700152}
153
154// This function takes a module and determines if it is a unique shared library
155// that should be installed in the fuzz target output directories. This function
156// returns true, unless:
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700157// - The module is not a shared library, or
158// - The module is a header, stub, or vendor-linked library.
Colin Crossdc809f92019-11-20 15:58:32 -0800159func isValidSharedDependency(dependency android.Module) bool {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700160 // TODO(b/144090547): We should be parsing these modules using
161 // ModuleDependencyTag instead of the current brute-force checking.
162
163 if linkable, ok := dependency.(LinkableInterface); !ok || // Discard non-linkables.
164 !linkable.CcLibraryInterface() || !linkable.Shared() || // Discard static libs.
165 linkable.UseVndk() || // Discard vendor linked libraries.
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800166 // Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
167 // be excluded on the basis of they're not CCLibrary()'s.
168 (linkable.CcLibrary() && linkable.BuildStubs()) {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700169 return false
170 }
171
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800172 // We discarded module stubs libraries above, but the LLNDK prebuilts stubs
173 // libraries must be handled differently - by looking for the stubDecorator.
174 // Discard LLNDK prebuilts stubs as well.
175 if ccLibrary, isCcLibrary := dependency.(*Module); isCcLibrary {
176 if _, isLLndkStubLibrary := ccLibrary.linker.(*stubDecorator); isLLndkStubLibrary {
177 return false
178 }
179 }
180
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700181 return true
182}
183
184func sharedLibraryInstallLocation(
185 libraryPath android.Path, isHost bool, archString string) string {
186 installLocation := "$(PRODUCT_OUT)/data"
187 if isHost {
188 installLocation = "$(HOST_OUT)"
189 }
190 installLocation = filepath.Join(
191 installLocation, "fuzz", archString, "lib", libraryPath.Base())
192 return installLocation
193}
194
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700195func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700196 fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
197 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
198 fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
199 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700200 fuzz.binaryDecorator.baseInstaller.install(ctx, file)
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700201
202 fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -0700203 builder := android.NewRuleBuilder()
204 intermediateDir := android.PathForModuleOut(ctx, "corpus")
205 for _, entry := range fuzz.corpus {
206 builder.Command().Text("cp").
207 Input(entry).
208 Output(intermediateDir.Join(ctx, entry.Base()))
209 }
210 builder.Build(pctx, ctx, "copy_corpus", "copy corpus")
211 fuzz.corpusIntermediateDir = intermediateDir
212
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700213 if fuzz.Properties.Dictionary != nil {
214 fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
215 if fuzz.dictionary.Ext() != ".dict" {
216 ctx.PropertyErrorf("dictionary",
217 "Fuzzer dictionary %q does not have '.dict' extension",
218 fuzz.dictionary.String())
219 }
220 }
Kris Alderf979ee32019-10-22 10:52:01 -0700221
222 if fuzz.Properties.Fuzz_config != nil {
Kris Alderdb97af42019-10-30 10:17:04 -0700223 configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
Kris Alderf979ee32019-10-22 10:52:01 -0700224 ctx.Build(pctx, android.BuildParams{
225 Rule: android.WriteFile,
226 Description: "fuzzer infrastructure configuration",
227 Output: configPath,
228 Args: map[string]string{
229 "content": fuzz.Properties.Fuzz_config.String(),
230 },
231 })
232 fuzz.config = configPath
233 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700234
235 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800236 seen := make(map[android.Module]bool)
237 var sharedLibraries android.Paths
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700238 ctx.WalkDeps(func(child, parent android.Module) bool {
Colin Crossdc809f92019-11-20 15:58:32 -0800239 if seen[child] {
240 return false
241 }
242 seen[child] = true
243
244 if isValidSharedDependency(child) {
245 sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700246 return true
247 }
248 return false
249 })
250
251 for _, lib := range sharedLibraries {
252 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
253 sharedLibraryInstallLocation(
254 lib, ctx.Host(), ctx.Arch().ArchType.String()))
255 }
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700256}
257
258func NewFuzz(hod android.HostOrDeviceSupported) *Module {
259 module, binary := NewBinary(hod)
260
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700261 binary.baseInstaller = NewFuzzInstaller()
262 module.sanitize.SetSanitizer(fuzzer, true)
263
264 fuzz := &fuzzBinary{
265 binaryDecorator: binary,
266 baseCompiler: NewBaseCompiler(),
267 }
268 module.compiler = fuzz
269 module.linker = fuzz
270 module.installer = fuzz
Colin Crosseec9b282019-07-18 16:20:52 -0700271
272 // The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin.
273 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
Alex Light71123ec2019-07-24 13:34:19 -0700274 disableDarwinAndLinuxBionic := struct {
Colin Crosseec9b282019-07-18 16:20:52 -0700275 Target struct {
276 Darwin struct {
277 Enabled *bool
278 }
Alex Light71123ec2019-07-24 13:34:19 -0700279 Linux_bionic struct {
280 Enabled *bool
281 }
Colin Crosseec9b282019-07-18 16:20:52 -0700282 }
283 }{}
Alex Light71123ec2019-07-24 13:34:19 -0700284 disableDarwinAndLinuxBionic.Target.Darwin.Enabled = BoolPtr(false)
285 disableDarwinAndLinuxBionic.Target.Linux_bionic.Enabled = BoolPtr(false)
286 ctx.AppendProperties(&disableDarwinAndLinuxBionic)
Colin Crosseec9b282019-07-18 16:20:52 -0700287 })
288
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700289 return module
290}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700291
292// Responsible for generating GNU Make rules that package fuzz targets into
293// their architecture & target/host specific zip file.
294type fuzzPackager struct {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700295 packages android.Paths
296 sharedLibInstallStrings []string
297 fuzzTargets map[string]bool
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700298}
299
300func fuzzPackagingFactory() android.Singleton {
301 return &fuzzPackager{}
302}
303
304type fileToZip struct {
305 SourceFilePath android.Path
306 DestinationPathPrefix string
307}
308
Colin Crossdc809f92019-11-20 15:58:32 -0800309type archOs struct {
310 hostOrTarget string
311 arch string
312 dir string
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700313}
314
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700315func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
316 // Map between each architecture + host/device combination, and the files that
317 // need to be packaged (in the tuple of {source file, destination folder in
318 // archive}).
Colin Crossdc809f92019-11-20 15:58:32 -0800319 archDirs := make(map[archOs][]fileToZip)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700320
Colin Crossdc809f92019-11-20 15:58:32 -0800321 // Map tracking whether each shared library has an install rule to avoid duplicate install rules from
322 // multiple fuzzers that depend on the same shared library.
323 sharedLibraryInstalled := make(map[string]bool)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700324
325 // List of individual fuzz targets, so that 'make fuzz' also installs the targets
326 // to the correct output directories as well.
327 s.fuzzTargets = make(map[string]bool)
328
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700329 ctx.VisitAllModules(func(module android.Module) {
330 // Discard non-fuzz targets.
331 ccModule, ok := module.(*Module)
332 if !ok {
333 return
334 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700335
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700336 fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
337 if !ok {
338 return
339 }
340
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800341 // Discard vendor-NDK-linked + recovery modules, they're duplicates of
342 // fuzz targets we're going to package anyway.
343 if !ccModule.Enabled() || ccModule.Properties.PreventInstall ||
344 ccModule.UseVndk() || ccModule.InRecovery() {
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700345 return
346 }
347
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700348 s.fuzzTargets[module.Name()] = true
349
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700350 hostOrTargetString := "target"
351 if ccModule.Host() {
352 hostOrTargetString = "host"
353 }
354
355 archString := ccModule.Arch().ArchType.String()
356 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800357 archOs := archOs{hostOrTarget: hostOrTargetString, arch: archString, dir: archDir.String()}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700358
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700359 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800360 sharedLibraries := collectAllSharedDependencies(ctx, module)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700361
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800362 var files []fileToZip
363 builder := android.NewRuleBuilder()
364
365 // Package the corpora into a zipfile.
366 if fuzzModule.corpus != nil {
367 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
368 command := builder.Command().BuiltTool(ctx, "soong_zip").
369 Flag("-j").
370 FlagWithOutput("-o ", corpusZip)
371 command.FlagWithRspFileInputList("-l ", fuzzModule.corpus)
372 files = append(files, fileToZip{corpusZip, ""})
373 }
374
375 // Find and mark all the transiently-dependent shared libraries for
376 // packaging.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700377 for _, library := range sharedLibraries {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800378 files = append(files, fileToZip{library, "lib"})
Mitch Phillips13ed3f52019-11-12 11:12:10 -0800379
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700380 // For each architecture-specific shared library dependency, we need to
381 // install it to the output directory. Setup the install destination here,
382 // which will be used by $(copy-many-files) in the Make backend.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700383 installDestination := sharedLibraryInstallLocation(
384 library, ccModule.Host(), archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800385 if sharedLibraryInstalled[installDestination] {
386 continue
387 }
388 sharedLibraryInstalled[installDestination] = true
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700389 // Escape all the variables, as the install destination here will be called
390 // via. $(eval) in Make.
391 installDestination = strings.ReplaceAll(
392 installDestination, "$", "$$")
393 s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
394 library.String()+":"+installDestination)
395 }
396
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700397 // The executable.
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800398 files = append(files, fileToZip{ccModule.UnstrippedOutputFile(), ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700399
400 // The dictionary.
401 if fuzzModule.dictionary != nil {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800402 files = append(files, fileToZip{fuzzModule.dictionary, ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700403 }
Kris Alderf979ee32019-10-22 10:52:01 -0700404
405 // Additional fuzz config.
406 if fuzzModule.config != nil {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800407 files = append(files, fileToZip{fuzzModule.config, ""})
Kris Alderf979ee32019-10-22 10:52:01 -0700408 }
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800409
410 fuzzZip := archDir.Join(ctx, module.Name()+".zip")
411 command := builder.Command().BuiltTool(ctx, "soong_zip").
412 Flag("-j").
413 FlagWithOutput("-o ", fuzzZip)
414 for _, file := range files {
415 if file.DestinationPathPrefix != "" {
416 command.FlagWithArg("-P ", file.DestinationPathPrefix)
417 } else {
418 command.Flag("-P ''")
419 }
420 command.FlagWithInput("-f ", file.SourceFilePath)
421 }
422
423 builder.Build(pctx, ctx, "create-"+fuzzZip.String(),
424 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
425
Colin Crossdc809f92019-11-20 15:58:32 -0800426 archDirs[archOs] = append(archDirs[archOs], fileToZip{fuzzZip, ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700427 })
428
Colin Crossdc809f92019-11-20 15:58:32 -0800429 var archOsList []archOs
430 for archOs := range archDirs {
431 archOsList = append(archOsList, archOs)
432 }
433 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].dir < archOsList[j].dir })
434
435 for _, archOs := range archOsList {
436 filesToZip := archDirs[archOs]
437 arch := archOs.arch
438 hostOrTarget := archOs.hostOrTarget
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700439 builder := android.NewRuleBuilder()
440 outputFile := android.PathForOutput(ctx, "fuzz-"+hostOrTarget+"-"+arch+".zip")
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700441 s.packages = append(s.packages, outputFile)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700442
443 command := builder.Command().BuiltTool(ctx, "soong_zip").
444 Flag("-j").
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800445 FlagWithOutput("-o ", outputFile).
446 Flag("-L 0") // No need to try and re-compress the zipfiles.
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700447
448 for _, fileToZip := range filesToZip {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800449 if fileToZip.DestinationPathPrefix != "" {
450 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
451 } else {
452 command.Flag("-P ''")
453 }
454 command.FlagWithInput("-f ", fileToZip.SourceFilePath)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700455 }
456
457 builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
458 "Create fuzz target packages for "+arch+"-"+hostOrTarget)
459 }
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700460}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700461
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700462func (s *fuzzPackager) MakeVars(ctx android.MakeVarsContext) {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700463 packages := s.packages.Strings()
464 sort.Strings(packages)
465 sort.Strings(s.sharedLibInstallStrings)
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700466 // TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
467 // ready to handle phony targets created in Soong. In the meantime, this
468 // exports the phony 'fuzz' target and dependencies on packages to
469 // core/main.mk so that we can use dist-for-goals.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700470 ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
471 ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
472 strings.Join(s.sharedLibInstallStrings, " "))
473
474 // Preallocate the slice of fuzz targets to minimise memory allocations.
475 fuzzTargets := make([]string, 0, len(s.fuzzTargets))
476 for target, _ := range s.fuzzTargets {
477 fuzzTargets = append(fuzzTargets, target)
478 }
479 sort.Strings(fuzzTargets)
480 ctx.Strict("ALL_FUZZ_TARGETS", strings.Join(fuzzTargets, " "))
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700481}