Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2011-11-21 21:56:38 -0500
committerAlena Laskavaia2011-11-21 21:56:38 -0500
commita3dd98987aac6bbe923499647d75c6e1f135f654 (patch)
treecd5f586b3412c0604c24b3213714b777af115cd3 /build/org.eclipse.cdt.managedbuilder.core
parent5c1a981cd7a29a202e88964acf034e76ffe289b2 (diff)
downloadorg.eclipse.cdt-a3dd98987aac6bbe923499647d75c6e1f135f654.tar.gz
org.eclipse.cdt-a3dd98987aac6bbe923499647d75c6e1f135f654.tar.xz
org.eclipse.cdt-a3dd98987aac6bbe923499647d75c6e1f135f654.zip
Bug 210248 - [Internal Builder]does not rebuild a dependent project in
case of a reference library project change Conflicts: build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java
Diffstat (limited to 'build/org.eclipse.cdt.managedbuilder.core')
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java332
1 files changed, 330 insertions, 2 deletions
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java
index b0ba81b5e2..01c05fd947 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java
@@ -11,17 +11,51 @@
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.internal.core;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.internal.core.SafeStringInterner;
+import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IAdditionalInput;
+import org.eclipse.cdt.managedbuilder.core.IBuildObject;
+import org.eclipse.cdt.managedbuilder.core.IBuilder;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
+import org.eclipse.cdt.managedbuilder.core.IFileInfo;
import org.eclipse.cdt.managedbuilder.core.IInputType;
import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement;
+import org.eclipse.cdt.managedbuilder.core.IOption;
+import org.eclipse.cdt.managedbuilder.core.IOutputType;
+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.macros.BuildMacroProvider;
+import org.eclipse.cdt.managedbuilder.internal.macros.IMacroContextInfo;
+import org.eclipse.cdt.managedbuilder.internal.macros.OptionContextData;
+import org.eclipse.cdt.managedbuilder.macros.BuildMacroException;
+import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider;
+import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver;
+import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
public class AdditionalInput implements IAdditionalInput {
private static final String EMPTY_STRING = new String();
+ private static final String BUILD_VARIABLE_STATIC_LIB = "ARCHIVES"; //$NON-NLS-1$
+ private static final String BUILD_VARIABLE_SHARED_LIB = "LIBRARIES"; //$NON-NLS-1$
+
+ private String[] expandedNames;
+
// Superclass
// Parent and children
private IInputType fParent;
@@ -295,9 +329,303 @@ public class AdditionalInput implements IAdditionalInput {
fResolved = true;
}
}
+
+ public boolean needsRebuild() {
+ // This shouldn't be called for an extension AdditionalInput
+ if (fIsExtensionAdditionalInput)
+ return false;
+ if (fRebuildState)
+ return fRebuildState;
+ if (fKind.intValue() == IAdditionalInput.KIND_ADDITIONAL_DEPENDENCY
+ || fKind.intValue() == IAdditionalInput.KIND_ADDITIONAL_INPUT_DEPENDENCY) {
+ IToolChain toolChain = getToolChain();
+ if (!toolChain.isExtensionElement()) {
+ long artifactTimeStamp = getArtifactTimeStamp(toolChain);
+ if (0 != artifactTimeStamp) {
+ String[] paths = getPaths();
+ for (int i = 0; i < paths.length; ++i) {
+ if (paths[i].length() == 0)
+ continue;
+ if (dependencyChanged(paths[i], artifactTimeStamp))
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private long getArtifactTimeStamp(IToolChain toolChain) {
+ IBuilder builder = toolChain.getBuilder();
+ IConfiguration configuration = toolChain.getParent();
+ URI buildLocationURI = ManagedBuildManager.getBuildLocationURI(configuration, builder);
+ if (buildLocationURI != null) {
+ if (!buildLocationURI.toString().endsWith("/")) { //$NON-NLS-1$
+ // ensure that it's a directory URI
+ buildLocationURI = URI.create(buildLocationURI.toString() + "/"); //$NON-NLS-1$
+ }
+
+ String artifactName = configuration.getArtifactName();
+ String artifactExt = configuration.getArtifactExtension();
+ String artifactPref = configuration.getOutputPrefix(artifactExt);
+ if (artifactName.length() > 0) {
+ if (artifactExt.length() > 0)
+ artifactName += "." + artifactExt; //$NON-NLS-1$
+ if (artifactPref.length() > 0)
+ artifactName = artifactPref + artifactName;
+ try {
+ artifactName = ManagedBuildManager.getBuildMacroProvider().resolveValue(artifactName, "", //$NON-NLS-1$
+ " ", IBuildMacroProvider.CONTEXT_CONFIGURATION, configuration); //$NON-NLS-1$
+ } catch (BuildMacroException e) {
+ }
+
+ URI buildArtifactURI = buildLocationURI.resolve(artifactName);
+
+ try {
+ IFileStore artifact = EFS.getStore(buildArtifactURI);
+ org.eclipse.core.filesystem.IFileInfo info = (artifact == null) ? null : artifact.fetchInfo();
+ if ((info != null) && info.exists()) {
+ return info.getLastModified();
+ }
+ } catch (CoreException e) {
+ // if we can't even inquire about it, then assume it doesn't exist
+ }
+ }
+ }
+ return 0;
+ }
+
+ private boolean dependencyChanged(String sPath, long artefactTimeStamp) {
+ try {
+ IToolChain toolChain = getToolChain();
+ IConfiguration configuration = toolChain.getParent();
+ if (fIsDirty || (null == expandedNames)) {
+ if ("$(LIBS)".equals(sPath)) //$NON-NLS-1$
+ expandedNames = getDepLibs();
+ else if ("$(USER_OBJS)".equals(sPath)) //$NON-NLS-1$
+ expandedNames = getDepObjs(configuration);
+ else {
+ expandedNames = getDepFiles(sPath);
+ }
+ }
+ for (int j = 0; j < expandedNames.length; ++j) {
+ if (expandedNames[j] != null) {
+ IFileStore file = getEFSFile(expandedNames[j]);
+ org.eclipse.core.filesystem.IFileInfo info = (file == null) ? null : file.fetchInfo();
+ if ((info != null) && info.exists() && (info.getLastModified() > artefactTimeStamp)) {
+ return true;
+ }
+ }
+ }
+ } catch (Exception e) {
+ // we'll have to assume that the dependency didn't change if we couldn't get its timestamp
+ ManagedBuilderCorePlugin.log(e);
+ }
+ return false;
+ }
+
+ private IToolChain getToolChain() {
+ IBuildObject bo = fParent.getParent().getParent();
+ IToolChain tCh = null;
+ if (bo instanceof IToolChain) {
+ tCh = ((IToolChain) bo);
+ } else if (bo instanceof IFileInfo) {
+ tCh = ((ResourceConfiguration) bo).getBaseToolChain();
+ }
+ return tCh;
+ }
+
+ private String[] getDepLibs() throws CoreException, BuildException, CdtVariableException {
+ IOption[] options = fParent.getParent().getOptions();
+ String[] libNames = null;
+ List<String> libPaths = null;
+ for (int i = 0; i < options.length; ++i) {
+ int type = options[i].getValueType();
+ if (type == IOption.LIBRARIES) {
+ libNames = options[i].getLibraries();
+ } else if (type == IOption.LIBRARY_PATHS) {
+ if (null == libPaths)
+ libPaths = new ArrayList<String>();
+ libPaths.addAll(Arrays.asList(restoreLibraryPaths(options[i])));
+ }
+ }
+
+ if ((libNames != null) && (libPaths != null)) {
+ IToolChain toolChain = getToolChain();
+ for (int i = 0; i < libNames.length; ++i) {
+ URI uri = findLibrary(toolChain, libNames[i], libPaths);
+ libNames[i] = (uri == null) ? null : uri.toString();
+ }
+ return libNames;
+ }
+ return new String[0];
+ }
+
+ private String[] restoreLibraryPaths(IOption option) throws BuildException, CdtVariableException {
+ @SuppressWarnings("unchecked")
+ List<String> libPaths = (List<String>) option.getValue();
+ String[] dirs = libPaths.toArray(new String[libPaths.size()]);
+ dirs = substituteEnvVars(option, dirs);
+ return dirs;
+ }
+
+ private URI findLibrary(IToolChain toolChain, final String libName, List<String> dirs) throws CoreException {
+ final String libSO = getDynamicLibPrefix(toolChain) + libName + '.'
+ + getDynamicLibExtension(toolChain);
+ final String libA = getStaticLibPrefix(toolChain) + libName + '.' + getStaticLibExtension(toolChain);
+
+ class LibFilter {
+ public boolean accept(String name) {
+ if (equals(libA, name))
+ return true;
+ if (!startsWith(name, libSO))
+ return false;
+ if (libSO.length() == name.length())
+ return true; // we don't necessarily have a version extension
+ if (name.charAt(libSO.length()) != '.')
+ return false;
+ String ext = libName.substring(libSO.length() + 1);
+ try {
+ Integer.parseInt(ext);
+ return true;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+
+ boolean equals(String a, String b) {
+ return a.equals(b);
+ }
+
+ boolean startsWith(String string, String prefix) {
+ return string.startsWith(prefix);
+ }
+
+ }
+ class CaseInsensitiveLibFilter extends LibFilter {
+ @Override
+ boolean equals(String a, String b) {
+ return a.equalsIgnoreCase(b);
+ }
+
+ @Override
+ boolean startsWith(String string, String prefix) {
+ return string.toLowerCase().startsWith(prefix.toLowerCase());
+ }
+ }
+
+ for (Iterator<String> i = dirs.iterator(); i.hasNext();) {
+ IFileStore dir = getEFSFile(i.next());
+ LibFilter filter = dir.getFileSystem().isCaseSensitive() ? new LibFilter() : new CaseInsensitiveLibFilter();
+ for (IFileStore child : dir.childStores(EFS.NONE, null)) {
+ if (filter.accept(child.getName())) {
+ return child.toURI();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets an EFS file-store for the specified path or URI, which may be a local filesystem path or may be a more abstract URI.
+ *
+ * @param pathOrURI a local filesystem path or URI
+ *
+ * @return the file store, if one could be determined
+ */
+ private static IFileStore getEFSFile(String pathOrURI) {
+ IFileStore result;
+
+ try {
+ // try it as a URI
+ result = EFS.getStore(URI.create(pathOrURI));
+ } catch (Exception e) {
+ // most likely, the path is not a URI, so assume a local file and try again
+ result = EFS.getLocalFileSystem().getStore(new Path(pathOrURI));
+ }
+
+ return result;
+ }
+
+ private String[] substituteEnvVars(IOption option, String[] paths) throws CdtVariableException {
+ BuildMacroProvider provider = (BuildMacroProvider) ManagedBuildManager.getBuildMacroProvider();
+ IMacroContextInfo info = provider.getMacroContextInfo(IBuildMacroProvider.CONTEXT_OPTION,
+ new OptionContextData(option, fParent));
+ String delimiter = ManagedBuildManager.getEnvironmentVariableProvider().getDefaultDelimiter();
+ String inexVal = " "; //$NON-NLS-1$
+ SupplierBasedCdtVariableSubstitutor subst = provider.getMacroSubstitutor(info, inexVal, delimiter);
+
+ String[] newPaths = CdtVariableResolver.resolveStringListValues(paths, subst, false);
+ for (int i = 0; i < newPaths.length; ++i) {
+ String newPath = newPaths[i];
+ int len = newPath.length();
+ if ((len > 1) && (newPath.charAt(0) == '\"') && (newPath.charAt(len - 1) == '\"'))
+ newPaths[i] = newPaths[i].substring(1, len - 1);
+ }
+ return newPaths;
+ }
+
+ private static String getStaticLibPrefix(IToolChain toolChain) {
+ IOutputType type = findOutputType(toolChain, BUILD_VARIABLE_STATIC_LIB);
+ if (null == type)
+ return "lib"; //$NON-NLS-1$
+ return type.getOutputPrefix();
+ }
+
+ private static String getStaticLibExtension(IToolChain toolChain) {
+ IOutputType type = findOutputType(toolChain, BUILD_VARIABLE_STATIC_LIB);
+ if (null == type || type.getOutputExtensionsAttribute().length == 0) {
+ return "a"; //$NON-NLS-1$
+ }
+ return type.getOutputExtensionsAttribute()[0];
+ }
+
+ private static String getDynamicLibPrefix(IToolChain toolChain) {
+ IOutputType type = findOutputType(toolChain, BUILD_VARIABLE_SHARED_LIB);
+ if (null == type)
+ return "lib"; //$NON-NLS-1$
+ return type.getOutputPrefix();
+ }
+
+ private static String getDynamicLibExtension(IToolChain toolChain) {
+ IOutputType type = findOutputType(toolChain, BUILD_VARIABLE_SHARED_LIB);
+ if (null == type || type.getOutputExtensionsAttribute().length == 0) {
+ return "so"; //$NON-NLS-1$
+ }
+ return type.getOutputExtensionsAttribute()[0];
+ }
+
+ public static IOutputType findOutputType(IToolChain toolChain, String buildVariable) {
+ // if we're determining whether to re-build an executable, then it won't have an output
+ // type for shared libraries from which we can get a filename extension or prefix.
+ // We have to scan the extension toolchain
+ toolChain = ManagedBuildManager.getExtensionToolChain(toolChain);
+ ITool[] tools = toolChain.getTools();
+ for (int i = 0; i < tools.length; ++i) {
+ IOutputType[] oTypes = tools[i].getOutputTypes();
+ for (int j = 0; j < oTypes.length; ++j) {
+ if (buildVariable.equals(oTypes[j].getBuildVariable()))
+ return oTypes[j];
+ }
+ }
+ return null;
+ }
+
+ private String[] getDepObjs(IConfiguration configuration) throws BuildException, CdtVariableException {
+ IOption[] options = fParent.getParent().getOptions();
+ String[] userObjs = null;
+ for (int i = 0; i < options.length; ++i) {
+ int type = options[i].getValueType();
+ if (type == IOption.OBJECTS) {
+ userObjs = options[i].getUserObjects();
+ return substituteEnvVars(options[i], userObjs);
+ }
+ }
+ return new String[0];
+ }
- public boolean needsRebuild(){
- return fRebuildState;
+ private String[] getDepFiles(String sPath) {
+ return new String[0];
}
public void setRebuildState(boolean rebuild){

Back to the top