Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-dev] Remote C/C++ Project Support Prototype

I have recently been working on Remote Project support for Autotools projects and wanted to start a discussion on what changes I made in the CDT and Autotools and whether this would be something the CDT would want to pursue.

To start with, my goal was to eliminate the need for separate Project types or wizards which IMO there are lots to confuse the user as-is. To create the remote project, I simply wanted to specify the location of a C or C++ project as being remote. To do this, in the C/C++ Project Wizards, one can specify a non-default location outside of the workspace and there is a file-system pull-down where one can choose the rse filesystem. From there, there is a browser to look at existing remote connections and select an existing remote directory. Trying this out was relatively easy, but as it turns out the RSE adds the connection name at the end of the URI it creates for the locaion, but does not add the project name. So, to create the project name directory, one has to add the name of new project ahead of the connection query portion of the URI. This obviously could be improved in the future so that the editing step would not be needed.

For my design, I chose to use RDT. The beauty of RDT is that it allows conversion between paths and URIs. This is an important feature in that it is possible to leave existing UI elements as-is and there is no real learning curve for the end-user. The context of paths can be implied by the project location. If the project is remote, the paths are on the same remote machine and no need to specify the full URI all over the place. The user doesn't really need to see the remote machine URI all over the place and by supporting paths, the data formats do not require changing (e.g. paths occur in many classes in the CDT and there would be no need to switch to URIs).

So, the first thing was for me to create the framework.

In my particular experiment, I created a RemoteProxyManager in org.eclipse.cdt.core.internal.remoteproxy that implemented IRemoteProxyManager:

public interface IRemoteProxyManager {
        String EXTENSION_POINT_ID = "RemoteProxyManager"; //$NON-NLS-1$
        String MANAGER_NAME = "manager"; //$NON-NLS-1$
        String SCHEME_ID = "scheme"; //$NON-NLS-1$
public IRemoteFileProxy getFileProxy(IProject project) throws CoreException; public IRemoteCommandLauncher getLauncher(IProject project) throws CoreException;
        public String getOS(IProject project) throws CoreException;
}

The job of the proxy manager was to fish out proxies for file and command access as well as to identify the remote OS.

For file access, there is the IRemoteFileProxy interface:

 public interface IRemoteFileProxy {

        public URI toURI(IPath path);
        public URI toURI(String path);
        public String toPath(URI uri);
        public String getDirectorySeparator();
        public IFileStore getResource(String path);

}

When accessing a path, one uses the project to get the IRemoteFileProxy and then paths can be converted to URIs or IFileStore objects directly. A path for storing or displaying in the UI can be obtained from the URI via the API.

The IRemoteCommandLauncher interface allows one to run commands on the same system as the project:
public interface IRemoteCommandLauncher {

        public final static int OK = 0;
        public final static int COMMAND_CANCELED = 1;
        public final static int ILLEGAL_COMMAND = -1;

public Process execute(String commandPath, String[] args, String[] env, String changeToDirectory, IProgressMonitor monitor) throws CoreException; public Process execute(String commandPath, String[] args, String[] env, String changeToDirectory, boolean usePTY, IProgressMonitor monitor) throws CoreException; public int waitAndRead(OutputStream output, OutputStream err, IProgressMonitor monitor);
        public String getErrorMessage();
        public String getCommandLine();

}

In my implementation, I also created a plug-in extension that would allow specification of an IRemoteProxyManager. The remote proxy manager would register itself to handle certain URI schema. The default RemoteProxyManager class only handles local references and then if not local, looks for an extension to handle the URI schema. It then punts what ever method call was requested to the IRemoteProxyManager extension class. For example, I created a remote proxy manager that uses RDT and handles URIs starting with rse:// and remotetools:// which handles projects set up via RSE or RDT.

I created the separate extension because my experiment started by altering the Autotools plug-ins in Linux Tools. I did not want to make Autotools force RDT to be required so I used the extension. The plug-in that implements the extension for RSE and RDT connections using RDT is not required for local project users. For the CDT, I copied over the code from Linux Tools for the most part so I also copied over the extension. The extension has the benefit that other systems could be used to plug in and handle other remote system types (e.g. IIRC, RDT doesn't support Windows as a target).

The design could easily be altered to use RDT directly and the CDT would then have a dependency on RDT.

Once the framework was in place, I started converting the Autotools and CDT code to use the proxies and found a few things that needed changing as a rule:

1. All path accesses that are project located can not use java.io.File.
   Instead, the project is used to get the IRemoteFileProxy and then
   a path can be used to get an IFileStore (EFS file).

2. The getLocation() method can not be used for a resource.  This
   returns null for a remote object.  Instead, one must use
   getLocationURI(), then use the IRemoteFileProxy to convert to a path
   which is what getLocation() returns.

3. Checking for existence requires getting the IFileStore as in 1), then
   using the fetchInfo() method to get the IFileInfo exists()
   method.

4. Running a command requires using a IRemoteCommandLauncher grabbed by
   using the project rather than a ICommandLauncher.

Once my changes were in place, I was able to create a remote Autotools Hello world project using the C Project Wizard (all I did was specify a remote location). The remote project configures and builds on the remote machine. I made a change so that the Binaries folder shows up and I am able to execute the binary on the remote system and have the results show up in the Console. In addition, I was able to invoke Autotools commands remotely.

I did not change all code in the CDT as this was a proof of concept. I added support to the TranslationUnit so the indexer appears to work but while it uses the correct remote source file, I did not make it use external headers so that would require further changes. There is a remote indexer and if the indexer changes are not desired, the remote indexer could be defaulted for the end-user by the C Project wizard.

I didn't actually have to change too much in the Autotools plug-ins nor the CDT to get all of this to work.

If someone would like to see the changes I made, I have a fork of the CDT with a branch called "rdt" which you can access read-only here:

git://github.com/jjohnstn/cdt.git

The Linux Tools changes for Autotools can be found in the RDT branch of the org.eclipse.linuxtools git repository.

The Autotool changes are not in the master branch and are not part of the code move currently under way.

Would there be interest in pursuing this further? I'm sure there are things I haven't thought of.

I could also look into posting a screen-cast somewhere so you could see how it all works.

-- Jeff J.


Back to the top