Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 317225

Summary: [FR] ability to compile multiple files at once
Product: [Tools] CDT Reporter: Miwako Tokugawa <miwako.tokugawa>
Component: cdt-build-managedAssignee: Project Inbox <cdt-build-managed-inbox>
Status: NEW --- QA Contact: Jonah Graham <jonah>
Severity: enhancement    
Priority: P3 CC: leo.treggiari, mario.pierro
Version: 7.0   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:

Description Miwako Tokugawa CLA 2010-06-17 13:42:51 EDT
Build Identifier: cdt8+

It would be nice to have ability to pass more than one file to the compilation command, i.e.
gcc a.c b.c c.c -c [other options]
instead of
gcc a.c -c [other options]
Our compiler has a feature that can be used only if multiple files are passed to it for compilation (not linking)

Reproducible: Always
Comment 1 Miwako Tokugawa CLA 2010-06-21 19:29:28 EDT
I thought setting 
multipleOfType="true"
with the compiler might take care of this but it doesn't seem that way. 
If I do that, subdir.mk lacks the following three

1. OBJS += ..

2. C_DEPS += ...

3. src/%.o: ../src/%.c
      @echo 'Building file: $<'
       @echo 'Invoking: Intel IA-32 C Compiler'
       icc -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -c -o "$@" "$<"
       @echo 'Finished building: $<'
       @echo ' '

and

makefile has this (no, my sourcefile is not caled default.c)
default.o:
       @echo 'Invoking: Intel IA-32 C Compiler'
       icc  -c -o "default.o"
       @echo 'Finished building: $@'
       @echo ' '

so something is wrong.
Comment 2 Miwako Tokugawa CLA 2010-06-24 16:14:21 EDT
Quoting Leo on multipleOfType:

multipleOfType is something that I specified and implemented.  It is primarily for the Linker case, with object files, but should work elsewhere where appropriate.

There are a couple of problems with using it with the compiler, I think:

The dependency calculation is much more complex with source files.  All of the dependency mechanism may interfere with multipleOfType.  With source files, you only need to compile the ones that are out of date.  With the linker, all object files are always used.
Source files may use different sets of compiler options and so you can’t always invoke the compiler once with all source files.
Comment 3 Mario Pierro CLA 2010-08-26 07:33:10 EDT
I have been trying to add a 'multipleOfType' compiler input to our toolchain plugin, and would like to share my experience here. I am using CDT 7.

With a 'multipleOfType' on its input, the compiler will receive all the source files in the project simultaneously. The output type from the compiler is also 'multipleOfType', uses the OBJS build variable and has a 'nameProvider' class which determines the object file name.

As long as there are no per-file/folder options in the project this seems to work with the internal builder. When using the GnuMakefileBuilder, I also hit the 'default.o' bug mentioned in the previous comments. 

I found out that in my case this was caused by the assembler tool adding its outputs to the OBJS build variable, in 

ManagedBuildGnuToolInfo.calculateOutputs()

<code>
.
.
.
  // Calculate the output name
  // The inputs must have been calculated before we can do this
  if (!inputsCalculated) {
	  done = false;
  } else {
	  Vector inputs = getEnumeratedInputs();
	  String fileName;
	  if (inputs.size() > 0) {
		  //  Get the input file name
		  fileName = (Path.fromOSString((String)inputs.get(0))).removeFileExtension().lastSegment();
		  //  Check if this is a build macro.  If so, use the raw macro name.
		  if (fileName.startsWith("$(") && fileName.endsWith(")")) {	
			  fileName = fileName.substring(2,fileName.length()-1);
		  }
	  } else {
		  fileName = "default"; //$NON-NLS-1$
	  }
.
.
.
</code>

Apparently this will add a 'default.o' output even if the tool has no inputs.

Since the compiler output also uses the OBJS build variable, and it is a multipleOfType, the contents of OBJS will be written in 'makefile' by GnuMakefileGenerator.writeTopAdditionMacros() , since

GnuMakefileGenerator.addTargetsRules()

would add it to the 'outputVarsAdditionsList'.

<code>
.
.
.
	//  Generate the rules for all Tools that specify InputType.multipleOfType, and any Tools that
	//  consume the output of those tools.  This does not apply to pre-3.0 integrations, since
	//  the only "multipleOfType" tool is the "target" tool
	for (int i=0; i<buildTools.length; i++) {
		ITool tool = buildTools[i];
		IInputType type = tool.getPrimaryInputType();
		if (type != null && type.getMultipleOfType()) {
			if (!buildToolsUsed[i]) {
				addRuleForTool(tool, buffer, false, null, null, outputVarsAdditionsList, null, false);
				//  Mark the target tool as processed
				buildToolsUsed[i] = true;
				// Look for tools that consume the output
				generateRulesForConsumers(tool, outputVarsAdditionsList, buffer);
			}
		}
	}
.
.
.
</code>

So it looks like the 'default.o' file is always in the OBJS build variable, it just does not show up unless OBJS is used by a 'multipleOfType' output type.

Hope this can help...
Comment 4 Mario Pierro CLA 2010-08-26 10:30:50 EDT
I have also ran in another problem when building a project which had no compiler sources in its root folder.

In this case, the OBJS build variable would get no values at all.

I think this is caused by ManagedBuildGnuToolInfo.calculateInputs(), in the code which determines tool inputs based on file extensions.
Apparently, it will only look at FILE resources in the root without recursing into subfolders.

<code>
.
.
.
	public boolean calculateInputs(GnuMakefileGenerator makeGen, IConfiguration config, IResource[] projResources, ToolInfoHolder h, boolean lastChance) {
		// Get the inputs for this tool invocation
		// Note that command inputs that are also dependencies are also added to the command dependencies list
		
		/* The priorities for determining the names of the inputs of a tool are:
		 *  1.  If an option is specified, use the value of the option.
		 *  2.  If a build variable is specified, use the files that have been added to the build variable as
		 *      the output(s) of other build steps.
		 *  3.  Use the file extensions and the resources in the project 
		 */
		boolean done = true;         
.
.
.
		if (projResources[j].getType() == IResource.FILE) {
			String fileExt = projResources[j].getFileExtension();
										
.
.
.
		} /////// <---- IResource.FOLDER is not considered
		}
.
.
.
</code>

As the 'multiple' compiler will not get OBJ values in the subdir.mk files, the resulting makefile will not build correctly.