/******************************************************************************* * Copyright (c) 2004, 2016 IBM 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM - Initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig2; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; import java.util.List; import org.eclipse.cdt.make.core.MakeCorePlugin; import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector2; import org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes; import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerConfigUtil; import org.eclipse.cdt.make.internal.core.scannerconfig.gnu.GCCScannerConfigUtil; import org.eclipse.cdt.make.internal.core.scannerconfig.util.CCommandDSC; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; /** * A 'provider' that will generate a special makefile to generate scanner config * * @author vhirsl */ public class SCDMakefileGenerator extends DefaultRunSIProvider { private static final String ENDL = System.getProperty("line.separator"); //$NON-NLS-1$ private static final String DENDL = ENDL+ENDL; private String fMakeCommand = "-f ${project_name}_scd.mk "; //$NON-NLS-1$ /* (non-Javadoc) * @see org.eclipse.cdt.make.internal.core.scannerconfig2.DefaultRunSIProvider#initialize() */ @Override protected boolean initialize() { String args = buildInfo.getProviderRunArguments(providerId); if (null == args) args = " -E -P -v -dD "; //$NON-NLS-1$ else { int nPos = args.indexOf('|'); if(nPos > 0) { fMakeCommand = args.substring(0, nPos); args = args.substring(nPos + 1); } } fCompileCommand = new Path(buildInfo.getProviderRunCommand(providerId)); args = substituteDynamicVariables(args); fCompileArguments = ScannerConfigUtil.tokenizeStringWithQuotes(args, "\"");//$NON-NLS-1$ fWorkingDirectory = MakeCorePlugin.getWorkingDirectory(); fMakeCommand = substituteDynamicVariables(fMakeCommand); return generateMakefile(resource.getProject().getName()); } private boolean generateMakefile(String projectName) { boolean rc = false; if (collector instanceof IScannerInfoCollector2) { IScannerInfoCollector2 collector2 = (IScannerInfoCollector2) collector; @SuppressWarnings("unchecked") List<CCommandDSC> commands = collector2.getCollectedScannerInfo( resource.getProject(), ScannerInfoTypes.UNDISCOVERED_COMPILER_COMMAND); if (commands != null && commands.size() > 0) { StringBuilder buffer = new StringBuilder(); buffer.append("# This is a generated file. Please do not edit."); //$NON-NLS-1$ buffer.append(DENDL); buffer.append(".PHONY: all"); //$NON-NLS-1$ buffer.append(DENDL); buffer.append("COMMANDS := "); //$NON-NLS-1$ for (CCommandDSC cmd : commands) { buffer.append("\t\\"); //$NON-NLS-1$ buffer.append(ENDL); buffer.append("\t scd_cmd_"); //$NON-NLS-1$ buffer.append(cmd.getCommandId()); } buffer.append(DENDL); buffer.append("all: $(COMMANDS)"); //$NON-NLS-1$ buffer.append(DENDL); for (CCommandDSC cmd : commands) { buffer.append("scd_cmd_"); //$NON-NLS-1$ buffer.append(cmd.getCommandId()); buffer.append(':'); buffer.append(ENDL); buffer.append("\t@echo begin generating scanner info for $@"); //$NON-NLS-1$ buffer.append(ENDL); buffer.append('\t'); buffer.append(cmd.getSCDRunnableCommand(true, true)); // quote includes and defines for (String arg : prepareArguments(buildInfo.isUseDefaultProviderCommand(providerId))) { buffer.append(' '); buffer.append(arg); } buffer.append(' '); buffer.append(cmd.appliesToCPPFileType() ? "specs.cpp" : "specs.c"); //$NON-NLS-1$ //$NON-NLS-2$ buffer.append(ENDL); buffer.append("\t@echo end generating scanner info for $@"); //$NON-NLS-1$ buffer.append(DENDL); } File makefile = new File(fWorkingDirectory.toFile(), getMakeFileName(projectName)); try { PrintStream ps = new PrintStream(new FileOutputStream(makefile)); ps.println(buffer.toString()); ps.close(); rc = true; } catch (FileNotFoundException e) { MakeCorePlugin.log(e); } } } return rc; } private String getMakeFileName(String projectName) { String[] makeArgs = ScannerConfigUtil.tokenizeStringWithQuotes(fMakeCommand, "\"");//$NON-NLS-1$ boolean found = false; for(String arg : makeArgs) { if(found) return arg; if(arg.equals("-f")) //$NON-NLS-1$ found = true; } return projectName+"_scd.mk"; //$NON-NLS-1$ } protected String substituteDynamicVariables(String in) { String string = in; // TODO: replace it with Eclipse Dynamic Variable Resolver // string = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(string, false); string = string.replaceAll("\\$\\{project_name\\}", //$NON-NLS-1$ resource.getProject().getName()); string = string.replaceAll("\\$\\{plugin_state_location\\}", //$NON-NLS-1$ MakeCorePlugin.getWorkingDirectory().toString()); string = string.replaceAll("\\$\\{specs_file\\}", //$NON-NLS-1$ GCCScannerConfigUtil.C_SPECS_FILE ); return string; } @Override protected String[] getCommandLineOptions() { return ScannerConfigUtil.tokenizeStringWithQuotes(fMakeCommand, "\""); //$NON-NLS-1$ } @Override protected IPath getCommandToLaunch() { return new Path("make"); //$NON-NLS-1$ } }