blob: b61d6727c567387f2a0cde770d54a8acfe024f0c [file] [log] [blame]
Colin Cross3f40fa42015-01-30 17:27:36 -08001// Copyright 2015 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
17// This file generates the final rules for compiling all C/C++. All properties related to
18// compiling should have been translated into builderFlags or another argument to the Transform*
19// functions.
20
21import (
22 "android/soong/common"
23
24 "blueprint"
25 "blueprint/pathtools"
26 "path/filepath"
27 "strings"
28)
29
30const (
31 sharedLibraryExtension = ".so"
32 staticLibraryExtension = ".a"
33)
34
35var (
36 pctx = blueprint.NewPackageContext("android/soong/cc")
37
38 cc = pctx.StaticRule("cc",
39 blueprint.RuleParams{
40 Depfile: "${out}.d",
41 Deps: blueprint.DepsGCC,
42 Command: "$ccCmd $incFlags -c $cFlags -MD -MF ${out}.d -o $out $in",
43 Description: "cc $out",
44 },
45 "ccCmd", "incFlags", "cFlags")
46
47 ld = pctx.StaticRule("ld",
48 blueprint.RuleParams{
49 Command: "$ldCmd ${ldDirFlags} ${crtBegin} ${in} " +
50 "${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${ldLibs}",
51 Description: "ld $out",
52 },
53 "ldCmd", "ldDirFlags", "crtBegin", "libFlags", "crtEnd", "ldFlags", "ldLibs")
54
55 partialLd = pctx.StaticRule("partialLd",
56 blueprint.RuleParams{
57 Command: "$ldCmd -r ${in} -o ${out}",
58 Description: "partialLd $out",
59 },
60 "ldCmd")
61
62 ar = pctx.StaticRule("ar",
63 blueprint.RuleParams{
64 Command: "rm -f ${out} && $arCmd $arFlags $out $in",
65 Description: "ar $out",
66 },
67 "arCmd", "arFlags")
68
69 copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh")
70
71 copyGccLib = pctx.StaticRule("copyGccLib",
72 blueprint.RuleParams{
73 Depfile: "${out}.d",
74 Deps: blueprint.DepsGCC,
75 Command: "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
76 Description: "copy gcc $out",
77 },
78 "ccCmd", "cFlags", "libName")
79)
80
81type builderFlags struct {
82 globalFlags string
83 asFlags string
84 cFlags string
85 conlyFlags string
86 cppFlags string
87 ldFlags string
88 ldLibs string
89 incFlags string
90 nocrt bool
91 toolchain toolchain
92 clang bool
93}
94
95// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
96func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles []string,
97 flags builderFlags) (objFiles []string) {
98
99 objFiles = make([]string, len(srcFiles))
100 objDir := common.ModuleObjDir(ctx)
101 if subdir != "" {
102 objDir = filepath.Join(objDir, subdir)
103 }
104
105 cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
106 cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
107 asflags := flags.globalFlags + " " + flags.asFlags
108
109 for i, srcFile := range srcFiles {
110 objFile := strings.TrimPrefix(srcFile, common.ModuleSrcDir(ctx))
111 objFile = filepath.Join(objDir, objFile)
112 objFile = pathtools.ReplaceExtension(objFile, "o")
113
114 objFiles[i] = objFile
115
116 var moduleCflags string
117 var ccCmd string
118
119 switch filepath.Ext(srcFile) {
120 case ".S", ".s":
121 ccCmd = "gcc"
122 moduleCflags = asflags
123 case ".c":
124 ccCmd = "gcc"
125 moduleCflags = cflags
126 case ".cpp", ".cc":
127 ccCmd = "g++"
128 moduleCflags = cppflags
129 default:
130 ctx.ModuleErrorf("File %s has unknown extension", srcFile)
131 continue
132 }
133
134 if flags.clang {
135 switch ccCmd {
136 case "gcc":
137 ccCmd = "clang"
138 case "g++":
139 ccCmd = "clang++"
140 default:
141 panic("unrecoginzied ccCmd")
142 }
143
144 ccCmd = "${clangPath}" + ccCmd
145 } else {
146 ccCmd = gccCmd(flags.toolchain, ccCmd)
147 }
148
149 ctx.Build(pctx, blueprint.BuildParams{
150 Rule: cc,
151 Outputs: []string{objFile},
152 Inputs: []string{srcFile},
153 Implicits: []string{ccCmd},
154 Args: map[string]string{
155 "cFlags": moduleCflags,
156 "incFlags": flags.incFlags,
157 "ccCmd": ccCmd,
158 },
159 })
160 }
161
162 return objFiles
163}
164
165// Generate a rule for compiling multiple .o files to a static library (.a)
166func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
167 flags builderFlags, outputFile string) {
168
169 arCmd := gccCmd(flags.toolchain, "ar")
170 arFlags := "crsPD"
171
172 ctx.Build(pctx, blueprint.BuildParams{
173 Rule: ar,
174 Outputs: []string{outputFile},
175 Inputs: objFiles,
176 Implicits: []string{arCmd},
177 Args: map[string]string{
178 "arFlags": arFlags,
179 "arCmd": arCmd,
180 },
181 })
182}
183
184// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
185// and shared libraires, to a shared library (.so) or dynamic executable
186func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
187 objFiles, sharedLibs, staticLibs, wholeStaticLibs []string, crtBegin, crtEnd string,
188 flags builderFlags, outputFile string) {
189
190 var ldCmd string
191 if flags.clang {
192 ldCmd = "${clangPath}clang++"
193 } else {
194 ldCmd = gccCmd(flags.toolchain, "g++")
195 }
196
197 var ldDirs []string
198 var libFlagsList []string
199
200 if len(wholeStaticLibs) > 0 {
201 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
202 libFlagsList = append(libFlagsList, wholeStaticLibs...)
203 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
204 }
205
206 libFlagsList = append(libFlagsList, staticLibs...)
207
208 for _, lib := range sharedLibs {
209 dir, file := filepath.Split(lib)
210 if !strings.HasPrefix(file, "lib") {
211 panic("shared library " + lib + " does not start with lib")
212 }
213 if !strings.HasSuffix(file, sharedLibraryExtension) {
214 panic("shared library " + lib + " does not end with " + sharedLibraryExtension)
215 }
216 libFlagsList = append(libFlagsList,
217 "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension))
218 ldDirs = append(ldDirs, dir)
219 }
220
221 deps := []string{ldCmd}
222 deps = append(deps, sharedLibs...)
223 deps = append(deps, staticLibs...)
224 deps = append(deps, wholeStaticLibs...)
225 if crtBegin != "" {
226 deps = append(deps, crtBegin, crtEnd)
227 }
228
229 ctx.Build(pctx, blueprint.BuildParams{
230 Rule: ld,
231 Outputs: []string{outputFile},
232 Inputs: objFiles,
233 Implicits: deps,
234 Args: map[string]string{
235 "ldCmd": ldCmd,
236 "ldDirFlags": ldDirsToFlags(ldDirs),
237 "crtBegin": crtBegin,
238 "libFlags": strings.Join(libFlagsList, " "),
239 "ldFlags": flags.ldFlags,
240 "crtEnd": crtEnd,
241 "ldLibs": flags.ldLibs,
242 },
243 })
244}
245
246// Generate a rule for compiling multiple .o files to a .o using ld partial linking
247func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
248 flags builderFlags, outputFile string) {
249
250 ldCmd := gccCmd(flags.toolchain, "ld")
251
252 deps := []string{ldCmd}
253
254 ctx.Build(pctx, blueprint.BuildParams{
255 Rule: partialLd,
256 Outputs: []string{outputFile},
257 Inputs: objFiles,
258 Implicits: deps,
259 Args: map[string]string{
260 "ldCmd": ldCmd,
261 },
262 })
263}
264
265func CopyGccLib(ctx common.AndroidModuleContext, libName string,
266 flags builderFlags, outputFile string) {
267
268 ctx.Build(pctx, blueprint.BuildParams{
269 Rule: copyGccLib,
270 Outputs: []string{outputFile},
271 Implicits: []string{
272 "$copyGccLibPath",
273 gccCmd(flags.toolchain, "gcc"),
274 },
275 Args: map[string]string{
276 "ccCmd": gccCmd(flags.toolchain, "gcc"),
277 "cFlags": flags.globalFlags,
278 "libName": libName,
279 },
280 })
281}
282
283func gccCmd(toolchain toolchain, cmd string) string {
284 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
285}