blob: 0d3cc743097d2b1d48c79caaab6b22cd4f37abfa [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"`
Tri Voad172d82019-11-27 13:45:45 -080052 // Optional list of data files to be installed to the fuzz target's output
53 // directory. Directory structure relative to the module is preserved.
54 Data []string `android:"path"`
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070055 // Optional dictionary to be installed to the fuzz target's output directory.
56 Dictionary *string `android:"path"`
Kris Alderf979ee32019-10-22 10:52:01 -070057 // Config for running the target on fuzzing infrastructure.
58 Fuzz_config *FuzzConfig
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070059}
60
Mitch Phillipsda9a4632019-07-15 09:34:09 -070061func init() {
62 android.RegisterModuleType("cc_fuzz", FuzzFactory)
Mitch Phillipsd3254b42019-09-24 13:03:28 -070063 android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070064}
65
66// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
67// $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on
68// your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
69func FuzzFactory() android.Module {
70 module := NewFuzz(android.HostAndDeviceSupported)
71 return module.Init()
72}
73
74func NewFuzzInstaller() *baseInstaller {
75 return NewBaseInstaller("fuzz", "fuzz", InstallInData)
76}
77
78type fuzzBinary struct {
79 *binaryDecorator
80 *baseCompiler
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070081
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -070082 Properties FuzzProperties
83 dictionary android.Path
84 corpus android.Paths
85 corpusIntermediateDir android.Path
Kris Alderf979ee32019-10-22 10:52:01 -070086 config android.Path
Tri Voad172d82019-11-27 13:45:45 -080087 data android.Paths
88 dataIntermediateDir android.Path
Mitch Phillipse1ee1a12019-10-17 19:20:41 -070089 installedSharedDeps []string
Mitch Phillipsda9a4632019-07-15 09:34:09 -070090}
91
92func (fuzz *fuzzBinary) linkerProps() []interface{} {
93 props := fuzz.binaryDecorator.linkerProps()
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070094 props = append(props, &fuzz.Properties)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070095 return props
96}
97
98func (fuzz *fuzzBinary) linkerInit(ctx BaseModuleContext) {
Mitch Phillipsda9a4632019-07-15 09:34:09 -070099 fuzz.binaryDecorator.linkerInit(ctx)
100}
101
102func (fuzz *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
103 deps.StaticLibs = append(deps.StaticLibs,
104 config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
105 deps = fuzz.binaryDecorator.linkerDeps(ctx, deps)
106 return deps
107}
108
109func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
110 flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800111 // RunPaths on devices isn't instantiated by the base linker. `../lib` for
112 // installed fuzz targets (both host and device), and `./lib` for fuzz
113 // target packages.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700114 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800115 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700116 return flags
117}
118
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700119// This function performs a breadth-first search over the provided module's
120// dependencies using `visitDirectDeps` to enumerate all shared library
121// dependencies. We require breadth-first expansion, as otherwise we may
122// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
123// from a dependency. This may cause issues when dependencies have explicit
124// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
Colin Crossdc809f92019-11-20 15:58:32 -0800125func collectAllSharedDependencies(ctx android.SingletonContext, module android.Module) android.Paths {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700126 var fringe []android.Module
127
Colin Crossdc809f92019-11-20 15:58:32 -0800128 seen := make(map[android.Module]bool)
129
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700130 // Enumerate the first level of dependencies, as we discard all non-library
131 // modules in the BFS loop below.
132 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800133 if isValidSharedDependency(dep) {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800134 fringe = append(fringe, dep)
135 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700136 })
137
Colin Crossdc809f92019-11-20 15:58:32 -0800138 var sharedLibraries android.Paths
139
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700140 for i := 0; i < len(fringe); i++ {
141 module := fringe[i]
Colin Crossdc809f92019-11-20 15:58:32 -0800142 if seen[module] {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700143 continue
144 }
Colin Crossdc809f92019-11-20 15:58:32 -0800145 seen[module] = true
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700146
147 ccModule := module.(*Module)
Colin Crossdc809f92019-11-20 15:58:32 -0800148 sharedLibraries = append(sharedLibraries, ccModule.UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700149 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800150 if isValidSharedDependency(dep) && !seen[dep] {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800151 fringe = append(fringe, dep)
152 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700153 })
154 }
Colin Crossdc809f92019-11-20 15:58:32 -0800155
156 return sharedLibraries
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700157}
158
159// This function takes a module and determines if it is a unique shared library
160// that should be installed in the fuzz target output directories. This function
161// returns true, unless:
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700162// - The module is not a shared library, or
163// - The module is a header, stub, or vendor-linked library.
Colin Crossdc809f92019-11-20 15:58:32 -0800164func isValidSharedDependency(dependency android.Module) bool {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700165 // TODO(b/144090547): We should be parsing these modules using
166 // ModuleDependencyTag instead of the current brute-force checking.
167
168 if linkable, ok := dependency.(LinkableInterface); !ok || // Discard non-linkables.
169 !linkable.CcLibraryInterface() || !linkable.Shared() || // Discard static libs.
170 linkable.UseVndk() || // Discard vendor linked libraries.
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800171 // Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
172 // be excluded on the basis of they're not CCLibrary()'s.
173 (linkable.CcLibrary() && linkable.BuildStubs()) {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700174 return false
175 }
176
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800177 // We discarded module stubs libraries above, but the LLNDK prebuilts stubs
178 // libraries must be handled differently - by looking for the stubDecorator.
179 // Discard LLNDK prebuilts stubs as well.
180 if ccLibrary, isCcLibrary := dependency.(*Module); isCcLibrary {
181 if _, isLLndkStubLibrary := ccLibrary.linker.(*stubDecorator); isLLndkStubLibrary {
182 return false
183 }
184 }
185
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700186 return true
187}
188
189func sharedLibraryInstallLocation(
190 libraryPath android.Path, isHost bool, archString string) string {
191 installLocation := "$(PRODUCT_OUT)/data"
192 if isHost {
193 installLocation = "$(HOST_OUT)"
194 }
195 installLocation = filepath.Join(
196 installLocation, "fuzz", archString, "lib", libraryPath.Base())
197 return installLocation
198}
199
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700200func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700201 fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
202 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
203 fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
204 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700205 fuzz.binaryDecorator.baseInstaller.install(ctx, file)
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700206
207 fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -0700208 builder := android.NewRuleBuilder()
209 intermediateDir := android.PathForModuleOut(ctx, "corpus")
210 for _, entry := range fuzz.corpus {
211 builder.Command().Text("cp").
212 Input(entry).
213 Output(intermediateDir.Join(ctx, entry.Base()))
214 }
215 builder.Build(pctx, ctx, "copy_corpus", "copy corpus")
216 fuzz.corpusIntermediateDir = intermediateDir
217
Tri Voad172d82019-11-27 13:45:45 -0800218 fuzz.data = android.PathsForModuleSrc(ctx, fuzz.Properties.Data)
219 builder = android.NewRuleBuilder()
220 intermediateDir = android.PathForModuleOut(ctx, "data")
221 for _, entry := range fuzz.data {
222 builder.Command().Text("cp").
223 Input(entry).
224 Output(intermediateDir.Join(ctx, entry.Rel()))
225 }
226 builder.Build(pctx, ctx, "copy_data", "copy data")
227 fuzz.dataIntermediateDir = intermediateDir
228
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700229 if fuzz.Properties.Dictionary != nil {
230 fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
231 if fuzz.dictionary.Ext() != ".dict" {
232 ctx.PropertyErrorf("dictionary",
233 "Fuzzer dictionary %q does not have '.dict' extension",
234 fuzz.dictionary.String())
235 }
236 }
Kris Alderf979ee32019-10-22 10:52:01 -0700237
238 if fuzz.Properties.Fuzz_config != nil {
Kris Alderdb97af42019-10-30 10:17:04 -0700239 configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
Kris Alderf979ee32019-10-22 10:52:01 -0700240 ctx.Build(pctx, android.BuildParams{
241 Rule: android.WriteFile,
242 Description: "fuzzer infrastructure configuration",
243 Output: configPath,
244 Args: map[string]string{
245 "content": fuzz.Properties.Fuzz_config.String(),
246 },
247 })
248 fuzz.config = configPath
249 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700250
251 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800252 seen := make(map[android.Module]bool)
253 var sharedLibraries android.Paths
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700254 ctx.WalkDeps(func(child, parent android.Module) bool {
Colin Crossdc809f92019-11-20 15:58:32 -0800255 if seen[child] {
256 return false
257 }
258 seen[child] = true
259
260 if isValidSharedDependency(child) {
261 sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700262 return true
263 }
264 return false
265 })
266
267 for _, lib := range sharedLibraries {
268 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
269 sharedLibraryInstallLocation(
270 lib, ctx.Host(), ctx.Arch().ArchType.String()))
271 }
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700272}
273
274func NewFuzz(hod android.HostOrDeviceSupported) *Module {
275 module, binary := NewBinary(hod)
276
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700277 binary.baseInstaller = NewFuzzInstaller()
278 module.sanitize.SetSanitizer(fuzzer, true)
279
280 fuzz := &fuzzBinary{
281 binaryDecorator: binary,
282 baseCompiler: NewBaseCompiler(),
283 }
284 module.compiler = fuzz
285 module.linker = fuzz
286 module.installer = fuzz
Colin Crosseec9b282019-07-18 16:20:52 -0700287
288 // The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin.
289 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
Alex Light71123ec2019-07-24 13:34:19 -0700290 disableDarwinAndLinuxBionic := struct {
Colin Crosseec9b282019-07-18 16:20:52 -0700291 Target struct {
292 Darwin struct {
293 Enabled *bool
294 }
Alex Light71123ec2019-07-24 13:34:19 -0700295 Linux_bionic struct {
296 Enabled *bool
297 }
Colin Crosseec9b282019-07-18 16:20:52 -0700298 }
299 }{}
Alex Light71123ec2019-07-24 13:34:19 -0700300 disableDarwinAndLinuxBionic.Target.Darwin.Enabled = BoolPtr(false)
301 disableDarwinAndLinuxBionic.Target.Linux_bionic.Enabled = BoolPtr(false)
302 ctx.AppendProperties(&disableDarwinAndLinuxBionic)
Colin Crosseec9b282019-07-18 16:20:52 -0700303 })
304
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700305 return module
306}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700307
308// Responsible for generating GNU Make rules that package fuzz targets into
309// their architecture & target/host specific zip file.
310type fuzzPackager struct {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700311 packages android.Paths
312 sharedLibInstallStrings []string
313 fuzzTargets map[string]bool
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700314}
315
316func fuzzPackagingFactory() android.Singleton {
317 return &fuzzPackager{}
318}
319
320type fileToZip struct {
321 SourceFilePath android.Path
322 DestinationPathPrefix string
323}
324
Colin Crossdc809f92019-11-20 15:58:32 -0800325type archOs struct {
326 hostOrTarget string
327 arch string
328 dir string
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700329}
330
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700331func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
332 // Map between each architecture + host/device combination, and the files that
333 // need to be packaged (in the tuple of {source file, destination folder in
334 // archive}).
Colin Crossdc809f92019-11-20 15:58:32 -0800335 archDirs := make(map[archOs][]fileToZip)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700336
Colin Crossdc809f92019-11-20 15:58:32 -0800337 // Map tracking whether each shared library has an install rule to avoid duplicate install rules from
338 // multiple fuzzers that depend on the same shared library.
339 sharedLibraryInstalled := make(map[string]bool)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700340
341 // List of individual fuzz targets, so that 'make fuzz' also installs the targets
342 // to the correct output directories as well.
343 s.fuzzTargets = make(map[string]bool)
344
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700345 ctx.VisitAllModules(func(module android.Module) {
346 // Discard non-fuzz targets.
347 ccModule, ok := module.(*Module)
348 if !ok {
349 return
350 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700351
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700352 fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
353 if !ok {
354 return
355 }
356
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800357 // Discard vendor-NDK-linked + recovery modules, they're duplicates of
358 // fuzz targets we're going to package anyway.
359 if !ccModule.Enabled() || ccModule.Properties.PreventInstall ||
360 ccModule.UseVndk() || ccModule.InRecovery() {
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700361 return
362 }
363
Mitch Phillips6a9bf212019-12-05 07:36:11 -0800364 // Discard modules that are in an unavailable namespace.
365 if !ccModule.ExportedToMake() {
366 return
367 }
368
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700369 s.fuzzTargets[module.Name()] = true
370
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700371 hostOrTargetString := "target"
372 if ccModule.Host() {
373 hostOrTargetString = "host"
374 }
375
376 archString := ccModule.Arch().ArchType.String()
377 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800378 archOs := archOs{hostOrTarget: hostOrTargetString, arch: archString, dir: archDir.String()}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700379
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700380 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800381 sharedLibraries := collectAllSharedDependencies(ctx, module)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700382
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800383 var files []fileToZip
384 builder := android.NewRuleBuilder()
385
386 // Package the corpora into a zipfile.
387 if fuzzModule.corpus != nil {
388 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
389 command := builder.Command().BuiltTool(ctx, "soong_zip").
390 Flag("-j").
391 FlagWithOutput("-o ", corpusZip)
392 command.FlagWithRspFileInputList("-l ", fuzzModule.corpus)
393 files = append(files, fileToZip{corpusZip, ""})
394 }
395
Tri Voad172d82019-11-27 13:45:45 -0800396 // Package the data into a zipfile.
397 if fuzzModule.data != nil {
398 dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
399 command := builder.Command().BuiltTool(ctx, "soong_zip").
400 FlagWithOutput("-o ", dataZip)
401 for _, f := range fuzzModule.data {
402 intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
403 command.FlagWithArg("-C ", intermediateDir)
404 command.FlagWithInput("-f ", f)
405 }
406 files = append(files, fileToZip{dataZip, ""})
407 }
408
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800409 // Find and mark all the transiently-dependent shared libraries for
410 // packaging.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700411 for _, library := range sharedLibraries {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800412 files = append(files, fileToZip{library, "lib"})
Mitch Phillips13ed3f52019-11-12 11:12:10 -0800413
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700414 // For each architecture-specific shared library dependency, we need to
415 // install it to the output directory. Setup the install destination here,
416 // which will be used by $(copy-many-files) in the Make backend.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700417 installDestination := sharedLibraryInstallLocation(
418 library, ccModule.Host(), archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800419 if sharedLibraryInstalled[installDestination] {
420 continue
421 }
422 sharedLibraryInstalled[installDestination] = true
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700423 // Escape all the variables, as the install destination here will be called
424 // via. $(eval) in Make.
425 installDestination = strings.ReplaceAll(
426 installDestination, "$", "$$")
427 s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
428 library.String()+":"+installDestination)
429 }
430
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700431 // The executable.
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800432 files = append(files, fileToZip{ccModule.UnstrippedOutputFile(), ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700433
434 // The dictionary.
435 if fuzzModule.dictionary != nil {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800436 files = append(files, fileToZip{fuzzModule.dictionary, ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700437 }
Kris Alderf979ee32019-10-22 10:52:01 -0700438
439 // Additional fuzz config.
440 if fuzzModule.config != nil {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800441 files = append(files, fileToZip{fuzzModule.config, ""})
Kris Alderf979ee32019-10-22 10:52:01 -0700442 }
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800443
444 fuzzZip := archDir.Join(ctx, module.Name()+".zip")
445 command := builder.Command().BuiltTool(ctx, "soong_zip").
446 Flag("-j").
447 FlagWithOutput("-o ", fuzzZip)
448 for _, file := range files {
449 if file.DestinationPathPrefix != "" {
450 command.FlagWithArg("-P ", file.DestinationPathPrefix)
451 } else {
452 command.Flag("-P ''")
453 }
454 command.FlagWithInput("-f ", file.SourceFilePath)
455 }
456
457 builder.Build(pctx, ctx, "create-"+fuzzZip.String(),
458 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
459
Colin Crossdc809f92019-11-20 15:58:32 -0800460 archDirs[archOs] = append(archDirs[archOs], fileToZip{fuzzZip, ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700461 })
462
Colin Crossdc809f92019-11-20 15:58:32 -0800463 var archOsList []archOs
464 for archOs := range archDirs {
465 archOsList = append(archOsList, archOs)
466 }
467 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].dir < archOsList[j].dir })
468
469 for _, archOs := range archOsList {
470 filesToZip := archDirs[archOs]
471 arch := archOs.arch
472 hostOrTarget := archOs.hostOrTarget
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700473 builder := android.NewRuleBuilder()
474 outputFile := android.PathForOutput(ctx, "fuzz-"+hostOrTarget+"-"+arch+".zip")
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700475 s.packages = append(s.packages, outputFile)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700476
477 command := builder.Command().BuiltTool(ctx, "soong_zip").
478 Flag("-j").
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800479 FlagWithOutput("-o ", outputFile).
480 Flag("-L 0") // No need to try and re-compress the zipfiles.
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700481
482 for _, fileToZip := range filesToZip {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800483 if fileToZip.DestinationPathPrefix != "" {
484 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
485 } else {
486 command.Flag("-P ''")
487 }
488 command.FlagWithInput("-f ", fileToZip.SourceFilePath)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700489 }
490
491 builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
492 "Create fuzz target packages for "+arch+"-"+hostOrTarget)
493 }
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700494}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700495
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700496func (s *fuzzPackager) MakeVars(ctx android.MakeVarsContext) {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700497 packages := s.packages.Strings()
498 sort.Strings(packages)
499 sort.Strings(s.sharedLibInstallStrings)
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700500 // TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
501 // ready to handle phony targets created in Soong. In the meantime, this
502 // exports the phony 'fuzz' target and dependencies on packages to
503 // core/main.mk so that we can use dist-for-goals.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700504 ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
505 ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
506 strings.Join(s.sharedLibInstallStrings, " "))
507
508 // Preallocate the slice of fuzz targets to minimise memory allocations.
509 fuzzTargets := make([]string, 0, len(s.fuzzTargets))
510 for target, _ := range s.fuzzTargets {
511 fuzzTargets = append(fuzzTargets, target)
512 }
513 sort.Strings(fuzzTargets)
514 ctx.Strict("ALL_FUZZ_TARGETS", strings.Join(fuzzTargets, " "))
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700515}