Monday, May 7, 2007

Structuring C++ Projects in Eclipse

We’ve been struggling with how to represent C++ projects in Eclipse so I thought I would share our story in case anyone can offer any better suggestions:

It’s common for developers to already have their code organized something like this:

/Source/Projects/CPPProjectOne/src – project one specific code
/Source/Projects/CPPProjectTwo/src – project two specific code
/Source/Projects/CPPProjectThree/src – project three specific code
/Source/Projects/Common/src – source common to all CPP projects

We can not copy the source files to another location or move anything around, we have to work with them exactly where they are in the file system. Since for each project we call a custom make builder that doesn’t depend on anything in Eclipse the main thing we want our Eclipse projects to do is contain as much of the code as possible so that all of the splendid IDE features work correctly.

Our first thought was to put the Eclipse projects in the workspace and then stuff them with linked resources to the actual source files and folders. That seemed like a great fit for linked resources and would be fairly straightforward to do. However we discovered that linked resources are not really first class citizens in the workspace: to begin with they don’t work with version control (41929) so we had to abandon that idea.

Our next try was to just locate the Eclipse project and it’s source root where the cpp project’s code actually lives. When we import a cpp project’s make file we can look at the included sources and determine a root location that covers all the files. So using the above example CPPProjectOne’s source root would be /Source/Projects. This works OK, we end up with an Eclipse project that lives at /Source/Projects/.project and includes resources for all of the desired files (plus lots of other stuff too).

The trouble begins when I want to work with CPPProjectTwo at the same time. I find that it has the same common source root location as CPPProjectOne, but I can’t put a second Eclipse project there as a .project file already exists in that location.

The best work around we have been able to think of for now is to have the second project use a more narrowly scoped source root, in this case it could use /Source/Projects/CPPProjectTwo. But that will leave other files it uses, like those from /Source/Projects/Common/src, out of the project.

If we could either put more than one Eclipse project in the same location or tell a project to use something other than its location as a source root (78438) then we could accommodate any number of projects. Or if linked resources worked better we could use those. Just now we’re stuck telling people to try the work around but we need to determine what direction to pursue longer term so we can make this work the way people expect.

7 comments:

Eric said...

Hmmm, I have to say I really am not a C++ expert but I wonder why in the case of C++ things should be so different from Java...?

I mean why not just have the workspace as usual, wherever that might live (should not matter at all), containing projects CPPProjectOne, CPPProjectTwo, ... (containing their .project file each) and each of those projects having a "src" folder. What's wrong with that approach? Why redesign everything and introduce loads of complications?

Genady Beryozkin said...

Maybe some kind of EFS magic can help here?

Adrian Taylor said...

Hi Ken,

Sadly, I don't think you'll ever find a satisfactory solution apart from having the Eclipse project files co-located with, and named in a similar way to, the original makefile (MMP). I'd love to pretend otherwise, but I don't think Carbide will ever replace prior tools (or even close) unless you achieve that!

There's lots of corner-cases which will blow up otherwise. For example, how's about two nearly-identical MMPs, in the same directory, referring to the same source code directories, but with slightly different TARGET and MACRO statements to alter exactly what gets built? A fairly common situation. The only way to distinguish them is the full name and path of the MMP (or of the target, but that would fail in other cases).

Or how's about a phone maker's variant kernel build files in /PhoneMakerSrc/kernel/ekern.mmp referring to source code in /SymbianSrc/src/common/... ... especially since you'll probably have a variant.mmh in the first directory that the indexer may need to refer to.

This probably means fixing 78438 but I don't think you'll find any short-cuts...

To make matters worse I'm not convinced searching for a common root will actually cover all the bases - in the kernel example above, the entire development drive would be the common root.

Of course, none of that actually helps you figure out how to achieve it within Eclipse; it probably just depresses you. Good luck! :-)

Eric: the problem is that Eclipse is being retro-fitted to a long-established, rather flexible and somewhat ugly Symbian OS build system. In the specific example Ken's given there are three projects sharing the same source code directory, to avoid duplication. Actually I think that's a fairly simplistic example compared to some of the convoluted situations Nokia may have to deal with! The C++ preprocessor also makes things more complicated than Java, especially when (as in Symbian's case) it can be applied to the makefile-equivalents themselves... it all gets icky quite quickly!

Unknown said...

Eric, the whole point is to share a single src directory. It sounds like you're suggesting creating a duplicate src directory in each project? That sounds like a maintenance nightmare.

We suffered from this problem too. We solved it by creating a single project, with all our actual projects in subdirectories:

/project/project1/
/project/project2/
/project/src

We use CDT's make targets to build the correct project's executables. Because the make targets follow your project's hierarchy, it's actually very manageable.

Yes, this is an ugly workaround, but it does work well. It's a shame that Eclipse's architectural limitations make it necessary.

Sean said...

I guess I am missing something.
I don't see why you can't create 4 projects -- /Source/Projects/CPPProjectOne, /Source/Projects/CPPProjectTwo, /Source/Projects/CPPProjectThree, and /Source/Projects/Common. Then you change the project properties for each of the first three projects indicating that each depends on the fourth project.

This only becomes prohibitive with a large number of interdependent projects.

suomiro said...

This is a big limitation. For example our project has text directories inside actual code.

/project/src
/project/src/test

Are there any plans to correct this limitation in next Carbide releases?

Unknown said...

I would just like to add that the limitation of creating .project files anywhere in the project tree is a real pain for me. We use ClearCase and when I create a dynamic view I get a copy of the code mounted on a remote file system that I have NO WRITE ACCESS to. This means I cannot even create the project from the source.

My use case here is I wish to use Eclipse to simply view the files in any particular project (of which there are 1000s) with all the convenience of a powerful IDE that I also use for my own development. I have no intention of keeping any of these files created by Eclipse when viewing another teams projects.

My only work-around is to create snapshot views which copy the 10Gb projects locally, then create the Eclipse project, then delete the whole lot when I'm done.

I'd like an option when creating projects from source to use another directory entirely for these Eclipse project files e.g. the Eclipse install folder.