blob: c843c2d610c9d891687c8d2cae7c12226e07427e [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{
50 Command: "$ldCmd ${ldDirFlags} ${crtBegin} ${in} " +
51 "${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${ldLibs}",
52 Description: "ld $out",
53 },
54 "ldCmd", "ldDirFlags", "crtBegin", "libFlags", "crtEnd", "ldFlags", "ldLibs")
55
56 partialLd = pctx.StaticRule("partialLd",
57 blueprint.RuleParams{
58 Command: "$ldCmd -r ${in} -o ${out}",
59 Description: "partialLd $out",
60 },
61 "ldCmd")
62
63 ar = pctx.StaticRule("ar",
64 blueprint.RuleParams{
65 Command: "rm -f ${out} && $arCmd $arFlags $out $in",
66 Description: "ar $out",
67 },
68 "arCmd", "arFlags")
69
Colin Crossbfae8852015-03-26 14:44:11 -070070 prefixSymbols = pctx.StaticRule("prefixSymbols",
71 blueprint.RuleParams{
72 Command: "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
73 Description: "prefixSymbols $out",
74 },
75 "objcopyCmd", "prefix")
76
Colin Cross3f40fa42015-01-30 17:27:36 -080077 copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh")
78
79 copyGccLib = pctx.StaticRule("copyGccLib",
80 blueprint.RuleParams{
81 Depfile: "${out}.d",
82 Deps: blueprint.DepsGCC,
83 Command: "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
84 Description: "copy gcc $out",
85 },
86 "ccCmd", "cFlags", "libName")
87)
88
89type builderFlags struct {
90 globalFlags string
91 asFlags string
92 cFlags string
93 conlyFlags string
94 cppFlags string
95 ldFlags string
96 ldLibs string
97 incFlags string
98 nocrt bool
Colin Cross97ba0732015-03-23 17:50:24 -070099 toolchain Toolchain
Colin Cross3f40fa42015-01-30 17:27:36 -0800100 clang bool
101}
102
103// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
104func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles []string,
105 flags builderFlags) (objFiles []string) {
106
107 objFiles = make([]string, len(srcFiles))
108 objDir := common.ModuleObjDir(ctx)
109 if subdir != "" {
110 objDir = filepath.Join(objDir, subdir)
111 }
112
113 cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
114 cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
115 asflags := flags.globalFlags + " " + flags.asFlags
116
117 for i, srcFile := range srcFiles {
118 objFile := strings.TrimPrefix(srcFile, common.ModuleSrcDir(ctx))
119 objFile = filepath.Join(objDir, objFile)
120 objFile = pathtools.ReplaceExtension(objFile, "o")
121
122 objFiles[i] = objFile
123
124 var moduleCflags string
125 var ccCmd string
126
127 switch filepath.Ext(srcFile) {
128 case ".S", ".s":
129 ccCmd = "gcc"
130 moduleCflags = asflags
131 case ".c":
132 ccCmd = "gcc"
133 moduleCflags = cflags
134 case ".cpp", ".cc":
135 ccCmd = "g++"
136 moduleCflags = cppflags
137 default:
138 ctx.ModuleErrorf("File %s has unknown extension", srcFile)
139 continue
140 }
141
142 if flags.clang {
143 switch ccCmd {
144 case "gcc":
145 ccCmd = "clang"
146 case "g++":
147 ccCmd = "clang++"
148 default:
149 panic("unrecoginzied ccCmd")
150 }
151
152 ccCmd = "${clangPath}" + ccCmd
153 } else {
154 ccCmd = gccCmd(flags.toolchain, ccCmd)
155 }
156
157 ctx.Build(pctx, blueprint.BuildParams{
158 Rule: cc,
159 Outputs: []string{objFile},
160 Inputs: []string{srcFile},
161 Implicits: []string{ccCmd},
162 Args: map[string]string{
163 "cFlags": moduleCflags,
164 "incFlags": flags.incFlags,
165 "ccCmd": ccCmd,
166 },
167 })
168 }
169
170 return objFiles
171}
172
173// Generate a rule for compiling multiple .o files to a static library (.a)
174func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
175 flags builderFlags, outputFile string) {
176
177 arCmd := gccCmd(flags.toolchain, "ar")
178 arFlags := "crsPD"
179
180 ctx.Build(pctx, blueprint.BuildParams{
181 Rule: ar,
182 Outputs: []string{outputFile},
183 Inputs: objFiles,
184 Implicits: []string{arCmd},
185 Args: map[string]string{
186 "arFlags": arFlags,
187 "arCmd": arCmd,
188 },
189 })
190}
191
192// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
193// and shared libraires, to a shared library (.so) or dynamic executable
194func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
Colin Cross77b00fa2015-03-16 16:15:49 -0700195 objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs []string,
Colin Crossed4cf0b2015-03-26 14:43:45 -0700196 crtBegin, crtEnd string, groupLate bool, flags builderFlags, outputFile string) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800197
198 var ldCmd string
199 if flags.clang {
200 ldCmd = "${clangPath}clang++"
201 } else {
202 ldCmd = gccCmd(flags.toolchain, "g++")
203 }
204
205 var ldDirs []string
206 var libFlagsList []string
207
208 if len(wholeStaticLibs) > 0 {
209 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
210 libFlagsList = append(libFlagsList, wholeStaticLibs...)
211 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
212 }
213
214 libFlagsList = append(libFlagsList, staticLibs...)
215
216 for _, lib := range sharedLibs {
217 dir, file := filepath.Split(lib)
218 if !strings.HasPrefix(file, "lib") {
219 panic("shared library " + lib + " does not start with lib")
220 }
221 if !strings.HasSuffix(file, sharedLibraryExtension) {
222 panic("shared library " + lib + " does not end with " + sharedLibraryExtension)
223 }
224 libFlagsList = append(libFlagsList,
225 "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension))
226 ldDirs = append(ldDirs, dir)
227 }
228
Colin Crossed4cf0b2015-03-26 14:43:45 -0700229 if groupLate {
230 libFlagsList = append(libFlagsList, "-Wl,--start-group")
231 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700232 libFlagsList = append(libFlagsList, lateStaticLibs...)
Colin Crossed4cf0b2015-03-26 14:43:45 -0700233 if groupLate {
234 libFlagsList = append(libFlagsList, "-Wl,--end-group")
235 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700236
Colin Cross3f40fa42015-01-30 17:27:36 -0800237 deps := []string{ldCmd}
238 deps = append(deps, sharedLibs...)
239 deps = append(deps, staticLibs...)
Colin Cross3075ad02015-03-17 10:47:08 -0700240 deps = append(deps, lateStaticLibs...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800241 deps = append(deps, wholeStaticLibs...)
242 if crtBegin != "" {
243 deps = append(deps, crtBegin, crtEnd)
244 }
245
246 ctx.Build(pctx, blueprint.BuildParams{
247 Rule: ld,
248 Outputs: []string{outputFile},
249 Inputs: objFiles,
250 Implicits: deps,
251 Args: map[string]string{
252 "ldCmd": ldCmd,
253 "ldDirFlags": ldDirsToFlags(ldDirs),
254 "crtBegin": crtBegin,
255 "libFlags": strings.Join(libFlagsList, " "),
256 "ldFlags": flags.ldFlags,
257 "crtEnd": crtEnd,
258 "ldLibs": flags.ldLibs,
259 },
260 })
261}
262
263// Generate a rule for compiling multiple .o files to a .o using ld partial linking
264func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
265 flags builderFlags, outputFile string) {
266
267 ldCmd := gccCmd(flags.toolchain, "ld")
268
269 deps := []string{ldCmd}
270
271 ctx.Build(pctx, blueprint.BuildParams{
272 Rule: partialLd,
273 Outputs: []string{outputFile},
274 Inputs: objFiles,
275 Implicits: deps,
276 Args: map[string]string{
277 "ldCmd": ldCmd,
278 },
279 })
280}
281
Colin Crossbfae8852015-03-26 14:44:11 -0700282// Generate a rule for runing objcopy --prefix-symbols on a binary
283func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile string,
284 flags builderFlags, outputFile string) {
285
286 objcopyCmd := gccCmd(flags.toolchain, "objcopy")
287
288 ctx.Build(pctx, blueprint.BuildParams{
289 Rule: prefixSymbols,
290 Outputs: []string{outputFile},
291 Inputs: []string{inputFile},
292 Implicits: []string{objcopyCmd},
293 Args: map[string]string{
294 "objcopyCmd": objcopyCmd,
295 "prefix": prefix,
296 },
297 })
298}
299
Colin Cross3f40fa42015-01-30 17:27:36 -0800300func CopyGccLib(ctx common.AndroidModuleContext, libName string,
301 flags builderFlags, outputFile string) {
302
303 ctx.Build(pctx, blueprint.BuildParams{
304 Rule: copyGccLib,
305 Outputs: []string{outputFile},
306 Implicits: []string{
307 "$copyGccLibPath",
308 gccCmd(flags.toolchain, "gcc"),
309 },
310 Args: map[string]string{
311 "ccCmd": gccCmd(flags.toolchain, "gcc"),
312 "cFlags": flags.globalFlags,
313 "libName": libName,
314 },
315 })
316}
317
Colin Cross97ba0732015-03-23 17:50:24 -0700318func gccCmd(toolchain Toolchain, cmd string) string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800319 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
320}