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