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