blob: f7d9081dbef4ef51d6acfdf4430660c702efdea5 [file] [log] [blame]
Colin Crossd00350c2017-11-17 10:55:38 -08001// Copyright 2017 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
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080015package cc
16
17import (
18 "fmt"
19
20 "android/soong/android"
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080021 "os"
22 "path"
23 "path/filepath"
24 "strings"
25)
26
27// This singleton generates CMakeLists.txt files. It does so for each blueprint Android.bp resulting in a cc.Module
28// when either make, mm, mma, mmm or mmma is called. CMakeLists.txt files are generated in a separate folder
29// structure (see variable CLionOutputProjectsDirectory for root).
30
31func init() {
32 android.RegisterSingletonType("cmakelists_generator", cMakeListsGeneratorSingleton)
33}
34
Colin Cross0875c522017-11-28 17:34:01 -080035func cMakeListsGeneratorSingleton() android.Singleton {
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080036 return &cmakelistsGeneratorSingleton{}
37}
38
39type cmakelistsGeneratorSingleton struct{}
40
41const (
42 cMakeListsFilename = "CMakeLists.txt"
43 cLionAggregateProjectsDirectory = "development" + string(os.PathSeparator) + "ide" + string(os.PathSeparator) + "clion"
44 cLionOutputProjectsDirectory = "out" + string(os.PathSeparator) + cLionAggregateProjectsDirectory
45 minimumCMakeVersionSupported = "3.5"
46
47 // Environment variables used to modify behavior of this singleton.
48 envVariableGenerateCMakeLists = "SOONG_GEN_CMAKEFILES"
49 envVariableGenerateDebugInfo = "SOONG_GEN_CMAKEFILES_DEBUG"
50 envVariableTrue = "1"
51)
52
53// Instruct generator to trace how header include path and flags were generated.
54// This is done to ease investigating bug reports.
55var outputDebugInfo = false
56
Colin Cross0875c522017-11-28 17:34:01 -080057func (c *cmakelistsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080058 if getEnvVariable(envVariableGenerateCMakeLists, ctx) != envVariableTrue {
59 return
60 }
61
62 outputDebugInfo = (getEnvVariable(envVariableGenerateDebugInfo, ctx) == envVariableTrue)
63
Colin Crossdfe47522018-06-07 14:16:27 -070064 // Track which projects have already had CMakeLists.txt generated to keep the first
65 // variant for each project.
66 seenProjects := map[string]bool{}
67
Colin Cross0875c522017-11-28 17:34:01 -080068 ctx.VisitAllModules(func(module android.Module) {
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080069 if ccModule, ok := module.(*Module); ok {
70 if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
Colin Crossdfe47522018-06-07 14:16:27 -070071 generateCLionProject(compiledModule, ctx, ccModule, seenProjects)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080072 }
73 }
74 })
75
76 // Link all handmade CMakeLists.txt aggregate from
77 // BASE/development/ide/clion to
78 // BASE/out/development/ide/clion.
Colin Cross988414c2020-01-11 01:11:46 +000079 dir := filepath.Join(android.AbsSrcDirForExistingUseCases(), cLionAggregateProjectsDirectory)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080080 filepath.Walk(dir, linkAggregateCMakeListsFiles)
81
82 return
83}
84
Colin Cross0875c522017-11-28 17:34:01 -080085func getEnvVariable(name string, ctx android.SingletonContext) string {
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080086 // Using android.Config.Getenv instead of os.getEnv to guarantee soong will
87 // re-run in case this environment variable changes.
Colin Crossaabf6792017-11-29 00:27:14 -080088 return ctx.Config().Getenv(name)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -080089}
90
91func exists(path string) bool {
92 _, err := os.Stat(path)
93 if err == nil {
94 return true
95 }
96 if os.IsNotExist(err) {
97 return false
98 }
99 return true
100}
101
102func linkAggregateCMakeListsFiles(path string, info os.FileInfo, err error) error {
103
104 if info == nil {
105 return nil
106 }
107
108 dst := strings.Replace(path, cLionAggregateProjectsDirectory, cLionOutputProjectsDirectory, 1)
109 if info.IsDir() {
110 // This is a directory to create
111 os.MkdirAll(dst, os.ModePerm)
112 } else {
113 // This is a file to link
114 os.Remove(dst)
115 os.Symlink(path, dst)
116 }
117 return nil
118}
119
Colin Crossdfe47522018-06-07 14:16:27 -0700120func generateCLionProject(compiledModule CompiledInterface, ctx android.SingletonContext, ccModule *Module,
121 seenProjects map[string]bool) {
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800122 srcs := compiledModule.Srcs()
123 if len(srcs) == 0 {
124 return
125 }
126
Colin Crossdfe47522018-06-07 14:16:27 -0700127 // Only write CMakeLists.txt for the first variant of each architecture of each module
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800128 clionproject_location := getCMakeListsForModule(ccModule, ctx)
Colin Crossdfe47522018-06-07 14:16:27 -0700129 if seenProjects[clionproject_location] {
130 return
131 }
132
133 seenProjects[clionproject_location] = true
134
135 // Ensure the directory hosting the cmakelists.txt exists
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800136 projectDir := path.Dir(clionproject_location)
137 os.MkdirAll(projectDir, os.ModePerm)
138
139 // Create cmakelists.txt
140 f, _ := os.Create(filepath.Join(projectDir, cMakeListsFilename))
141 defer f.Close()
142
143 // Header.
144 f.WriteString("# THIS FILE WAS AUTOMATICALY GENERATED!\n")
145 f.WriteString("# ANY MODIFICATION WILL BE OVERWRITTEN!\n\n")
146 f.WriteString("# To improve project view in Clion :\n")
147 f.WriteString("# Tools > CMake > Change Project Root \n\n")
148 f.WriteString(fmt.Sprintf("cmake_minimum_required(VERSION %s)\n", minimumCMakeVersionSupported))
149 f.WriteString(fmt.Sprintf("project(%s)\n", ccModule.ModuleBase.Name()))
Colin Cross988414c2020-01-11 01:11:46 +0000150 f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", android.AbsSrcDirForExistingUseCases()))
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800151
Dan Willemsen8536d6b2018-10-07 20:54:34 -0700152 pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
153 f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang"))
154 f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang++"))
155
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800156 // Add all sources to the project.
157 f.WriteString("list(APPEND\n")
158 f.WriteString(" SOURCE_FILES\n")
159 for _, src := range srcs {
160 f.WriteString(fmt.Sprintf(" ${ANDROID_ROOT}/%s\n", src.String()))
161 }
162 f.WriteString(")\n")
163
164 // Add all header search path and compiler parameters (-D, -W, -f, -XXXX)
Colin Cross4af21ed2019-11-04 09:37:55 -0800165 f.WriteString("\n# GLOBAL ALL FLAGS:\n")
166 globalAllParameters := parseCompilerParameters(ccModule.flags.Global.CommonFlags, ctx, f)
167 translateToCMake(globalAllParameters, f, true, true)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800168
Colin Cross4af21ed2019-11-04 09:37:55 -0800169 f.WriteString("\n# LOCAL ALL FLAGS:\n")
170 localAllParameters := parseCompilerParameters(ccModule.flags.Local.CommonFlags, ctx, f)
171 translateToCMake(localAllParameters, f, true, true)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800172
Colin Cross4af21ed2019-11-04 09:37:55 -0800173 f.WriteString("\n# GLOBAL CFLAGS:\n")
174 globalCParameters := parseCompilerParameters(ccModule.flags.Global.CFlags, ctx, f)
175 translateToCMake(globalCParameters, f, true, true)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800176
Colin Cross4af21ed2019-11-04 09:37:55 -0800177 f.WriteString("\n# LOCAL CFLAGS:\n")
178 localCParameters := parseCompilerParameters(ccModule.flags.Local.CFlags, ctx, f)
179 translateToCMake(localCParameters, f, true, true)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800180
Colin Cross4af21ed2019-11-04 09:37:55 -0800181 f.WriteString("\n# GLOBAL C ONLY FLAGS:\n")
182 globalConlyParameters := parseCompilerParameters(ccModule.flags.Global.ConlyFlags, ctx, f)
183 translateToCMake(globalConlyParameters, f, true, false)
184
185 f.WriteString("\n# LOCAL C ONLY FLAGS:\n")
186 localConlyParameters := parseCompilerParameters(ccModule.flags.Local.ConlyFlags, ctx, f)
187 translateToCMake(localConlyParameters, f, true, false)
188
189 f.WriteString("\n# GLOBAL CPP FLAGS:\n")
190 globalCppParameters := parseCompilerParameters(ccModule.flags.Global.CppFlags, ctx, f)
191 translateToCMake(globalCppParameters, f, false, true)
192
193 f.WriteString("\n# LOCAL CPP FLAGS:\n")
194 localCppParameters := parseCompilerParameters(ccModule.flags.Local.CppFlags, ctx, f)
195 translateToCMake(localCppParameters, f, false, true)
196
197 f.WriteString("\n# GLOBAL SYSTEM INCLUDE FLAGS:\n")
198 globalIncludeParameters := parseCompilerParameters(ccModule.flags.SystemIncludeFlags, ctx, f)
199 translateToCMake(globalIncludeParameters, f, true, true)
Colin Crossc3199482017-03-30 15:03:04 -0700200
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800201 // Add project executable.
Fabien Sanglard7da49262017-03-23 17:49:09 -0700202 f.WriteString(fmt.Sprintf("\nadd_executable(%s ${SOURCE_FILES})\n",
203 cleanExecutableName(ccModule.ModuleBase.Name())))
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800204}
205
Fabien Sanglard7da49262017-03-23 17:49:09 -0700206func cleanExecutableName(s string) string {
207 return strings.Replace(s, "@", "-", -1)
208}
209
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800210func translateToCMake(c compilerParameters, f *os.File, cflags bool, cppflags bool) {
Fabien Sanglardd9233f12017-03-24 12:02:50 -0700211 writeAllIncludeDirectories(c.systemHeaderSearchPath, f, true)
212 writeAllIncludeDirectories(c.headerSearchPath, f, false)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800213 if cflags {
Jack He4a10b652018-08-14 17:27:15 -0700214 writeAllRelativeFilePathFlags(c.relativeFilePathFlags, f, "CMAKE_C_FLAGS")
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800215 writeAllFlags(c.flags, f, "CMAKE_C_FLAGS")
216 }
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800217 if cppflags {
Jack He4a10b652018-08-14 17:27:15 -0700218 writeAllRelativeFilePathFlags(c.relativeFilePathFlags, f, "CMAKE_CXX_FLAGS")
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800219 writeAllFlags(c.flags, f, "CMAKE_CXX_FLAGS")
220 }
221 if c.sysroot != "" {
222 f.WriteString(fmt.Sprintf("include_directories(SYSTEM \"%s\")\n", buildCMakePath(path.Join(c.sysroot, "usr", "include"))))
223 }
224
225}
226
227func buildCMakePath(p string) string {
228 if path.IsAbs(p) {
229 return p
230 }
231 return fmt.Sprintf("${ANDROID_ROOT}/%s", p)
232}
233
Fabien Sanglardd9233f12017-03-24 12:02:50 -0700234func writeAllIncludeDirectories(includes []string, f *os.File, isSystem bool) {
Fabien Sanglard67472412017-03-21 10:19:19 -0700235 if len(includes) == 0 {
236 return
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800237 }
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800238
Fabien Sanglardd9233f12017-03-24 12:02:50 -0700239 system := ""
Colin Cross51d4ab22017-05-09 13:44:49 -0700240 if isSystem {
Fabien Sanglardd9233f12017-03-24 12:02:50 -0700241 system = "SYSTEM"
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800242 }
Fabien Sanglardd9233f12017-03-24 12:02:50 -0700243
244 f.WriteString(fmt.Sprintf("include_directories(%s \n", system))
245
Fabien Sanglard67472412017-03-21 10:19:19 -0700246 for _, include := range includes {
Fabien Sanglardd9233f12017-03-24 12:02:50 -0700247 f.WriteString(fmt.Sprintf(" \"%s\"\n", buildCMakePath(include)))
248 }
249 f.WriteString(")\n\n")
250
251 // Also add all headers to source files.
Colin Cross51d4ab22017-05-09 13:44:49 -0700252 f.WriteString("file (GLOB_RECURSE TMP_HEADERS\n")
Fabien Sanglardd9233f12017-03-24 12:02:50 -0700253 for _, include := range includes {
254 f.WriteString(fmt.Sprintf(" \"%s/**/*.h\"\n", buildCMakePath(include)))
Fabien Sanglard67472412017-03-21 10:19:19 -0700255 }
256 f.WriteString(")\n")
Colin Cross51d4ab22017-05-09 13:44:49 -0700257 f.WriteString("list (APPEND SOURCE_FILES ${TMP_HEADERS})\n\n")
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800258}
259
Jack He4a10b652018-08-14 17:27:15 -0700260type relativeFilePathFlagType struct {
261 flag string
262 relativeFilePath string
263}
264
265func writeAllRelativeFilePathFlags(relativeFilePathFlags []relativeFilePathFlagType, f *os.File, tag string) {
266 for _, flag := range relativeFilePathFlags {
267 f.WriteString(fmt.Sprintf("set(%s \"${%s} %s=%s\")\n", tag, tag, flag.flag, buildCMakePath(flag.relativeFilePath)))
268 }
269}
270
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800271func writeAllFlags(flags []string, f *os.File, tag string) {
272 for _, flag := range flags {
273 f.WriteString(fmt.Sprintf("set(%s \"${%s} %s\")\n", tag, tag, flag))
274 }
275}
276
277type parameterType int
278
279const (
280 headerSearchPath parameterType = iota
281 variable
282 systemHeaderSearchPath
283 flag
284 systemRoot
Jack He4a10b652018-08-14 17:27:15 -0700285 relativeFilePathFlag
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800286)
287
288type compilerParameters struct {
Fabien Sanglard67472412017-03-21 10:19:19 -0700289 headerSearchPath []string
290 systemHeaderSearchPath []string
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800291 flags []string
292 sysroot string
Jack He4a10b652018-08-14 17:27:15 -0700293 // Must be in a=b/c/d format and can be split into "a" and "b/c/d"
294 relativeFilePathFlags []relativeFilePathFlagType
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800295}
296
297func makeCompilerParameters() compilerParameters {
298 return compilerParameters{
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800299 sysroot: "",
300 }
301}
302
303func categorizeParameter(parameter string) parameterType {
304 if strings.HasPrefix(parameter, "-I") {
305 return headerSearchPath
306 }
307 if strings.HasPrefix(parameter, "$") {
308 return variable
309 }
310 if strings.HasPrefix(parameter, "-isystem") {
311 return systemHeaderSearchPath
312 }
313 if strings.HasPrefix(parameter, "-isysroot") {
314 return systemRoot
315 }
316 if strings.HasPrefix(parameter, "--sysroot") {
317 return systemRoot
318 }
Jack He4a10b652018-08-14 17:27:15 -0700319 if strings.HasPrefix(parameter, "-fsanitize-blacklist") {
320 return relativeFilePathFlag
321 }
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800322 return flag
323}
324
Fabien Sanglard33ca8082019-11-05 16:18:47 -0800325// Flattens a list of strings potentially containing space characters into a list of string containing no
326// spaces.
327func normalizeParameters(params []string) []string {
328 var flatParams []string
329 for _, s := range params {
330 s = strings.Trim(s, " ")
331 if len(s) == 0 {
332 continue
333 }
334 flatParams = append(flatParams, strings.Split(s, " ")...)
335 }
336 return flatParams
337}
338
Colin Cross0875c522017-11-28 17:34:01 -0800339func parseCompilerParameters(params []string, ctx android.SingletonContext, f *os.File) compilerParameters {
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800340 var compilerParameters = makeCompilerParameters()
341
342 for i, str := range params {
343 f.WriteString(fmt.Sprintf("# Raw param [%d] = '%s'\n", i, str))
344 }
345
Fabien Sanglard33ca8082019-11-05 16:18:47 -0800346 // Soong does not guarantee that each flag will be in an individual string. e.g: The
347 // input received could be:
348 // params = {"-isystem", "path/to/system"}
349 // or it could be
350 // params = {"-isystem path/to/system"}
351 // To normalize the input, we split all strings with the "space" character and consolidate
352 // all tokens into a flattened parameters list
353 params = normalizeParameters(params)
354
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800355 for i := 0; i < len(params); i++ {
356 param := params[i]
357 if param == "" {
358 continue
359 }
360
361 switch categorizeParameter(param) {
362 case headerSearchPath:
Fabien Sanglard67472412017-03-21 10:19:19 -0700363 compilerParameters.headerSearchPath =
364 append(compilerParameters.headerSearchPath, strings.TrimPrefix(param, "-I"))
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800365 case variable:
366 if evaluated, error := evalVariable(ctx, param); error == nil {
367 if outputDebugInfo {
368 f.WriteString(fmt.Sprintf("# variable %s = '%s'\n", param, evaluated))
369 }
370
371 paramsFromVar := parseCompilerParameters(strings.Split(evaluated, " "), ctx, f)
372 concatenateParams(&compilerParameters, paramsFromVar)
373
374 } else {
375 if outputDebugInfo {
376 f.WriteString(fmt.Sprintf("# variable %s could NOT BE RESOLVED\n", param))
377 }
378 }
379 case systemHeaderSearchPath:
380 if i < len(params)-1 {
Fabien Sanglard67472412017-03-21 10:19:19 -0700381 compilerParameters.systemHeaderSearchPath =
382 append(compilerParameters.systemHeaderSearchPath, params[i+1])
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800383 } else if outputDebugInfo {
384 f.WriteString("# Found a header search path marker with no path")
385 }
386 i = i + 1
387 case flag:
Fabien Sanglard5cb35192017-02-06 09:49:58 -0800388 c := cleanupParameter(param)
389 f.WriteString(fmt.Sprintf("# FLAG '%s' became %s\n", param, c))
390 compilerParameters.flags = append(compilerParameters.flags, c)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800391 case systemRoot:
392 if i < len(params)-1 {
393 compilerParameters.sysroot = params[i+1]
394 } else if outputDebugInfo {
395 f.WriteString("# Found a system root path marker with no path")
396 }
397 i = i + 1
Jack He4a10b652018-08-14 17:27:15 -0700398 case relativeFilePathFlag:
399 flagComponents := strings.Split(param, "=")
400 if len(flagComponents) == 2 {
401 flagStruct := relativeFilePathFlagType{flag: flagComponents[0], relativeFilePath: flagComponents[1]}
402 compilerParameters.relativeFilePathFlags = append(compilerParameters.relativeFilePathFlags, flagStruct)
403 } else {
404 if outputDebugInfo {
405 f.WriteString(fmt.Sprintf("# Relative File Path Flag [%s] is not formatted as a=b/c/d \n", param))
406 }
407 }
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800408 }
409 }
410 return compilerParameters
411}
412
Fabien Sanglard5cb35192017-02-06 09:49:58 -0800413func cleanupParameter(p string) string {
414 // In the blueprint, c flags can be passed as:
415 // cflags: [ "-DLOG_TAG=\"libEGL\"", ]
416 // which becomes:
417 // '-DLOG_TAG="libEGL"' in soong.
418 // In order to be injected in CMakelists.txt we need to:
419 // - Remove the wrapping ' character
420 // - Double escape all special \ and " characters.
421 // For a end result like:
422 // -DLOG_TAG=\\\"libEGL\\\"
423 if !strings.HasPrefix(p, "'") || !strings.HasSuffix(p, "'") || len(p) < 3 {
424 return p
425 }
426
427 // Reverse wrapper quotes and escaping that may have happened in NinjaAndShellEscape
428 // TODO: It is ok to reverse here for now but if NinjaAndShellEscape becomes more complex,
429 // we should create a method NinjaAndShellUnescape in escape.go and use that instead.
430 p = p[1 : len(p)-1]
431 p = strings.Replace(p, `'\''`, `'`, -1)
432 p = strings.Replace(p, `$$`, `$`, -1)
433
434 p = doubleEscape(p)
435 return p
436}
437
438func escape(s string) string {
439 s = strings.Replace(s, `\`, `\\`, -1)
440 s = strings.Replace(s, `"`, `\"`, -1)
441 return s
442}
443
444func doubleEscape(s string) string {
445 s = escape(s)
446 s = escape(s)
447 return s
448}
449
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800450func concatenateParams(c1 *compilerParameters, c2 compilerParameters) {
Fabien Sanglard67472412017-03-21 10:19:19 -0700451 c1.headerSearchPath = append(c1.headerSearchPath, c2.headerSearchPath...)
452 c1.systemHeaderSearchPath = append(c1.systemHeaderSearchPath, c2.systemHeaderSearchPath...)
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800453 if c2.sysroot != "" {
454 c1.sysroot = c2.sysroot
455 }
456 c1.flags = append(c1.flags, c2.flags...)
457}
458
Colin Cross0875c522017-11-28 17:34:01 -0800459func evalVariable(ctx android.SingletonContext, str string) (string, error) {
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800460 evaluated, err := ctx.Eval(pctx, str)
461 if err == nil {
462 return evaluated, nil
463 }
464 return "", err
465}
466
Colin Cross0875c522017-11-28 17:34:01 -0800467func getCMakeListsForModule(module *Module, ctx android.SingletonContext) string {
Colin Cross988414c2020-01-11 01:11:46 +0000468 return filepath.Join(android.AbsSrcDirForExistingUseCases(),
Fabien Sanglardd61f1f42017-01-10 16:21:22 -0800469 cLionOutputProjectsDirectory,
470 path.Dir(ctx.BlueprintFile(module)),
471 module.ModuleBase.Name()+"-"+
472 module.ModuleBase.Arch().ArchType.Name+"-"+
473 module.ModuleBase.Os().Name,
474 cMakeListsFilename)
475}