1// Copyright 2024 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 ( 18 "android/soong/android" 19 "slices" 20 "strings" 21) 22 23func init() { 24 RegisterCCPreprocessNoConfiguration(android.InitRegistrationContext) 25} 26 27func RegisterCCPreprocessNoConfiguration(ctx android.RegistrationContext) { 28 ctx.RegisterModuleType("cc_preprocess_no_configuration", ccPreprocessNoConfigurationFactory) 29} 30 31// cc_preprocess_no_configuration modules run the c preprocessor on a single input source file. 32// They also have "no configuration", meaning they don't have an arch or os associated with them, 33// they should be thought of as pure textual transformations of the input file. In some cases this 34// is good, in others you might want to do different transformations depending on what arch the 35// result will be compiled in, in which case you can use cc_object instead of this module. 36func ccPreprocessNoConfigurationFactory() android.Module { 37 m := &ccPreprocessNoConfiguration{} 38 m.AddProperties(&m.properties) 39 android.InitAndroidModule(m) 40 return m 41} 42 43type ccPreprocessNoConfigurationProps struct { 44 // Called Srcs for consistency with the other cc module types, but only accepts 1 input source 45 // file. 46 Srcs []string `android:"path"` 47 // The flags to pass to the c compiler. Must include -E in order to enable preprocessing-only 48 // mode. 49 Cflags []string `android:"path"` 50} 51 52type ccPreprocessNoConfiguration struct { 53 android.ModuleBase 54 properties ccPreprocessNoConfigurationProps 55} 56 57func (m *ccPreprocessNoConfiguration) GenerateAndroidBuildActions(ctx android.ModuleContext) { 58 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs) 59 if len(srcs) != 1 { 60 ctx.PropertyErrorf("Srcs", "cc_preprocess_no_configuration only accepts 1 source file, found: %v", srcs.Strings()) 61 return 62 } 63 src := srcs[0] 64 65 hasE := false 66 for _, cflag := range m.properties.Cflags { 67 if cflag == "-E" { 68 hasE = true 69 break 70 } else if cflag == "-P" || strings.HasPrefix(cflag, "-D") { 71 // do nothing, allow it 72 } else { 73 ctx.PropertyErrorf("Cflags", "cc_preprocess_no_configuration only allows -D and -P flags, found: %q", cflag) 74 return 75 } 76 } 77 if !hasE { 78 ctx.PropertyErrorf("Cflags", "cc_preprocess_no_configuration must have a -E cflag") 79 return 80 } 81 82 cflags := slices.Clone(m.properties.Cflags) 83 84 // Match behavior of other cc modules: 85 // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/cc/compiler.go;l=422;drc=7297f05ee8cda422ccb32c4af4d9d715d6bac10e 86 cflags = append(cflags, "-I"+ctx.ModuleDir()) 87 88 var ccCmd string 89 switch src.Ext() { 90 case ".c": 91 ccCmd = "clang" 92 case ".cpp", ".cc", ".cxx", ".mm": 93 ccCmd = "clang++" 94 default: 95 ctx.PropertyErrorf("srcs", "File %s has unknown extension. Supported extensions: .c, .cpp, .cc, .cxx, .mm", src) 96 return 97 } 98 99 ccCmd = "${config.ClangBin}/" + ccCmd 100 101 outFile := android.PathForModuleOut(ctx, src.Base()) 102 103 ctx.Build(pctx, android.BuildParams{ 104 Rule: cc, 105 Description: ccCmd + " " + src.Rel(), 106 Output: outFile, 107 Input: src, 108 Args: map[string]string{ 109 "cFlags": strings.Join(cflags, " "), 110 "ccCmd": ccCmd, 111 }, 112 }) 113 114 ctx.SetOutputFiles([]android.Path{outFile}, "") 115} 116