blob: f46a67075b68ab42a68eb12aebb8f496536b76df [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
24 "blueprint"
25 "blueprint/pathtools"
26 "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
91 toolchain toolchain
92 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
286func gccCmd(toolchain toolchain, cmd string) string {
287 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
288}