blob: cb2bf9ac0c4a65bb26810777176cfa1f50a772d3 [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,
43 Command: "$ccCmd $incFlags -c $cFlags -MD -MF ${out}.d -o $out $in",
44 Description: "cc $out",
45 },
46 "ccCmd", "incFlags", "cFlags")
47
48 ld = pctx.StaticRule("ld",
49 blueprint.RuleParams{
Colin Cross7d21c442015-03-30 17:47:53 -070050 Command: "$ldCmd ${ldDirFlags} ${crtBegin} @${out}.rsp " +
Colin Cross3f40fa42015-01-30 17:27:36 -080051 "${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${ldLibs}",
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 },
56 "ldCmd", "ldDirFlags", "crtBegin", "libFlags", "crtEnd", "ldFlags", "ldLibs")
57
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
100 ldLibs string
101 incFlags string
102 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,
109 flags builderFlags) (objFiles []string) {
110
111 objFiles = make([]string, len(srcFiles))
112 objDir := common.ModuleObjDir(ctx)
113 if subdir != "" {
114 objDir = filepath.Join(objDir, subdir)
115 }
116
117 cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
118 cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
119 asflags := flags.globalFlags + " " + flags.asFlags
120
121 for i, srcFile := range srcFiles {
122 objFile := strings.TrimPrefix(srcFile, common.ModuleSrcDir(ctx))
123 objFile = filepath.Join(objDir, objFile)
124 objFile = pathtools.ReplaceExtension(objFile, "o")
125
126 objFiles[i] = objFile
127
128 var moduleCflags string
129 var ccCmd string
130
131 switch filepath.Ext(srcFile) {
132 case ".S", ".s":
133 ccCmd = "gcc"
134 moduleCflags = asflags
135 case ".c":
136 ccCmd = "gcc"
137 moduleCflags = cflags
138 case ".cpp", ".cc":
139 ccCmd = "g++"
140 moduleCflags = cppflags
141 default:
142 ctx.ModuleErrorf("File %s has unknown extension", srcFile)
143 continue
144 }
145
146 if flags.clang {
147 switch ccCmd {
148 case "gcc":
149 ccCmd = "clang"
150 case "g++":
151 ccCmd = "clang++"
152 default:
153 panic("unrecoginzied ccCmd")
154 }
155
156 ccCmd = "${clangPath}" + ccCmd
157 } else {
158 ccCmd = gccCmd(flags.toolchain, ccCmd)
159 }
160
161 ctx.Build(pctx, blueprint.BuildParams{
162 Rule: cc,
163 Outputs: []string{objFile},
164 Inputs: []string{srcFile},
165 Implicits: []string{ccCmd},
166 Args: map[string]string{
167 "cFlags": moduleCflags,
168 "incFlags": flags.incFlags,
169 "ccCmd": ccCmd,
170 },
171 })
172 }
173
174 return objFiles
175}
176
177// Generate a rule for compiling multiple .o files to a static library (.a)
178func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
179 flags builderFlags, outputFile string) {
180
181 arCmd := gccCmd(flags.toolchain, "ar")
182 arFlags := "crsPD"
183
184 ctx.Build(pctx, blueprint.BuildParams{
185 Rule: ar,
186 Outputs: []string{outputFile},
187 Inputs: objFiles,
188 Implicits: []string{arCmd},
189 Args: map[string]string{
190 "arFlags": arFlags,
191 "arCmd": arCmd,
192 },
193 })
194}
195
196// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
197// and shared libraires, to a shared library (.so) or dynamic executable
198func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
Colin Cross77b00fa2015-03-16 16:15:49 -0700199 objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs []string,
Colin Crossed4cf0b2015-03-26 14:43:45 -0700200 crtBegin, crtEnd string, groupLate bool, flags builderFlags, outputFile string) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800201
202 var ldCmd string
203 if flags.clang {
204 ldCmd = "${clangPath}clang++"
205 } else {
206 ldCmd = gccCmd(flags.toolchain, "g++")
207 }
208
209 var ldDirs []string
210 var libFlagsList []string
211
212 if len(wholeStaticLibs) > 0 {
213 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
214 libFlagsList = append(libFlagsList, wholeStaticLibs...)
215 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
216 }
217
218 libFlagsList = append(libFlagsList, staticLibs...)
219
220 for _, lib := range sharedLibs {
221 dir, file := filepath.Split(lib)
222 if !strings.HasPrefix(file, "lib") {
223 panic("shared library " + lib + " does not start with lib")
224 }
225 if !strings.HasSuffix(file, sharedLibraryExtension) {
226 panic("shared library " + lib + " does not end with " + sharedLibraryExtension)
227 }
228 libFlagsList = append(libFlagsList,
229 "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension))
230 ldDirs = append(ldDirs, dir)
231 }
232
Colin Crossed4cf0b2015-03-26 14:43:45 -0700233 if groupLate {
234 libFlagsList = append(libFlagsList, "-Wl,--start-group")
235 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700236 libFlagsList = append(libFlagsList, lateStaticLibs...)
Colin Crossed4cf0b2015-03-26 14:43:45 -0700237 if groupLate {
238 libFlagsList = append(libFlagsList, "-Wl,--end-group")
239 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700240
Colin Cross3f40fa42015-01-30 17:27:36 -0800241 deps := []string{ldCmd}
242 deps = append(deps, sharedLibs...)
243 deps = append(deps, staticLibs...)
Colin Cross3075ad02015-03-17 10:47:08 -0700244 deps = append(deps, lateStaticLibs...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800245 deps = append(deps, wholeStaticLibs...)
246 if crtBegin != "" {
247 deps = append(deps, crtBegin, crtEnd)
248 }
249
250 ctx.Build(pctx, blueprint.BuildParams{
251 Rule: ld,
252 Outputs: []string{outputFile},
253 Inputs: objFiles,
254 Implicits: deps,
255 Args: map[string]string{
256 "ldCmd": ldCmd,
257 "ldDirFlags": ldDirsToFlags(ldDirs),
258 "crtBegin": crtBegin,
259 "libFlags": strings.Join(libFlagsList, " "),
260 "ldFlags": flags.ldFlags,
261 "crtEnd": crtEnd,
262 "ldLibs": flags.ldLibs,
263 },
264 })
265}
266
267// Generate a rule for compiling multiple .o files to a .o using ld partial linking
268func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
269 flags builderFlags, outputFile string) {
270
271 ldCmd := gccCmd(flags.toolchain, "ld")
272
273 deps := []string{ldCmd}
274
275 ctx.Build(pctx, blueprint.BuildParams{
276 Rule: partialLd,
277 Outputs: []string{outputFile},
278 Inputs: objFiles,
279 Implicits: deps,
280 Args: map[string]string{
281 "ldCmd": ldCmd,
282 },
283 })
284}
285
Colin Crossbfae8852015-03-26 14:44:11 -0700286// Generate a rule for runing objcopy --prefix-symbols on a binary
287func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile string,
288 flags builderFlags, outputFile string) {
289
290 objcopyCmd := gccCmd(flags.toolchain, "objcopy")
291
292 ctx.Build(pctx, blueprint.BuildParams{
293 Rule: prefixSymbols,
294 Outputs: []string{outputFile},
295 Inputs: []string{inputFile},
296 Implicits: []string{objcopyCmd},
297 Args: map[string]string{
298 "objcopyCmd": objcopyCmd,
299 "prefix": prefix,
300 },
301 })
302}
303
Colin Cross3f40fa42015-01-30 17:27:36 -0800304func CopyGccLib(ctx common.AndroidModuleContext, libName string,
305 flags builderFlags, outputFile string) {
306
307 ctx.Build(pctx, blueprint.BuildParams{
308 Rule: copyGccLib,
309 Outputs: []string{outputFile},
310 Implicits: []string{
311 "$copyGccLibPath",
312 gccCmd(flags.toolchain, "gcc"),
313 },
314 Args: map[string]string{
315 "ccCmd": gccCmd(flags.toolchain, "gcc"),
316 "cFlags": flags.globalFlags,
317 "libName": libName,
318 },
319 })
320}
321
Colin Cross97ba0732015-03-23 17:50:24 -0700322func gccCmd(toolchain Toolchain, cmd string) string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800323 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
324}