Package it.baeyens.arduino.toolchain

Source Code of it.baeyens.arduino.toolchain.ArduinoManagedBuildGnuToolInfo

package it.baeyens.arduino.toolchain;

import it.baeyens.arduino.common.ArduinoConst;
import it.baeyens.arduino.common.Common;
import it.baeyens.arduino.toolchain.ArduinoGnuMakefileGenerator.ToolInfoHolder;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Vector;

import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IAdditionalInput;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IInputType;
import org.eclipse.cdt.managedbuilder.core.IManagedOutputNameProvider;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.core.IOutputType;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages;
import org.eclipse.cdt.managedbuilder.internal.core.Tool;
import org.eclipse.cdt.managedbuilder.internal.macros.OptionContextData;
import org.eclipse.cdt.managedbuilder.macros.BuildMacroException;
import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider;
import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyCalculator;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator2;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGeneratorType;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyInfo;
import org.eclipse.cdt.managedbuilder.makegen.gnu.IManagedBuildGnuToolInfo;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;

/**
* This class represents information about a Tool's inputs and outputs while a Gnu makefile is being generated.
*
* @noextend This class is not intended to be subclassed by clients.
*/
@SuppressWarnings({ "restriction", "deprecation" })
public class ArduinoManagedBuildGnuToolInfo implements IManagedBuildGnuToolInfo {

    /*
     * Members
     */
    private IProject project;
    private Tool tool;
    private boolean bIsTargetTool;
    private String targetName;
    private String targetExt;
    private boolean inputsCalculated = false;
    private boolean outputsCalculated = false;
    private boolean outputVariablesCalculated = false;
    private boolean dependenciesCalculated = false;
    private Vector<String> commandInputs = new Vector<String>();
    private Vector<String> enumeratedInputs = new Vector<String>();
    private Vector<String> commandOutputs = new Vector<String>();
    private Vector<String> enumeratedPrimaryOutputs = new Vector<String>();
    private Vector<String> enumeratedSecondaryOutputs = new Vector<String>();
    private Vector<String> outputVariables = new Vector<String>();
    private Vector<String> commandDependencies = new Vector<String>();
    private Vector<String> additionalTargets = new Vector<String>();

    // private Vector enumeratedDependencies = new Vector();
    // Map of macro names (String) to values (List)

    /*
     * Constructor
     */
    public ArduinoManagedBuildGnuToolInfo(IProject project, ITool tool, boolean targetTool, String name, String ext) {
  this.project = project;
  this.tool = (Tool) tool;
  bIsTargetTool = targetTool;
  if (bIsTargetTool) {
      targetName = name;
      targetExt = ext;
  }
    }

    /*
     * IManagedBuildGnuToolInfo Methods
     */
    @Override
    public boolean areInputsCalculated() {
  return inputsCalculated;
    }

    // Command inputs are top build directory relative
    @Override
    public Vector<String> getCommandInputs() {
  return commandInputs;
    }

    // Enumerated inputs are project relative
    @Override
    public Vector<String> getEnumeratedInputs() {
  return enumeratedInputs;
    }

    @Override
    public boolean areOutputsCalculated() {
  return outputsCalculated;
    }

    // Command outputs are top build directory relative
    @Override
    public Vector<String> getCommandOutputs() {
  return commandOutputs;
    }

    @Override
    public Vector<String> getEnumeratedPrimaryOutputs() {
  return enumeratedPrimaryOutputs;
    }

    @Override
    public Vector<String> getEnumeratedSecondaryOutputs() {
  return enumeratedSecondaryOutputs;
    }

    @Override
    public Vector<String> getOutputVariables() {
  return outputVariables;
    }

    public boolean areOutputVariablesCalculated() {
  return outputVariablesCalculated;
    }

    @Override
    public boolean areDependenciesCalculated() {
  return dependenciesCalculated;
    }

    // Command dependencies are top build directory relative
    @Override
    public Vector<String> getCommandDependencies() {
  return commandDependencies;
    }

    // Additional targets are top build directory relative
    @Override
    public Vector<String> getAdditionalTargets() {
  return additionalTargets;
    }

    // public Vector getEnumeratedDependencies() {
    // return enumeratedDependencies;
    // }

    @Override
    public boolean isTargetTool() {
  return bIsTargetTool;
    }

    /*
     * Other Methods
     */

    public boolean calculateInputs(ArduinoGnuMakefileGenerator 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;
  Vector<String> myCommandInputs = new Vector<String>(); // Inputs for the
                     // tool command
                     // line
  Vector<String> myCommandDependencies = new Vector<String>(); // Dependencies
                     // for the
                     // make
                     // rule
  Vector<String> myEnumeratedInputs = new Vector<String>(); // Complete
                  // list of
                  // individual
                  // inputs

  IInputType[] inTypes = tool.getInputTypes();
  if (inTypes != null && inTypes.length > 0) {
      for (IInputType type : inTypes) {
    Vector<String> itCommandInputs = new Vector<String>(); // Inputs
                       // for
                       // the
                       // tool
                       // command
                       // line
                       // for
                       // this
                       // input-type
    Vector<String> itCommandDependencies = new Vector<String>(); // Dependencies
                       // for
                       // the
                       // make
                       // rule
                       // for
                       // this
                       // input-type
    Vector<String> itEnumeratedInputs = new Vector<String>(); // Complete
                    // list
                    // of
                    // individual
                    // inputs
                    // for
                    // this
                    // input-type
    String variable = type.getBuildVariable();
    boolean primaryInput = type.getPrimaryInput();
    boolean useFileExts = false;
    IOption option = tool.getOptionBySuperClassId(type.getOptionId());
    IOption assignToOption = tool.getOptionBySuperClassId(type.getAssignToOptionId());

    // Option?
    if (option != null) {
        try {
      List<String> inputs = new ArrayList<String>();
      int optType = option.getValueType();
      if (optType == IOption.STRING) {
          inputs.add(option.getStringValue());
      } else if (optType == IOption.STRING_LIST || optType == IOption.LIBRARIES || optType == IOption.OBJECTS
        || optType == IOption.INCLUDE_FILES || optType == IOption.LIBRARY_PATHS || optType == IOption.LIBRARY_FILES
        || optType == IOption.MACRO_FILES) {
          @SuppressWarnings("unchecked")
          List<String> valueList = (List<String>) option.getValue();
          inputs = valueList;
          tool.filterValues(optType, inputs);
          tool.filterValues(optType, inputs);
      }
      for (int j = 0; j < inputs.size(); j++) {
          String inputName = inputs.get(j);

          try {
        // try to resolve the build macros in the output
        // names

        String resolved = null;

        // does the input name contain spaces?
        // TODO: support other special characters
        if (inputName.indexOf(" ") != -1) //$NON-NLS-1$
        {
            // resolve to string
            resolved = ManagedBuildManager.getBuildMacroProvider().resolveValue(inputName, "", //$NON-NLS-1$
              " ", //$NON-NLS-1$
              IBuildMacroProvider.CONTEXT_OPTION, new OptionContextData(option, tool));
        } else {

            // resolve to makefile variable format
            resolved = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat(inputName, "", //$NON-NLS-1$
              " ", //$NON-NLS-1$
              IBuildMacroProvider.CONTEXT_OPTION, new OptionContextData(option, tool));
        }

        if ((resolved = resolved.trim()).length() > 0)
            inputName = resolved;
          } catch (BuildMacroException e) {// JABA is not
                   // going to add
                   // code
          }

          if (primaryInput) {
        itCommandDependencies.add(j, inputName);
          } else {
        itCommandDependencies.add(inputName);
          }
          // NO - itCommandInputs.add(inputName);
          // NO - itEnumeratedInputs.add(inputName);
      }
        } catch (BuildException ex) {// JABA is not going to add
             // code
        }

    } else {

        // Build Variable?
        if (variable.length() > 0) {
      String cmdVariable = variable = "$(" + variable + ")"; //$NON-NLS-1$  //$NON-NLS-2$
      itCommandInputs.add(cmdVariable);
      if (primaryInput) {
          itCommandDependencies.add(0, cmdVariable);
      } else {
          itCommandDependencies.add(cmdVariable);
      }
      // If there is an output variable with the same name,
      // get
      // the files associated with it.
      List<String> outMacroList = makeGen.getBuildVariableList(h, variable, ArduinoGnuMakefileGenerator.PROJECT_RELATIVE, null,
        true);
      if (outMacroList != null) {
          itEnumeratedInputs.addAll(outMacroList);
      } else {
          // If "last chance", then calculate using file
          // extensions below
          if (lastChance) {
        useFileExts = true;
          } else {
        done = false;
        break;
          }
      }
        }

        // Use file extensions
        if (variable.length() == 0 || useFileExts) {
      // if (type.getMultipleOfType()) {
      // Calculate EnumeratedInputs using the file extensions
      // and the resources in the project
      // Note: This is only correct for tools with
      // multipleOfType == true, but for other tools
      // it gives us an input resource for generating default
      // names
      // Determine the set of source input macros to use
      HashSet<String> handledInputExtensions = new HashSet<String>();
      String[] exts = type.getSourceExtensions(tool);
      if (projResources != null) {
          for (IResource rc : projResources) {
        if (rc.getType() == IResource.FILE) {
            String fileExt = rc.getFileExtension();

            // fix for NPE, bugzilla 99483
            if (fileExt == null) {
          fileExt = ""; //$NON-NLS-1$
            }

            for (int k = 0; k < exts.length; k++) {
          if (fileExt.equals(exts[k])) {
              if (!useFileExts) {
            if (!handledInputExtensions.contains(fileExt)) {
                handledInputExtensions.add(fileExt);
                String buildMacro = "$(" + makeGen.getSourceMacroName(fileExt).toString() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
                itCommandInputs.add(buildMacro);
                if (primaryInput) {
              itCommandDependencies.add(0, buildMacro);
                } else {
              itCommandDependencies.add(buildMacro);
                }
            }
              }
              if (type.getMultipleOfType() || itEnumeratedInputs.size() == 0) {
            // Add a path that is relative
            // to the project directory
            itEnumeratedInputs.add(rc.getProjectRelativePath().toString());
              }
              break;
          }
            }
        }
          }
      }
      // }
        }
    }

    // Get any additional inputs specified in the manifest file or
    // the project file
    IAdditionalInput[] addlInputs = type.getAdditionalInputs();
    if (addlInputs != null) {
        for (int j = 0; j < addlInputs.length; j++) {
      IAdditionalInput addlInput = addlInputs[j];
      int kind = addlInput.getKind();
      if (kind == IAdditionalInput.KIND_ADDITIONAL_INPUT || kind == IAdditionalInput.KIND_ADDITIONAL_INPUT_DEPENDENCY) {
          String[] paths = addlInput.getPaths();
          if (paths != null) {
        for (int k = 0; k < paths.length; k++) {
            String path = paths[k];
            itEnumeratedInputs.add(path);
            // Translate the path from project relative
            // to build directory relative
            if (!(path.startsWith("$("))) { //$NON-NLS-1$
          IResource addlResource = project.getFile(path);
          if (addlResource != null) {
              IPath addlPath = addlResource.getLocation();
              if (addlPath != null) {
            path = ManagedBuildManager.calculateRelativePath(makeGen.getTopBuildDir(), addlPath).toString();
              }
          }
            }
            itCommandInputs.add(path);
        }
          }
      }
        }
    }

    // If the assignToOption attribute is specified, set the
    // input(s) as the value of that option
    if (assignToOption != null && option == null) {
        try {
      int optType = assignToOption.getValueType();
      if (optType == IOption.STRING) {
          String optVal = ""; //$NON-NLS-1$
          for (int j = 0; j < itCommandInputs.size(); j++) {
        if (j != 0) {
            optVal += " "; //$NON-NLS-1$
        }
        optVal += itCommandInputs.get(j);
          }
          ManagedBuildManager.setOption(config, tool, assignToOption, optVal);
      } else if (optType == IOption.STRING_LIST || optType == IOption.LIBRARIES || optType == IOption.OBJECTS
        || optType == IOption.INCLUDE_FILES || optType == IOption.LIBRARY_PATHS || optType == IOption.LIBRARY_FILES
        || optType == IOption.MACRO_FILES) {
          // TODO: do we need to do anything with undefs here?
          // Mote that when using the enumerated inputs, the
          // path(s) must be translated from project relative
          // to top build directory relative
          String[] paths = new String[itEnumeratedInputs.size()];
          for (int j = 0; j < itEnumeratedInputs.size(); j++) {
        paths[j] = itEnumeratedInputs.get(j);
        IResource enumResource = project.getFile(paths[j]);
        if (enumResource != null) {
            IPath enumPath = enumResource.getLocation();
            if (enumPath != null) {
          paths[j] = ManagedBuildManager.calculateRelativePath(makeGen.getTopBuildDir(), enumPath).toString();
            }
        }
          }
          ManagedBuildManager.setOption(config, tool, assignToOption, paths);
      } else if (optType == IOption.BOOLEAN) {
          if (itEnumeratedInputs.size() > 0) {
        ManagedBuildManager.setOption(config, tool, assignToOption, true);
          } else {
        ManagedBuildManager.setOption(config, tool, assignToOption, false);
          }
      } else if (optType == IOption.ENUMERATED || optType == IOption.TREE) {
          if (itCommandInputs.size() > 0) {
        ManagedBuildManager.setOption(config, tool, assignToOption, itCommandInputs.firstElement());
          }
      }
      itCommandInputs.removeAllElements();
      // itEnumeratedInputs.removeAllElements();
        } catch (BuildException ex) {// JABA is not going to add
             // code
        }
    }

    myCommandInputs.addAll(itCommandInputs);
    myCommandDependencies.addAll(itCommandDependencies);
    myEnumeratedInputs.addAll(itEnumeratedInputs);
      }
  } else {
      // For support of pre-CDT 3.0 integrations.
      if (bIsTargetTool) {
    // NOTE WELL: This only supports the case of a single
    // "target tool"
    // with the following characteristics:
    // 1. The tool consumes exactly all of the object files produced
    // by other tools in the build and produces a single output
    // 2. The target name comes from the configuration artifact name
    // The rule looks like:
    // <targ_prefix><target>.<extension>: $(OBJS) <refd_project_1
    // ... refd_project_n>
    myCommandInputs.add("$(OBJS)"); //$NON-NLS-1$
    myCommandInputs.add("$(USER_OBJS)"); //$NON-NLS-1$
    myCommandInputs.add("$(LIBS)"); //$NON-NLS-1$
      } else {
    // Rule will be generated by addRuleForSource
      }
  }

  if (done) {
      commandInputs.addAll(myCommandInputs);
      commandDependencies.addAll(0, myCommandDependencies);
      enumeratedInputs.addAll(myEnumeratedInputs);
      inputsCalculated = true;
      return true;
  }

  return false;
    }

    /*
     * The priorities for determining the names of the outputs of a tool are: 1. If the tool is the build target and primary output, use artifact name
     * & extension 2. If an option is specified, use the value of the option 3. If a nameProvider is specified, call it 4. If outputNames is
     * specified, use it 5. Use the name pattern to generate a transformation macro so that the source names can be transformed into the target names
     * using the built-in string substitution functions of <code>make</code>.
     *
     * NOTE: If an option is not specified and this is not the primary output type, the outputs from the type are not added to the command line
     */
    @SuppressWarnings("unused")
    public boolean calculateOutputs(ArduinoGnuMakefileGenerator makeGen, IConfiguration config, HashSet<String> handledInputExtensions,
      boolean lastChance) {

  boolean done = true;
  Vector<String> myCommandOutputs = new Vector<String>();
  Vector<String> myEnumeratedPrimaryOutputs = new Vector<String>();
  Vector<String> myEnumeratedSecondaryOutputs = new Vector<String>();
  HashMap<String, List<IPath>> myOutputMacros = new HashMap<String, List<IPath>>();
  // The next two fields are used together
  Vector<String> myBuildVars = new Vector<String>();
  Vector<Vector<String>> myBuildVarsValues = new Vector<Vector<String>>();

  // Get the outputs for this tool invocation
  IOutputType[] outTypes = tool.getOutputTypes();
  if (outTypes != null && outTypes.length > 0) {
      for (int i = 0; i < outTypes.length; i++) {
    Vector<String> typeEnumeratedOutputs = new Vector<String>();
    IOutputType type = outTypes[i];
    String outputPrefix = type.getOutputPrefix();

    // Resolve any macros in the outputPrefix
    // Note that we cannot use file macros because if we do a clean
    // we need to know the actual name of the file to clean, and
    // cannot use any builder variables such as $@. Hence we use the
    // next best thing, i.e. configuration context.

    if (config != null) {

        try {
      outputPrefix = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat(outputPrefix, "", //$NON-NLS-1$
        " ", //$NON-NLS-1$
        IBuildMacroProvider.CONTEXT_CONFIGURATION, config);
        }

        catch (BuildMacroException e) {// JABA is not going to add
               // code
        }
    }

    String variable = type.getBuildVariable();
    boolean multOfType = type.getMultipleOfType();
    boolean primaryOutput = (type == tool.getPrimaryOutputType());
    IOption option = tool.getOptionBySuperClassId(type.getOptionId());
    IManagedOutputNameProvider nameProvider = type.getNameProvider();
    String[] outputNames = type.getOutputNames();

    // 1. If the tool is the build target and this is the primary
    // output,
    // use artifact name & extension
    if (bIsTargetTool && primaryOutput) {
        String outputName = outputPrefix + targetName;
        if (targetExt.length() > 0) {
      outputName += (DOT + targetExt);
        }
        myCommandOutputs.add(outputName);
        typeEnumeratedOutputs.add(outputName);
        // But this doesn't use any output macro...
    } else
    // 2. If an option is specified, use the value of the option
    if (option != null) {
        try {
      List<String> outputs = new ArrayList<String>();
      int optType = option.getValueType();
      if (optType == IOption.STRING) {
          outputs.add(outputPrefix + option.getStringValue());
      } else if (optType == IOption.STRING_LIST || optType == IOption.LIBRARIES || optType == IOption.OBJECTS
        || optType == IOption.INCLUDE_FILES || optType == IOption.LIBRARY_PATHS || optType == IOption.LIBRARY_FILES
        || optType == IOption.MACRO_FILES) {
          @SuppressWarnings("unchecked")
          List<String> value = (List<String>) option.getValue();
          outputs = value;
          tool.filterValues(optType, outputs);
          // Add outputPrefix to each if necessary
          if (outputPrefix.length() > 0) {
        for (int j = 0; j < outputs.size(); j++) {
            outputs.set(j, outputPrefix + outputs.get(j));
        }
          }
      }
      for (int j = 0; j < outputs.size(); j++) {
          String outputName = outputs.get(j);
          try {
        // try to resolve the build macros in the output
        // names
        String resolved = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat(outputName, "", //$NON-NLS-1$
          " ", //$NON-NLS-1$
          IBuildMacroProvider.CONTEXT_OPTION, new OptionContextData(option, tool));
        if ((resolved = resolved.trim()).length() > 0)
            outputs.set(j, resolved);
          } catch (BuildMacroException e) {// JABA is not
                   // going to add
                   // code
          }
      }

      // NO - myCommandOutputs.addAll(outputs);
      typeEnumeratedOutputs.addAll(outputs);
      if (variable.length() > 0) {
          List<IPath> outputPaths = new ArrayList<IPath>();
          for (int j = 0; j < outputs.size(); j++) {
        outputPaths.add(Path.fromOSString(outputs.get(j)));
          }
          if (myOutputMacros.containsKey(variable)) {
        List<IPath> currList = myOutputMacros.get(variable);
        currList.addAll(outputPaths);
        myOutputMacros.put(variable, currList);
          } else {
        myOutputMacros.put(variable, outputPaths);
          }
      }
        } catch (BuildException ex) {// JABA is not going to add
             // code
        }
    } else
    // 3. If a nameProvider is specified, call it
    if (nameProvider != null) {
        // The inputs must have been calculated before we can do
        // this
        IPath[] outNames = null;
        if (!inputsCalculated) {
      done = false;
        } else {
      Vector<String> inputs = getEnumeratedInputs();
      IPath[] inputPaths = new IPath[inputs.size()];
      for (int j = 0; j < inputPaths.length; j++) {
          inputPaths[j] = Path.fromOSString(inputs.get(j));
      }
      // JABA: I inserted this code to cater for bin or hex
      // extensions based on the board. Basically you need the
      // Project
      // to get to information to know whether this is a sam
      // or avr project (having it in the platform file would
      // be easier)
      // To make it as much compliant as possible with the
      // "CDT way" I added a getOutputNames which takes al the
      // info needed to
      // know the correct output name
      // if (inputPaths.length == 0) {
      try {
          IManagedOutputNameProviderJaba newNameProvider = (IManagedOutputNameProviderJaba) nameProvider;
          outNames = newNameProvider.getOutputNames(project, config, tool, inputPaths);
      } catch (Exception e) {
          // The provided class is not a
          // IManagedOutputNameProviderJaba class;
          Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID,
            "The provided class is not of type IManagedOutputNameProviderJaba", e));
      }
      // } else {
      // outNames = nameProvider.getOutputNames(tool,
      // inputPaths);
      // }
      // JABA end of insertion
      if (outNames != null) {
          for (int j = 0; j < outNames.length; j++) {
        String outputName = outNames[j].toString();
        try {
            // try to resolve the build macros in the
            // output names
            String resolved = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat(outputName, "", //$NON-NLS-1$
              " ", //$NON-NLS-1$
              IBuildMacroProvider.CONTEXT_CONFIGURATION, config);
            if ((resolved = resolved.trim()).length() > 0) {
          outputName = resolved;
          outNames[j] = Path.fromOSString(resolved);
            }
        } catch (BuildMacroException e) {// JABA is not
                 // going to add
                 // code
        }

        if (primaryOutput) {
            myCommandOutputs.add(outputName);
        }
        typeEnumeratedOutputs.add(outputName);
          }
      }
        }
        if (variable.length() > 0 && outNames != null) {
      if (myOutputMacros.containsKey(variable)) {
          List<IPath> currList = myOutputMacros.get(variable);
          currList.addAll(Arrays.asList(outNames));
          myOutputMacros.put(variable, currList);
      } else {
          myOutputMacros.put(variable, new ArrayList<IPath>(Arrays.asList(outNames)));
      }
        }
    } else
    // 4. If outputNames is specified, use it
    if (outputNames != null) {
        if (outputNames.length > 0) {
      for (int j = 0; j < outputNames.length; j++) {
          String outputName = outputNames[j];
          try {
        // try to resolve the build macros in the output
        // names
        String resolved = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat(outputName, "", //$NON-NLS-1$
          " ", //$NON-NLS-1$
          IBuildMacroProvider.CONTEXT_OPTION, new OptionContextData(option, tool));
        if ((resolved = resolved.trim()).length() > 0)
            outputNames[j] = resolved;
          } catch (BuildMacroException e) {// JABA is not
                   // going to add
                   // code
          }
      }
      List<String> namesList = Arrays.asList(outputNames);
      if (primaryOutput) {
          myCommandOutputs.addAll(namesList);
      }
      typeEnumeratedOutputs.addAll(namesList);
      if (variable.length() > 0) {
          List<IPath> outputPaths = new ArrayList<IPath>();
          for (int j = 0; j < namesList.size(); j++) {
        outputPaths.add(Path.fromOSString(namesList.get(j)));
          }
          if (myOutputMacros.containsKey(variable)) {
        List<IPath> currList = myOutputMacros.get(variable);
        currList.addAll(outputPaths);
        myOutputMacros.put(variable, currList);
          } else {
        myOutputMacros.put(variable, outputPaths);
          }
      }
        }
    } else {
        // 5. Use the name pattern to generate a transformation
        // macro
        // so that the source names can be transformed into the
        // target names
        // using the built-in string substitution functions of
        // <code>make</code>.
        if (multOfType) {
      // This case is not handled - a nameProvider or
      // outputNames must be specified
      List<String> errList = new ArrayList<String>();
      errList.add(ManagedMakeMessages.getResourceString("MakefileGenerator.error.no.nameprovider")); //$NON-NLS-1$
      myCommandOutputs.addAll(errList);
        } else {
      String namePattern = type.getNamePattern();
      if (namePattern == null || namePattern.length() == 0) {
          namePattern = outputPrefix + IManagedBuilderMakefileGenerator.WILDCARD;
          String outExt = (type.getOutputExtensions(tool))[0];
          if (outExt != null && outExt.length() > 0) {
        namePattern += DOT + outExt;
          }
      } else if (outputPrefix.length() > 0) {
          namePattern = outputPrefix + namePattern;
      }

      // Calculate the output name
      // The inputs must have been calculated before we can do
      // this
      if (!inputsCalculated) {
          done = false;
      } else {
          Vector<String> inputs = getEnumeratedInputs();
          String fileName;
          if (inputs.size() > 0) {
        // Get the input file name
        fileName = (Path.fromOSString(inputs.get(0))).removeFileExtension().lastSegment();
        // Check if this is a build macro. If so, use
        // the raw macro name.
        if (fileName.startsWith("$(") && fileName.endsWith(")")) { //$NON-NLS-1$ //$NON-NLS-2$
            fileName = fileName.substring(2, fileName.length() - 1);
        }
          } else {
        fileName = "default"; //$NON-NLS-1$
          }
          // Replace the % with the file name
          if (primaryOutput) {
        myCommandOutputs.add(namePattern.replaceAll("%", fileName)); //$NON-NLS-1$
          }
          typeEnumeratedOutputs.add(namePattern.replaceAll("%", fileName)); //$NON-NLS-1$
          if (variable.length() > 0) {
        List<IPath> outputs = new ArrayList<IPath>();
        outputs.add(Path.fromOSString(fileName));
        if (myOutputMacros.containsKey(variable)) {
            List<IPath> currList = myOutputMacros.get(variable);
            currList.addAll(outputs);
            myOutputMacros.put(variable, currList);
        } else {
            myOutputMacros.put(variable, outputs);
        }
          }
      }
        }
    }
    if (variable.length() > 0) {
        myBuildVars.add(variable);
        myBuildVarsValues.add(typeEnumeratedOutputs);
    }
    if (primaryOutput) {
        myEnumeratedPrimaryOutputs.addAll(typeEnumeratedOutputs);
    } else {
        myEnumeratedSecondaryOutputs.addAll(typeEnumeratedOutputs);
    }
      }
  } else {
      if (bIsTargetTool) {
    String outputPrefix = tool.getOutputPrefix();
    String outputName = outputPrefix + targetName;
    if (targetExt.length() > 0) {
        outputName += (DOT + targetExt);
    }
    myCommandOutputs.add(outputName);
    myEnumeratedPrimaryOutputs.add(outputName);
      } else {
    // For support of pre-CDT 3.0 integrations.
    // NOTE WELL: This only supports the case of a single
    // "target tool"
    // that consumes exactly all of the object files, $OBJS,
    // produced
    // by other tools in the build and produces a single output
      }
  }

  // Add the output macros of this tool to the buildOutVars map
  Set<Entry<String, List<IPath>>> entrySet = myOutputMacros.entrySet();
  for (Entry<String, List<IPath>> entry : entrySet) {
      String macroName = entry.getKey();
      List<IPath> newMacroValue = entry.getValue();
      HashMap<String, List<IPath>> map = makeGen.getBuildOutputVars();
      if (map.containsKey(macroName)) {
    List<IPath> macroValue = map.get(macroName);
    macroValue.addAll(newMacroValue);
    map.put(macroName, macroValue);
      } else {
    map.put(macroName, newMacroValue);
      }
  }
  outputVariablesCalculated = true;

  if (done) {
      commandOutputs.addAll(myCommandOutputs);
      enumeratedPrimaryOutputs.addAll(myEnumeratedPrimaryOutputs);
      enumeratedSecondaryOutputs.addAll(myEnumeratedSecondaryOutputs);
      outputVariables.addAll(myOutputMacros.keySet());
      outputsCalculated = true;
      for (int i = 0; i < myBuildVars.size(); i++) {
    makeGen.addMacroAdditionFiles(makeGen.getTopBuildOutputVars(), myBuildVars.get(i), myBuildVarsValues.get(i));
      }
      return true;
  }

  return false;
    }

    private boolean callDependencyCalculator(ArduinoGnuMakefileGenerator makeGen, IConfiguration config, HashSet<String> handledInputExtensions,
      IManagedDependencyGeneratorType depGen, String[] extensionsList, Vector<String> myCommandDependencies,
      HashMap<String, List<IPath>> myOutputMacros, Vector<String> myAdditionalTargets, ToolInfoHolder h, boolean _done) {
  boolean done = _done;
  int calcType = depGen.getCalculatorType();
  switch (calcType) {
  case IManagedDependencyGeneratorType.TYPE_COMMAND:
  case IManagedDependencyGeneratorType.TYPE_BUILD_COMMANDS:
      // iterate over all extensions that the tool knows how to handle
      for (int i = 0; i < extensionsList.length; i++) {
    String extensionName = extensionsList[i];

    // Generated files should not appear in the list.
    if (!makeGen.getOutputExtensions(h).contains(extensionName) && !handledInputExtensions.contains(extensionName)) {
        handledInputExtensions.add(extensionName);
        String depExt = IManagedBuilderMakefileGenerator.DEP_EXT;
        if (calcType == IManagedDependencyGeneratorType.TYPE_BUILD_COMMANDS) {
      IManagedDependencyGenerator2 depGen2 = (IManagedDependencyGenerator2) depGen;
      String xt = depGen2.getDependencyFileExtension(config, tool);
      if (xt != null && xt.length() > 0)
          depExt = xt;
        }
        String depsMacroEntry = calculateSourceMacro(makeGen, extensionName, depExt, IManagedBuilderMakefileGenerator.WILDCARD);

        List<IPath> depsList = new ArrayList<IPath>();
        depsList.add(Path.fromOSString(depsMacroEntry));
        String depsMacro = makeGen.getDepMacroName(extensionName).toString();
        if (myOutputMacros.containsKey(depsMacro)) {
      List<IPath> currList = myOutputMacros.get(depsMacro);
      currList.addAll(depsList);
      myOutputMacros.put(depsMacro, currList);
        } else {
      myOutputMacros.put(depsMacro, depsList);
        }
    }
      }
      break;

  case IManagedDependencyGeneratorType.TYPE_INDEXER:
  case IManagedDependencyGeneratorType.TYPE_EXTERNAL:
  case IManagedDependencyGeneratorType.TYPE_CUSTOM:
      // The inputs must have been calculated before we can do this
      if (!inputsCalculated) {
    done = false;
      } else {
    Vector<String> inputs = getEnumeratedInputs();

    if (calcType == IManagedDependencyGeneratorType.TYPE_CUSTOM) {
        IManagedDependencyGenerator2 depGen2 = (IManagedDependencyGenerator2) depGen;
        IManagedDependencyInfo depInfo = null;
        for (int i = 0; i < inputs.size(); i++) {

      depInfo = depGen2.getDependencySourceInfo(Path.fromOSString(inputs.get(i)), config, tool, makeGen.getBuildWorkingDir());

      if (depInfo instanceof IManagedDependencyCalculator) {
          IManagedDependencyCalculator depCalc = (IManagedDependencyCalculator) depInfo;
          IPath[] depPaths = depCalc.getDependencies();
          if (depPaths != null) {
        for (int j = 0; j < depPaths.length; j++) {
            if (!depPaths[j].isAbsolute()) {
          // Convert from project relative to
          // build directory relative
          IPath absolutePath = project.getLocation().append(depPaths[j]);
          depPaths[j] = ManagedBuildManager.calculateRelativePath(makeGen.getTopBuildDir(), absolutePath);
            }
            myCommandDependencies.add(depPaths[j].toString());
        }
          }
          IPath[] targetPaths = depCalc.getAdditionalTargets();
          if (targetPaths != null) {
        for (int j = 0; j < targetPaths.length; j++) {
            myAdditionalTargets.add(targetPaths[j].toString());
        }
          }
      }
        }
    } else {
        IManagedDependencyGenerator oldDepGen = (IManagedDependencyGenerator) depGen;
        for (String input : inputs) {
      IResource[] outNames = oldDepGen.findDependencies(project.getFile(input), project);
      if (outNames != null) {
          for (IResource outName : outNames) {
        myCommandDependencies.add(outName.toString());
          }
      }
        }
    }
      }
      break;

  default:
      break;
  }

  return done;
    }

    /**
     * @param lastChance
     */
    public boolean calculateDependencies(ArduinoGnuMakefileGenerator makeGen, IConfiguration config, HashSet<String> handledInputExtensions,
      ToolInfoHolder h, boolean lastChance) {
  // Get the dependencies for this tool invocation
  boolean done = true;
  Vector<String> myCommandDependencies = new Vector<String>();
  Vector<String> myAdditionalTargets = new Vector<String>();
  // Vector myEnumeratedDependencies = new Vector();
  HashMap<String, List<IPath>> myOutputMacros = new HashMap<String, List<IPath>>();

  IInputType[] inTypes = tool.getInputTypes();
  if (inTypes != null && inTypes.length > 0) {
      for (int i = 0; i < inTypes.length; i++) {
    IInputType type = inTypes[i];

    // Handle dependencies from the dependencyCalculator
    IManagedDependencyGeneratorType depGen = type.getDependencyGenerator();
    String[] extensionsList = type.getSourceExtensions(tool);
    if (depGen != null) {
        done = callDependencyCalculator(makeGen, config, handledInputExtensions, depGen, extensionsList, myCommandDependencies,
          myOutputMacros, myAdditionalTargets, h, done);
    }

    // Add additional dependencies specified in AdditionalInput
    // elements
    IAdditionalInput[] addlInputs = type.getAdditionalInputs();
    if (addlInputs != null && addlInputs.length > 0) {
        for (int j = 0; j < addlInputs.length; j++) {
      IAdditionalInput addlInput = addlInputs[j];
      int kind = addlInput.getKind();
      if (kind == IAdditionalInput.KIND_ADDITIONAL_DEPENDENCY || kind == IAdditionalInput.KIND_ADDITIONAL_INPUT_DEPENDENCY) {
          String[] paths = addlInput.getPaths();
          if (paths != null) {
        for (int k = 0; k < paths.length; k++) {
            // Translate the path from project relative
            // to
            // build directory relative
            String path = paths[k];
            if (!(path.startsWith("$("))) { //$NON-NLS-1$
          IResource addlResource = project.getFile(path);
          if (addlResource != null) {
              IPath addlPath = addlResource.getLocation();
              if (addlPath != null) {
            path = ManagedBuildManager.calculateRelativePath(makeGen.getTopBuildDir(), addlPath).toString();
              }
          }
            }
            myCommandDependencies.add(path);
            // myEnumeratedInputs.add(path);
        }
          }
      }
        }
    }
      }
  } else {
      if (bIsTargetTool) {
    // For support of pre-CDT 3.0 integrations.
    // NOTE WELL: This only supports the case of a single
    // "target tool"
    // with the following characteristics:
    // 1. The tool consumes exactly all of the object files produced
    // by other tools in the build and produces a single output
    // 2. The target name comes from the configuration artifact name
    // The rule looks like:
    // <targ_prefix><target>.<extension>: $(OBJS) <refd_project_1
    // ... refd_project_n>
    myCommandDependencies.add("$(OBJS)"); //$NON-NLS-1$
    myCommandDependencies.add("$(USER_OBJS)"); //$NON-NLS-1$
      } else {
    // Handle dependencies from the dependencyCalculator
    IManagedDependencyGeneratorType depGen = tool.getDependencyGenerator();
    String[] extensionsList = tool.getAllInputExtensions();
    if (depGen != null) {
        done = callDependencyCalculator(makeGen, config, handledInputExtensions, depGen, extensionsList, myCommandDependencies,
          myOutputMacros, myAdditionalTargets, h, done);
    }

      }
  }

  // Add the output macros of this tool to the buildOutVars map
  Set<Entry<String, List<IPath>>> entrySet = myOutputMacros.entrySet();
  for (Entry<String, List<IPath>> entry : entrySet) {
      String macroName = entry.getKey();
      List<IPath> newMacroValue = entry.getValue();
      HashMap<String, List<IPath>> map = makeGen.getBuildOutputVars();
      if (map.containsKey(macroName)) {
    List<IPath> macroValue = map.get(macroName);
    macroValue.addAll(newMacroValue);
    map.put(macroName, macroValue);
      } else {
    map.put(macroName, newMacroValue);
      }
  }

  if (done) {
      commandDependencies.addAll(myCommandDependencies);
      additionalTargets.addAll(myAdditionalTargets);
      // enumeratedDependencies.addAll(myEnumeratedDependencies);
      dependenciesCalculated = true;
      return true;
  }

  return false;
    }

    /*
     * Calculate the source macro for the given extension
     */
    protected String calculateSourceMacro(ArduinoGnuMakefileGenerator makeGen, String srcExtensionName, String outExtensionName, String wildcard) {
  StringBuffer macroName = makeGen.getSourceMacroName(srcExtensionName);
  String OptDotExt = ""; //$NON-NLS-1$
  if (outExtensionName != null) {
      OptDotExt = DOT + outExtensionName;
  } else if (tool.getOutputExtension(srcExtensionName) != "") //$NON-NLS-1$
      OptDotExt = DOT + tool.getOutputExtension(srcExtensionName);

  // create rule of the form
  // OBJS = $(macroName1: ../%.input1=%.output1) ... $(macroNameN:
  // ../%.inputN=%.outputN)
  StringBuffer objectsBuffer = new StringBuffer();
  objectsBuffer.append(IManagedBuilderMakefileGenerator.WHITESPACE + "$(" + macroName + //$NON-NLS-1$
    IManagedBuilderMakefileGenerator.COLON + IManagedBuilderMakefileGenerator.ROOT + IManagedBuilderMakefileGenerator.SEPARATOR
    + IManagedBuilderMakefileGenerator.WILDCARD + DOT + srcExtensionName + "=" + wildcard + OptDotExt + ")"); //$NON-NLS-1$ //$NON-NLS-2$
  return objectsBuffer.toString();
    }

}
TOP

Related Classes of it.baeyens.arduino.toolchain.ArduinoManagedBuildGnuToolInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.