Colin Cross | d00350c | 2017-11-17 10:55:38 -0800 | [diff] [blame] | 1 | // 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 Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 15 | package cc |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | |
| 20 | "android/soong/android" |
| 21 | "android/soong/cc/config" |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 22 | "os" |
| 23 | "path" |
| 24 | "path/filepath" |
| 25 | "strings" |
| 26 | ) |
| 27 | |
| 28 | // This singleton generates CMakeLists.txt files. It does so for each blueprint Android.bp resulting in a cc.Module |
| 29 | // when either make, mm, mma, mmm or mmma is called. CMakeLists.txt files are generated in a separate folder |
| 30 | // structure (see variable CLionOutputProjectsDirectory for root). |
| 31 | |
| 32 | func init() { |
| 33 | android.RegisterSingletonType("cmakelists_generator", cMakeListsGeneratorSingleton) |
| 34 | } |
| 35 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 36 | func cMakeListsGeneratorSingleton() android.Singleton { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 37 | return &cmakelistsGeneratorSingleton{} |
| 38 | } |
| 39 | |
| 40 | type cmakelistsGeneratorSingleton struct{} |
| 41 | |
| 42 | const ( |
| 43 | cMakeListsFilename = "CMakeLists.txt" |
| 44 | cLionAggregateProjectsDirectory = "development" + string(os.PathSeparator) + "ide" + string(os.PathSeparator) + "clion" |
| 45 | cLionOutputProjectsDirectory = "out" + string(os.PathSeparator) + cLionAggregateProjectsDirectory |
| 46 | minimumCMakeVersionSupported = "3.5" |
| 47 | |
| 48 | // Environment variables used to modify behavior of this singleton. |
| 49 | envVariableGenerateCMakeLists = "SOONG_GEN_CMAKEFILES" |
| 50 | envVariableGenerateDebugInfo = "SOONG_GEN_CMAKEFILES_DEBUG" |
| 51 | envVariableTrue = "1" |
| 52 | ) |
| 53 | |
| 54 | // Instruct generator to trace how header include path and flags were generated. |
| 55 | // This is done to ease investigating bug reports. |
| 56 | var outputDebugInfo = false |
| 57 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 58 | func (c *cmakelistsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 59 | if getEnvVariable(envVariableGenerateCMakeLists, ctx) != envVariableTrue { |
| 60 | return |
| 61 | } |
| 62 | |
| 63 | outputDebugInfo = (getEnvVariable(envVariableGenerateDebugInfo, ctx) == envVariableTrue) |
| 64 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 65 | ctx.VisitAllModules(func(module android.Module) { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 66 | if ccModule, ok := module.(*Module); ok { |
| 67 | if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok { |
| 68 | generateCLionProject(compiledModule, ctx, ccModule) |
| 69 | } |
| 70 | } |
| 71 | }) |
| 72 | |
| 73 | // Link all handmade CMakeLists.txt aggregate from |
| 74 | // BASE/development/ide/clion to |
| 75 | // BASE/out/development/ide/clion. |
| 76 | dir := filepath.Join(getAndroidSrcRootDirectory(ctx), cLionAggregateProjectsDirectory) |
| 77 | filepath.Walk(dir, linkAggregateCMakeListsFiles) |
| 78 | |
| 79 | return |
| 80 | } |
| 81 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 82 | func getEnvVariable(name string, ctx android.SingletonContext) string { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 83 | // Using android.Config.Getenv instead of os.getEnv to guarantee soong will |
| 84 | // re-run in case this environment variable changes. |
| 85 | return ctx.Config().(android.Config).Getenv(name) |
| 86 | } |
| 87 | |
| 88 | func exists(path string) bool { |
| 89 | _, err := os.Stat(path) |
| 90 | if err == nil { |
| 91 | return true |
| 92 | } |
| 93 | if os.IsNotExist(err) { |
| 94 | return false |
| 95 | } |
| 96 | return true |
| 97 | } |
| 98 | |
| 99 | func linkAggregateCMakeListsFiles(path string, info os.FileInfo, err error) error { |
| 100 | |
| 101 | if info == nil { |
| 102 | return nil |
| 103 | } |
| 104 | |
| 105 | dst := strings.Replace(path, cLionAggregateProjectsDirectory, cLionOutputProjectsDirectory, 1) |
| 106 | if info.IsDir() { |
| 107 | // This is a directory to create |
| 108 | os.MkdirAll(dst, os.ModePerm) |
| 109 | } else { |
| 110 | // This is a file to link |
| 111 | os.Remove(dst) |
| 112 | os.Symlink(path, dst) |
| 113 | } |
| 114 | return nil |
| 115 | } |
| 116 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 117 | func generateCLionProject(compiledModule CompiledInterface, ctx android.SingletonContext, ccModule *Module) { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 118 | srcs := compiledModule.Srcs() |
| 119 | if len(srcs) == 0 { |
| 120 | return |
| 121 | } |
| 122 | |
| 123 | // Ensure the directory hosting the cmakelists.txt exists |
| 124 | clionproject_location := getCMakeListsForModule(ccModule, ctx) |
| 125 | projectDir := path.Dir(clionproject_location) |
| 126 | os.MkdirAll(projectDir, os.ModePerm) |
| 127 | |
| 128 | // Create cmakelists.txt |
| 129 | f, _ := os.Create(filepath.Join(projectDir, cMakeListsFilename)) |
| 130 | defer f.Close() |
| 131 | |
| 132 | // Header. |
| 133 | f.WriteString("# THIS FILE WAS AUTOMATICALY GENERATED!\n") |
| 134 | f.WriteString("# ANY MODIFICATION WILL BE OVERWRITTEN!\n\n") |
| 135 | f.WriteString("# To improve project view in Clion :\n") |
| 136 | f.WriteString("# Tools > CMake > Change Project Root \n\n") |
| 137 | f.WriteString(fmt.Sprintf("cmake_minimum_required(VERSION %s)\n", minimumCMakeVersionSupported)) |
| 138 | f.WriteString(fmt.Sprintf("project(%s)\n", ccModule.ModuleBase.Name())) |
| 139 | f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", getAndroidSrcRootDirectory(ctx))) |
| 140 | |
| 141 | if ccModule.flags.Clang { |
| 142 | pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/") |
| 143 | f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang")) |
| 144 | f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang++")) |
| 145 | } else { |
| 146 | toolchain := config.FindToolchain(ccModule.Os(), ccModule.Arch()) |
| 147 | root, _ := evalVariable(ctx, toolchain.GccRoot()) |
| 148 | triple, _ := evalVariable(ctx, toolchain.GccTriple()) |
| 149 | pathToCC := filepath.Join(root, "bin", triple+"-") |
| 150 | f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "gcc")) |
| 151 | f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "g++")) |
| 152 | } |
| 153 | // Add all sources to the project. |
| 154 | f.WriteString("list(APPEND\n") |
| 155 | f.WriteString(" SOURCE_FILES\n") |
| 156 | for _, src := range srcs { |
| 157 | f.WriteString(fmt.Sprintf(" ${ANDROID_ROOT}/%s\n", src.String())) |
| 158 | } |
| 159 | f.WriteString(")\n") |
| 160 | |
| 161 | // Add all header search path and compiler parameters (-D, -W, -f, -XXXX) |
| 162 | f.WriteString("\n# GLOBAL FLAGS:\n") |
| 163 | globalParameters := parseCompilerParameters(ccModule.flags.GlobalFlags, ctx, f) |
| 164 | translateToCMake(globalParameters, f, true, true) |
| 165 | |
| 166 | f.WriteString("\n# CFLAGS:\n") |
| 167 | cParameters := parseCompilerParameters(ccModule.flags.CFlags, ctx, f) |
| 168 | translateToCMake(cParameters, f, true, true) |
| 169 | |
| 170 | f.WriteString("\n# C ONLY FLAGS:\n") |
| 171 | cOnlyParameters := parseCompilerParameters(ccModule.flags.ConlyFlags, ctx, f) |
| 172 | translateToCMake(cOnlyParameters, f, true, false) |
| 173 | |
| 174 | f.WriteString("\n# CPP FLAGS:\n") |
| 175 | cppParameters := parseCompilerParameters(ccModule.flags.CppFlags, ctx, f) |
| 176 | translateToCMake(cppParameters, f, false, true) |
| 177 | |
Colin Cross | c319948 | 2017-03-30 15:03:04 -0700 | [diff] [blame] | 178 | f.WriteString("\n# SYSTEM INCLUDE FLAGS:\n") |
| 179 | includeParameters := parseCompilerParameters(ccModule.flags.SystemIncludeFlags, ctx, f) |
| 180 | translateToCMake(includeParameters, f, true, true) |
| 181 | |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 182 | // Add project executable. |
Fabien Sanglard | 7da4926 | 2017-03-23 17:49:09 -0700 | [diff] [blame] | 183 | f.WriteString(fmt.Sprintf("\nadd_executable(%s ${SOURCE_FILES})\n", |
| 184 | cleanExecutableName(ccModule.ModuleBase.Name()))) |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 185 | } |
| 186 | |
Fabien Sanglard | 7da4926 | 2017-03-23 17:49:09 -0700 | [diff] [blame] | 187 | func cleanExecutableName(s string) string { |
| 188 | return strings.Replace(s, "@", "-", -1) |
| 189 | } |
| 190 | |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 191 | func translateToCMake(c compilerParameters, f *os.File, cflags bool, cppflags bool) { |
Fabien Sanglard | d9233f1 | 2017-03-24 12:02:50 -0700 | [diff] [blame] | 192 | writeAllIncludeDirectories(c.systemHeaderSearchPath, f, true) |
| 193 | writeAllIncludeDirectories(c.headerSearchPath, f, false) |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 194 | if cflags { |
| 195 | writeAllFlags(c.flags, f, "CMAKE_C_FLAGS") |
| 196 | } |
| 197 | |
| 198 | if cppflags { |
| 199 | writeAllFlags(c.flags, f, "CMAKE_CXX_FLAGS") |
| 200 | } |
| 201 | if c.sysroot != "" { |
| 202 | f.WriteString(fmt.Sprintf("include_directories(SYSTEM \"%s\")\n", buildCMakePath(path.Join(c.sysroot, "usr", "include")))) |
| 203 | } |
| 204 | |
| 205 | } |
| 206 | |
| 207 | func buildCMakePath(p string) string { |
| 208 | if path.IsAbs(p) { |
| 209 | return p |
| 210 | } |
| 211 | return fmt.Sprintf("${ANDROID_ROOT}/%s", p) |
| 212 | } |
| 213 | |
Fabien Sanglard | d9233f1 | 2017-03-24 12:02:50 -0700 | [diff] [blame] | 214 | func writeAllIncludeDirectories(includes []string, f *os.File, isSystem bool) { |
Fabien Sanglard | 6747241 | 2017-03-21 10:19:19 -0700 | [diff] [blame] | 215 | if len(includes) == 0 { |
| 216 | return |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 217 | } |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 218 | |
Fabien Sanglard | d9233f1 | 2017-03-24 12:02:50 -0700 | [diff] [blame] | 219 | system := "" |
Colin Cross | 51d4ab2 | 2017-05-09 13:44:49 -0700 | [diff] [blame] | 220 | if isSystem { |
Fabien Sanglard | d9233f1 | 2017-03-24 12:02:50 -0700 | [diff] [blame] | 221 | system = "SYSTEM" |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 222 | } |
Fabien Sanglard | d9233f1 | 2017-03-24 12:02:50 -0700 | [diff] [blame] | 223 | |
| 224 | f.WriteString(fmt.Sprintf("include_directories(%s \n", system)) |
| 225 | |
Fabien Sanglard | 6747241 | 2017-03-21 10:19:19 -0700 | [diff] [blame] | 226 | for _, include := range includes { |
Fabien Sanglard | d9233f1 | 2017-03-24 12:02:50 -0700 | [diff] [blame] | 227 | f.WriteString(fmt.Sprintf(" \"%s\"\n", buildCMakePath(include))) |
| 228 | } |
| 229 | f.WriteString(")\n\n") |
| 230 | |
| 231 | // Also add all headers to source files. |
Colin Cross | 51d4ab2 | 2017-05-09 13:44:49 -0700 | [diff] [blame] | 232 | f.WriteString("file (GLOB_RECURSE TMP_HEADERS\n") |
Fabien Sanglard | d9233f1 | 2017-03-24 12:02:50 -0700 | [diff] [blame] | 233 | for _, include := range includes { |
| 234 | f.WriteString(fmt.Sprintf(" \"%s/**/*.h\"\n", buildCMakePath(include))) |
Fabien Sanglard | 6747241 | 2017-03-21 10:19:19 -0700 | [diff] [blame] | 235 | } |
| 236 | f.WriteString(")\n") |
Colin Cross | 51d4ab2 | 2017-05-09 13:44:49 -0700 | [diff] [blame] | 237 | f.WriteString("list (APPEND SOURCE_FILES ${TMP_HEADERS})\n\n") |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | func writeAllFlags(flags []string, f *os.File, tag string) { |
| 241 | for _, flag := range flags { |
| 242 | f.WriteString(fmt.Sprintf("set(%s \"${%s} %s\")\n", tag, tag, flag)) |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | type parameterType int |
| 247 | |
| 248 | const ( |
| 249 | headerSearchPath parameterType = iota |
| 250 | variable |
| 251 | systemHeaderSearchPath |
| 252 | flag |
| 253 | systemRoot |
| 254 | ) |
| 255 | |
| 256 | type compilerParameters struct { |
Fabien Sanglard | 6747241 | 2017-03-21 10:19:19 -0700 | [diff] [blame] | 257 | headerSearchPath []string |
| 258 | systemHeaderSearchPath []string |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 259 | flags []string |
| 260 | sysroot string |
| 261 | } |
| 262 | |
| 263 | func makeCompilerParameters() compilerParameters { |
| 264 | return compilerParameters{ |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 265 | sysroot: "", |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | func categorizeParameter(parameter string) parameterType { |
| 270 | if strings.HasPrefix(parameter, "-I") { |
| 271 | return headerSearchPath |
| 272 | } |
| 273 | if strings.HasPrefix(parameter, "$") { |
| 274 | return variable |
| 275 | } |
| 276 | if strings.HasPrefix(parameter, "-isystem") { |
| 277 | return systemHeaderSearchPath |
| 278 | } |
| 279 | if strings.HasPrefix(parameter, "-isysroot") { |
| 280 | return systemRoot |
| 281 | } |
| 282 | if strings.HasPrefix(parameter, "--sysroot") { |
| 283 | return systemRoot |
| 284 | } |
| 285 | return flag |
| 286 | } |
| 287 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 288 | func parseCompilerParameters(params []string, ctx android.SingletonContext, f *os.File) compilerParameters { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 289 | var compilerParameters = makeCompilerParameters() |
| 290 | |
| 291 | for i, str := range params { |
| 292 | f.WriteString(fmt.Sprintf("# Raw param [%d] = '%s'\n", i, str)) |
| 293 | } |
| 294 | |
| 295 | for i := 0; i < len(params); i++ { |
| 296 | param := params[i] |
| 297 | if param == "" { |
| 298 | continue |
| 299 | } |
| 300 | |
| 301 | switch categorizeParameter(param) { |
| 302 | case headerSearchPath: |
Fabien Sanglard | 6747241 | 2017-03-21 10:19:19 -0700 | [diff] [blame] | 303 | compilerParameters.headerSearchPath = |
| 304 | append(compilerParameters.headerSearchPath, strings.TrimPrefix(param, "-I")) |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 305 | case variable: |
| 306 | if evaluated, error := evalVariable(ctx, param); error == nil { |
| 307 | if outputDebugInfo { |
| 308 | f.WriteString(fmt.Sprintf("# variable %s = '%s'\n", param, evaluated)) |
| 309 | } |
| 310 | |
| 311 | paramsFromVar := parseCompilerParameters(strings.Split(evaluated, " "), ctx, f) |
| 312 | concatenateParams(&compilerParameters, paramsFromVar) |
| 313 | |
| 314 | } else { |
| 315 | if outputDebugInfo { |
| 316 | f.WriteString(fmt.Sprintf("# variable %s could NOT BE RESOLVED\n", param)) |
| 317 | } |
| 318 | } |
| 319 | case systemHeaderSearchPath: |
| 320 | if i < len(params)-1 { |
Fabien Sanglard | 6747241 | 2017-03-21 10:19:19 -0700 | [diff] [blame] | 321 | compilerParameters.systemHeaderSearchPath = |
| 322 | append(compilerParameters.systemHeaderSearchPath, params[i+1]) |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 323 | } else if outputDebugInfo { |
| 324 | f.WriteString("# Found a header search path marker with no path") |
| 325 | } |
| 326 | i = i + 1 |
| 327 | case flag: |
Fabien Sanglard | 5cb3519 | 2017-02-06 09:49:58 -0800 | [diff] [blame] | 328 | c := cleanupParameter(param) |
| 329 | f.WriteString(fmt.Sprintf("# FLAG '%s' became %s\n", param, c)) |
| 330 | compilerParameters.flags = append(compilerParameters.flags, c) |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 331 | case systemRoot: |
| 332 | if i < len(params)-1 { |
| 333 | compilerParameters.sysroot = params[i+1] |
| 334 | } else if outputDebugInfo { |
| 335 | f.WriteString("# Found a system root path marker with no path") |
| 336 | } |
| 337 | i = i + 1 |
| 338 | } |
| 339 | } |
| 340 | return compilerParameters |
| 341 | } |
| 342 | |
Fabien Sanglard | 5cb3519 | 2017-02-06 09:49:58 -0800 | [diff] [blame] | 343 | func cleanupParameter(p string) string { |
| 344 | // In the blueprint, c flags can be passed as: |
| 345 | // cflags: [ "-DLOG_TAG=\"libEGL\"", ] |
| 346 | // which becomes: |
| 347 | // '-DLOG_TAG="libEGL"' in soong. |
| 348 | // In order to be injected in CMakelists.txt we need to: |
| 349 | // - Remove the wrapping ' character |
| 350 | // - Double escape all special \ and " characters. |
| 351 | // For a end result like: |
| 352 | // -DLOG_TAG=\\\"libEGL\\\" |
| 353 | if !strings.HasPrefix(p, "'") || !strings.HasSuffix(p, "'") || len(p) < 3 { |
| 354 | return p |
| 355 | } |
| 356 | |
| 357 | // Reverse wrapper quotes and escaping that may have happened in NinjaAndShellEscape |
| 358 | // TODO: It is ok to reverse here for now but if NinjaAndShellEscape becomes more complex, |
| 359 | // we should create a method NinjaAndShellUnescape in escape.go and use that instead. |
| 360 | p = p[1 : len(p)-1] |
| 361 | p = strings.Replace(p, `'\''`, `'`, -1) |
| 362 | p = strings.Replace(p, `$$`, `$`, -1) |
| 363 | |
| 364 | p = doubleEscape(p) |
| 365 | return p |
| 366 | } |
| 367 | |
| 368 | func escape(s string) string { |
| 369 | s = strings.Replace(s, `\`, `\\`, -1) |
| 370 | s = strings.Replace(s, `"`, `\"`, -1) |
| 371 | return s |
| 372 | } |
| 373 | |
| 374 | func doubleEscape(s string) string { |
| 375 | s = escape(s) |
| 376 | s = escape(s) |
| 377 | return s |
| 378 | } |
| 379 | |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 380 | func concatenateParams(c1 *compilerParameters, c2 compilerParameters) { |
Fabien Sanglard | 6747241 | 2017-03-21 10:19:19 -0700 | [diff] [blame] | 381 | c1.headerSearchPath = append(c1.headerSearchPath, c2.headerSearchPath...) |
| 382 | c1.systemHeaderSearchPath = append(c1.systemHeaderSearchPath, c2.systemHeaderSearchPath...) |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 383 | if c2.sysroot != "" { |
| 384 | c1.sysroot = c2.sysroot |
| 385 | } |
| 386 | c1.flags = append(c1.flags, c2.flags...) |
| 387 | } |
| 388 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 389 | func evalVariable(ctx android.SingletonContext, str string) (string, error) { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 390 | evaluated, err := ctx.Eval(pctx, str) |
| 391 | if err == nil { |
| 392 | return evaluated, nil |
| 393 | } |
| 394 | return "", err |
| 395 | } |
| 396 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 397 | func getCMakeListsForModule(module *Module, ctx android.SingletonContext) string { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 398 | return filepath.Join(getAndroidSrcRootDirectory(ctx), |
| 399 | cLionOutputProjectsDirectory, |
| 400 | path.Dir(ctx.BlueprintFile(module)), |
| 401 | module.ModuleBase.Name()+"-"+ |
| 402 | module.ModuleBase.Arch().ArchType.Name+"-"+ |
| 403 | module.ModuleBase.Os().Name, |
| 404 | cMakeListsFilename) |
| 405 | } |
| 406 | |
Colin Cross | 0875c52 | 2017-11-28 17:34:01 -0800 | [diff] [blame^] | 407 | func getAndroidSrcRootDirectory(ctx android.SingletonContext) string { |
Fabien Sanglard | d61f1f4 | 2017-01-10 16:21:22 -0800 | [diff] [blame] | 408 | srcPath, _ := filepath.Abs(android.PathForSource(ctx).String()) |
| 409 | return srcPath |
| 410 | } |