/*******************************************************************************
* Copyright (c) 2014 Rohde & Schwarz GmbH & Co. KG 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:
* Martin Runge - initial implementation of cmake support
*******************************************************************************/
package org.eclipse.cdt.cmake.langset;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.cmake.Activator;
import org.eclipse.cdt.cmake.langset.IBuildCommandParserEx.CompileUnitInfo;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.osgi.service.prefs.BackingStoreException;
/**
* @author runge_m
*
*/
public class CompileCmdsHandler {
private String configName = null;
private IProject project = null;
private String filename = null;
private String xCompExe;
private String xCompPath;
private String xCompCmd;
private String xCompFlags;
private List<CompileUnitInfo> foreignSources = new ArrayList<CompileUnitInfo>();
private List<CompileUnitInfo> sources = new ArrayList<CompileUnitInfo>();
public static final String COMPILE_CMDS_FILENAME = "compile_commands.json";
public static final String CROSS_GCC_TOOL_ID = "org.eclipse.cdt.cmake.compiler.c";
public static final String CROSS_GPP_TOOL_ID = "org.eclipse.cdt.cmake.compiler.c++";
//public static final String CROSS_TOOLCHAIN_PREFIX_OPTION_ID = "cdt.managedbuild.option.gnu.cross.prefix";
public static final String CROSS_TOOLCHAIN_PREFIX_OPTION_ID = "org.eclipse.cdt.cmake.cross.prefix";
public static final String CROSS_TOOLCHAIN_PATH_OPTION_ID = "cdt.managedbuild.option.gnu.cross.path";
public CompileCmdsHandler(IProject project, String configName, String filename) {
this.configName = configName;
this.project = project;
this.filename = filename;
}
/**
* @return the filename
*/
public String getFilename() {
return filename;
}
public Long getFileModTime() {
File f = new File(this.filename);
Long current_ts = f.lastModified();
return current_ts;
}
public String getProjectName() {
return this.project.getName();
}
public String getConfigName() {
return this.configName;
}
public String getxCompFlags() {
return xCompFlags;
}
public void setxCompFlags(String xCompFlags) {
this.xCompFlags = xCompFlags;
}
public String getxCompExe() {
return xCompExe;
}
public void setxCompExe(String xCompExe) {
this.xCompExe = xCompExe;
}
public String getxCompCmd() {
return xCompCmd;
}
public void setxCompCmd(String xCompCmd) {
this.xCompCmd = xCompCmd;
}
public String getxCompPath() {
return xCompPath;
}
public void setxCompPath(String compilerPath) {
this.xCompPath = compilerPath;
}
public void parseCMakeCompileCommands() throws FileNotFoundException, JSONException {
foreignSources.clear();
sources.clear();
FileReader reader = new FileReader(this.filename);
JSONTokener tokener = new JSONTokener(reader);
JSONArray rootArray = new JSONArray(tokener);
for(int i=0; i < rootArray.length(); i++) {
Object obj = rootArray.get(i);
if(obj instanceof JSONObject) {
JSONObject jobj = (JSONObject)obj;
String directory = jobj.getString("directory");
String command = jobj.getString("command");
String sourceFile = jobj.getString("file");
CompileUnitInfo cu = new CompileUnitInfo(sourceFile, new Path(directory), command);
sources.add(cu);
detectCompiler();
}
}
}
public boolean isOutsideProject(CompileUnitInfo cu) {
return false;
}
protected void detectCompiler() {
if(sources.size() < 1 ) {
return;
}
CompileUnitInfo cui = sources.get(0);
String compilerCommand = "";
String flags = "";
String sysrootPath = "";
boolean nextPartIsSysrootPath = false;
String cmd = cui.getCmdLine();
String[] parts = cmd.split(" ");
for(String part: parts) {
if(part.endsWith("gcc") || part.endsWith("g++") || part.endsWith("c++") || part.endsWith("cc") ) {
// this is the compiler part
compilerCommand = part ;
continue;
}
if(part.startsWith("--sysroot")) {
if(part.startsWith("--sysroot=")) {
// path in included part
/// TODO: handle path with whitespaces which would be continues in next part
sysrootPath = part.substring("--sysroot=".length());
}
else {
// path is in next part
/// TODO: handle path with whitespaces which would be continues in next part
nextPartIsSysrootPath = true;
}
continue;
}
if(nextPartIsSysrootPath == true) {
sysrootPath = part;
nextPartIsSysrootPath = false;
}
}
if(!sysrootPath.isEmpty()) {
flags += "--sysroot " + sysrootPath;
}
xCompCmd = compilerCommand;
java.nio.file.Path compCmd = Paths.get(compilerCommand);
xCompPath = compCmd.getParent().toString();
xCompExe = compCmd.getFileName().toString();
xCompFlags = flags;
}
/**
* @return
*/
public boolean hasSourcesOutsideProject() {
// TODO Auto-generated method stub
return false;
}
/**
* @return
* @throws BackingStoreException
*/
public boolean hasChanged(boolean resetModifiedTimestamp) throws BackingStoreException {
ProjectScope ps = new ProjectScope(project);
IEclipsePreferences prefs = ps.getNode( Activator.getId() );
String key = this.filename;
Long value = prefs.getLong(key, 0);
Long current_ts = getFileModTime();
if(resetModifiedTimestamp) {
prefs.putLong(key, current_ts);
prefs.flush();
}
if(value.longValue() == current_ts.longValue()) {
return false;
}
else {
return true;
}
}
/**
* @return
*/
public List<CompileUnitInfo> getSources() {
return sources;
}
/**
* @return
*/
public List<CompileUnitInfo> getSourcesOutsideProject() {
return foreignSources;
}
}