Let's walk through a trivial example. In this example we use REDHAWK 1.10 although 1.8, 1.9, and 2.0 should be similar. We have a C++ Component called HelloWorldPython that will have a serviceFunction that does nothing but invoke a python script called "HelloWorld.py" that prints Hello World!
Create and generate the C++ Component as usual within the IDE. Next we need to create the HelloWorld.py script and place it within the cpp folder. Here's what I've got:
$ cat HelloWorldPython/cpp/HelloWorld.py
#!/bin/env python
print "Hello World"
Now we need to inform two entities of this file, the build system used to build and install the Component (autotools) and the REDHAWK framework so that when it deploys the Component to a Node it copies this script along with the executable.
Modify the Makefile.am and add:
dist_bin_SCRIPTS = HelloWorld.py
Just below the line defining the dist_xml_DATA. This will tell the build system to install the HelloWorld.py file within the bin directory which is defined above. Note that after adding this, you will need to rerun ./reconf and ./configure for the change to take affect.
Now we need to tell the REDHAWK Domain Manger about the script. When a Component is launched in a Waveform, the Domain Manger copies a file / folder over to the Node. It is this copy that gets executed on the Node, not the one in $SDRROOT/dom/components. The field which tells the Domain Manager what to copy is the SPD file's "localfile" tag. You may either change the HelloWorldPython.spd.xml directly or use the IDE's implementations tab, Code Section's "File" text box from within the SPD editor. In either case we need to change it from "cpp/HelloWorldPython" which was just the executable to "cpp" which is the folder which contains both the executable and the python script.
Lastly, I've placed my Component code below. It may not be the best way to do this but it proves out the idea. I used the proc file system to get the full path to the executing binary, then used boost's string replace to replace the Component name with the python file. This was done so that I could specify the full path to the python script that was deployed via the Domain Manager rather than the one in the SDRROOT. If this was a multi-machine system with remote Nodes, the SDRROOT on the remote Node may not have the Component in $SDRROOT/dom/components.
#include "HelloWorldPython.h"
#include <iostream>
#include <unistd.h>
#include <boost/algorithm/string/replace.hpp>
#include <stdlib.h>
PREPARE_LOGGING(HelloWorldPython_i)
HelloWorldPython_i::HelloWorldPython_i(const char *uuid, const char *label) : HelloWorldPython_base(uuid, label) {}
HelloWorldPython_i::~HelloWorldPython_i() {}
void HelloWorldPython_i::constructor() {}
int HelloWorldPython_i::serviceFunction()
{
#define BUFSIZE 256
char locationBuffer[BUFSIZE] = {0};
readlink("/proc/self/exe", locationBuffer, BUFSIZE);
std::string location(locationBuffer);
boost::replace_last(location, "HelloWorldPython", "HelloWorld.py");
std::string command = "python " + location;
system(command.c_str());
return FINISH;
}
EDIT
jdclfc Pointed out two issues:
I think that there are side effects to changing the Code section's 'localfile' tag. After changing the 'localfile' tag, the component doesn't launch in the sandbox anymore.
Thank you for pointing this out, looks as though it is an issue with the following line. The ATTR_PROGRAM_NAME should be set to the entry point rather than the local file. This should be fixed in a future release. This code path is only executed if the the component resides in your workspace. To work around this bug, install the component into the SDRROOT. Then, from the chalkboard pallet, launch the component into the sandbox from the "Components" section rather than the "Workspace" section.
Also the export command exports all source code to $SDRROOT/dom/components
This is true of versions of the IDE prior to 2.0.0. Rather than using the "build.sh install" or "make install" command line commands, the drag and drop of a component from the workspace to the SDRROOT, or the use of the export wizard, would try and determine what to deploy based partially on the localfile parameter. In the 2.0 release, the IDE uses the existing build.sh / make install methods. As you pointed out, the extra files do no harm however if you'd like to work around this, you may install the component from the command line using ./build.sh install or make install. If you'd like to tie that behavior into the IDE, you could override the default build command to include the install step. To do this, you would right click on the project in question, select properties. Then select the C/C++ Build section and the Behaviour tab. For the Build, rather than "all" you could change this to "install". Now when the IDE builds your component it will also install it (sans source) into the SDRROOT. You will however need to click on the SDRROOT and hit either F5 or right click and select refresh.