Moving common fuzzing code to fuzz package

Test: make haiku and make haiku-rust
Change-Id: Ife80cc10672f51bd6afbae7061cc9373a2a15e7d
diff --git a/cc/Android.bp b/cc/Android.bp
index 164d32b..bff2761 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -13,6 +13,7 @@
         "soong-bazel",
         "soong-cc-config",
         "soong-etc",
+        "soong-fuzz",
         "soong-genrule",
         "soong-snapshot",
         "soong-tradefed",
@@ -59,7 +60,6 @@
         "binary.go",
         "binary_sdk_member.go",
         "fuzz.go",
-        "fuzz_common.go",
         "library.go",
         "library_headers.go",
         "library_sdk_member.go",
diff --git a/cc/cc.go b/cc/cc.go
index e4f4761..f65af30 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -29,6 +29,7 @@
 
 	"android/soong/android"
 	"android/soong/cc/config"
+	"android/soong/fuzz"
 	"android/soong/genrule"
 )
 
@@ -762,7 +763,7 @@
 // members of the cc.Module to this decorator. Thus, a cc_binary module has custom linker and
 // installer logic.
 type Module struct {
-	FuzzModule
+	fuzz.FuzzModule
 
 	android.SdkBase
 	android.BazelModuleBase
@@ -3415,7 +3416,7 @@
 		&TestProperties{},
 		&TestBinaryProperties{},
 		&BenchmarkProperties{},
-		&FuzzProperties{},
+		&fuzz.FuzzProperties{},
 		&StlProperties{},
 		&SanitizeProperties{},
 		&StripProperties{},
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 8b0f93e..fbef12b 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -15,7 +15,6 @@
 package cc
 
 import (
-	"encoding/json"
 	"path/filepath"
 	"sort"
 	"strings"
@@ -24,55 +23,9 @@
 
 	"android/soong/android"
 	"android/soong/cc/config"
+	"android/soong/fuzz"
 )
 
-type FuzzConfig struct {
-	// Email address of people to CC on bugs or contact about this fuzz target.
-	Cc []string `json:"cc,omitempty"`
-	// Specify whether to enable continuous fuzzing on devices. Defaults to true.
-	Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
-	// Specify whether to enable continuous fuzzing on host. Defaults to true.
-	Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"`
-	// Component in Google's bug tracking system that bugs should be filed to.
-	Componentid *int64 `json:"componentid,omitempty"`
-	// Hotlists in Google's bug tracking system that bugs should be marked with.
-	Hotlists []string `json:"hotlists,omitempty"`
-	// Specify whether this fuzz target was submitted by a researcher. Defaults
-	// to false.
-	Researcher_submitted *bool `json:"researcher_submitted,omitempty"`
-	// Specify who should be acknowledged for CVEs in the Android Security
-	// Bulletin.
-	Acknowledgement []string `json:"acknowledgement,omitempty"`
-	// Additional options to be passed to libfuzzer when run in Haiku.
-	Libfuzzer_options []string `json:"libfuzzer_options,omitempty"`
-	// Additional options to be passed to HWASAN when running on-device in Haiku.
-	Hwasan_options []string `json:"hwasan_options,omitempty"`
-	// Additional options to be passed to HWASAN when running on host in Haiku.
-	Asan_options []string `json:"asan_options,omitempty"`
-}
-
-func (f *FuzzConfig) String() string {
-	b, err := json.Marshal(f)
-	if err != nil {
-		panic(err)
-	}
-
-	return string(b)
-}
-
-type FuzzProperties struct {
-	// Optional list of seed files to be installed to the fuzz target's output
-	// directory.
-	Corpus []string `android:"path"`
-	// Optional list of data files to be installed to the fuzz target's output
-	// directory. Directory structure relative to the module is preserved.
-	Data []string `android:"path"`
-	// Optional dictionary to be installed to the fuzz target's output directory.
-	Dictionary *string `android:"path"`
-	// Config for running the target on fuzzing infrastructure.
-	Fuzz_config *FuzzConfig
-}
-
 func init() {
 	android.RegisterModuleType("cc_fuzz", FuzzFactory)
 	android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
@@ -94,7 +47,7 @@
 	*binaryDecorator
 	*baseCompiler
 
-	fuzzPackagedModule FuzzPackagedModule
+	fuzzPackagedModule fuzz.FuzzPackagedModule
 
 	installedSharedDeps []string
 }
@@ -355,7 +308,7 @@
 // Responsible for generating GNU Make rules that package fuzz targets into
 // their architecture & target/host specific zip file.
 type ccFuzzPackager struct {
-	FuzzPackager
+	fuzz.FuzzPackager
 	sharedLibInstallStrings []string
 }
 
@@ -367,7 +320,7 @@
 	// Map between each architecture + host/device combination, and the files that
 	// need to be packaged (in the tuple of {source file, destination folder in
 	// archive}).
-	archDirs := make(map[ArchOs][]FileToZip)
+	archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
 
 	// Map tracking whether each shared library has an install rule to avoid duplicate install rules from
 	// multiple fuzzers that depend on the same shared library.
@@ -384,7 +337,7 @@
 		}
 
 		// Discard non-fuzz targets.
-		if ok := IsValid(ccModule.FuzzModule); !ok {
+		if ok := fuzz.IsValid(ccModule.FuzzModule); !ok {
 			return
 		}
 
@@ -400,12 +353,12 @@
 
 		archString := ccModule.Arch().ArchType.String()
 		archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
-		archOs := ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
+		archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
 
 		// Grab the list of required shared libraries.
 		sharedLibraries := collectAllSharedDependencies(ctx, module)
 
-		var files []FileToZip
+		var files []fuzz.FileToZip
 		builder := android.NewRuleBuilder(pctx, ctx)
 
 		// Package the corpus, data, dict and config into a zipfile.
@@ -414,7 +367,7 @@
 		// Find and mark all the transiently-dependent shared libraries for
 		// packaging.
 		for _, library := range sharedLibraries {
-			files = append(files, FileToZip{library, "lib"})
+			files = append(files, fuzz.FileToZip{library, "lib"})
 
 			// For each architecture-specific shared library dependency, we need to
 			// install it to the output directory. Setup the install destination here,
@@ -446,7 +399,7 @@
 		}
 
 		// The executable.
-		files = append(files, FileToZip{ccModule.UnstrippedOutputFile(), ""})
+		files = append(files, fuzz.FileToZip{ccModule.UnstrippedOutputFile(), ""})
 
 		archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
 		if !ok {
@@ -454,7 +407,7 @@
 		}
 	})
 
-	s.CreateFuzzPackage(ctx, archDirs, Cc)
+	s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx)
 
 }
 
diff --git a/cc/fuzz_common.go b/cc/fuzz_common.go
deleted file mode 100644
index 98ed7f4..0000000
--- a/cc/fuzz_common.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cc
-
-// This file contains the common code for compiling C/C++ and Rust fuzzers for Android.
-
-import (
-	"sort"
-	"strings"
-
-	"android/soong/android"
-)
-
-type Lang string
-
-const (
-	Cc   Lang = ""
-	Rust Lang = "rust"
-)
-
-type FuzzModule struct {
-	android.ModuleBase
-	android.DefaultableModuleBase
-	android.ApexModuleBase
-}
-
-type FuzzPackager struct {
-	Packages    android.Paths
-	FuzzTargets map[string]bool
-}
-
-type FileToZip struct {
-	SourceFilePath        android.Path
-	DestinationPathPrefix string
-}
-
-type ArchOs struct {
-	HostOrTarget string
-	Arch         string
-	Dir          string
-}
-
-type FuzzPackagedModule struct {
-	FuzzProperties        FuzzProperties
-	Dictionary            android.Path
-	Corpus                android.Paths
-	CorpusIntermediateDir android.Path
-	Config                android.Path
-	Data                  android.Paths
-	DataIntermediateDir   android.Path
-}
-
-func IsValid(fuzzModule FuzzModule) bool {
-	// Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
-	// fuzz targets we're going to package anyway.
-	if !fuzzModule.Enabled() || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
-		return false
-	}
-
-	// Discard modules that are in an unavailable namespace.
-	if !fuzzModule.ExportedToMake() {
-		return false
-	}
-
-	return true
-}
-
-func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
-	// Package the corpora into a zipfile.
-	var files []FileToZip
-	if fuzzModule.Corpus != nil {
-		corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
-		command := builder.Command().BuiltTool("soong_zip").
-			Flag("-j").
-			FlagWithOutput("-o ", corpusZip)
-		rspFile := corpusZip.ReplaceExtension(ctx, "rsp")
-		command.FlagWithRspFileInputList("-r ", rspFile, fuzzModule.Corpus)
-		files = append(files, FileToZip{corpusZip, ""})
-	}
-
-	// Package the data into a zipfile.
-	if fuzzModule.Data != nil {
-		dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
-		command := builder.Command().BuiltTool("soong_zip").
-			FlagWithOutput("-o ", dataZip)
-		for _, f := range fuzzModule.Data {
-			intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
-			command.FlagWithArg("-C ", intermediateDir)
-			command.FlagWithInput("-f ", f)
-		}
-		files = append(files, FileToZip{dataZip, ""})
-	}
-
-	// The dictionary.
-	if fuzzModule.Dictionary != nil {
-		files = append(files, FileToZip{fuzzModule.Dictionary, ""})
-	}
-
-	// Additional fuzz config.
-	if fuzzModule.Config != nil {
-		files = append(files, FileToZip{fuzzModule.Config, ""})
-	}
-
-	return files
-}
-
-func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) {
-	fuzzZip := archDir.Join(ctx, module.Name()+".zip")
-
-	command := builder.Command().BuiltTool("soong_zip").
-		Flag("-j").
-		FlagWithOutput("-o ", fuzzZip)
-
-	for _, file := range files {
-		if file.DestinationPathPrefix != "" {
-			command.FlagWithArg("-P ", file.DestinationPathPrefix)
-		} else {
-			command.Flag("-P ''")
-		}
-		command.FlagWithInput("-f ", file.SourceFilePath)
-	}
-
-	builder.Build("create-"+fuzzZip.String(),
-		"Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
-
-	// Don't add modules to 'make haiku-rust' that are set to not be
-	// exported to the fuzzing infrastructure.
-	if config := fuzzModule.FuzzProperties.Fuzz_config; config != nil {
-		if strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_host, true) {
-			return archDirs[archOs], false
-		} else if !BoolDefault(config.Fuzz_on_haiku_device, true) {
-			return archDirs[archOs], false
-		}
-	}
-
-	s.FuzzTargets[module.Name()] = true
-	archDirs[archOs] = append(archDirs[archOs], FileToZip{fuzzZip, ""})
-
-	return archDirs[archOs], true
-}
-
-func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, lang Lang) {
-	var archOsList []ArchOs
-	for archOs := range archDirs {
-		archOsList = append(archOsList, archOs)
-	}
-	sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].Dir < archOsList[j].Dir })
-
-	for _, archOs := range archOsList {
-		filesToZip := archDirs[archOs]
-		arch := archOs.Arch
-		hostOrTarget := archOs.HostOrTarget
-		builder := android.NewRuleBuilder(pctx, ctx)
-		zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip"
-		if lang == Rust {
-			zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
-		}
-		outputFile := android.PathForOutput(ctx, zipFileName)
-
-		s.Packages = append(s.Packages, outputFile)
-
-		command := builder.Command().BuiltTool("soong_zip").
-			Flag("-j").
-			FlagWithOutput("-o ", outputFile).
-			Flag("-L 0") // No need to try and re-compress the zipfiles.
-
-		for _, fileToZip := range filesToZip {
-
-			if fileToZip.DestinationPathPrefix != "" {
-				command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
-			} else {
-				command.Flag("-P ''")
-			}
-			command.FlagWithInput("-f ", fileToZip.SourceFilePath)
-
-		}
-		builder.Build("create-fuzz-package-"+arch+"-"+hostOrTarget,
-			"Create fuzz target packages for "+arch+"-"+hostOrTarget)
-	}
-}
-
-func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets string) {
-	fuzzTargets := make([]string, 0, len(s.FuzzTargets))
-	for target, _ := range s.FuzzTargets {
-		fuzzTargets = append(fuzzTargets, target)
-	}
-	sort.Strings(fuzzTargets)
-	ctx.Strict(targets, strings.Join(fuzzTargets, " "))
-}