/* Copyright (C) 2009 Mobile Sorcery AB This program is free software; you can redistribute it and/or modify it under the terms of the Eclipse Public License v1.0. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for more details. You should have received a copy of the Eclipse Public License v1.0 along with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html */ package com.mobilesorcery.sdk.internal.cdt; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.CoreModelUtil; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.IMacroEntry; import org.eclipse.cdt.core.model.IOutputEntry; import org.eclipse.cdt.core.model.IPathEntry; import org.eclipse.cdt.core.model.IPathEntryContainer; import org.eclipse.cdt.core.model.ISourceEntry; import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import com.mobilesorcery.sdk.core.CoreMoSyncPlugin; import com.mobilesorcery.sdk.core.IBuildVariant; import com.mobilesorcery.sdk.core.MoSyncBuilder; import com.mobilesorcery.sdk.core.MoSyncProject; import com.mobilesorcery.sdk.core.ParameterResolverException; import com.mobilesorcery.sdk.core.Util; public class MoSyncIncludePathContainer implements IPathEntryContainer { public final static IPath CONTAINER_ID = new Path("com.mobilesorcery.mosync.includepaths"); private final IProject project; public MoSyncIncludePathContainer(IProject project) { this.project = project; } @Override public String getDescription() { return "MoSync Include Path"; } @Override public IPath getPath() { return CONTAINER_ID; } @Override public IPathEntry[] getPathEntries() { List<IPathEntry> entries = new ArrayList<IPathEntry>(); MoSyncProject project = MoSyncProject.create(this.project); if (project != null) { IBuildVariant variant = MoSyncBuilder.getActiveVariant(project); try { IPath[] includePaths = MoSyncBuilder.getBaseIncludePaths(project, variant); for (int i = 0; i < includePaths.length; i++) { IContainer[] includePathInWorkspace = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocation(includePaths[i]); IPath resourcePath = includePathInWorkspace.length > 0 ? includePathInWorkspace[0].getProjectRelativePath() : Path.EMPTY; entries.add(CoreModel.newIncludeEntry(resourcePath, Path.EMPTY, includePaths[i], true)); } } catch (ParameterResolverException e) { // TODO: Error marker? CoreMoSyncPlugin.getDefault().log(e); } } entries.addAll(Arrays.asList(createCompilerSymbols())); entries.addAll(createOutputEntries(project.getWrappedProject())); return entries.toArray(new IPathEntry[entries.size()]); } private IMacroEntry[] createCompilerSymbols() { ArrayList<IMacroEntry> compilerSymbols = new ArrayList<IMacroEntry>(createPredefinedCompilerSymbols()); compilerSymbols.addAll(extractCompilerSymbolsFromGCCArgs(project)); return compilerSymbols.toArray(new IMacroEntry[0]); } private List<IMacroEntry> createPredefinedCompilerSymbols() { return Arrays.asList(new IMacroEntry[] { CoreModel.newMacroEntry(Path.EMPTY, "__GNUC__", ""), CoreModel.newMacroEntry(Path.EMPTY, "MAPIP", "") }); } /** * <p>Given a project with mosync nature, extracts all user defined -Darg=value * from the project's <i>extra</i> gcc command line arguments, and converts * them into a set of <code>IMacroEntry</code>s.</p> * <p>Refactoring note: this method could (should?) be moved</p> * @return */ public static List<IMacroEntry> extractCompilerSymbolsFromGCCArgs(IProject project) { ArrayList<IMacroEntry> compilerSymbols = new ArrayList<IMacroEntry>(); MoSyncProject mosyncProject = MoSyncProject.create(project); if (mosyncProject == null) { throw new IllegalStateException("Project does not have MoSync Nature"); } Map<String, String> defines = MoSyncBuilder.extractMacroDefinesFromGCCArgs(mosyncProject, MoSyncBuilder.getActiveVariant(mosyncProject)); for (Map.Entry<String, String> define : defines.entrySet()) { IMacroEntry macroEntry = CoreModel.newMacroEntry(Path.EMPTY, define.getKey(), define.getValue()); compilerSymbols.add(macroEntry); } return compilerSymbols; } private static List<IOutputEntry> createOutputEntries(IProject project) { // This one seems to be a bit prototype-ish, feel free to rip it out and replace it with something useful // Note that the original intent of this was to make sure that the indexer does not index the large // generated XCode files for the iPhone. HOWEVER, I've left this approach and started using resource filters instead... IFolder outputPath = project.getFolder(new Path(MoSyncBuilder.OUTPUT)); IPath[] exclusionPattern = new IPath[] { new Path("rebuild.build.cpp") }; List<IOutputEntry> result = new ArrayList<IOutputEntry>(); addAsOutputEntryIfExists(result, outputPath, exclusionPattern); return result; } private static void addAsOutputEntryIfExists(List<IOutputEntry> result, IFolder sourceFolder, IPath[] exclusionPattern) { if (sourceFolder.exists()) { result.add(CoreModel.newOutputEntry(sourceFolder.getFullPath(), exclusionPattern)); } } }