Creating a new C++ Project in Eclipse CDT with the same settings as another project
Asked Answered
R

2

5

Is there a straightforward way to create a new C++ project that clones the settings of an existing project? When developing C++, I like to write many small tests and examples, but if my code depends on external libraries, as they often do, I have to set the includes, libraries, compiler settings, etc., up from scratch each time. Is there some sort of template mechanism?

I know about Export/Import of C/C++ Project Settings. However, this only appears to pick up include paths and #defines for the C++ compilation. The fact that it doesn't export the full slate of settings (compiler options, warning settings, linker options, libraries, library paths, ...) really limit its usefulness.

Also, you have to do it separately for each run configuration, though this is a minor inconvenience.

What I usually resort to is copying one test project and manually editing the .project and .cproject files and then nuking and replacing the files. But this seems like an error-prone hack.

Are there other approaches? Do I need to switch to a separate build system and generate the eclipse projects externally in order to have what seems like pretty basic functionality?


UPDATE

I've tried creating a Plug-in Project but the instructions leave more than a little to be desired if you haven't done this before. I definitely want to figure out how to do this.

I copied and modified the sample template in some very simple ways, just to get started, but the "How to register a project template with CDT" instructions lost me from the start: "1. Create an empty plug-in project from the Eclipse workbench without the source folders." I assume this requires installing the PDE, which I did, but then I'm lost. I tried "File / New / Plug-in Project", deselected "Create a Java Project" (I assumed this was what was meant by "Empty"). This creates a project that still has a lot of stuff in it. I then created the subdirectories as described in step 2, but can't figure out how to get these to show up in Eclipse, and as a result I can't browse to the template XML file in step 11. Also, in steps 9/10, I don't get a template 'literally named "(template)"' - instead it creates one with the full name of my template project.

Rome answered 13/10, 2015 at 1:32 Comment(0)
O
6

CDT has a complete Templating mechanism for creating new projects.

Basically, you extend the org.eclipse.cdt.core.templates extension point and that points to a template.xml file that has a bunch of commands you can do. You don't need to write any Java code for this, but you do need to create a Plug-in project.

The kinds of things you can do:

  • Create folders
  • Add files to a project
  • Set Managed Build settings (this is the one most relevant because you can set compiler options and add libraries, etc)
  • Add extra pages to the New Project Wizard to prompt user for extra information

The Eclipse documentation has a special section giving a run down on how to do it here: http://help.eclipse.org/mars/topic/org.eclipse.cdt.doc.isv/guide/projectTemplateEngine/index.html

The Hello World project that comes with CDT has its template here: https://github.com/eclipse/cdt/blob/master/build/org.eclipse.cdt.managedbuilder.gnu.ui/templates/projecttemplates/HelloWorldCAnsiProject/template.xml

A little note, if you initially create your plug-in to install as a non-packed plug-in, you can edit it in place, adding new templates or editing the one you have already done.

Going further, you can share this template plug-in project with your team and all benefit from having this feature.

Step-by-step

The step by step process to do this (tested on Eclipse Mars.1 with CDT and Plug-in development tools installed plus an XML editor for editing the template.xml)

  1. Create a Plug-in project (File | New | Other... | Plug-in project)

step 1

  1. Fill in a project name and press Next / Finish until done

step 2

You should now have files on your disk that looks like this in the project you created:

$ find . -type f
./.classpath
./bin/com/example/cdt/templates/Activator.class
./.project
./src/com/example/cdt/templates/Activator.java
./.settings/org.eclipse.jdt.core.prefs
./META-INF/MANIFEST.MF
./build.properties
  1. Open the plug-in.xml and do the following
    1. Select the Extensions tab
    2. Press Add
    3. Type the extension point org.eclipse.cdt.core.templates
    4. Un-check the Show only extension points [...] checkbox
    5. Select the org.eclipse.cdt.core.templates from the list
    6. Press Finish
    7. Say Yes to adding dependency

step 3

  1. Add the required settings to the plugin.xml as shown in the screenshot and given in the plugin.xml code sample after.

step4

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         point="org.eclipse.cdt.core.templates">
      <template
            filterPattern=".*gcc"
            id="com.example.cdt.templates.template1"
            location="template/template.xml"
            projectType="org.eclipse.cdt.build.core.buildArtefactType.exe">
      </template>
   </extension>
</plugin>
  1. Now create the template.xml in the location specified in the plugin.xml (template/template.xml) with these contents:
<?xml version="1.0" encoding="ISO-8859-1"?>
<template type="ProjTempl" version="1.0" supplier="Stack Overflow"
    revision="1.0" author="Jonah Graham" id="EXE" label="Stack Overflow Example"
    description="An example for https://mcmap.net/q/1964351/-creating-a-new-c-project-in-eclipse-cdt-with-the-same-settings-as-another-project."
    help="help.html">


    <process type="org.eclipse.cdt.managedbuilder.core.NewManagedProject">
        <simple name="name" value="$(projectName)" />
        <simple name="artifactExtension" value="exe" />
        <simple name="isCProject" value="true" />
    </process>

    <process type="org.eclipse.cdt.core.CreateSourceFolder">
        <simple name="projectName" value="$(projectName)" />
        <simple name="path" value="src" />
    </process>

    <process type="org.eclipse.cdt.core.AddFiles">
        <simple name="projectName" value="$(projectName)" />
        <complex-array name="files">
            <element>
                <simple name="source" value="src/basename.c" />
                <simple name="target" value="src/$(projectName).c" />
                <simple name="replaceable" value="true" />
            </element>
        </complex-array>
    </process>

    <process type="org.eclipse.cdt.ui.OpenFiles">
        <simple name="projectName" value="$(projectName)" />
        <complex-array name="files">
            <element>
                <simple name="target" value="src/$(projectName).c" />
            </element>
        </complex-array>
    </process>

    <!--  Set -Wall by checking the checkbox in the settings -->
    <process
        type="org.eclipse.cdt.managedbuilder.core.SetMBSBooleanOptionValue">
        <simple name="projectName" value="$(projectName)" />
        <complex-array name="resourcePaths">
            <element>
                <simple name="id" value=".*compiler\.option\.warnings\.extrawarn.*" />
                <simple name="value" value="true" />
                <simple name="path" value="" />
            </element>
        </complex-array>
    </process>

    <!--  Set -Werror by adding textual build settings -->
    <process
        type="org.eclipse.cdt.managedbuilder.core.SetMBSStringOptionValue">
        <simple name="projectName" value="$(projectName)" />
        <complex-array name="resourcePaths">
            <element>
                <simple name="id" value=".*compiler\.option\.misc\.other.*" />
                <simple name="value" value="-c -fmessage-length=0 -Werror" />
                <simple name="path" value="" />
            </element>
        </complex-array>
    </process>

    <!--  Add -lmylibname to libraries to link -->
    <process
        type="org.eclipse.cdt.managedbuilder.core.AppendToMBSStringListOptionValues">
        <simple name="projectName" value="$(projectName)" />
        <complex-array name="resourcePaths">
            <element>
                <simple name="id" value=".*link\.option\.libs.*" />
                <simple-array name="values">
                    <element value="mylibname" />
                </simple-array>
                <simple name="path" value="" />
            </element>
        </complex-array>
    </process>
</template>
  1. Add the source file listed in the template with any content you want in template/src/basename.c

You should now have a directory structure that looks like this:

$ find . -type f
./.classpath
./template/src/basename.c
./template/template.xml
./bin/com/example/cdt/templates/Activator.class
./.project
./src/com/example/cdt/templates/Activator.java
./.settings/org.eclipse.jdt.core.prefs
./META-INF/MANIFEST.MF
./plugin.xml
./build.properties
  1. Launch the Eclipse Application to test (Run menu | Run As | Eclipse Application). You can also right-click on the project and choose Run As | Eclipse Application.

  2. In the newly running Eclipse, start a new project wizard and select your new C project type:

new project wizard

Running a build shows the new settings (the error is expected as I don't actually have a library called mylibname):

Building file: ../src/hello2.c
Invoking: GCC C Compiler
gcc -O0 -g3 -Wall -Wextra -c -fmessage-length=0 -Werror -MMD -MP -MF"src/hello2.d" -MT"src/hello2.o" -o "src/hello2.o" "../src/hello2.c"
Finished building: ../src/hello2.c

Building target: hello2
Invoking: GCC C Linker
gcc  -o "hello2"  ./src/hello2.o   -lmylibname
/usr/bin/ld: cannot find -lmylibname
collect2: error: ld returned 1 exit status
make: *** [hello2] Error 1

The tricky part?

You may need to examine the .cproject file from your base project to determine the magic strings that go in the id fields. For example, in my .cproject for -Wextra I can see this:

<option id="gnu.c.compiler.option.warnings.extrawarn.176373860" name="Extra warnings (-Wextra)" superClass="gnu.c.compiler.option.warnings.extrawarn" value="true" valueType="boolean"/>

That translates to this command in the template.xml:

<!--  Set -Wall by checking the checkbox in the settings -->
<process
    type="org.eclipse.cdt.managedbuilder.core.SetMBSBooleanOptionValue">
    <simple name="projectName" value="$(projectName)" />
    <complex-array name="resourcePaths">
        <element>
            <simple name="id" value=".*compiler\.option\.warnings\.extrawarn.*" />
            <simple name="value" value="true" />
            <simple name="path" value="" />
        </element>
    </complex-array>
</process>

The id goes from gnu.c.compiler.option.warnings.extrawarn.176373860 to regexp .*compiler\.option\.warnings\.extrawarn.*. The beginning is .* so that this applies to C and C++ compiler options as the C++ id would have started with gnu.cc.compiler[...] and I get rid of the end with .* because the number and suffix is not known to you in the template.xml

Next steps

When you are done, see Launching Eclipse plug in template for how to export the plug-in into your running Eclipse.

Osteo answered 16/10, 2015 at 22:19 Comment(9)
See update to my question - if you've done this before, any hints would be appreciated. I've never delved into eclipse plug-in development and feel pretty lost as their instructions seem to assume that you know what you're doing in this space.Rome
I have added some extra details. Hopefully sufficient. I also added all the above code to my github if that helps: github.com/jonahkichwacoders/example_cdt_templateOsteo
Got your example to work. Hit a snag trying to get my C++ version so may have another Q or 2, but great walk-through - thanks!Rome
Most of this has come together. Any idea how to set something in a drop-down? I thought maybe it was SetMBSStringListOptionValues, but that didn't seem to work. I want to set the C++ dialect to the eclipse C++ setting. I can do it as an "extra option" instead but it would be clearer if done as the Dialect setting.Rome
@Rome Sorry, I can't see how to do that one. The template mechanism is primarily used by vendors to enhance Eclipse for their customers and as such are generally created by plug-in developers. The process types are themselves extensible (i.e. you can define your own ones) using this extension point: org.eclipse.cdt.core.templateProcessTypes. But as I assume you are not a vendor in this case, so probably out of your scope?Osteo
See github.com/eclipse/cdt/blob/master/build/… for starting point as that code allows setting a string value, it should not be too hard to adapt it to a enum value.Osteo
I'll keep looking. I can work around it by just setting the textual "Other Dialect Option". But if you can check check-boxes, there must be a way to select from a drop-down. I'm going to move this to a new question as SO is complaining about this "extended discussion". :)Rome
OK, if you add another question, cross ref it here and I'll see it.Osteo
See #33264661Rome
H
3

I like Jonah's answer, it is very informative. Lately I've been using Ease and Py4J to automatically re-recreate a large number of projects with the cdt settings I need. I just wanted to mention another possible way of doing this type of automation.

  1. Create your template project , store it in some workspace, doesn't necessarily need to be in the same workspace as the one you are importing to

  2. File->Import->Gneral->Existing Projects-> Select your template project directory

  3. Select "Copy projects into workspace" option

  4. Finish

  5. Optionally rename the project, this way when you import the project again as a new project, there will be no naming conflicts

Hyacinthie answered 25/7, 2016 at 17:56 Comment(4)
What happens to the configuration ID when you do this? For example, if you create a new project, the .cproject will contain something like: <cconfiguration id="cdt.managedbuild.config.gnu.exe.debug.1050458263">; the 1050458263 should be unique or you can get issues (in my experience) dealing with referencing build configurations from the "Paths and Symbols"/"References" tab. Does the method you've described cause the imported project to be assigned a new, unique ID?Richierichlad
@Richierichlad Yes, it should, I think that is the point of the import functionality, to replace these ids from the incoming project. Note it has been a long time since I have worked on this .Hyacinthie
Thanks for your reply, after all these years :-), but I thought the point of the import functionality was simply to let you share projects across workspaces (assuming you don't select the "copy into the workspace" option), in which case it shouldn't do anything to the existing build configuration ids, and you'll potentially have multiple projects with the same ids. I'm guessing you haven't checked, which is fair enough if it works for you. Thanks again.Richierichlad
My answer was specifically addressing the copy into workspace option in order to create new projects, importing an existing project would probably throw a conflict if there was another project in the same path on the file system. Good luck!!Hyacinthie

© 2022 - 2024 — McMap. All rights reserved.