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 0797a92904b..0563d84d3d9 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 @@ -21,13 +21,16 @@ public class HeadlessBuildMessages extends NLS { public static String HeadlessBuilder_cant_be_found; public static String HeadlessBuilder_clean_failed; public static String HeadlessBuilder_cleaning_all_projects; + public static String HeadlessBuilder_completed_successfully; public static String HeadlessBuilder_CouldntLockWorkspace; public static String HeadlessBuilder_Directory; + public static String HeadlessBuilder_encountered_errors; public static String HeadlessBuilder_EnvVar_Append; public static String HeadlessBuilder_EnvVar_Prepend; public static String HeadlessBuilder_EnvVar_Remove; public static String HeadlessBuilder_EnvVar_Replace; public static String HeadlessBuilder_Error; + public static String HeadlessBuilder_help_requested; public static String HeadlessBuilder_importAll; public static String HeadlessBuilder_IncludeFile; public static String HeadlessBuilder_InlucdePath; @@ -57,7 +60,9 @@ public class HeadlessBuildMessages extends NLS { public static String HeadlessBuilder_invalid_uri; public static String HeadlessBuilder_PreprocessorDefine; public static String HeadlessBuilder_usage_import; + public static String HeadlessBuilder_usage_marker_type; public static String HeadlessBuilder_usage_no_indexer; + public static String HeadlessBuilder_usage_print_all_error_markers; public static String HeadlessBuilder_Workspace; public static String HeadlessBuilder_WorkspaceInUse; static { diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuildMessages.properties b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuildMessages.properties index 8abccfdd911..311eec70e1d 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuildMessages.properties +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/HeadlessBuildMessages.properties @@ -16,13 +16,16 @@ HeadlessBuilder_building_all=Building All Projects... HeadlessBuilder_cant_be_found=\ can't be found\! HeadlessBuilder_clean_failed=Couldn't CLEAN project HeadlessBuilder_cleaning_all_projects=Cleaning All Projects... +HeadlessBuilder_completed_successfully=Headless build completed successfully HeadlessBuilder_CouldntLockWorkspace=Could not obtain lock for workspace location HeadlessBuilder_Directory=Directory: +HeadlessBuilder_encountered_errors=Headless build encountered errors HeadlessBuilder_EnvVar_Append=\ \ \ -Ea {var=value} append value to environment variable when running all tools HeadlessBuilder_EnvVar_Prepend=\ \ \ -Ep {var=value} prepend value to environment variable when running all tools HeadlessBuilder_EnvVar_Remove=\ \ \ -Er {var} remove/unset the given environment variable HeadlessBuilder_EnvVar_Replace=\ \ \ -E {var=value} replace/add value to environment variable when running all tools HeadlessBuilder_Error=Error: +HeadlessBuilder_help_requested=Help Requested HeadlessBuilder_invalid_argument=Invalid Arguments: HeadlessBuilder_is_not_accessible=\ is not accessible\! HeadlessBuilder_is_not_valid_in_workspace=\ is not valid in the workspace\! @@ -41,7 +44,9 @@ HeadlessBuilder_usage=Usage: 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_usage_marker_type=\ \ \ -marker-type Marker types to fail build on {all | cdt | marker_id} HeadlessBuilder_usage_no_indexer=\ \ \ -no-indexer Disable indexer +HeadlessBuilder_usage_print_all_error_markers=\ \ \ -printErrorMarkers Print all error markers HeadlessBuilder_importAll=\ \ \ -importAll {[uri:/]/path/to/projectTreeURI} Import all projects under URI HeadlessBuilder_IncludeFile=\ \ \ -include {include_file} additional include_file to pass to tools HeadlessBuilder_InlucdePath=\ \ \ -I {include_path} additional include_path to add to tools 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 991cdde5244..5af700a4178 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 @@ -36,6 +36,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.cdt.core.resources.ACBuilder; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription; @@ -97,6 +98,12 @@ import org.eclipse.osgi.service.datalocation.Location; * - Prepend to a tool option value: -Tp {toolid} {optionid=value} * - Remove a tool option: -Tr {toolid} {optionid=value} * - Disable indexer: -no-indexer + * - Error marker types to consider: -marker-type {all | cdt | marker_id} + * where: + * all is all markers -- default + * cdt is C/C++ Problem markers + * marker_id, e.g. org.eclipse.cdt.core.problem + * - Display all error markers: -printErrorMarkers * * Build output is automatically sent to stdout. * @since 6.0 @@ -182,6 +189,10 @@ public class HeadlessBuilder implements IApplication { private List toolOptions = new ArrayList(); /** Map from configuration ID -> Set of SavedToolOptions */ private Map> savedToolOptions = new HashMap>(); + private boolean markerTypesDefault = true; + private boolean markerTypesAll = false; + private Set markerTypes = new HashSet<>(); + private boolean printErrorMarkers = false; private static final String MATCH_ALL_CONFIGS = ".*"; //$NON-NLS-1$ @@ -387,19 +398,43 @@ public class HeadlessBuilder implements IApplication { } private boolean isProjectSuccesfullyBuild(IProject project) { - boolean result = false; try { - result = project.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE) < IMarker.SEVERITY_ERROR; + for (String markerType : markerTypes) { + int findMaxProblemSeverity = project.findMaxProblemSeverity(markerType, true, IResource.DEPTH_INFINITE); + if (findMaxProblemSeverity >= IMarker.SEVERITY_ERROR) { + return false; + } + } + } catch (CoreException e) { + ManagedBuilderCorePlugin.log(e); + return false; + } + return true; + } + + private void accumulateErrorMarkers(IProject project, List allBuildErrors) { + try { + for (String markerType : markerTypes) { + IMarker[] findMarkers = project.findMarkers(markerType, true, IResource.DEPTH_INFINITE); + for (IMarker marker : findMarkers) { + int severity = marker.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO); + if (severity >= IMarker.SEVERITY_ERROR) { + // the string format of Markers is not API and recommended only for debugging, but + // it suits our purpose here. + allBuildErrors.add(marker.toString()); + } + } + } } catch (CoreException e) { ManagedBuilderCorePlugin.log(e); } - return result; } @Override public Object start(IApplicationContext context) throws Exception { // Build result: whether projects were built successfully boolean buildSuccessful = true; + List allBuildErrors = new ArrayList<>(); // Check its OK to use this workspace as IDEApplication does if (!checkInstanceLocation()) @@ -426,6 +461,11 @@ public class HeadlessBuilder implements IApplication { if (!getArguments((String[])context.getArguments().get(IApplicationContext.APPLICATION_ARGS))) return ERROR; + if (markerTypesDefault || markerTypesAll) { + markerTypes.clear(); + markerTypes.add(IMarker.PROBLEM); + } + if (disableIndexer) { CCorePlugin.getIndexManager().setDefaultIndexerId(IPDOMManager.ID_NO_INDEXER); // yes, this is ugly - but I haven't found a way to "officially" @@ -513,16 +553,24 @@ public class HeadlessBuilder implements IApplication { System.out.println(HeadlessBuildMessages.HeadlessBuilder_building_all); root.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, monitor); - for(IProject p : root.getProjects()) + for(IProject p : root.getProjects()) { buildSuccessful = buildSuccessful && isProjectSuccesfullyBuild(p); + if (printErrorMarkers) { + accumulateErrorMarkers(p, allBuildErrors); + } + } } else { // 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); - for(IProject p : configsToBuild.keySet()) + for(IProject p : configsToBuild.keySet()) { buildSuccessful = buildSuccessful && isProjectSuccesfullyBuild(p); + if (printErrorMarkers) { + accumulateErrorMarkers(p, allBuildErrors); + } + } } } finally { // Reset the tool options @@ -555,41 +603,48 @@ public class HeadlessBuilder implements IApplication { // Save modified workspace (bug 513763) root.getWorkspace().save(true, monitor); } - + if (printErrorMarkers) { + if (buildSuccessful) { + System.out.println(HeadlessBuildMessages.HeadlessBuilder_completed_successfully); + } else { + System.out.println(HeadlessBuildMessages.HeadlessBuilder_encountered_errors); + for (String buildError : allBuildErrors) { + System.err.println(buildError); + } + } + } return buildSuccessful ? OK : ERROR; } - /** - * Verify that it's safe to use the specified workspace. i.e. that - * we can write to it and that it's not already locked / in-use. - * - * Return true if a valid workspace path has been set and false otherwise. - * - * @return true if a valid instance location has been set and false - * otherwise - */ - private boolean checkInstanceLocation() { - // -data @none was specified but an ide requires workspace - Location instanceLoc = Platform.getInstanceLocation(); - if (instanceLoc == null || !instanceLoc.isSet()) { - System.err.println(HeadlessBuildMessages.HeadlessBuilder_MustSpecifyWorkspace); - return false; - } - - // -data "/valid/path", workspace already set - try { - // at this point its valid, so try to lock it to prevent concurrent use - if (!instanceLoc.lock()) { - System.err.println(HeadlessBuildMessages.HeadlessBuilder_WorkspaceInUse); - return false; - } - return true; - } catch (IOException e) { - System.err.println(HeadlessBuildMessages.HeadlessBuilder_CouldntLockWorkspace); - } - return false; - } + /** + * Verify that it's safe to use the specified workspace. i.e. that we can write to it and that it's not + * already locked / in-use. + * + * Return true if a valid workspace path has been set and false otherwise. + * + * @return true if a valid instance location has been set and false otherwise + */ + private boolean checkInstanceLocation() { + // -data @none was specified but an ide requires workspace + Location instanceLoc = Platform.getInstanceLocation(); + if (instanceLoc == null || !instanceLoc.isSet()) { + System.err.println(HeadlessBuildMessages.HeadlessBuilder_MustSpecifyWorkspace); + return false; + } + // -data "/valid/path", workspace already set + try { + // at this point its valid, so try to lock it to prevent concurrent use + if (!instanceLoc.lock()) { + System.err.println(HeadlessBuildMessages.HeadlessBuilder_WorkspaceInUse); + return false; + } + return true; + } catch (IOException e) { + System.err.println(HeadlessBuildMessages.HeadlessBuilder_CouldntLockWorkspace); + } + return false; + } /** * Helper method to process expected arguments @@ -611,6 +666,8 @@ public class HeadlessBuilder implements IApplication { * -Tp {toolid} {optionid=value} prepend to a tool option value * -Tr {toolid} {optionid=value} remove a tool option value * -no-indexer Disable indexer + * -marker-types Which markers to consider + * -printErrorMarkers Print all error markers that caused build to fail * * Each argument may be specified more than once * @param args String[] of arguments to parse @@ -621,7 +678,9 @@ public class HeadlessBuilder implements IApplication { if (args == null || args.length == 0) throw new Exception(HeadlessBuildMessages.HeadlessBuilder_no_arguments); for (int i = 0; i < args.length; i++) { - if ("-import".equals(args[i])) { //$NON-NLS-1$ + if ("-help".equals(args[i])) { //$NON-NLS-1$ + throw new Exception(HeadlessBuildMessages.HeadlessBuilder_help_requested); + } else if ("-import".equals(args[i])) { //$NON-NLS-1$ projectsToImport.add(args[++i]); } else if ("-importAll".equals(args[i])) { //$NON-NLS-1$ projectTreeToImport.add(args[++i]); @@ -667,6 +726,10 @@ public class HeadlessBuilder implements IApplication { addToolOption(toolId, option, ToolOption.REMOVE); } else if ("-no-indexer".equals(args[i])) { //$NON-NLS-1$ disableIndexer = true; + } else if ("-marker-type".equals(args[i])) { //$NON-NLS-1$ + addMarkerType(args[++i]); + } else if ("-printErrorMarkers".equals(args[i])) { //$NON-NLS-1$ + printErrorMarkers = true; } else { throw new Exception(HeadlessBuildMessages.HeadlessBuilder_unknown_argument + args[i]); } @@ -681,6 +744,8 @@ public class HeadlessBuilder implements IApplication { System.err.println(HeadlessBuildMessages.HeadlessBuilder_usage_build); System.err.println(HeadlessBuildMessages.HeadlessBuilder_usage_clean_build); System.err.println(HeadlessBuildMessages.HeadlessBuilder_usage_no_indexer); + System.err.println(HeadlessBuildMessages.HeadlessBuilder_usage_marker_type); + System.err.println(HeadlessBuildMessages.HeadlessBuilder_usage_print_all_error_markers); System.err.println(HeadlessBuildMessages.HeadlessBuilder_InlucdePath); System.err.println(HeadlessBuildMessages.HeadlessBuilder_IncludeFile); System.err.println(HeadlessBuildMessages.HeadlessBuilder_PreprocessorDefine); @@ -730,6 +795,17 @@ public class HeadlessBuilder implements IApplication { toolOptions.add(new ToolOption(toolId, optionId, value, operation)); } + private void addMarkerType(String markerType) { + markerTypesDefault = false; + if ("all".equals(markerType)) { //$NON-NLS-1$ + markerTypesAll = true; + } else if ("cdt".equals(markerType)) { //$NON-NLS-1$ + markerTypes.add(ICModelMarker.C_MODEL_PROBLEM_MARKER); + } else { + markerTypes.add(markerType); + } + } + /** * Set the tool options in a configuration, and saves the current values so that * they can be restored at the end of the build. These are reset after the build