/******************************************************************************* * Copyright (c) 2009, 2013 Andrew Gvozdev 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrew Gvozdev - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.language.settings.providers; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.managedbuilder.core.BuildException; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IInputType; import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.eclipse.cdt.managedbuilder.internal.envvar.EnvironmentVariableManagerToolChain; /** * Abstract parser capable to execute compiler command printing built-in compiler * specs and parse built-in language settings out of it. The compiler to be used * is taken from MBS tool-chain definition. * <p> * <strong>EXPERIMENTAL</strong>. This class interface is not stable yet as * it is not currently (CDT 8.1, Juno) clear how it may need to be used in future. * There is no guarantee that this API will work or that it will remain the same. * Please do not use this API without consulting with the CDT team. * </p> * @noextend This class is not intended to be subclassed by clients. * * @since 8.1 */ public abstract class ToolchainBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector { private static final String EMPTY_QUOTED_STRING = "\"\""; //$NON-NLS-1$ private Map<String, ITool> toolMap = new HashMap<String, ITool>(); /** * Concrete compiler specs detectors need to supply tool-chain ID. * * Tool-chain id must be supplied for global providers where we don't * have configuration description to figure that out programmatically. * @since 8.2 */ public abstract String getToolchainId(); /** * Finds a tool handling given language in the tool-chain of the provider. * This returns the first tool found. */ private ITool getTool(String languageId) { if (languageId == null) { return null; } if (currentCfgDescription == null) { ITool tool = toolMap.get(languageId); if (tool != null) { return tool; } } String toolchainId = null; IToolChain toolchain = null; ITool tool = null; if (currentCfgDescription != null) { IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription(currentCfgDescription); toolchain = cfg != null ? cfg.getToolChain() : null; toolchainId = toolchain != null ? toolchain.getId() : null; } if (toolchain == null) { toolchainId = getToolchainId(); toolchain = ManagedBuildManager.getExtensionToolChain(toolchainId); } for (;toolchain != null;toolchain = toolchain.getSuperClass()) { tool = getTool(languageId, toolchain); if (tool != null) { break; } } if (currentCfgDescription == null && tool != null) { // cache only for global providers which use extension tool-chains that can not change toolMap.put(languageId, tool); } if (tool == null) { ManagedBuilderCorePlugin.error("Unable to find tool in toolchain=" + toolchainId + " for language=" + languageId); //$NON-NLS-1$ //$NON-NLS-2$ } return tool; } /** * Finds a tool handling given language in the tool-chain. * This returns the first tool found. */ private ITool getTool(String languageId, IToolChain toolchain) { ITool[] tools = toolchain.getTools(); for (ITool tool : tools) { IInputType[] inputTypes = tool.getInputTypes(); for (IInputType inType : inputTypes) { String lang = inType.getLanguageId(tool); if (languageId.equals(lang)) { return tool; } } } return null; } @Override protected String getCompilerCommand(String languageId) { ITool tool = getTool(languageId); String compilerCommand = tool != null ? tool.getToolCommand() : ""; //$NON-NLS-1$ if (compilerCommand.isEmpty()) { ManagedBuilderCorePlugin.error("Unable to find compiler command in toolchain=" + getToolchainId()); //$NON-NLS-1$ } return compilerCommand; } @Override protected String getSpecFileExtension(String languageId) { String ext = null; ITool tool = getTool(languageId); String[] srcFileExtensions = tool != null ? tool.getAllInputExtensions() : null; if (srcFileExtensions != null && srcFileExtensions.length > 0) { ext = srcFileExtensions[0]; } if (ext == null || ext.isEmpty()) { ManagedBuilderCorePlugin.error("Unable to find file extension for language " + languageId); //$NON-NLS-1$ } return ext; } @Override protected String getToolOptions(String languageId) { String flags = ""; //$NON-NLS-1$ ITool tool = getTool(languageId); if (tool != null) { IOption[] options = tool.getOptions(); for (IOption option : options) { if (option.isForScannerDiscovery()) { try { String optionValue = null; switch (option.getBasicValueType()) { case IOption.BOOLEAN: if (option.getBooleanValue()) { optionValue = option.getCommand(); } else { optionValue = option.getCommandFalse(); } break; case IOption.ENUMERATED: optionValue = option.getEnumCommand(option.getSelectedEnum()); break; case IOption.STRING: optionValue = option.getCommand() + option.getStringValue(); break; case IOption.STRING_LIST: String[] values = option.getBasicStringListValue(); if(values != null) { optionValue = ""; //$NON-NLS-1$ String cmd = option.getCommand(); for (String value : values) { if(!value.isEmpty() && !value.equals(EMPTY_QUOTED_STRING)) { optionValue = optionValue + cmd + value + ' '; } } } break; case IOption.TREE: optionValue = option.getCommand(option.getStringValue()); break; default: } if (optionValue != null) { flags = flags + ' ' + optionValue.trim(); } } catch (BuildException e) { ManagedBuilderCorePlugin.log(e); } } } } return flags.trim(); } @Override protected List<IEnvironmentVariable> getEnvironmentVariables() { if (envMngr == null && currentCfgDescription == null) { // For global provider need to include toolchain in the equation IToolChain toolchain = ManagedBuildManager.getExtensionToolChain(getToolchainId()); envMngr = new EnvironmentVariableManagerToolChain(toolchain); } List<IEnvironmentVariable> vars = super.getEnvironmentVariables(); return vars; } }