Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Papyrus for Real Time » Invoke code generator command line(How can I incorporate the code-generator in the build server)
Invoke code generator command line [message #1799511] Fri, 07 December 2018 22:26 Go to next message
Dimo Ditchev is currently offline Dimo DitchevFriend
Messages: 33
Registered: September 2018
Member
Hi Charles and Ernesto,
How I can set up the code-generator in the build server, so that I will check in only the model files in the source control and the source files will be generated by the build server?

Thanks,
Dimo
Re: Invoke code generator command line [message #1799514 is a reply to message #1799511] Fri, 07 December 2018 23:42 Go to previous messageGo to next message
Ernesto Posse is currently offline Ernesto PosseFriend
Messages: 438
Registered: March 2011
Senior Member
I imagine you are trying to use some form of continous-integration (e.g. jenkins/hudson + maven/tycho or buckminster)? To do this you'll need to have Papyrus-RT installed on your build server and you'll need the standalone version of the code generator which can be found under <papyrus-rt-install-folder>/plugins/org.eclipse.papyrusrt.codegen.standalone_1.0.0.201707181457. There is a (bash) shell script there called "umlrtgen.sh". If you are on Windows, you'll have to run it in a Cygwin terminal.

The problem is that I'm not completely sure the script works as I haven't tested it in a very long time, but you can try to give it a go.

The standard usage is

umlrtgen.sh <plugin-dir> <src-dir> <java-vm> [options] <model-file>

where

  <plugin-dir> is the root directory of plugin dependencies, i.e. the 'plugins' directory of the target eclipse platform, or just a directory that contains all required Eclipse jar files.

  <src-dir> is the root of the development directory containing the binaries of the development version of the code generator. If used in a production (end-user) environment and not in a development environment, it should be the same as <plugin-dir>.

  <java-vm> the name of the Java VM to use. Normally should be "java".

  <model-file> is the name of the .uml file (including the extension)

The options are:

  -h 		help (lists options)
  -q 		quiet mode: Inhibits printing messages during generation
  -l LEVEL	log-level: Set the level of logging (OFF, SEVERE, INFO, WARNING, CONFIG, FINE, FINER, FINEST). The default is OFF
  -s		Print the stack trace for exceptions
  -p		Specifies the plugins folders of the PapyrusRT installation
  -t		Specify the name of the top capsule. By default it is "Top".
  -o		Specifies the output folder. By default it is 'gen' in the same folder as the input model.
  -d		Development mode: this is to be used only when invoking the generator from a development environment.
  -x		Translate an input UML2 model into an xtUMLrt model instead of generating code.


So you are most likely to use the -o option, and maybe the -s and -l options for debugging.

If not using the script, you can try calling directly the java class org.eclipse.papyrusrt.codegen.standalone.StandaloneUMLRTCodeGenerator, using the -p option and calling java with -cp to set the class-path to include all the Papyrus-RT jar files (this is actually what the script does).
Re: Invoke code generator command line [message #1799515 is a reply to message #1799514] Sat, 08 December 2018 00:04 Go to previous messageGo to next message
Dimo Ditchev is currently offline Dimo DitchevFriend
Messages: 33
Registered: September 2018
Member
Yes, this is exactly my intention.

Thank you,
Dimo
Re: Invoke code generator command line [message #1799595 is a reply to message #1799515] Mon, 10 December 2018 18:29 Go to previous messageGo to next message
Dimo Ditchev is currently offline Dimo DitchevFriend
Messages: 33
Registered: September 2018
Member
Ernesto,

Can you please, help - I am stuck at:
user@ubuntu:~/p4/px/uic/sw/01.0/int/app/therapy/model$ ~/org.eclipse.papyrus-rt/plugins/umlrt/codegen/org.eclipse.papyrusrt.codegen.standalone/umlrtgen.sh ~/Desktop/Papyrus-RT/plugins/ /home/user/Desktop/Papyrus-RT/plugins/org.eclipse.papyrusrt.codegen.standalone_1.0.0.201707181457/org/eclipse/papyrusrt/codegen/standalone/ java Therapy.uml
.......
org.eclipse.papyrusrt.codegen.standalone.StandaloneUMLRTCodeGenerator -p /home/user/Desktop/Papyrus-RT/plugins/ Therapy.uml
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/inject/AbstractModule
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: com.google.inject.AbstractModule
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
user@ubuntu:~/p4/px/uic/sw/01.0/int/app/therapy/model$

I also have another issue to resolve- I want to keep only he umlrt model in source controI and I need to spawn a custom thread in TopMain.cc. :

// targetStartup:
// This method can be overridden by the application code to initialize their run-time platform.
// The method must return 'true' if the application is to continue running. If it returns 'false',
// the application is terminated with a failure indication.
static bool targetStartup ( );

I don't understand how I can override this function as it is not virtual.

TopMain.cc is auto-generated and I don't see how I can write custom code into TopMain.

Do you have any suggestion how to achieve this?

Thanks,
Dimo

Re: Invoke code generator command line [message #1799602 is a reply to message #1799595] Mon, 10 December 2018 23:23 Go to previous messageGo to next message
Ernesto Posse is currently offline Ernesto PosseFriend
Messages: 438
Registered: March 2011
Senior Member
There are several problems with that script. We included it in the distribution but not "officially", as standalone generation was not a required feature for 1.0. Nevertheless I've updated it and I'm attaching a new copy which will hopefully work for you. Use as follows:

./umlrtgen.sh <path-to-papyrus-rt-plugins-folder>  <uml-file> -o <output-folder>


As for overriding the target startup, I think the RTS developer meant that you could link alternative implementations of the umlrtmain.hh header. If you look at the source in the git repo, you'll see there is a file called umlrtmaintargetstartup.cc under plugins/umlrt/runtime/rts/umlrt.

Nevertheless, I don't think this is the place to launch new "external" threads. If you need an external thread, you could modify the TopMain.cc and spawn the new threads there. But If I were you, I would deal with it in a more model-oriented approach: create a Capsule which has a simple state machine with only one state and launch new (external) threads in that state's entry action, or the initial transition. If this solution is not satisfactory to you, I'd be very interested in understanding your use-case.
  • Attachment: umlrtgen.sh
    (Size: 4.70KB, Downloaded 88 times)
Re: Invoke code generator command line [message #1799604 is a reply to message #1799602] Tue, 11 December 2018 00:37 Go to previous messageGo to next message
Dimo Ditchev is currently offline Dimo DitchevFriend
Messages: 33
Registered: September 2018
Member
Ernesto,

The script works like a "fine Swiss Watch"!!!
Thank you.
In the back of my mind I was considering to create a capsule and then assign a separate tread from the main thread as it was described somewhere in the forum.
But before you steering in this direction this was not my first choice, also I don't think I saw an example, and it is always good to start with a working example like the Ping.Ponger or the ComputerSystem models :).
Now I am much more confident that I am not going to do something that will get away from the main development effort and require a lot of maintenance.
Even if I don't get it right at the first try like the standalone code generator, I can see the light in the tunnel!
Thanks again and if you don't mind I will share our progress and come to you as I hit more roadblocks.

Dimo
Re: Invoke code generator command line [message #1799637 is a reply to message #1799604] Tue, 11 December 2018 17:49 Go to previous messageGo to next message
Ernesto Posse is currently offline Ernesto PosseFriend
Messages: 438
Registered: March 2011
Senior Member
With respect to threads: are you trying to a) start a new "outside" thread to execute code that is external to the (code generated by) the model, or b) execute some behaviour, which could be part of the model, in a separate thread?

For option a), I would still recommend the idea I described before: create a capsule, say "ExternalThread" with a simple state machine with only one state and in the state's entry action start your "external" thread, e.g. using POSIX threads [1]. Then, in the Top capsule (or wherever you need it), create a part typed by this "ExternalThread" capsule. If the part is a fixed part, it will be created when it's container is created, which in the case of Top, is when you start the application. I would not recommend messing with the runtime or modifying the generated TopMain.cc, as it would be overwritten whenever you re-generate.

Option b) means that any capsule instance can be executed in a separate thread. More precisely, the thread will run a (RTS) controller, which will execute one or more capsule's behaviours. A controller is the central element of the runtime system. It runs in its own thread, and manages the life-cycle of a set of capsule instances. It contains a queue of incoming messages (shared by all capsules managed by the controller). It basically runs a loop where it gets the event from the incoming event queue with the highest priority, looks at the event's recipient (some capsule) and "gives it" to the capsule to process, which means executing a "run-to-completion" step on the capsule's state machine. It is a "run-to-completion" step because the event will be fully processed by that recipient capsule state machine before the next event in the queue is processed by the controller.

Now, you can have more than one controller and you can assign capsule instances to different controllers, and therefore different threads. There are two ways of doing this:

1) Statically by specifying a "Top.controllers" file. This is a simple text file that you place next to the model and has a simple format consisting of lines of the form:

<capsule-part-qualified-name> = <controller-name>


Where the <controller-name> is given by you. Different controller names will result in spawning different threads. For example

Top.pinger = Controller1
Top.ponger = Controller2


Note that the part's name is qualified, starting with the name of the Top capsule. If capsule "Ponger" had a part called, say "leftHand" of type "Hand", you could write a line like this:

Top.ponger.leftHand = Controller3


or if it had a part called "hands" with replication 2, you could write:

Top.ponger.hands[0] = Controller3
Top.ponger.hands[1] = Controller3


Several capsule parts can be assigned to the same controller, as above or to different controllers. If there is a part for which no controller is specified, it will be created and run in its container's controller, e.g, if Ponger had a part called "eyes" and no controller was specified, its instance would run in Controller2 in this example.

2) Dynamically by specifying a controller on the incarnate operation on an optional part. In this case the container capsule must have a port of type "Frame", and in some action in the state machine you invoke the "incarnate" operation on the Frame port providing a reference to the optional part where you are going to instantiate the capsule, and optionally a reference to some controller. If no controller is specified, the capsule is incarnated in the same controller as the part's owner.

<frame-port>.incarnate(<part-name>)


or

<frame-port>.incarnate(<part-name>, <pointer-to-controller>)


These methods return a "UMLRTCapsuleId" that can be checked for validity, to ensure that the incarnation was successful.

So for example, suppose that "ponger" was an optional part and the Top capsule had a "frame" port of type Frame. Then, you could incarnate ponger in some controller named, e.g. "PlayerController" by writing this in some action in Top's state machine:

UMLRTCapsuleId id = frame.incarnate(ponger, PlayerController);
if (!id.valid()) {
    // error
}


One catch is that this code will not compile alone if PlayerController doesn't refer to a (pointer to a) UMLRTController. The code generator will create these pointers and controllers based on the names that appear on the Top.controllers file described above, so even in this dynamic case, you would still need to provide the file, but the incarnate operation would allow you to dynamically assign a controller to a part that has not been assigned one in the file.

Anyway, those are approaches of running capsules in separate threads. If you need to run code that is not in the model, in a separate thread, I would still recommend option a) above. If you don't have some element in the model that you know is responsible for launching a thread, you'll have maintenance difficulties, as it will not be visible in the model who is responsible for some behaviour.


[1] https://en.wikipedia.org/wiki/POSIX_Threads
Re: Invoke code generator command line [message #1799644 is a reply to message #1799637] Tue, 11 December 2018 20:16 Go to previous message
Dimo Ditchev is currently offline Dimo DitchevFriend
Messages: 33
Registered: September 2018
Member
Hi Ernesto,

This is great explanation and we will help us a lot in dealing with most of our use cases.
I think we can use option a) to model a proxy server or client.
I think we can use option b) to split the model in 2 or 3 sub-modules with separate physical threads.

But we also have a quite complex platform at hand and there is a business need to start various initialization processes, and after that launch the state machines with Papyrus main() function. We need to define/control main() and then later call your "main()" as a subroutine to start up Papyrus.
Right now we are considering to use 'sed' and rename Papyrus main in TopMain.cc so that we can call it inside our main as an external.
Yes, it is a kludge. But I believe that there will be similar business cases in the future.
Can you implement something similar?
It could be on a branch or split. We will gladly test it and contribute in this way to the mainline development of PapyrusRT.

Thanks,
Dimo
Previous Topic:Just curious: Industrial use of Papyrus RT examples?
Next Topic:Generating code for specific hardware
Goto Forum:
  


Current Time: Fri Apr 19 08:55:21 GMT 2024

Powered by FUDForum. Page generated in 0.24960 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top