Skip to content

Commit

Permalink
Use build CWD for object path processing within GNU archive files
Browse files Browse the repository at this point in the history
  • Loading branch information
jld01 committed Dec 12, 2023
1 parent f7a6337 commit 9aa6fb1
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.managedbuilder.gnu.ui; singleton:=true
Bundle-Version: 8.6.0.qualifier
Bundle-Version: 8.6.100.qualifier
Bundle-Activator: org.eclipse.cdt.managedbuilder.gnu.ui.GnuUIPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Expand Down
2 changes: 1 addition & 1 deletion build/org.eclipse.cdt.managedbuilder.gnu.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@
id="gnu.lib.category.general">
</optionCategory>
<option
defaultValue="-r"
defaultValue="-r -P"
name="%Option.Posix.Archiver.Flags"
category="gnu.lib.category.general"
valueType="string"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,39 @@
* QNX Software Systems - Initial API and implementation
* Anton Leherbauer (Wind River Systems)
* John Dallaway - Adapt for IBinaryFile (#413)
* John Dallaway - Fix object path processing (#630)
*******************************************************************************/
package org.eclipse.cdt.internal.core.model;

import java.util.Map;
import java.util.Optional;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IArchive;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICOutputEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.extension.CBuildData;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.internal.core.util.MementoTokenizer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;

public class Archive extends Openable implements IArchive {

Expand Down Expand Up @@ -75,16 +90,30 @@ protected boolean buildStructure(OpenableInfo info, IProgressMonitor pm, Map<ICE

public boolean computeChildren(OpenableInfo info, IResource res) {
IBinaryArchive ar = getBinaryArchive();
if (ar != null) {
IBinaryObject[] objects = ar.getObjects();
for (final IBinaryObject obj : objects) {
Binary binary = new Binary(this, ar.getPath().append(obj.getName()), obj);
IPath location = res.getLocation();
if (ar != null && location != null) {
// find the build CWD for the archive file
IPath buildCWD = Optional.ofNullable(findBuildConfiguration(res)).map(Archive::getBuildCWD)
.orElse(location.removeLastSegments(1));
for (IBinaryObject obj : ar.getObjects()) {
// assume object names are paths as specified on the archiver command line ("ar -P")
IPath objPath = new Path(obj.getName());
if (!objPath.isAbsolute()) {
// assume path is relative to the build CWD
objPath = buildCWD.append(objPath);
}
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(objPath);
if (file == null) { // if object path is external to the workspace
// fallback to legacy behaviour
// TODO: support external paths in Binary class as we do in TranslationUnit
objPath = ar.getPath().append(objPath.lastSegment());
}
Binary binary = new Binary(this, objPath, obj);
info.addChild(binary);
}
} else {
return false;
return true;
}
return true;
return false;
}

@Override
Expand Down Expand Up @@ -133,4 +162,50 @@ protected char getHandleMementoDelimiter() {
return 0;
}

private static ICConfigurationDescription findBuildConfiguration(IResource resource) {
IPath location = resource.getLocation();
IProject project = resource.getProject();
ICProjectDescription projectDesc = CoreModel.getDefault().getProjectDescription(project, false);
if (projectDesc == null) {
return null; // not a CDT project
}
// for each build configuration of the project
for (ICConfigurationDescription configDesc : projectDesc.getConfigurations()) {
CConfigurationData configData = configDesc.getConfigurationData();
if (configData == null) {
continue; // no configuration data
}
CBuildData buildData = configData.getBuildData();
if (buildData == null) {
continue; // no build data
}
// for each build output directory of the build configuration
for (ICOutputEntry dir : buildData.getOutputDirectories()) {
IPath dirLocation = CDataUtil.makeAbsolute(project, dir).getLocation();
// if the build output directory is an ancestor of the resource
if ((dirLocation != null) && dirLocation.isPrefixOf(location)) {
return configDesc; // build configuration found
}
}
}
return null;
}

private static IPath getBuildCWD(ICConfigurationDescription configDesc) {
IPath builderCWD = configDesc.getBuildSetting().getBuilderCWD();
if (builderCWD != null) {
ICdtVariableManager manager = CCorePlugin.getDefault().getCdtVariableManager();
try {
String cwd = builderCWD.toString();
cwd = manager.resolveValue(cwd, "", null, configDesc); //$NON-NLS-1$
if (!cwd.isEmpty()) {
return new Path(cwd);
}
} catch (CdtVariableException e) {
CCorePlugin.log(e);
}
}
return null;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2014 QNX Software Systems and others.
* Copyright (c) 2000, 2023 QNX Software Systems and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -10,11 +10,13 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* John Dallaway - Use file path when testing for equality (#630)
*******************************************************************************/
package org.eclipse.cdt.internal.core.model;

import java.util.Enumeration;
import java.util.Map;
import java.util.Objects;

import org.eclipse.cdt.core.model.BufferChangedEvent;
import org.eclipse.cdt.core.model.CModelException;
Expand Down Expand Up @@ -104,6 +106,16 @@ protected void closing(Object info) throws CModelException {
closeBuffer();
}

/**
* Tests if an element has the same name, type, parent and path.
* Path comparison is required for multiple object files with the
* same filename under an ArchiveContainer or BinaryContainer.
*/
@Override
public boolean equals(Object o) {
return super.equals(o) && (o instanceof Openable openable) && Objects.equals(getPath(), openable.getPath());
}

/**
* @see org.eclipse.cdt.core.model.IOpenable#getBuffer()
*/
Expand Down

0 comments on commit 9aa6fb1

Please sign in to comment.