blob: 721d478a8a5da306d4b673f95f111b3ff589dc17 [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 (
32 sharedLibraryExtension = ".so"
33 staticLibraryExtension = ".a"
34)
35
36var (
37 pctx = blueprint.NewPackageContext("android/soong/cc")
38
39 cc = pctx.StaticRule("cc",
40 blueprint.RuleParams{
41 Depfile: "${out}.d",
42 Deps: blueprint.DepsGCC,
Colin Cross28344522015-04-22 13:07:53 -070043 Command: "$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in",
Colin Cross3f40fa42015-01-30 17:27:36 -080044 Description: "cc $out",
45 },
Colin Cross28344522015-04-22 13:07:53 -070046 "ccCmd", "cFlags")
Colin Cross3f40fa42015-01-30 17:27:36 -080047
48 ld = pctx.StaticRule("ld",
49 blueprint.RuleParams{
Colin Cross7d21c442015-03-30 17:47:53 -070050 Command: "$ldCmd ${ldDirFlags} ${crtBegin} @${out}.rsp " +
Colin Cross28344522015-04-22 13:07:53 -070051 "${libFlags} ${crtEnd} -o ${out} ${ldFlags}",
Colin Cross7d21c442015-03-30 17:47:53 -070052 Description: "ld $out",
53 Rspfile: "${out}.rsp",
54 RspfileContent: "${in}",
Colin Cross3f40fa42015-01-30 17:27:36 -080055 },
Colin Cross28344522015-04-22 13:07:53 -070056 "ldCmd", "ldDirFlags", "crtBegin", "libFlags", "crtEnd", "ldFlags")
Colin Cross3f40fa42015-01-30 17:27:36 -080057
58 partialLd = pctx.StaticRule("partialLd",
59 blueprint.RuleParams{
60 Command: "$ldCmd -r ${in} -o ${out}",
61 Description: "partialLd $out",
62 },
63 "ldCmd")
64
65 ar = pctx.StaticRule("ar",
66 blueprint.RuleParams{
Colin Cross7d21c442015-03-30 17:47:53 -070067 Command: "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp",
68 Description: "ar $out",
69 Rspfile: "${out}.rsp",
70 RspfileContent: "${in}",
Colin Cross3f40fa42015-01-30 17:27:36 -080071 },
72 "arCmd", "arFlags")
73
Colin Crossbfae8852015-03-26 14:44:11 -070074 prefixSymbols = pctx.StaticRule("prefixSymbols",
75 blueprint.RuleParams{
76 Command: "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
77 Description: "prefixSymbols $out",
78 },
79 "objcopyCmd", "prefix")
80
Colin Cross3f40fa42015-01-30 17:27:36 -080081 copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh")
82
83 copyGccLib = pctx.StaticRule("copyGccLib",
84 blueprint.RuleParams{
85 Depfile: "${out}.d",
86 Deps: blueprint.DepsGCC,
87 Command: "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
88 Description: "copy gcc $out",
89 },
90 "ccCmd", "cFlags", "libName")
91)
92
93type builderFlags struct {
94 globalFlags string
95 asFlags string
96 cFlags string
97 conlyFlags string
98 cppFlags string
99 ldFlags string
Colin Cross581c1892015-04-07 16:50:10 -0700100 yaccFlags string
Colin Cross3f40fa42015-01-30 17:27:36 -0800101 nocrt bool
Colin Cross97ba0732015-03-23 17:50:24 -0700102 toolchain Toolchain
Colin Cross3f40fa42015-01-30 17:27:36 -0800103 clang bool
104}
105
106// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
107func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles []string,
Colin Cross581c1892015-04-07 16:50:10 -0700108 flags builderFlags, deps []string) (objFiles []string) {
109
Colin Cross1332b002015-04-07 17:11:30 -0700110 srcRoot := ctx.AConfig().SrcDir()
111 intermediatesRoot := ctx.AConfig().IntermediatesDir()
Colin Cross3f40fa42015-01-30 17:27:36 -0800112
113 objFiles = make([]string, len(srcFiles))
114 objDir := common.ModuleObjDir(ctx)
115 if subdir != "" {
116 objDir = filepath.Join(objDir, subdir)
117 }
118
119 cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
120 cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
121 asflags := flags.globalFlags + " " + flags.asFlags
122
123 for i, srcFile := range srcFiles {
Colin Cross581c1892015-04-07 16:50:10 -0700124 var objFile string
125 if strings.HasPrefix(srcFile, srcRoot) {
126 objFile = strings.TrimPrefix(srcFile, srcRoot)
127 objFile = filepath.Join(objDir, objFile)
128 } else if strings.HasPrefix(srcFile, intermediatesRoot) {
129 objFile = strings.TrimPrefix(srcFile, intermediatesRoot)
130 objFile = filepath.Join(objDir, "gen", objFile)
131 } else {
132 ctx.ModuleErrorf("source file %q is not in source directory %q", srcFile, srcRoot)
133 continue
134 }
135
Colin Cross3f40fa42015-01-30 17:27:36 -0800136 objFile = pathtools.ReplaceExtension(objFile, "o")
137
138 objFiles[i] = objFile
139
140 var moduleCflags string
141 var ccCmd string
142
143 switch filepath.Ext(srcFile) {
144 case ".S", ".s":
145 ccCmd = "gcc"
146 moduleCflags = asflags
147 case ".c":
148 ccCmd = "gcc"
149 moduleCflags = cflags
150 case ".cpp", ".cc":
151 ccCmd = "g++"
152 moduleCflags = cppflags
153 default:
154 ctx.ModuleErrorf("File %s has unknown extension", srcFile)
155 continue
156 }
157
158 if flags.clang {
159 switch ccCmd {
160 case "gcc":
161 ccCmd = "clang"
162 case "g++":
163 ccCmd = "clang++"
164 default:
165 panic("unrecoginzied ccCmd")
166 }
167
168 ccCmd = "${clangPath}" + ccCmd
169 } else {
170 ccCmd = gccCmd(flags.toolchain, ccCmd)
171 }
172
Colin Cross581c1892015-04-07 16:50:10 -0700173 deps = append([]string{ccCmd}, deps...)
174
Colin Cross3f40fa42015-01-30 17:27:36 -0800175 ctx.Build(pctx, blueprint.BuildParams{
176 Rule: cc,
177 Outputs: []string{objFile},
178 Inputs: []string{srcFile},
Colin Cross581c1892015-04-07 16:50:10 -0700179 Implicits: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800180 Args: map[string]string{
Colin Cross28344522015-04-22 13:07:53 -0700181 "cFlags": moduleCflags,
182 "ccCmd": ccCmd,
Colin Cross3f40fa42015-01-30 17:27:36 -0800183 },
184 })
185 }
186
187 return objFiles
188}
189
190// Generate a rule for compiling multiple .o files to a static library (.a)
191func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
192 flags builderFlags, outputFile string) {
193
194 arCmd := gccCmd(flags.toolchain, "ar")
195 arFlags := "crsPD"
196
197 ctx.Build(pctx, blueprint.BuildParams{
198 Rule: ar,
199 Outputs: []string{outputFile},
200 Inputs: objFiles,
201 Implicits: []string{arCmd},
202 Args: map[string]string{
203 "arFlags": arFlags,
204 "arCmd": arCmd,
205 },
206 })
207}
208
209// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
210// and shared libraires, to a shared library (.so) or dynamic executable
211func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
Colin Cross77b00fa2015-03-16 16:15:49 -0700212 objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs []string,
Colin Crossed4cf0b2015-03-26 14:43:45 -0700213 crtBegin, crtEnd string, groupLate bool, flags builderFlags, outputFile string) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800214
215 var ldCmd string
216 if flags.clang {
217 ldCmd = "${clangPath}clang++"
218 } else {
219 ldCmd = gccCmd(flags.toolchain, "g++")
220 }
221
222 var ldDirs []string
223 var libFlagsList []string
224
225 if len(wholeStaticLibs) > 0 {
226 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
227 libFlagsList = append(libFlagsList, wholeStaticLibs...)
228 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
229 }
230
231 libFlagsList = append(libFlagsList, staticLibs...)
232
233 for _, lib := range sharedLibs {
234 dir, file := filepath.Split(lib)
235 if !strings.HasPrefix(file, "lib") {
236 panic("shared library " + lib + " does not start with lib")
237 }
238 if !strings.HasSuffix(file, sharedLibraryExtension) {
239 panic("shared library " + lib + " does not end with " + sharedLibraryExtension)
240 }
241 libFlagsList = append(libFlagsList,
242 "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension))
243 ldDirs = append(ldDirs, dir)
244 }
245
Colin Crossed4cf0b2015-03-26 14:43:45 -0700246 if groupLate {
247 libFlagsList = append(libFlagsList, "-Wl,--start-group")
248 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700249 libFlagsList = append(libFlagsList, lateStaticLibs...)
Colin Crossed4cf0b2015-03-26 14:43:45 -0700250 if groupLate {
251 libFlagsList = append(libFlagsList, "-Wl,--end-group")
252 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700253
Colin Cross3f40fa42015-01-30 17:27:36 -0800254 deps := []string{ldCmd}
255 deps = append(deps, sharedLibs...)
256 deps = append(deps, staticLibs...)
Colin Cross3075ad02015-03-17 10:47:08 -0700257 deps = append(deps, lateStaticLibs...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800258 deps = append(deps, wholeStaticLibs...)
259 if crtBegin != "" {
260 deps = append(deps, crtBegin, crtEnd)
261 }
262
263 ctx.Build(pctx, blueprint.BuildParams{
264 Rule: ld,
265 Outputs: []string{outputFile},
266 Inputs: objFiles,
267 Implicits: deps,
268 Args: map[string]string{
269 "ldCmd": ldCmd,
270 "ldDirFlags": ldDirsToFlags(ldDirs),
271 "crtBegin": crtBegin,
272 "libFlags": strings.Join(libFlagsList, " "),
273 "ldFlags": flags.ldFlags,
274 "crtEnd": crtEnd,
Colin Cross3f40fa42015-01-30 17:27:36 -0800275 },
276 })
277}
278
279// Generate a rule for compiling multiple .o files to a .o using ld partial linking
280func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
281 flags builderFlags, outputFile string) {
282
283 ldCmd := gccCmd(flags.toolchain, "ld")
284
285 deps := []string{ldCmd}
286
287 ctx.Build(pctx, blueprint.BuildParams{
288 Rule: partialLd,
289 Outputs: []string{outputFile},
290 Inputs: objFiles,
291 Implicits: deps,
292 Args: map[string]string{
293 "ldCmd": ldCmd,
294 },
295 })
296}
297
Colin Crossbfae8852015-03-26 14:44:11 -0700298// Generate a rule for runing objcopy --prefix-symbols on a binary
299func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile string,
300 flags builderFlags, outputFile string) {
301
302 objcopyCmd := gccCmd(flags.toolchain, "objcopy")
303
304 ctx.Build(pctx, blueprint.BuildParams{
305 Rule: prefixSymbols,
306 Outputs: []string{outputFile},
307 Inputs: []string{inputFile},
308 Implicits: []string{objcopyCmd},
309 Args: map[string]string{
310 "objcopyCmd": objcopyCmd,
311 "prefix": prefix,
312 },
313 })
314}
315
Colin Cross3f40fa42015-01-30 17:27:36 -0800316func CopyGccLib(ctx common.AndroidModuleContext, libName string,
317 flags builderFlags, outputFile string) {
318
319 ctx.Build(pctx, blueprint.BuildParams{
320 Rule: copyGccLib,
321 Outputs: []string{outputFile},
322 Implicits: []string{
323 "$copyGccLibPath",
324 gccCmd(flags.toolchain, "gcc"),
325 },
326 Args: map[string]string{
327 "ccCmd": gccCmd(flags.toolchain, "gcc"),
328 "cFlags": flags.globalFlags,
329 "libName": libName,
330 },
331 })
332}
333
Colin Cross97ba0732015-03-23 17:50:24 -0700334func gccCmd(toolchain Toolchain, cmd string) string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800335 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
336}