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.logging.Logger; 29 30 /** 31 * Build Intellij projects. 32 */ 33 public class IntellijProject { 34 35 public static final String FRAMEWORK_MODULE_DIR = "frameworks/base"; 36 public static final Charset CHARSET = Charset.forName("UTF-8"); 37 38 private static final Logger logger = Logger.getLogger(IntellijProject.class.getName()); 39 40 private static final String MODULES_TEMPLATE_FILE_NAME = "modules.xml"; 41 private static final String VCS_TEMPLATE_FILE_NAME = "vcs.xml"; 42 43 ModuleCache cache = ModuleCache.getInstance(); 44 45 boolean buildFramework; 46 File indexFile; 47 File projectPath; 48 ArrayList<String> moduleDirs; 49 50 public IntellijProject(String indexFile, String projectPath, ArrayList<String> moduleDirs, 51 boolean buildFramework) { 52 this.indexFile = new File(Preconditions.checkNotNull(indexFile)); 53 this.projectPath = new File(Preconditions.checkNotNull(projectPath)); 54 this.moduleDirs = Preconditions.checkNotNull(moduleDirs); 55 this.buildFramework = buildFramework; 56 DirectorySearch.findAndInitRepoRoot(this.indexFile); 57 } 58 59 public void build() throws IOException { 60 cache.init(indexFile); 61 File repoRoot = DirectorySearch.getRepoRoot(); 62 if (buildFramework) { 63 File frameworkDir = new File(repoRoot, FRAMEWORK_MODULE_DIR); 64 // Some unbundled apps/branches do not include the framework. 65 if (frameworkDir.exists()) { 66 buildFrameWorkModule(new File(repoRoot, FRAMEWORK_MODULE_DIR)); 67 } 68 } 69 70 for (String moduleDir : moduleDirs) { 71 // First pass, find all dependencies and cache them. 72 File dir = new File(repoRoot, moduleDir); 73 if (!dir.exists()) { 74 logger.info("Directory " + moduleDir + " does not exist in " + repoRoot + 75 ". Are you sure the directory is correct?"); 76 return; 77 } 78 Module module = cache.getAndCacheByDir(dir); 79 if (module == null) { 80 logger.info("Module '" + dir.getPath() + "' not found." + 81 " Module names are case senstive."); 82 return; 83 } 84 } 85 86 // Finally create iml files for dependencies 87 Iterable<Module> modules = cache.getModules(); 88 for (Module mod : modules) { 89 mod.buildImlFile(); 90 } 91 92 createProjectFiles(); 93 } 94 95 private void createProjectFiles() throws IOException { 96 File ideaDir = new File(projectPath, ".idea"); 97 ideaDir.mkdirs(); 98 copyTemplates(ideaDir); 99 createModulesFile(ideaDir, cache.getModules()); 100 createVcsFile(ideaDir, cache.getModules()); 101 createNameFile(ideaDir, projectPath.getName()); 102 } 103 104 /** 105 * Framework module needs special handling due to one off resource path: 106 * frameworks/base/Android.mk 107 */ 108 private void buildFrameWorkModule(File frameworkModuleDir) throws IOException { 109 FrameworkModule frameworkModule = new FrameworkModule(frameworkModuleDir); 110 frameworkModule.build(); 111 cache.put(frameworkModule); 112 } 113 114 private void createModulesFile(File ideaDir, Iterable<Module> modules) throws IOException { 115 String modulesContent = Files.toString(new File(DirectorySearch.findTemplateDir(), 116 "idea" + File.separator + MODULES_TEMPLATE_FILE_NAME), CHARSET); 117 StringBuilder sb = new StringBuilder(); 118 for (Module mod : modules) { 119 File iml = mod.getImlFile(); 120 sb.append(" <module fileurl=\"file://").append(iml.getCanonicalPath()).append( 121 "\" filepath=\"").append(iml.getCanonicalPath()).append("\" />\n"); 122 } 123 modulesContent = modulesContent.replace("@MODULES@", sb.toString()); 124 125 File out = new File(ideaDir, "modules.xml"); 126 logger.info("Creating " + out.getCanonicalPath()); 127 Files.write(modulesContent, out, CHARSET); 128 } 129 130 private void createVcsFile(File ideaDir, Iterable<Module> modules) throws IOException { 131 String vcsTemplate = Files.toString(new File(DirectorySearch.findTemplateDir(), 132 "idea" + File.separator + VCS_TEMPLATE_FILE_NAME), CHARSET); 133 134 StringBuilder sb = new StringBuilder(); 135 for (Module mod : modules) { 136 File dir = mod.getDir(); 137 File gitRoot = new File(dir, ".git"); 138 if (gitRoot.exists()) { 139 sb.append(" <mapping directory=\"").append(dir.getCanonicalPath()).append( 140 "\" vcs=\"Git\" />\n"); 141 } 142 } 143 vcsTemplate = vcsTemplate.replace("@VCS@", sb.toString()); 144 Files.write(vcsTemplate, new File(ideaDir, "vcs.xml"), CHARSET); 145 } 146 147 private void createNameFile(File ideaDir, String name) throws IOException { 148 File out = new File(ideaDir, ".name"); 149 Files.write(name, out, CHARSET); 150 } 151 152 private void copyTemplates(File ideaDir) throws IOException { 153 File templateDir = DirectorySearch.findTemplateDir(); 154 copyTemplates(new File(templateDir, "idea"), ideaDir); 155 } 156 157 private void copyTemplates(File fromDir, File toDir) throws IOException { 158 toDir.mkdir(); 159 File[] files = fromDir.listFiles(); 160 for (File file : files) { 161 if (file.isDirectory()) { 162 File destDir = new File(toDir, file.getName()); 163 if (!destDir.exists()) { 164 destDir.mkdirs(); 165 } 166 copyTemplates(file, destDir); 167 } else { 168 File toFile = new File(toDir, file.getName()); 169 logger.info("copying " + file.getCanonicalPath() + " to " + 170 toFile.getCanonicalPath()); 171 Files.copy(file, toFile); 172 } 173 } 174 } 175 176 public static void main(String[] args) { 177 logger.info("Args: " + Arrays.toString(args)); 178 179 if (args.length < 3) { 180 logger.severe("Not enough input arguments. Aborting"); 181 return; 182 } 183 184 boolean buildFramework = true; 185 int argIndex = 0; 186 String arg = args[argIndex]; 187 while (arg.startsWith("--")) { 188 if (arg.equals("--no-framework")) { 189 buildFramework = false; 190 } 191 argIndex++; 192 arg = args[argIndex]; 193 } 194 195 String indexFile = args[argIndex++]; 196 String projectPath = args[argIndex++]; 197 // Remaining args are module directories 198 ArrayList<String> moduleDirs = Lists.newArrayList(); 199 for (int i = argIndex; i < args.length; i++) { 200 moduleDirs.add(args[i]); 201 } 202 203 IntellijProject intellij = new IntellijProject(indexFile, projectPath, moduleDirs, 204 buildFramework); 205 try { 206 intellij.build(); 207 } catch (IOException e) { 208 e.printStackTrace(); 209 } 210 } 211 } 212