diff options
author | James Blackburn | 2010-02-22 12:54:39 +0000 |
---|---|---|
committer | James Blackburn | 2010-02-22 12:54:39 +0000 |
commit | f2530640603a5703f5df03ce9d4bc49050263421 (patch) | |
tree | 0765e00b6a71b474cea4d39f27c56a540051a9bb /build/org.eclipse.cdt.managedbuilder.core | |
parent | 2bad84d03136e65866a2c3271a2c3039fa24ab1c (diff) | |
download | org.eclipse.cdt-f2530640603a5703f5df03ce9d4bc49050263421.tar.gz org.eclipse.cdt-f2530640603a5703f5df03ce9d4bc49050263421.tar.xz org.eclipse.cdt-f2530640603a5703f5df03ce9d4bc49050263421.zip |
Bug 281397 Headless builder should support build configuration selection. Add support for specifying the project_name/build_config using regular expression syntax.
Diffstat (limited to 'build/org.eclipse.cdt.managedbuilder.core')
3 files changed, 175 insertions, 53 deletions
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuildMessages.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuildMessages.java index 60567a960b4..f635230971e 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuildMessages.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuildMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Broadcom Corporation and others. + * Copyright (c) 2009, 2010 Broadcom Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -26,7 +26,13 @@ public class HeadlessBuildMessages extends NLS { public static String HeadlessBuilder_is_not_accessible; public static String HeadlessBuilder_is_not_valid_in_workspace; public static String HeadlessBuilder_no_arguments; + public static String HeadlessBuilder_NoConfigMatched; + public static String HeadlessBuilder_NoProjectMatched; public static String HeadlessBuilder_project; + public static String HeadlessBuilder_Quote; + public static String HeadlessBuilder_RegExSyntaxError; + public static String HeadlessBuilder_Skipping; + public static String HeadlessBuilder_Skipping2; public static String HeadlessBuilder_unknown_argument; public static String HeadlessBuilder_URI; public static String HeadlessBuilder_usage; diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuilder.java index 61363693a80..9c4a7f03565 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuilder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Broadcom Corporation and others. + * Copyright (c) 2009, 2010 Broadcom Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * Broadcom Corporation - initial API and implementation + * Clare Richardson (Motorola) - Bug 281397 building specific configs *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; @@ -14,25 +15,36 @@ package org.eclipse.cdt.managedbuilder.internal.core; import java.io.InputStream; import java.net.URI; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; -import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.resources.ACBuilder; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.core.resources.ICommand; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IWorkspaceDescription; import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; @@ -43,11 +55,10 @@ import org.eclipse.equinox.app.IApplicationContext; * IApplication ID: org.eclipse.cdt.managedbuilder.core.headlessbuild * Provides: * - Import projects : -import {[uri:/]/path/to/project} - * - Build projects / the workspace : -build {project_name | all} - * - Clean build projects / the workspace : -cleanBuild {project_name | all} + * - Build projects / the workspace : -build {project_name_reg_ex/config_name_reg_ex | all} + * - Clean build projects / the workspace : -cleanBuild {project_name_reg_ex/config_name_reg_ex | all} * * Build output is automatically sent to stdout. - * All CDT configurations are built. * @since 6.0 */ public class HeadlessBuilder implements IApplication { @@ -63,23 +74,115 @@ public class HeadlessBuilder implements IApplication { } } - /** Preference Value for building all configurations taken from ACBuilder */ - private static final String PREF_BUILD_ALL_CONFIGS = "build.all.configs.enabled"; //$NON-NLS-1$ - /** Error return status */ - public static final Integer ERROR = -1; + public static final Integer ERROR = 1; /** OK return status */ public static final Integer OK = IApplication.EXIT_OK; /** Set of project URIs / paths to import */ private final Set<String> projectsToImport = new HashSet<String>(); /** Set of project names to build */ - private final Set<String> projectsToBuild = new HashSet<String>(); + private final Set<String> projectRegExToBuild = new HashSet<String>(); /** Set of project names to clean */ - private final Set<String> projectsToClean = new HashSet<String>(); + private final Set<String> projectRegExToClean = new HashSet<String>(); private boolean buildAll = false; private boolean cleanAll = false; + private static final String MATCH_ALL_CONFIGS = ".*"; //$NON-NLS-1$ + + /* + * Find all project build configurations that match the regular expression ("project/config") + */ + private Map<IProject, HashSet<IConfiguration>> matchConfigurations(String regularExpression, IProject[] projectList, Map<IProject, HashSet<IConfiguration>> cfgMap) { + try { + int separatorIndex = regularExpression.indexOf('/'); + + String projectRegEx; + String configRegEx; + if(separatorIndex == -1 || separatorIndex == regularExpression.length()-1) { + // build all configurations for this project + projectRegEx = regularExpression; + configRegEx = MATCH_ALL_CONFIGS; + } else { + projectRegEx = regularExpression.substring(0, separatorIndex); + configRegEx = regularExpression.substring(separatorIndex + 1, regularExpression.length()); + } + + Pattern projectPattern = Pattern.compile(projectRegEx); + Pattern configPattern = Pattern.compile(configRegEx); + + // Find the projects that match the regular expression + boolean projectMatched = false; + boolean configMatched = false; + for(IProject project : projectList) { + Matcher projectMatcher = projectPattern.matcher(project.getName()); + + if(projectMatcher.matches()) { + projectMatched = true; + // Find the configurations that match the regular expression + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + IConfiguration[] cfgs = info.getManagedProject().getConfigurations(); + + for(IConfiguration cfg : cfgs) { + Matcher cfgMatcher = configPattern.matcher(cfg.getName()); + + if(cfgMatcher.matches()) { + configMatched = true; + // Build this configuration for this project + HashSet<IConfiguration> set = cfgMap.get(project); + if(set == null){ + set = new HashSet<IConfiguration>(); + } + set.add(cfg); + cfgMap.put(project, set); + } + } + } + } + if (!projectMatched) + System.err.println(HeadlessBuildMessages.HeadlessBuilder_NoProjectMatched + regularExpression + HeadlessBuildMessages.HeadlessBuilder_Skipping2); + else if (!configMatched) + System.err.println(HeadlessBuildMessages.HeadlessBuilder_NoConfigMatched + regularExpression + HeadlessBuildMessages.HeadlessBuilder_Skipping2); + } catch (PatternSyntaxException e) { + System.err.println(HeadlessBuildMessages.HeadlessBuilder_RegExSyntaxError + e.toString()); + System.err.println(HeadlessBuildMessages.HeadlessBuilder_Skipping + regularExpression + HeadlessBuildMessages.HeadlessBuilder_Quote); + } + return cfgMap; + } + + /* + * Build the given configurations using the specified build type (FULL, CLEAN, INCREMENTAL) + */ + private void buildConfigurations(Map<IProject, HashSet<IConfiguration>> projConfigs, final IProgressMonitor monitor, final int buildType) throws CoreException { + for (Map.Entry<IProject, HashSet<IConfiguration>> entry : projConfigs.entrySet()) { + final IProject proj = entry.getKey(); + HashSet<IConfiguration> cfgs = entry.getValue(); + + final Map<String, String> map = BuilderFactory.createBuildArgs(cfgs.toArray(new IConfiguration[cfgs.size()])); + + IWorkspaceRunnable op = new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + ICommand[] commands = proj.getDescription().getBuildSpec(); + monitor.beginTask("", commands.length); //$NON-NLS-1$ + for (int i = 0; i < commands.length; i++) { + if (commands[i].getBuilderName().equals(CommonBuilder.BUILDER_ID)) { + proj.build(buildType, CommonBuilder.BUILDER_ID, map, new SubProgressMonitor(monitor, 1)); + } else { + proj.build(buildType, commands[i].getBuilderName(), + commands[i].getArguments(), new SubProgressMonitor(monitor, 1)); + } + } + monitor.done(); + } + }; + try { + ResourcesPlugin.getWorkspace().run(op, monitor); + } finally { + monitor.done(); + } + } + } + public Object start(IApplicationContext context) throws Exception { IProgressMonitor monitor = new PrintingProgressMonitor(); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); @@ -116,7 +219,7 @@ public class HeadlessBuilder implements IApplication { try { URI project_uri = null; try { - project_uri = URI.create(projURIStr); + project_uri = URI.create(projURIStr); } catch (Exception e) { // Will be treated as straightforward path in the case below } @@ -137,7 +240,7 @@ public class HeadlessBuilder implements IApplication { // Load the project description IFileStore fstore = EFS.getStore(project_uri.resolve(".project")); //$NON-NLS-1$ if (!fstore.fetchInfo().exists()) { - System.err.println(HeadlessBuildMessages.HeadlessBuilder_project + project_uri.resolve(".project") + HeadlessBuildMessages.HeadlessBuilder_cant_be_found); //$NON-NLS-2$ + System.err.println(HeadlessBuildMessages.HeadlessBuilder_project + project_uri.resolve(".project") + HeadlessBuildMessages.HeadlessBuilder_cant_be_found); //$NON-NLS-1$ return ERROR; } in = fstore.openInputStream(EFS.NONE, monitor); @@ -165,48 +268,50 @@ public class HeadlessBuilder implements IApplication { } } + IProject[] allProjects = root.getProjects(); + // Map from Project -> Configurations to build. We also Build all projects which are clean'd + Map<IProject, HashSet<IConfiguration>> configsToBuild = new HashMap<IProject, HashSet<IConfiguration>>(); + /* * Perform the Clean / Build */ - final Preferences prefs = CCorePlugin.getDefault().getPluginPreferences(); - final boolean buildAllConfigs = prefs.getBoolean(PREF_BUILD_ALL_CONFIGS); + final boolean buildAllConfigs = ACBuilder.needAllConfigBuild(); try { - // Ensure we clean / build all the configurations - prefs.setValue(PREF_BUILD_ALL_CONFIGS, true); - // Clean the projects if (cleanAll) { + // Ensure we clean all the configurations + ACBuilder.setAllConfigBuild(true); + System.out.println(HeadlessBuildMessages.HeadlessBuilder_cleaning_all_projects); root.getWorkspace().build(IncrementalProjectBuilder.CLEAN_BUILD, monitor); + + // Reset the build_all_configs preference value to its previous state + ACBuilder.setAllConfigBuild(buildAllConfigs); } else { - for (String project : projectsToClean) { - IProject prj = root.getProject(project); - if (!prj.exists()) { - System.err.println(HeadlessBuildMessages.HeadlessBuilder_clean_failed + project + HeadlessBuildMessages.HeadlessBuilder_16); - continue; - } - prj.build(IncrementalProjectBuilder.CLEAN_BUILD, monitor); - } + // Resolve the regular expression project names to build configurations + for (String regEx : projectRegExToClean) + matchConfigurations(regEx, allProjects, configsToBuild); + // Clean the list of configurations + buildConfigurations(configsToBuild, monitor, IncrementalProjectBuilder.CLEAN_BUILD); } // Build the projects the user wants building if (buildAll) { + // Ensure we build all the configurations + ACBuilder.setAllConfigBuild(true); + System.out.println(HeadlessBuildMessages.HeadlessBuilder_building_all); root.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, monitor); } else { - for (String project : projectsToBuild) { - IProject prj = root.getProject(project); - if (!prj.exists()) { - System.err.println(HeadlessBuildMessages.HeadlessBuilder_build_failed + project + HeadlessBuildMessages.HeadlessBuilder_16); - continue; - } - prj.build(IncrementalProjectBuilder.FULL_BUILD, monitor); - } + // Resolve the regular expression project names to build configurations + for (String regEx : projectRegExToBuild) + matchConfigurations(regEx, allProjects, configsToBuild); + // Build the list of configurations + buildConfigurations(configsToBuild, monitor, IncrementalProjectBuilder.FULL_BUILD); } } finally { // Reset the build_all_configs preference value to its previous state - prefs.setValue(PREF_BUILD_ALL_CONFIGS, buildAllConfigs); - CCorePlugin.getDefault().savePluginPreferences(); + ACBuilder.setAllConfigBuild(buildAllConfigs); } } finally { // Reset workspace auto-build preference @@ -227,14 +332,14 @@ public class HeadlessBuilder implements IApplication { * * Arguments * -import {[uri:/]/path/to/project} - * -build {project_name | all} - * -cleanBuild {projec_name | all} + * -build {project_name_reg_ex/config_name_reg_ex | all} + * -cleanBuild {project_name_reg_ex/config_name_reg_ex | all} * * Each argument may be specified more than once * @param args * @return boolean indicating success */ - private boolean getArguments(String[] args) { + public boolean getArguments(String[] args) { try { if (args == null || args.length == 0) throw new Exception(HeadlessBuildMessages.HeadlessBuilder_no_arguments); @@ -242,16 +347,16 @@ public class HeadlessBuilder implements IApplication { if ("-import".equals(args[i])) { //$NON-NLS-1$ projectsToImport.add(args[++i]); } else if ("-build".equals(args[i])) { //$NON-NLS-1$ - projectsToBuild.add(args[++i]); + projectRegExToBuild.add(args[++i]); } else if ("-cleanBuild".equals(args[i])) { //$NON-NLS-1$ - projectsToClean.add(args[++i]); + projectRegExToClean.add(args[++i]); } else { - System.err.println(HeadlessBuildMessages.HeadlessBuilder_unknown_argument + args[i]); + throw new Exception(HeadlessBuildMessages.HeadlessBuilder_unknown_argument + args[i]); } } } catch (Exception e) { // Print usage - System.err.println(HeadlessBuildMessages.HeadlessBuilder_invalid_argument + args != null ? Arrays.toString(args) : ""); //$NON-NLS-2$ + System.err.println(HeadlessBuildMessages.HeadlessBuilder_invalid_argument + args != null ? Arrays.toString(args) : ""); //$NON-NLS-1$ System.err.println(HeadlessBuildMessages.HeadlessBuilder_Error + e.getMessage()); System.err.println(HeadlessBuildMessages.HeadlessBuilder_usage); System.err.println(HeadlessBuildMessages.HeadlessBuilder_usage_import); @@ -259,17 +364,19 @@ public class HeadlessBuilder implements IApplication { System.err.println(HeadlessBuildMessages.HeadlessBuilder_usage_clean_build); return false; } - if (projectsToClean.contains("all")) { //$NON-NLS-1$ + + if (projectRegExToClean.contains("all") || projectRegExToClean.contains("*")) { //$NON-NLS-1$ //$NON-NLS-2$ cleanAll = true; buildAll = true; - projectsToClean.remove("all"); //$NON-NLS-1$ + projectRegExToClean.remove("all"); //$NON-NLS-1$ + projectRegExToClean.remove("*"); //$NON-NLS-1$ } - if (projectsToBuild.contains("all")) { //$NON-NLS-1$ + if (projectRegExToBuild.contains("all") || projectRegExToBuild.contains("*")) { //$NON-NLS-1$ //$NON-NLS-2$ buildAll = true; - projectsToBuild.remove("all"); //$NON-NLS-1$ + projectRegExToBuild.remove("all"); //$NON-NLS-1$ + projectRegExToBuild.remove("*"); //$NON-NLS-1$ } - // We must build all the projects the user wants build - projectsToBuild.addAll(projectsToClean); + return true; } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties index 39839273960..8097510da47 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties @@ -158,6 +158,8 @@ CommonBuilder.13=can not clean programmatically: build folder is not accessible CommonBuilder.22=Building referenced configurations.. CommonBuilder.23=Buildfile generation error occurred.. CommonBuilder.24=Build stopped.. + +# Headless builder HeadlessBuilder_16=\ as it doesn't exist in the workspace\! HeadlessBuilder_already_exists_in_workspace=\ already exists in the workspace\! HeadlessBuilder_build_failed=Couldn't BUILD project @@ -170,14 +172,21 @@ HeadlessBuilder_invalid_argument=Invalid Arguments: HeadlessBuilder_is_not_accessible=\ is not accessible\! HeadlessBuilder_is_not_valid_in_workspace=\ is not valid in the workspace\! HeadlessBuilder_no_arguments=No arguments specified. +HeadlessBuilder_NoConfigMatched=WARNING: No Config matched " +HeadlessBuilder_NoProjectMatched=WARNING: No Project matched " HeadlessBuilder_project=Project: +HeadlessBuilder_Quote=" +HeadlessBuilder_RegExSyntaxError=Project/Configuration Regular Expression Syntax error: +HeadlessBuilder_Skipping=Skipping " +HeadlessBuilder_Skipping2=". Skipping... HeadlessBuilder_unknown_argument=Unknown argument: HeadlessBuilder_URI=URI: HeadlessBuilder_usage=Usage: -HeadlessBuilder_usage_build=\ \ \ -build {project_name | all} -HeadlessBuilder_usage_clean_build=\ \ \ -cleanBuild {project_name | all} +HeadlessBuilder_usage_build=\ \ \ -build {project_name_reg_ex{/config_reg_ex} | all} +HeadlessBuilder_usage_clean_build=\ \ \ -cleanBuild {project_name_reg_ex{/config_reg_ex} | all} HeadlessBuilder_usage_import=\ \ \ -import {[uri:/]/path/to/project} HeadlessBuilder_Workspace=Workspace + MakeBuilder.buildError= MultiResourceInfo.MultiResourceInfo.UnhandledIHoldsOptionsType=Unhandled parent type: not ITool nor IToolChain ResourceChangeHandler2.0=project build settings update job |