Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Papyrus/Codegen/CppHelloWorld
Contents
Create a C++ Hello World Example
This walkthrough is now complete but still needs some work to clean it up. Please post any questions, comments, error or omissions to the Papyrus forum.
There is probably too much detail and too many screenshots at the moment.
Goals
Starting from a blank page, create a Papyrus/C++ "Hello World" example, then generate and run the resulting C++ code.
The screenshots were created running Eclipse Neon on a Windows 7 machine. Your result will probably look slight different when run on a different OS.
If you already have all the required components install, skip ahead to the "Create The Model" section.
Prerequisites
1 Eclipse
Eclipse Neon.3 release 4.6.3 was used to create the example. Eclipse Oxygen.1 release 4.7.1 is currently being checked. Differences will be noted in the text.
I started with the Eclipse Modeling Tools packages and added the other components from there. To check your Eclipse version, select "Help" from the main menu and select "About Eclipse".
Q. Is there a minimum version that can be used? TODO: Add a link to instructions on installing Eclipse.
2 Papyrus (obviously!)
Papyrus version 2.0.3 was used to create this example. Papyrus version 3.1.0 is currently being checked.
To check your Papyrus version, select "Help" from the main menu and select "About Eclipse". In the resulting popup window, click on the Papyrus icon.
NOTE: An existing hello world example is available via File->New->Example however it is broken in version 2.0.3. This guide was created using a nightly snapshot pending the release of 2.0.4 where the issue should be resolved. See this forum thread for more information: [1]
Q. Is there a minimum version that can be used? TODO: Add a link to instructions on installing Papyrus on the Eclipse.
3 A C++ tool chain
I used the g++ compiler and make in cygwin. I used the GNU g++ compiler version 5.4.0 under ubuntu 16.04.4 to check the Oxygen release.
4 Eclipse CDT (Optional)
I used version 9.2.1 for these examples. I used version 9.3.0 to check the Oxygen release.
Setup
Now everything is installed, start Eclipse. Open the Papyrus perspective. Select Window->Perspective->Open Perspective->Other... from the main menu.
The "Open Perspective" window pops up.
Neon: Select Papyrus and then click the "OK" button. Note the new icon.
Oxygen: Select Papyrus and then click the "Open" button. Note the new icon.
Close the Welcome screen to reveal the Papyrus perspective. Make sure that you have the Project Explorer, Model Explorer and Properties windows open.
If not, open them using the main menu Window->Show View.
Create The Model
1. Create the project
From the main menu, select "File"->"New"->"Papyrus Project". The "New Papyrus Project" window pops up.
Make sure that the "UML" radio button is selected and then click the "Next >" button.
Enter a name for the project, another for the model and leave the default workspace checkbox checked, then click the "Finish" button.
The name you entered for the project will be displayed in the "Project Explorer" area and the name you entered for the model will be displayed if you expand the project.
As you can see below, I used "myHelloWorldProject" for the project name and "myHelloWorldModel" for the model name. If you would like to exactly recreate the example that comes with Papyrus, use "HellooWorldOO" and "HelloWorld" for the Project and Model names respectively.
2. Rename the root element.
Oxygen: Skip this step. The model aready has the name you gave it in the previous step.
Select "RootElement" in the "Model Explorer" area and notice that the "Properties" window changes to show the "RootElement" properties. In the "UML" tab edit the name to be "myHelloWorldRootElement" (or "HelloWorld" to exactly recreate the example).
3. Create a package.
Right click on the "myHelloWorldRootElement", select "New Child"->"Package" from the context menu. Name the package "myHelloWorldPackage" (or "classes").
4. Create the class diagram.
Right click on the "myHelloWorldPackage" in the "Model Explorer", select "New Diagram"->"Class Diagram". Name the diagram "myHelloWorldClassDiagram" (or "HelloWorld"). Note that a new tab has been created in the main drawing area labelled with the diagram name and that it is empty. Expand the package in the "Model Explorer" and see that the diagram is a child of the package.
5. Add the classes.
Drag a class from the "Palette" and drop it in the class diagram. It will have a default name of "Class1" which will be highlighted. Rename the class to "myHelloWorldClass" (or "HelloWorld"). Repeat the process and create a second class and call it "myMainClass" (or "Main"). Adjust the positioning and sizing by using the main menu options "Diagram"->"Make Same Size" and "Diagram->Alignment".
Oxygen: Main menu -> Papyrus -> Diagram -> "Make Same Size".
Your screen should now look something like this:
Also note that the classes have been added to the "Model Explorer" as children of "myHelloWorldPackage".
5. Add the dependency.
Find the "Dependency" edge in the "Palette". Click on the "myMainClass" class and the drag to other end to the "myHelloWorldClass" class and click again. You will be prompted to enter a name for the dependency. I left it blank but the example calls it "Dependency1". The important thing is to get the direction correct. The arrow head must be pointing to the "myHelloWorldClass".
The dependency is added to the "Model Explorer" as a child of "myHelloWorldPackage". If you named it, that name will be displayed but if you didn't it will have the name of the class that depends on the other, ie "myHelloWorldClass".
6. (Optional) Add the notes.
The Papyrus "HelloWorldOO" example contains a few notes which don't affect the code in any way but for the sake of completeness. I'm including the instructions to add them.
Drag a comment from the "Palette" and drop it to the right of the "myHelloWorldClass" class. Enter the text as shown below.
With the new comment selected, note that it is displayed as a child of the "myHelloWorldPackage" and that the text of the comment is displayed in the "Body" section of the "UML" tab in the "Properties" window. Hover your mouse pointer over the comment until the Decorations (official name?) are displayed as shown.
Move the mouse pointer over the arrow pointing away from the comment, click and drag a line to the "myHelloWorldClass" class and release to add the association. (Not sure if "association" is the correct term for this link.
In the "Model Explorer" select the "myHelloWorldPackage" and then select the "Comments" tab in the "Properties" window. Note that new comment is displayed as an "Owned Comment".
Add the other 2 comments in a similar manner. Your display should now look like this:
7. Add the operation.
Drag an "Operation" from the "Palette" and drop it on the "myHelloWorldClass" class. It must be dropped either in the class header or in the 2nd compartment otherwise it will not show up. Give it the name "myHelloWorldOperation" (or "run").
Note that the operation is displayed in the class diagram and as a child of "myHelloWorldClass" in the "Model Explorer".
8. Optional.
The example the comes with Papyrus also has the root element displayed on the class diagram. This is not necessary and in my opinion, clutters the diagram. However, not everyone always agrees with my opinions so if desired, click on the "myHelloWorldRootElement" in the "Model Explorer" and drag it onto the class diagram. Also, if desired, create the comment and associate it with the root element in a similar fashion to before.
Validate The Model
This step is not strictly necessary but it is a good idea to get in the habit of validating your models, particularly as they get more complicated.
Neon: Right click on "myHelloWorlRootElement" in the "Model Explorer" to bring up the context menu.
Oxygen: Right click on "myHelloWorldModel" in the "Model Explorer" to bring up the context menu.
Then select "Validation" -> "Validate model".
Select the "Model Validation" window and check that there are no errors. In case you do not have the "Model Validation" window open, select "Window" -> "Show View" -> "Model Validation" from the main menu.
Add The Code
1. Add the C++ profile.
We are coding in C++ so the first thing to do is to add the C++ profile.
Neon: Select the myHelloWorldRootElement
Oxygen: Select the myHellowWorldModel
in the "Model Explorer" and make sure its properties are displayed in the "Properties" window. Select the "Profile" tab in the "Properties" window and then click on the "Apply Registered Profile" icon.
This pops up the "Apply Profiles" window. Select the "C/C++" profile and then click the "OK" button.
Next the "Choose Profile" window pops up. There is only one option, so check the checkbox and click the "OK" button.
The "C_Cpp" profile now appears in the "Profile tab" of the myHelloWorldRootElement.
Due to the way the code generator handles namespaces, we have to repeat these steps for the myHelloWorldPackage. I have not included the screenshots here but select myHelloWorldPackage in the "Model Explorer" window, select the "Profile" tab in the "Properties" window and repeat the steps to add the "C/C++" profile.
2. Write the main() function.
In the class diagram, select myMainClass, the "Profile" tab in the "Properties" window and then the "Add Stereotype" button.
This pops up and untitled window. Select the "Include" stereotype from the "Applicable Stereotypes" window on the left, press the right pointing arrow in the middle to move the stereotype to the "Applied Stereotypes" window on the right and then click the "OK" button.
The "Include" stereotype is now added to the "Profile" window in the "Properties" tab of the myMainClass properties. Click on the arrow to the left of the stereotype to expand it, then select the body child. Enter the main function code in the window to the right.
In the example included with Papyrus, the declaration of the hw object is classes::helloWorld. This is a bug which I have deliberately reproduced as myHelloWorldPackage::myHelloWorldClass. We'll fix this later.
3. Write The myHelloWorldRunMethod (or run()) Method.
In the "Model Explorer", select the "myHelloEorldOperation" (or "run()") operation in the myHelloWorldClass. In the "Properties" view, make sure the "UML" tab is selected and click the "Add Elements" button at the top of the "Method" text box.
This pops up the "Method" window. Click the "Create new element" button on the right side and select OpaqueBehavior from the context menu.
This pops up the "Create a new OpaqueBehavior" window. Next click on the "Container:" "Edit the Reference Value" button.
Now the "Container" window pops up. Expand the root element and the package and select "myHelloWorldClass" as the container. Click the "OK" button.
We are now returned to the "Create a new OpaqueBehavior" window and the Container line is filled in with "myHelloWorldClass". Now select the "Edit the Reference Value" button on the "Reference" line:
This pops up the "Reference:" window. Select "OwnedBehavior : Behavior" and then click the "OK" button.
Again we are returned to the "Create a new OpaqueBehavior" window and both the "Container:" and "Reference:" lines are filled in.
Click the "OK" button. Now a new, different "Create a new OpaqueBehavior" window pops up.
Enter the name of the method, ie "myHelloWorldRunMethod" (or "run") in the name line and then click on the Language "Add elements" icon. This pops up the "Language" window.
Select "C++" from the left pane, and click the right pointing arrow in the middle to move C++ to the right pane. Click the "OK" button to return to the previous "Create a new OpaqueBehavior" window.
Note that the name and language are filled in and that a new text area is displayed to the right of the Language area. Enter the code as shown. Click on the "OK" button to return to the "Method" window.
Note that our new "myHelloWorldRunMethod" (or "run") method shows up in the right pane. Finally, click the "OK" button in the "Method" window.
The new "myHelloWorldRunMethod" (or "run") method is displayed in the "Properties" tab "Method" text area and also in the "Model Explorer".
3. Add the #include
Our "myHelloWorldRunMethod" (or "run") method uses "std::cout" and "std::endl" so we need to add an "#include <iostream>" directive or the code will not compile. There are a couple of places where this can be added but I prefer to see it in the .cpp file where the code is used. Select the "myHelloWorldClass" (or "HelloWorld") from the "Model Explorer" and then select the "Profile" tab in the "Properties" window. Apply the "Include" stereotype as we did before.
Generate the Code
Generating the code from the model is very simple. In the Model Explorer, right click on
Neon: myHelloWorldRootElement
Oxygen: myHelloWorldModel
to display the context menu. Select Designer -> "Generate C++ Code". If you dragged the root element onto the class diagram, you can also right click myHelloWorldElement there and get the same context menu.
This action pops up a dialog that asks you to confirm the creation of a new Project.
Click on the "Yes" button. Next the create project window is displayed. We are going to use "make" to build the project and the "Cygwin" tool chain to compile it. Expand the "Makefile project" folder in the "Project type:" and select "Empty project". Select an appropriate tool chain from the "Toolchains:" pane. Finally, click the "Finish" button.
The new project is created an displayed in the "Project Explorer" area. Expand the new project and observe the .h and .cpp files that were created.
Build The Project
In the "Project Explorer" window, right click on the code project and select "Properties".
This brings up the project Properties window. The "C/C++ Build" properties should already be selected but if not select them now. Check the "Generate Makefiles Automatically" checkbox in the "Makefile Generation" frame. Click the "OK" button which removes the window.
From the main menu, select "Project" -> "Build Project". The results of the build are displayed in the "Console" window. If you did not already have a console window open, one will be opened automatically and positioned, by default, to the right of the "Palette" window. In the screen shot below, I have dragged the "Console" window down to the lower area.
As I noted earlier, in the "Add The Code" section, there is an error in the main() function. In the screenshot above, note that the code project in the "Project Explorer" window has a small "X" added to the icon. In the screenshot above I have expanded the project and followed the "X" icon down to the myMainClass.cpp file. Then I opened that file and hovered the mouse over the first "X". As you can see the type of the hw class was not able to be resolved. You can also see from the screenshot that the main function is not in any namespace; that is the point, but the myHelloWorldClass is in the myHelloWorldPackage namespace which in turn is in the
Neon: myHelloWorldRootElement
Oxygen: myHelloWorldModel
namespace. You can check this by opening up the myHelloWorldClass.h file.
One solution to our build issue is to fully qualify the hw object. Return to the model, select myMainClass from the class diagram, select the "Profile" tab in the "Properties" window, expand the "Include" and select "body" to display the main() function code. Add
Neon: "myHelloWorldRootElement::"
Oxygen: "myHelloWorldModel::"
to the from of the hw declaration. This line is getting tool long for the small code window so display it in the C/C++ view. From the main menu, select "Window" -> "Show View" -> "Other..." to display the "Show View" window. Scroll down to the "Papyrus" folder and expand it. Select "C/C++".
Click the "OK" button and the C/C++ view is displayed.
Follow the instructions in the window and select the myMainClass class in the class diagram. Now the main code in displayed in the "C/C++" view.
Now save the model and regenerate the code. Check the myHelloWorldClass.cpp file again and check that the red "X"s in the margin are gone. I see that the red "X" in the icons of the "Project Explorer" are still there. TODO: See if this is a known bug.
Run The Code
From the main menu, select "Run" -> "Run Configurations..."
This pops up the "Run Configurations" window.
Expand "C/C++ Application" and select the configuration for our project which is called "Default". Next we need to specify the name of the executable. The easiest way to to this is to use the "Search Project" button. Clicking this pops up the "Program Selection" window. Select the binary, there should only be one, and click the "OK" button to close the window and return to the "Run Configurations" window.
Finally!!! Click the "Run" button in the "Run Configurations" window. "make" will run again, but should have nothing to do, and the results will be displayed in the "Console" view.