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