1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.idegen; 18 19 import com.google.common.base.Preconditions; 20 import com.google.common.collect.Lists; 21 import com.google.common.io.Files; 22 23 import java.io.File; 24 import java.io.IOException; 25 import java.nio.charset.Charset; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.HashSet; 29 import java.util.Set; 30 import java.util.logging.Logger; 31 32 /** 33 * Build Intellij projects. 34 */ 35 public class IntellijProject { 36 37 public static final String FRAMEWORK_MODULE_DIR = "frameworks/base"; 38 public static final Charset CHARSET = Charset.forName("UTF-8"); 39 40 private static final Logger logger = Logger.getLogger(IntellijProject.class.getName()); 41 42 private static final String MODULES_TEMPLATE_FILE_NAME = "modules.xml"; 43 private static final String VCS_TEMPLATE_FILE_NAME = "vcs.xml"; 44 45 ModuleCache cache = ModuleCache.getInstance(); 46 47 boolean buildFramework; 48 File indexFile; 49 File projectPath; 50 ArrayList<String> moduleDirs; 51 IntellijProject(String indexFile, String projectPath, ArrayList<String> moduleDirs, boolean buildFramework)52 public IntellijProject(String indexFile, String projectPath, ArrayList<String> moduleDirs, 53 boolean buildFramework) { 54 this.indexFile = new File(Preconditions.checkNotNull(indexFile)); 55 this.projectPath = new File(Preconditions.checkNotNull(projectPath)); 56 this.moduleDirs = Preconditions.checkNotNull(moduleDirs); 57 this.buildFramework = buildFramework; 58 DirectorySearch.findAndInitRepoRoot(this.indexFile); 59 } 60 build()61 public void build() throws IOException { 62 cache.init(indexFile); 63 File repoRoot = DirectorySearch.getRepoRoot(); 64 if (buildFramework) { 65 File frameworkDir = new File(repoRoot, FRAMEWORK_MODULE_DIR); 66 // Some unbundled apps/branches do not include the framework. 67 if (frameworkDir.exists()) { 68 buildFrameWorkModule(new File(repoRoot, FRAMEWORK_MODULE_DIR)); 69 } 70 } 71 72 for (String moduleDir : moduleDirs) { 73 // First pass, find all dependencies and cache them. 74 File dir = new File(repoRoot, moduleDir); 75 if (!dir.exists()) { 76 logger.info("Directory " + moduleDir + " does not exist in " + repoRoot + 77 ". Are you sure the directory is correct?"); 78 return; 79 } 80 Module module = cache.getAndCacheByDir(dir); 81 if (module == null) { 82 logger.info("Module '" + dir.getPath() + "' not found." + 83 " Module names are case senstive."); 84 return; 85 } 86 } 87 88 // Finally create iml files for dependencies 89 Iterable<Module> modules = cache.getModules(); 90 for (Module mod : modules) { 91 mod.buildImlFile(); 92 } 93 94 createProjectFiles(); 95 } 96 createProjectFiles()97 private void createProjectFiles() throws IOException { 98 File ideaDir = new File(projectPath, ".idea"); 99 ideaDir.mkdirs(); 100 copyTemplates(ideaDir); 101 createModulesFile(ideaDir, cache.getModules()); 102 createVcsFile(ideaDir, cache.getModules()); 103 createNameFile(ideaDir, projectPath.getName()); 104 } 105 106 /** 107 * Framework module needs special handling due to one off resource path: 108 * frameworks/base/Android.mk 109 */ buildFrameWorkModule(File frameworkModuleDir)110 private void buildFrameWorkModule(File frameworkModuleDir) throws IOException { 111 FrameworkModule frameworkModule = new FrameworkModule(frameworkModuleDir); 112 frameworkModule.build(); 113 cache.put(frameworkModule); 114 } 115 createModulesFile(File ideaDir, Iterable<Module> modules)116 private void createModulesFile(File ideaDir, Iterable<Module> modules) throws IOException { 117 String modulesContent = Files.toString(new File(DirectorySearch.findTemplateDir(), 118 "idea" + File.separator + MODULES_TEMPLATE_FILE_NAME), CHARSET); 119 StringBuilder sb = new StringBuilder(); 120 for (Module mod : modules) { 121 File iml = mod.getImlFile(); 122 sb.append(" <module fileurl=\"file://").append(iml.getCanonicalPath()).append( 123 "\" filepath=\"").append(iml.getCanonicalPath()).append("\" />\n"); 124 } 125 modulesContent = modulesContent.replace("@MODULES@", sb.toString()); 126 127 File out = new File(ideaDir, "modules.xml"); 128 logger.info("Creating " + out.getCanonicalPath()); 129 Files.write(modulesContent, out, CHARSET); 130 } 131 createVcsFile(File ideaDir, Iterable<Module> modules)132 private void createVcsFile(File ideaDir, Iterable<Module> modules) throws IOException { 133 String vcsTemplate = Files.toString(new File(DirectorySearch.findTemplateDir(), 134 "idea" + File.separator + VCS_TEMPLATE_FILE_NAME), CHARSET); 135 136 Set<String> gitRoots = new HashSet<>(); 137 for (Module mod : modules) { 138 File dir = mod.getDir(); 139 // Look for git root in the module directory and its parents. 140 while (dir != null) { 141 File gitRoot = new File(dir, ".git"); 142 if (gitRoot.exists()) { 143 gitRoots.add(dir.getCanonicalPath()); 144 break; 145 } else { 146 dir = dir.getParentFile(); 147 } 148 } 149 } 150 StringBuilder sb = new StringBuilder(); 151 for (String root : gitRoots) { 152 sb.append(" <mapping directory=\"").append(root).append("\" vcs=\"Git\" />\n"); 153 } 154 155 vcsTemplate = vcsTemplate.replace("@VCS@", sb.toString()); 156 Files.write(vcsTemplate, new File(ideaDir, "vcs.xml"), CHARSET); 157 } 158 createNameFile(File ideaDir, String name)159 private void createNameFile(File ideaDir, String name) throws IOException { 160 File out = new File(ideaDir, ".name"); 161 Files.write(name, out, CHARSET); 162 } 163 copyTemplates(File ideaDir)164 private void copyTemplates(File ideaDir) throws IOException { 165 File templateDir = DirectorySearch.findTemplateDir(); 166 copyTemplates(new File(templateDir, "idea"), ideaDir); 167 } 168 copyTemplates(File fromDir, File toDir)169 private void copyTemplates(File fromDir, File toDir) throws IOException { 170 toDir.mkdir(); 171 File[] files = fromDir.listFiles(); 172 for (File file : files) { 173 if (file.isDirectory()) { 174 File destDir = new File(toDir, file.getName()); 175 if (!destDir.exists()) { 176 destDir.mkdirs(); 177 } 178 copyTemplates(file, destDir); 179 } else { 180 File toFile = new File(toDir, file.getName()); 181 logger.info("copying " + file.getCanonicalPath() + " to " + 182 toFile.getCanonicalPath()); 183 Files.copy(file, toFile); 184 } 185 } 186 } 187 main(String[] args)188 public static void main(String[] args) { 189 logger.info("Args: " + Arrays.toString(args)); 190 191 if (args.length < 3) { 192 logger.severe("Not enough input arguments. Aborting"); 193 return; 194 } 195 196 boolean buildFramework = true; 197 int argIndex = 0; 198 String arg = args[argIndex]; 199 while (arg.startsWith("--")) { 200 if (arg.equals("--no-framework")) { 201 buildFramework = false; 202 } 203 argIndex++; 204 arg = args[argIndex]; 205 } 206 207 String indexFile = args[argIndex++]; 208 String projectPath = args[argIndex++]; 209 // Remaining args are module directories 210 ArrayList<String> moduleDirs = Lists.newArrayList(); 211 for (int i = argIndex; i < args.length; i++) { 212 moduleDirs.add(args[i]); 213 } 214 215 IntellijProject intellij = new IntellijProject(indexFile, projectPath, moduleDirs, 216 buildFramework); 217 try { 218 intellij.build(); 219 } catch (IOException e) { 220 e.printStackTrace(); 221 } 222 } 223 } 224