blob: 4c86110a4f8e51c17d76ddd13d44557d43ec27d2 [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
70 copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh")
71
72 copyGccLib = pctx.StaticRule("copyGccLib",
73 blueprint.RuleParams{
74 Depfile: "${out}.d",
75 Deps: blueprint.DepsGCC,
76 Command: "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
77 Description: "copy gcc $out",
78 },
79 "ccCmd", "cFlags", "libName")
80)
81
82type builderFlags struct {
83 globalFlags string
84 asFlags string
85 cFlags string
86 conlyFlags string
87 cppFlags string
88 ldFlags string
89 ldLibs string
90 incFlags string
91 nocrt bool
Colin Cross97ba0732015-03-23 17:50:24 -070092 toolchain Toolchain
Colin Cross3f40fa42015-01-30 17:27:36 -080093 clang bool
94}
95
96// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
97func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles []string,
98 flags builderFlags) (objFiles []string) {
99
100 objFiles = make([]string, len(srcFiles))
101 objDir := common.ModuleObjDir(ctx)
102 if subdir != "" {
103 objDir = filepath.Join(objDir, subdir)
104 }
105
106 cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
107 cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
108 asflags := flags.globalFlags + " " + flags.asFlags
109
110 for i, srcFile := range srcFiles {
111 objFile := strings.TrimPrefix(srcFile, common.ModuleSrcDir(ctx))
112 objFile = filepath.Join(objDir, objFile)
113 objFile = pathtools.ReplaceExtension(objFile, "o")
114
115 objFiles[i] = objFile
116
117 var moduleCflags string
118 var ccCmd string
119
120 switch filepath.Ext(srcFile) {
121 case ".S", ".s":
122 ccCmd = "gcc"
123 moduleCflags = asflags
124 case ".c":
125 ccCmd = "gcc"
126 moduleCflags = cflags
127 case ".cpp", ".cc":
128 ccCmd = "g++"
129 moduleCflags = cppflags
130 default:
131 ctx.ModuleErrorf("File %s has unknown extension", srcFile)
132 continue
133 }
134
135 if flags.clang {
136 switch ccCmd {
137 case "gcc":
138 ccCmd = "clang"
139 case "g++":
140 ccCmd = "clang++"
141 default:
142 panic("unrecoginzied ccCmd")
143 }
144
145 ccCmd = "${clangPath}" + ccCmd
146 } else {
147 ccCmd = gccCmd(flags.toolchain, ccCmd)
148 }
149
150 ctx.Build(pctx, blueprint.BuildParams{
151 Rule: cc,
152 Outputs: []string{objFile},
153 Inputs: []string{srcFile},
154 Implicits: []string{ccCmd},
155 Args: map[string]string{
156 "cFlags": moduleCflags,
157 "incFlags": flags.incFlags,
158 "ccCmd": ccCmd,
159 },
160 })
161 }
162
163 return objFiles
164}
165
166// Generate a rule for compiling multiple .o files to a static library (.a)
167func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
168 flags builderFlags, outputFile string) {
169
170 arCmd := gccCmd(flags.toolchain, "ar")
171 arFlags := "crsPD"
172
173 ctx.Build(pctx, blueprint.BuildParams{
174 Rule: ar,
175 Outputs: []string{outputFile},
176 Inputs: objFiles,
177 Implicits: []string{arCmd},
178 Args: map[string]string{
179 "arFlags": arFlags,
180 "arCmd": arCmd,
181 },
182 })
183}
184
185// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
186// and shared libraires, to a shared library (.so) or dynamic executable
187func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
Colin Cross77b00fa2015-03-16 16:15:49 -0700188 objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs []string,
Colin Crossed4cf0b2015-03-26 14:43:45 -0700189 crtBegin, crtEnd string, groupLate bool, flags builderFlags, outputFile string) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800190
191 var ldCmd string
192 if flags.clang {
193 ldCmd = "${clangPath}clang++"
194 } else {
195 ldCmd = gccCmd(flags.toolchain, "g++")
196 }
197
198 var ldDirs []string
199 var libFlagsList []string
200
201 if len(wholeStaticLibs) > 0 {
202 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
203 libFlagsList = append(libFlagsList, wholeStaticLibs...)
204 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
205 }
206
207 libFlagsList = append(libFlagsList, staticLibs...)
208
209 for _, lib := range sharedLibs {
210 dir, file := filepath.Split(lib)
211 if !strings.HasPrefix(file, "lib") {
212 panic("shared library " + lib + " does not start with lib")
213 }
214 if !strings.HasSuffix(file, sharedLibraryExtension) {
215 panic("shared library " + lib + " does not end with " + sharedLibraryExtension)
216 }
217 libFlagsList = append(libFlagsList,
218 "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension))
219 ldDirs = append(ldDirs, dir)
220 }
221
Colin Crossed4cf0b2015-03-26 14:43:45 -0700222 if groupLate {
223 libFlagsList = append(libFlagsList, "-Wl,--start-group")
224 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700225 libFlagsList = append(libFlagsList, lateStaticLibs...)
Colin Crossed4cf0b2015-03-26 14:43:45 -0700226 if groupLate {
227 libFlagsList = append(libFlagsList, "-Wl,--end-group")
228 }
Colin Cross77b00fa2015-03-16 16:15:49 -0700229
Colin Cross3f40fa42015-01-30 17:27:36 -0800230 deps := []string{ldCmd}
231 deps = append(deps, sharedLibs...)
232 deps = append(deps, staticLibs...)
Colin Cross3075ad02015-03-17 10:47:08 -0700233 deps = append(deps, lateStaticLibs...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800234 deps = append(deps, wholeStaticLibs...)
235 if crtBegin != "" {
236 deps = append(deps, crtBegin, crtEnd)
237 }
238
239 ctx.Build(pctx, blueprint.BuildParams{
240 Rule: ld,
241 Outputs: []string{outputFile},
242 Inputs: objFiles,
243 Implicits: deps,
244 Args: map[string]string{
245 "ldCmd": ldCmd,
246 "ldDirFlags": ldDirsToFlags(ldDirs),
247 "crtBegin": crtBegin,
248 "libFlags": strings.Join(libFlagsList, " "),
249 "ldFlags": flags.ldFlags,
250 "crtEnd": crtEnd,
251 "ldLibs": flags.ldLibs,
252 },
253 })
254}
255
256// Generate a rule for compiling multiple .o files to a .o using ld partial linking
257func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
258 flags builderFlags, outputFile string) {
259
260 ldCmd := gccCmd(flags.toolchain, "ld")
261
262 deps := []string{ldCmd}
263
264 ctx.Build(pctx, blueprint.BuildParams{
265 Rule: partialLd,
266 Outputs: []string{outputFile},
267 Inputs: objFiles,
268 Implicits: deps,
269 Args: map[string]string{
270 "ldCmd": ldCmd,
271 },
272 })
273}
274
275func CopyGccLib(ctx common.AndroidModuleContext, libName string,
276 flags builderFlags, outputFile string) {
277
278 ctx.Build(pctx, blueprint.BuildParams{
279 Rule: copyGccLib,
280 Outputs: []string{outputFile},
281 Implicits: []string{
282 "$copyGccLibPath",
283 gccCmd(flags.toolchain, "gcc"),
284 },
285 Args: map[string]string{
286 "ccCmd": gccCmd(flags.toolchain, "gcc"),
287 "cFlags": flags.globalFlags,
288 "libName": libName,
289 },
290 })
291}
292
Colin Cross97ba0732015-03-23 17:50:24 -0700293func gccCmd(toolchain Toolchain, cmd string) string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800294 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
295}