blob: e7c08b78ac220d2a72f0459c28fc364eb4903540 [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
Colin Cross3f40fa42015-01-30 17:27:36 -080024 "path/filepath"
25 "strings"
Colin Crossed4cf0b2015-03-26 14:43:45 -070026
27 "github.com/google/blueprint"
28 "github.com/google/blueprint/pathtools"
Colin Cross3f40fa42015-01-30 17:27:36 -080029)
30
31const (
Dan Albertc3144b12015-04-28 18:17:56 -070032 objectExtension = ".o"
Colin Cross3f40fa42015-01-30 17:27:36 -080033 sharedLibraryExtension = ".so"
34 staticLibraryExtension = ".a"
35)
36
37var (
38 pctx = blueprint.NewPackageContext("android/soong/cc")
39
40 cc = pctx.StaticRule("cc",
41 blueprint.RuleParams{
42 Depfile: "${out}.d",
43 Deps: blueprint.DepsGCC,
Colin Cross28344522015-04-22 13:07:53 -070044 Command: "$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in",
Colin Cross3f40fa42015-01-30 17:27:36 -080045 Description: "cc $out",
46 },
Colin Cross28344522015-04-22 13:07:53 -070047 "ccCmd", "cFlags")
Colin Cross3f40fa42015-01-30 17:27:36 -080048
49 ld = pctx.StaticRule("ld",
50 blueprint.RuleParams{
Colin Cross7d21c442015-03-30 17:47:53 -070051 Command: "$ldCmd ${ldDirFlags} ${crtBegin} @${out}.rsp " +
Colin Cross28344522015-04-22 13:07:53 -070052 "${libFlags} ${crtEnd} -o ${out} ${ldFlags}",
Colin Cross7d21c442015-03-30 17:47:53 -070053 Description: "ld $out",
54 Rspfile: "${out}.rsp",
55 RspfileContent: "${in}",
Colin Cross3f40fa42015-01-30 17:27:36 -080056 },
Colin Cross28344522015-04-22 13:07:53 -070057 "ldCmd", "ldDirFlags", "crtBegin", "libFlags", "crtEnd", "ldFlags")
Colin Cross3f40fa42015-01-30 17:27:36 -080058
59 partialLd = pctx.StaticRule("partialLd",
60 blueprint.RuleParams{
61 Command: "$ldCmd -r ${in} -o ${out}",
62 Description: "partialLd $out",
63 },
64 "ldCmd")
65
66 ar = pctx.StaticRule("ar",
67 blueprint.RuleParams{
Colin Cross7d21c442015-03-30 17:47:53 -070068 Command: "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp",
69 Description: "ar $out",
70 Rspfile: "${out}.rsp",
71 RspfileContent: "${in}",
Colin Cross3f40fa42015-01-30 17:27:36 -080072 },
73 "arCmd", "arFlags")
74
Colin Crossbfae8852015-03-26 14:44:11 -070075 prefixSymbols = pctx.StaticRule("prefixSymbols",
76 blueprint.RuleParams{
77 Command: "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
78 Description: "prefixSymbols $out",
79 },
80 "objcopyCmd", "prefix")
81
Colin Cross3f40fa42015-01-30 17:27:36 -080082 copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh")
83
84 copyGccLib = pctx.StaticRule("copyGccLib",
85 blueprint.RuleParams{
86 Depfile: "${out}.d",
87 Deps: blueprint.DepsGCC,
88 Command: "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
89 Description: "copy gcc $out",
90 },
91 "ccCmd", "cFlags", "libName")
92)
93
94type builderFlags struct {
95 globalFlags string
96 asFlags string
97 cFlags string
98 conlyFlags string
99 cppFlags string
100 ldFlags string
Colin Cross581c1892015-04-07 16:50:10 -0700101 yaccFlags string
Colin Cross3f40fa42015-01-30 17:27:36 -0800102 nocrt bool
Colin Cross97ba0732015-03-23 17:50:24 -0700103 toolchain Toolchain
Colin Cross3f40fa42015-01-30 17:27:36 -0800104 clang bool
105}
106
107// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
108func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles []string,
Colin Cross581c1892015-04-07 16:50:10 -0700109 flags builderFlags, deps []string) (objFiles []string) {
110
Colin Cross1332b002015-04-07 17:11:30 -0700111 srcRoot := ctx.AConfig().SrcDir()
112 intermediatesRoot := ctx.AConfig().IntermediatesDir()
Colin Cross3f40fa42015-01-30 17:27:36 -0800113
114 objFiles = make([]string, len(srcFiles))
115 objDir := common.ModuleObjDir(ctx)
116 if subdir != "" {
117 objDir = filepath.Join(objDir, subdir)
118 }
119
120 cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
121 cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
122 asflags := flags.globalFlags + " " + flags.asFlags
123
124 for i, srcFile := range srcFiles {
Colin Cross581c1892015-04-07 16:50:10 -0700125 var objFile string
126 if strings.HasPrefix(srcFile, srcRoot) {
127 objFile = strings.TrimPrefix(srcFile, srcRoot)
128 objFile = filepath.Join(objDir, objFile)
129 } else if strings.HasPrefix(srcFile, intermediatesRoot) {
130 objFile = strings.TrimPrefix(srcFile, intermediatesRoot)
131 objFile = filepath.Join(objDir, "gen", objFile)
132 } else {
133 ctx.ModuleErrorf("source file %q is not in source directory %q", srcFile, srcRoot)
134 continue
135 }
136
Colin Cross3f40fa42015-01-30 17:27:36 -0800137 objFile = pathtools.ReplaceExtension(objFile, "o")
138
139 objFiles[i] = objFile
140
141 var moduleCflags string
142 var ccCmd string
143
144 switch filepath.Ext(srcFile) {
145 case ".S", ".s":
146 ccCmd = "gcc"
147 moduleCflags = asflags
148 case ".c":
149 ccCmd = "gcc"
150 moduleCflags = cflags
151 case ".cpp", ".cc":
152 ccCmd = "g++"
153 moduleCflags = cppflags
154 default:
155 ctx.ModuleErrorf("File %s has unknown extension", srcFile)
156 continue
157 }
158
159 if flags.clang {
160 switch ccCmd {
161 case "gcc":
162 ccCmd = "clang"
163 case "g++":
164 ccCmd = "clang++"
165 default:
166 panic("unrecoginzied ccCmd")
167 }
168
169 ccCmd = "${clangPath}" + ccCmd
170 } else {
171 ccCmd = gccCmd(flags.toolchain, ccCmd)
172 }
173
Colin Cross581c1892015-04-07 16:50:10 -0700174 deps = append([]string{ccCmd}, deps...)
175
Colin Cross3f40fa42015-01-30 17:27:36 -0800176 ctx.Build(pctx, blueprint.BuildParams{
177 Rule: cc,
178 Outputs: []string{objFile},
179 Inputs: []string{srcFile},
Colin Cross581c1892015-04-07 16:50:10 -0700180 Implicits: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800181 Args: map[string]string{
Colin Cross28344522015-04-22 13:07:53 -0700182 "cFlags": moduleCflags,
183 "ccCmd": ccCmd,
Colin Cross3f40fa42015-01-30 17:27:36 -0800184 },
185 })
186 }
187
188 return objFiles
189}
190
191// Generate a rule for compiling multiple .o files to a static library (.a)
192func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
193 flags builderFlags, outputFile string) {
194
195 arCmd := gccCmd(flags.toolchain, "ar")
196 arFlags := "crsPD"
197
198 ctx.Build(pctx, blueprint.BuildParams{
199 Rule: ar,
200 Outputs: []string{outputFile},
201 Inputs: objFiles,
202 Implicits: []string{arCmd},
203 Args: map[string]string{
204 "arFlags": arFlags,
205 "arCmd": arCmd,
206 },
207 })
208}
209
210// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
211// and shared libraires, to a shared library (.so) or dynamic executable
212func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
Colin Cross77b00fa2015-03-16 16:15:49 -0700213 objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs []string,
Colin Crossed4cf0b2015-03-26 14:43:45 -0700214 crtBegin, crtEnd string, groupLate bool, flags builderFlags, outputFile string) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800215
216 var ldCmd string
217 if flags.clang {
218 ldCmd = "${clangPath}clang++"
219 } else {
220 ldCmd = gccCmd(flags.toolchain, "g++")
221 }
222
223 var ldDirs []string
224 var libFlagsList []string
225
226 if len(wholeStaticLibs) > 0 {
227 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
228 libFlagsList = append(libFlagsList, wholeStaticLibs...)
229 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
230 }
231
232 libFlagsList = append(libFlagsList, staticLibs...)
233
234 for _, lib := range sharedLibs {
235 dir, file := filepath.Split(lib)
236 if !strings.HasPrefix(file, "lib") {
237 panic("shared library " + lib + " does not start with lib")
238 }
239 if !strings.HasSuffix(file, sharedLibraryExtension) {
240 panic("shared library " + lib + " does not end with " + sharedLibraryExtension)
241 }
242 libFlagsList = append(libFlagsList,
243 "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension))
244 ldDirs = append(ldDirs, dir)
245 }
246
Colin Crossed4cf0b2015-03-26 14:43:45 -0700247 if groupLate {
248 libFlagsList = append(libFlagsList, "-Wl,--start-group")
249 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700250 libFlagsList = append(libFlagsList, lateStaticLibs...)
Colin Crossed4cf0b2015-03-26 14:43:45 -0700251 if groupLate {
252 libFlagsList = append(libFlagsList, "-Wl,--end-group")
253 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700254
Colin Cross3f40fa42015-01-30 17:27:36 -0800255 deps := []string{ldCmd}
256 deps = append(deps, sharedLibs...)
257 deps = append(deps, staticLibs...)
Colin Cross3075ad02015-03-17 10:47:08 -0700258 deps = append(deps, lateStaticLibs...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800259 deps = append(deps, wholeStaticLibs...)
260 if crtBegin != "" {
261 deps = append(deps, crtBegin, crtEnd)
262 }
263
264 ctx.Build(pctx, blueprint.BuildParams{
265 Rule: ld,
266 Outputs: []string{outputFile},
267 Inputs: objFiles,
268 Implicits: deps,
269 Args: map[string]string{
270 "ldCmd": ldCmd,
271 "ldDirFlags": ldDirsToFlags(ldDirs),
272 "crtBegin": crtBegin,
273 "libFlags": strings.Join(libFlagsList, " "),
274 "ldFlags": flags.ldFlags,
275 "crtEnd": crtEnd,
Colin Cross3f40fa42015-01-30 17:27:36 -0800276 },
277 })
278}
279
280// Generate a rule for compiling multiple .o files to a .o using ld partial linking
281func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
282 flags builderFlags, outputFile string) {
283
284 ldCmd := gccCmd(flags.toolchain, "ld")
285
286 deps := []string{ldCmd}
287
288 ctx.Build(pctx, blueprint.BuildParams{
289 Rule: partialLd,
290 Outputs: []string{outputFile},
291 Inputs: objFiles,
292 Implicits: deps,
293 Args: map[string]string{
294 "ldCmd": ldCmd,
295 },
296 })
297}
298
Colin Crossbfae8852015-03-26 14:44:11 -0700299// Generate a rule for runing objcopy --prefix-symbols on a binary
300func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile string,
301 flags builderFlags, outputFile string) {
302
303 objcopyCmd := gccCmd(flags.toolchain, "objcopy")
304
305 ctx.Build(pctx, blueprint.BuildParams{
306 Rule: prefixSymbols,
307 Outputs: []string{outputFile},
308 Inputs: []string{inputFile},
309 Implicits: []string{objcopyCmd},
310 Args: map[string]string{
311 "objcopyCmd": objcopyCmd,
312 "prefix": prefix,
313 },
314 })
315}
316
Colin Cross3f40fa42015-01-30 17:27:36 -0800317func CopyGccLib(ctx common.AndroidModuleContext, libName string,
318 flags builderFlags, outputFile string) {
319
320 ctx.Build(pctx, blueprint.BuildParams{
321 Rule: copyGccLib,
322 Outputs: []string{outputFile},
323 Implicits: []string{
324 "$copyGccLibPath",
325 gccCmd(flags.toolchain, "gcc"),
326 },
327 Args: map[string]string{
328 "ccCmd": gccCmd(flags.toolchain, "gcc"),
329 "cFlags": flags.globalFlags,
330 "libName": libName,
331 },
332 })
333}
334
Colin Cross97ba0732015-03-23 17:50:24 -0700335func gccCmd(toolchain Toolchain, cmd string) string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800336 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
337}