blob: 64a18c53f6e445080cec7c62b150ccc932d445de [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems 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:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.arduino.core.internal;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.Writer;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoardManager;
import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuilder;
import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedProject;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.remote.core.IRemoteConnection;
import org.eclipse.remote.core.IRemoteConnectionType;
import org.eclipse.remote.core.IRemoteServicesManager;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
@SuppressWarnings("restriction")
public class ArduinoProjectGenerator {
private final IProject project;
private IFile sourceFile;
public ArduinoProjectGenerator(IProject project) {
this.project = project;
}
public void setupArduinoProject(IProgressMonitor monitor) throws CoreException {
// Add Arduino nature
IProjectDescription projDesc = project.getDescription();
String[] oldIds = projDesc.getNatureIds();
String[] newIds = new String[oldIds.length + 1];
System.arraycopy(oldIds, 0, newIds, 0, oldIds.length);
newIds[newIds.length - 1] = ArduinoProjectNature.ID;
projDesc.setNatureIds(newIds);
// Add Arduino Builder
ICommand command = projDesc.newCommand();
command.setBuilderName(ArduinoBuilder.ID);
projDesc.setBuildSpec(new ICommand[] { command });
project.setDescription(projDesc, monitor);
// create the CDT natures and build setup
CCorePlugin.getDefault().createCDTProject(projDesc, project, monitor);
ICProjectDescription cprojDesc = CCorePlugin.getDefault().createProjectDescription(project, false);
ManagedBuildInfo info = ManagedBuildManager.createBuildInfo(project);
ManagedProject mProj = new ManagedProject(cprojDesc);
info.setManagedProject(mProj);
// TODO make this a preference, the default board
String boardName = "Arduino Uno"; //$NON-NLS-1$
String platformName = "Arduino AVR Boards"; //$NON-NLS-1$
String packageName = "arduino"; //$NON-NLS-1$
IRemoteServicesManager remoteManager = Activator.getService(IRemoteServicesManager.class);
IRemoteConnectionType connectionType = remoteManager.getConnectionType(ArduinoRemoteConnection.TYPE_ID);
Collection<IRemoteConnection> connections = connectionType.getConnections();
if (!connections.isEmpty()) {
IRemoteConnection firstConnection = connections.iterator().next();
IArduinoRemoteConnection firstArduino = firstConnection.getService(IArduinoRemoteConnection.class);
boardName = firstArduino.getBoardName();
platformName = firstArduino.getPlatformName();
packageName = firstArduino.getPackageName();
}
ArduinoBoardManager.instance.createBuildConfiguration(cprojDesc, boardName, platformName, packageName);
CCorePlugin.getDefault().setProjectDescription(project, cprojDesc, true, monitor);
// Generate files
try {
Configuration fmConfig = new Configuration(Configuration.VERSION_2_3_22);
URL templateDirURL = FileLocator.find(Activator.getContext().getBundle(), new Path("/templates"), null); //$NON-NLS-1$
fmConfig.setDirectoryForTemplateLoading(new File(FileLocator.toFileURL(templateDirURL).toURI()));
final Map<String, Object> fmModel = new HashMap<>();
fmModel.put("projectName", project.getName()); //$NON-NLS-1$
generateFile(fmModel, fmConfig.getTemplate("Makefile"), project.getFile("Makefile")); //$NON-NLS-1$ //$NON-NLS-2$
generateFile(fmModel, fmConfig.getTemplate("arduino.mk"), project.getFile("arduino.mk")); //$NON-NLS-1$ //$NON-NLS-2$
sourceFile = project.getFile(project.getName() + ".cpp"); //$NON-NLS-1$
generateFile(fmModel, fmConfig.getTemplate("arduino.cpp"), sourceFile); //$NON-NLS-1$
} catch (IOException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), e.getLocalizedMessage(), e));
} catch (URISyntaxException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), e.getLocalizedMessage(), e));
} catch (TemplateException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), e.getLocalizedMessage(), e));
}
// Do the initial build
project.build(IncrementalProjectBuilder.FULL_BUILD, monitor);
}
private static void generateFile(Object model, Template template, final IFile outputFile)
throws TemplateException, IOException, CoreException {
final PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
final Writer writer = new OutputStreamWriter(out);
Job job = new Job(Messages.ArduinoProjectGenerator_0) {
protected IStatus run(IProgressMonitor monitor) {
try {
outputFile.create(in, true, monitor);
} catch (CoreException e) {
return e.getStatus();
}
return Status.OK_STATUS;
}
};
job.setRule(outputFile.getProject());
job.schedule();
template.process(model, writer);
writer.close();
try {
job.join();
} catch (InterruptedException e) {
// TODO anything?
}
IStatus status = job.getResult();
if (!status.isOK())
throw new CoreException(status);
}
public IFile getSourceFile() {
return sourceFile;
}
}