blob: f67f9bd3138351bbca344cf0d39abae673d0de31 [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"
Colin Cross0af4b842015-04-30 16:36:18 -070023 "fmt"
24 "runtime"
25 "strconv"
Colin Cross3f40fa42015-01-30 17:27:36 -080026
Colin Cross3f40fa42015-01-30 17:27:36 -080027 "path/filepath"
28 "strings"
Colin Crossed4cf0b2015-03-26 14:43:45 -070029
30 "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -080031)
32
33const (
Dan Albertc3144b12015-04-28 18:17:56 -070034 objectExtension = ".o"
Colin Cross3f40fa42015-01-30 17:27:36 -080035 staticLibraryExtension = ".a"
36)
37
38var (
Dan Willemsen34cc69e2015-09-23 15:26:20 -070039 pctx = common.NewPackageContext("android/soong/cc")
Colin Cross3f40fa42015-01-30 17:27:36 -080040
41 cc = pctx.StaticRule("cc",
42 blueprint.RuleParams{
43 Depfile: "${out}.d",
44 Deps: blueprint.DepsGCC,
Dan Willemsene6540452015-10-20 15:21:33 -070045 Command: "$relPwd $ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in",
Dan Willemsenc94a7682015-11-17 15:27:28 -080046 CommandDeps: []string{"$ccCmd"},
Colin Cross3f40fa42015-01-30 17:27:36 -080047 Description: "cc $out",
48 },
Dan Willemsen322a0a62015-11-17 15:19:46 -080049 "ccCmd", "cFlags")
Colin Cross3f40fa42015-01-30 17:27:36 -080050
51 ld = pctx.StaticRule("ld",
52 blueprint.RuleParams{
Colin Cross7d21c442015-03-30 17:47:53 -070053 Command: "$ldCmd ${ldDirFlags} ${crtBegin} @${out}.rsp " +
Colin Cross28344522015-04-22 13:07:53 -070054 "${libFlags} ${crtEnd} -o ${out} ${ldFlags}",
Dan Willemsenc94a7682015-11-17 15:27:28 -080055 CommandDeps: []string{"$ldCmd"},
Colin Cross7d21c442015-03-30 17:47:53 -070056 Description: "ld $out",
57 Rspfile: "${out}.rsp",
58 RspfileContent: "${in}",
Colin Cross3f40fa42015-01-30 17:27:36 -080059 },
Colin Cross28344522015-04-22 13:07:53 -070060 "ldCmd", "ldDirFlags", "crtBegin", "libFlags", "crtEnd", "ldFlags")
Colin Cross3f40fa42015-01-30 17:27:36 -080061
62 partialLd = pctx.StaticRule("partialLd",
63 blueprint.RuleParams{
Colin Cross41280a42015-11-23 14:01:42 -080064 Command: "$ldCmd -nostdlib -Wl,-r ${in} -o ${out} ${ldFlags}",
Dan Willemsenc94a7682015-11-17 15:27:28 -080065 CommandDeps: []string{"$ldCmd"},
Colin Cross3f40fa42015-01-30 17:27:36 -080066 Description: "partialLd $out",
67 },
Colin Cross41280a42015-11-23 14:01:42 -080068 "ldCmd", "ldFlags")
Colin Cross3f40fa42015-01-30 17:27:36 -080069
70 ar = pctx.StaticRule("ar",
71 blueprint.RuleParams{
Colin Cross7d21c442015-03-30 17:47:53 -070072 Command: "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp",
Dan Willemsenc94a7682015-11-17 15:27:28 -080073 CommandDeps: []string{"$arCmd"},
Colin Cross7d21c442015-03-30 17:47:53 -070074 Description: "ar $out",
75 Rspfile: "${out}.rsp",
76 RspfileContent: "${in}",
Colin Cross3f40fa42015-01-30 17:27:36 -080077 },
78 "arCmd", "arFlags")
79
Colin Cross0af4b842015-04-30 16:36:18 -070080 darwinAr = pctx.StaticRule("darwinAr",
81 blueprint.RuleParams{
82 Command: "rm -f ${out} && $arCmd $arFlags $out $in",
Dan Willemsenc94a7682015-11-17 15:27:28 -080083 CommandDeps: []string{"$arCmd"},
Colin Cross0af4b842015-04-30 16:36:18 -070084 Description: "ar $out",
85 },
86 "arCmd", "arFlags")
87
88 darwinAppendAr = pctx.StaticRule("darwinAppendAr",
89 blueprint.RuleParams{
90 Command: "cp -f ${inAr} ${out}.tmp && $arCmd $arFlags ${out}.tmp $in && mv ${out}.tmp ${out}",
Dan Willemsenc94a7682015-11-17 15:27:28 -080091 CommandDeps: []string{"$arCmd"},
Colin Cross0af4b842015-04-30 16:36:18 -070092 Description: "ar $out",
93 },
94 "arCmd", "arFlags", "inAr")
95
Colin Crossbfae8852015-03-26 14:44:11 -070096 prefixSymbols = pctx.StaticRule("prefixSymbols",
97 blueprint.RuleParams{
98 Command: "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
Dan Willemsenc94a7682015-11-17 15:27:28 -080099 CommandDeps: []string{"$objcopyCmd"},
Colin Crossbfae8852015-03-26 14:44:11 -0700100 Description: "prefixSymbols $out",
101 },
102 "objcopyCmd", "prefix")
103
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700104 copyGccLibPath = pctx.SourcePathVariable("copyGccLibPath", "build/soong/copygcclib.sh")
Colin Cross3f40fa42015-01-30 17:27:36 -0800105
106 copyGccLib = pctx.StaticRule("copyGccLib",
107 blueprint.RuleParams{
108 Depfile: "${out}.d",
109 Deps: blueprint.DepsGCC,
110 Command: "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
Dan Willemsenc94a7682015-11-17 15:27:28 -0800111 CommandDeps: []string{"$copyGccLibPath", "$ccCmd"},
Colin Cross3f40fa42015-01-30 17:27:36 -0800112 Description: "copy gcc $out",
113 },
114 "ccCmd", "cFlags", "libName")
115)
116
Dan Willemsen322a0a62015-11-17 15:19:46 -0800117func init() {
118 // We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
119 // debug output. That way two builds in two different directories will
120 // create the same output.
121 if runtime.GOOS != "darwin" {
122 pctx.StaticVariable("relPwd", "PWD=/proc/self/cwd")
123 } else {
124 // Darwin doesn't have /proc
125 pctx.StaticVariable("relPwd", "")
126 }
127}
128
Colin Cross3f40fa42015-01-30 17:27:36 -0800129type builderFlags struct {
130 globalFlags string
131 asFlags string
132 cFlags string
133 conlyFlags string
134 cppFlags string
135 ldFlags string
Colin Cross16b23492016-01-06 14:41:07 -0800136 libFlags string
Colin Cross581c1892015-04-07 16:50:10 -0700137 yaccFlags string
Colin Cross3f40fa42015-01-30 17:27:36 -0800138 nocrt bool
Colin Cross97ba0732015-03-23 17:50:24 -0700139 toolchain Toolchain
Colin Cross3f40fa42015-01-30 17:27:36 -0800140 clang bool
141}
142
143// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700144func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles common.Paths,
145 flags builderFlags, deps common.Paths) (objFiles common.Paths) {
Colin Cross581c1892015-04-07 16:50:10 -0700146
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700147 objFiles = make(common.Paths, len(srcFiles))
Colin Cross3f40fa42015-01-30 17:27:36 -0800148
149 cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
150 cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
151 asflags := flags.globalFlags + " " + flags.asFlags
152
Dan Willemsenbe03f342016-03-03 17:21:04 -0800153 if flags.clang {
154 cflags += " ${noOverrideClangGlobalCflags}"
155 cppflags += " ${noOverrideClangGlobalCflags}"
156 } else {
157 cflags += " ${noOverrideGlobalCflags}"
158 cppflags += " ${noOverrideGlobalCflags}"
159 }
160
Colin Cross3f40fa42015-01-30 17:27:36 -0800161 for i, srcFile := range srcFiles {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700162 objFile := common.ObjPathWithExt(ctx, srcFile, subdir, "o")
Colin Cross3f40fa42015-01-30 17:27:36 -0800163
164 objFiles[i] = objFile
165
166 var moduleCflags string
167 var ccCmd string
168
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700169 switch srcFile.Ext() {
Colin Cross3f40fa42015-01-30 17:27:36 -0800170 case ".S", ".s":
171 ccCmd = "gcc"
172 moduleCflags = asflags
173 case ".c":
174 ccCmd = "gcc"
175 moduleCflags = cflags
176 case ".cpp", ".cc":
177 ccCmd = "g++"
178 moduleCflags = cppflags
179 default:
180 ctx.ModuleErrorf("File %s has unknown extension", srcFile)
181 continue
182 }
183
184 if flags.clang {
185 switch ccCmd {
186 case "gcc":
187 ccCmd = "clang"
188 case "g++":
189 ccCmd = "clang++"
190 default:
191 panic("unrecoginzied ccCmd")
192 }
193
Colin Cross16b23492016-01-06 14:41:07 -0800194 ccCmd = "${clangBin}/" + ccCmd
Colin Cross3f40fa42015-01-30 17:27:36 -0800195 } else {
196 ccCmd = gccCmd(flags.toolchain, ccCmd)
197 }
198
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700199 ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Colin Cross3f40fa42015-01-30 17:27:36 -0800200 Rule: cc,
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700201 Output: objFile,
202 Input: srcFile,
Dan Willemsenb40aab62016-04-20 14:21:14 -0700203 OrderOnly: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800204 Args: map[string]string{
Colin Cross28344522015-04-22 13:07:53 -0700205 "cFlags": moduleCflags,
206 "ccCmd": ccCmd,
Colin Cross3f40fa42015-01-30 17:27:36 -0800207 },
208 })
209 }
210
211 return objFiles
212}
213
214// Generate a rule for compiling multiple .o files to a static library (.a)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700215func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles common.Paths,
216 flags builderFlags, outputFile common.ModuleOutPath) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800217
218 arCmd := gccCmd(flags.toolchain, "ar")
219 arFlags := "crsPD"
220
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700221 ctx.ModuleBuild(pctx, common.ModuleBuildParams{
222 Rule: ar,
223 Output: outputFile,
224 Inputs: objFiles,
Colin Cross3f40fa42015-01-30 17:27:36 -0800225 Args: map[string]string{
226 "arFlags": arFlags,
227 "arCmd": arCmd,
228 },
229 })
230}
231
Colin Cross0af4b842015-04-30 16:36:18 -0700232// Generate a rule for compiling multiple .o files to a static library (.a) on
233// darwin. The darwin ar tool doesn't support @file for list files, and has a
234// very small command line length limit, so we have to split the ar into multiple
235// steps, each appending to the previous one.
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700236func TransformDarwinObjToStaticLib(ctx common.AndroidModuleContext, objFiles common.Paths,
237 flags builderFlags, outputPath common.ModuleOutPath) {
Colin Cross0af4b842015-04-30 16:36:18 -0700238
Dan Willemsencf7c71b2015-12-14 20:02:44 -0800239 arCmd := "${macArPath}"
Colin Cross0af4b842015-04-30 16:36:18 -0700240 arFlags := "cqs"
241
242 // ARG_MAX on darwin is 262144, use half that to be safe
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700243 objFilesLists, err := splitListForSize(objFiles.Strings(), 131072)
Colin Cross0af4b842015-04-30 16:36:18 -0700244 if err != nil {
245 ctx.ModuleErrorf("%s", err.Error())
246 }
247
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700248 outputFile := outputPath.String()
249
Colin Cross0af4b842015-04-30 16:36:18 -0700250 var in, out string
251 for i, l := range objFilesLists {
252 in = out
253 out = outputFile
254 if i != len(objFilesLists)-1 {
255 out += "." + strconv.Itoa(i)
256 }
257
258 if in == "" {
259 ctx.Build(pctx, blueprint.BuildParams{
260 Rule: darwinAr,
261 Outputs: []string{out},
262 Inputs: l,
263 Args: map[string]string{
264 "arFlags": arFlags,
265 "arCmd": arCmd,
266 },
267 })
268 } else {
269 ctx.Build(pctx, blueprint.BuildParams{
270 Rule: darwinAppendAr,
271 Outputs: []string{out},
272 Inputs: l,
273 Implicits: []string{in},
274 Args: map[string]string{
275 "arFlags": arFlags,
276 "arCmd": arCmd,
277 "inAr": in,
278 },
279 })
280 }
281 }
282}
283
Colin Cross3f40fa42015-01-30 17:27:36 -0800284// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
285// and shared libraires, to a shared library (.so) or dynamic executable
286func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700287 objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps common.Paths,
288 crtBegin, crtEnd common.OptionalPath, groupLate bool, flags builderFlags, outputFile common.WritablePath) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800289
290 var ldCmd string
291 if flags.clang {
Colin Cross16b23492016-01-06 14:41:07 -0800292 ldCmd = "${clangBin}/clang++"
Colin Cross3f40fa42015-01-30 17:27:36 -0800293 } else {
294 ldCmd = gccCmd(flags.toolchain, "g++")
295 }
296
297 var ldDirs []string
298 var libFlagsList []string
299
Colin Cross16b23492016-01-06 14:41:07 -0800300 if len(flags.libFlags) > 0 {
301 libFlagsList = append(libFlagsList, flags.libFlags)
302 }
303
Colin Cross3f40fa42015-01-30 17:27:36 -0800304 if len(wholeStaticLibs) > 0 {
Dan Willemsen490fd492015-11-24 17:53:15 -0800305 if ctx.Host() && ctx.Darwin() {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700306 libFlagsList = append(libFlagsList, common.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
Colin Cross0af4b842015-04-30 16:36:18 -0700307 } else {
308 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700309 libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...)
Colin Cross0af4b842015-04-30 16:36:18 -0700310 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
311 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800312 }
313
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700314 libFlagsList = append(libFlagsList, staticLibs.Strings()...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800315
Dan Willemsenedc385f2015-07-08 13:02:23 -0700316 if groupLate && len(lateStaticLibs) > 0 {
317 libFlagsList = append(libFlagsList, "-Wl,--start-group")
318 }
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700319 libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...)
Dan Willemsenedc385f2015-07-08 13:02:23 -0700320 if groupLate && len(lateStaticLibs) > 0 {
321 libFlagsList = append(libFlagsList, "-Wl,--end-group")
322 }
323
Colin Cross3f40fa42015-01-30 17:27:36 -0800324 for _, lib := range sharedLibs {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700325 dir, file := filepath.Split(lib.String())
Colin Cross3f40fa42015-01-30 17:27:36 -0800326 if !strings.HasPrefix(file, "lib") {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700327 panic("shared library " + lib.String() + " does not start with lib")
Colin Cross3f40fa42015-01-30 17:27:36 -0800328 }
Dan Willemsen490fd492015-11-24 17:53:15 -0800329 if !strings.HasSuffix(file, flags.toolchain.ShlibSuffix()) {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700330 panic("shared library " + lib.String() + " does not end with " + flags.toolchain.ShlibSuffix())
Colin Cross3f40fa42015-01-30 17:27:36 -0800331 }
332 libFlagsList = append(libFlagsList,
Dan Willemsen490fd492015-11-24 17:53:15 -0800333 "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), flags.toolchain.ShlibSuffix()))
Colin Cross3f40fa42015-01-30 17:27:36 -0800334 ldDirs = append(ldDirs, dir)
335 }
336
Colin Cross3f40fa42015-01-30 17:27:36 -0800337 deps = append(deps, sharedLibs...)
338 deps = append(deps, staticLibs...)
Colin Cross3075ad02015-03-17 10:47:08 -0700339 deps = append(deps, lateStaticLibs...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800340 deps = append(deps, wholeStaticLibs...)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700341 if crtBegin.Valid() {
342 deps = append(deps, crtBegin.Path(), crtEnd.Path())
Colin Cross3f40fa42015-01-30 17:27:36 -0800343 }
344
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700345 ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Colin Cross3f40fa42015-01-30 17:27:36 -0800346 Rule: ld,
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700347 Output: outputFile,
Colin Cross3f40fa42015-01-30 17:27:36 -0800348 Inputs: objFiles,
349 Implicits: deps,
350 Args: map[string]string{
351 "ldCmd": ldCmd,
352 "ldDirFlags": ldDirsToFlags(ldDirs),
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700353 "crtBegin": crtBegin.String(),
Colin Cross3f40fa42015-01-30 17:27:36 -0800354 "libFlags": strings.Join(libFlagsList, " "),
355 "ldFlags": flags.ldFlags,
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700356 "crtEnd": crtEnd.String(),
Colin Cross3f40fa42015-01-30 17:27:36 -0800357 },
358 })
359}
360
361// Generate a rule for compiling multiple .o files to a .o using ld partial linking
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700362func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles common.Paths,
363 flags builderFlags, outputFile common.WritablePath) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800364
Colin Cross41280a42015-11-23 14:01:42 -0800365 var ldCmd string
366 if flags.clang {
Colin Cross16b23492016-01-06 14:41:07 -0800367 ldCmd = "${clangBin}clang++"
Colin Cross41280a42015-11-23 14:01:42 -0800368 } else {
369 ldCmd = gccCmd(flags.toolchain, "g++")
370 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800371
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700372 ctx.ModuleBuild(pctx, common.ModuleBuildParams{
373 Rule: partialLd,
374 Output: outputFile,
375 Inputs: objFiles,
Colin Cross3f40fa42015-01-30 17:27:36 -0800376 Args: map[string]string{
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700377 "ldCmd": ldCmd,
Colin Cross41280a42015-11-23 14:01:42 -0800378 "ldFlags": flags.ldFlags,
Colin Cross3f40fa42015-01-30 17:27:36 -0800379 },
380 })
381}
382
Colin Crossbfae8852015-03-26 14:44:11 -0700383// Generate a rule for runing objcopy --prefix-symbols on a binary
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700384func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile common.Path,
385 flags builderFlags, outputFile common.WritablePath) {
Colin Crossbfae8852015-03-26 14:44:11 -0700386
387 objcopyCmd := gccCmd(flags.toolchain, "objcopy")
388
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700389 ctx.ModuleBuild(pctx, common.ModuleBuildParams{
390 Rule: prefixSymbols,
391 Output: outputFile,
392 Input: inputFile,
Colin Crossbfae8852015-03-26 14:44:11 -0700393 Args: map[string]string{
394 "objcopyCmd": objcopyCmd,
395 "prefix": prefix,
396 },
397 })
398}
399
Colin Cross3f40fa42015-01-30 17:27:36 -0800400func CopyGccLib(ctx common.AndroidModuleContext, libName string,
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700401 flags builderFlags, outputFile common.WritablePath) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800402
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700403 ctx.ModuleBuild(pctx, common.ModuleBuildParams{
404 Rule: copyGccLib,
405 Output: outputFile,
Colin Cross3f40fa42015-01-30 17:27:36 -0800406 Args: map[string]string{
407 "ccCmd": gccCmd(flags.toolchain, "gcc"),
408 "cFlags": flags.globalFlags,
409 "libName": libName,
410 },
411 })
412}
413
Colin Cross97ba0732015-03-23 17:50:24 -0700414func gccCmd(toolchain Toolchain, cmd string) string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800415 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
416}
Colin Cross0af4b842015-04-30 16:36:18 -0700417
418func splitListForSize(list []string, limit int) (lists [][]string, err error) {
419 var i int
420
421 start := 0
422 bytes := 0
423 for i = range list {
424 l := len(list[i])
425 if l > limit {
426 return nil, fmt.Errorf("list element greater than size limit (%d)", limit)
427 }
428 if bytes+l > limit {
429 lists = append(lists, list[start:i])
430 start = i
431 bytes = 0
432 }
433 bytes += l + 1 // count a space between each list element
434 }
435
436 lists = append(lists, list[start:])
437
438 totalLen := 0
439 for _, l := range lists {
440 totalLen += len(l)
441 }
442 if totalLen != len(list) {
443 panic(fmt.Errorf("Failed breaking up list, %d != %d", len(list), totalLen))
444 }
445 return lists, nil
446}