I'm looking for a way to register somthing like an end-build callback in scons. For example, I'm doing something like this right now:
def print_build_summary():
failures = SCons.Script.GetBuildFailures()
notifyExe = 'notify-send '
if len(failures) > 0:
notifyExe = notifyExe + ' --urgency=critical Build Failed'
else:
notifyExe = notifyExe + ' --urgency=normal Build Succeed'
os.system(notifyExe)
atexit.register(print_build_summary)
This only works in non-interactive mode. I'd like to be able to pop up something like this at the end of every build, specifically, when running multiple 'build' commands in an interactive scons session.
The only suggestions I've found, looking around, seem to be to use the dependency system or the AddPostAction call to glom this on. It doesn't seem quite right to me to do it that way, since it's not really a dependency (it's not even really a part of the build, strictly speaking) - it's just a static bit of code that needs to be run at the end of every build.
Thanks!
I don't think there's anything wrong with using the dependency system to resolve this. This is how I normally do it:
def finish( target, source, env ):
raise Exception( 'DO IT' )
finish_command = Command( 'finish', [], finish )
Depends( finish_command, DEFAULT_TARGETS )
Default( finish_command )
This creates a command that depends on the default targets for it's execution (so you know it'll always run last - see DEFAULT_TARGETS in scons manual). Hope this helps.
Ive been looking into this and havent found that SCons offers anything that would help. This seems like quite a usefull feature, maybe the SCons developers are watching these threads and will take the suggestion...
I looked at the source code and figured out how to do it. I'll try to suggest this change to the SCons developers on scons.org.
If you're interested, the file is engine/SCons/Script/Main.py, and the function is _build_targets(). At the end of this funcion, you would simply need to add a call to a user supplied callback. Of course this solution would not be very useful if you build on several different machines in your network, since you would have to port the change everywhere its needed, but if you're only building on one machine, then maybe you could make the change until/if SCons officially provides a solution.
Let me know if you need help implementing the change, and I'll see what I can do.
Another option would be to wrap the call to SCons, and have the wrapper script perform the desired actions, but that wouldnt help in SCons interactive mode.
Hope this helps,
Brady
EDIT:
I create a feature request for this: http://scons.tigris.org/issues/show_bug.cgi?id=2834
Related
My setup is: ROS melodic, Ubuntu: 18.04
I want simulate turtlebot3 moving with my own global planner and have been following this tutorial to get started: http://wiki.ros.org/navigation/Tutorials/Writing%20A%20Global%20Path%20Planner%20As%20Plugin%20in%20ROS#Running_the_Plugin_on_the_Turtlebot. The tutorial seem to be made for ROS hydro, but as it was the best source of guidance I could find I hoped it would work.
The error I'm having is:
Failed to create the global_planner/GlobalPlanner planner, are you sure it is properly registered and that the containing library is built? Exception: MultiLibraryClassLoader: Could not create object of class type global_planner::GlobalPlanner as no factory exists for it. Make sure that the library exists and was explicitly loaded through MultiLibraryClassLoader::loadLibrary()
To my knowledge I've followed the tutorial as much as possible with a only a few things done differently because I wanted to test it, couldn't do as the tutorial asked, or because I thought it wouldn't impact the results. What I have done differently is:
I use the carrot_planner.h and carrot_planner.cpp files in the tutorial section 1 to test that it works before trying with my own code to avoid confusion about where possible errors come from. It's not 'different' from the tutorial to my knowledge, but figured I'd mention it. They are placed in catkin_ws/src/carrot_planner/src/global_planner/
The ros package I'm working from is in catkin_ws/src and is called the carrot_planner. In the tutorial step 1.3 I use add_library(global_planner_lib src/global_planner/carrot_planner.cpp). Would not imagine it affects the results either.
In section 3 of the tutorial it mentions that 'First, you need to copy the package that contains your global planner (in our case global_planner) into the catkin workspace of your Turtlebot (e.g. catkin_ws).' Since my package was already in catkin_ws/src/ I haven't moved it since I guess I didn't need to.
I've altered the 'move_base.launch' file in '/opt/ros/melodic/share/turtlebot3_navigation/launch/' instead of the 'move_base.launch.xml' in '/opt/ros/hydro/share/turtlebot_navigation/launch/includes/' as there doesn't seem to be a destination '...turtlebot3_navigation/launch/includes/'. There are files in launch, but no includes folder. Maybe that a difference from Hydro to Melodic, I don't know. There may be a whole lot of things that need to be done differently from the tutorial when using Melodic, or with turtlebot3, but I don't know.
I haven't made my own launch file for bringup of the turtlebot, but have instead followed this tutorial (https://emanual.robotis.com/docs/en/platform/turtlebot3/nav_simulation/) to guide me with turtlebot3. After finishing this step in the global planner tutorial 'Save and close the move_base.launch.xml. Note that the name of the planner is global_planner/GlobalPlanner the same specified in global_planner_plugin.xml. Now, you are ready to use your new planner' I tested whether it worked by running: 'roslaunch turtlebot3_gazebo turtlebot3_world.launch' and then I tried running: 'roslaunch turtlebot3_navigation turtlebot3_navigation.launch map_file:=$HOME/map.yaml' which led to the error I showed above. I have created the map-yaml, so there's no misunderstanding whether that's missing.
I would be very glad for any help, thank you ^^
Edit: My system only had 'navfn' on it, not 'global_planner' or 'carrot_planner', if that makes a difference.
After looking over the code I found a solution. It doesn't make everything work perfectly yet, but seems to solve the immediate problem.
The problem was that in my 'global_planner_plugin.xml' I just used the code provided in the tutorial:
<library path="lib/libglobal_planner_lib">
<class name="global_planner/GlobalPlanner" type="global_planner::GlobalPlanner" base_class_type="nav_core::BaseGlobalPlanner">
<description>This is a global planner plugin by iroboapp project.</description>
</class>
</library>
But in the carrot_planner.cpp file it says:
PLUGINLIB_EXPORT_CLASS(carrot_planner::CarrotPlanner, nav_core::BaseGlobalPlanner)
Changing type="global_planner::GlobalPlanner to type="carrot_planner::CarrotPlanner and then launching turtlebot3 doesn't give the same error anymore.
I am trying to securely clear out a directory using SDelete. I know that this is used from the Command line, but how I would I go about automatically clearing the directory from my C++ code, also using Qt if this has a built any built in functions. I could not find anything with searching and this is my first time doing something like this. Any help would be greatly appreciated, thanks.
It is good that you're not trying to re-create the functionality of SDelete. It would be a LOT of work to do as good as a job as what SDelete does. Invoking the existing application is a wise choice.
Now, on to your question... If you want to use QT, then what you need is something like this:
QString path = QString("sdelete", QStringList() << "Bogus.txt");
QProcess sdelete;
sdelete.start( path );
sdelete.waitForFinished();
That will start the process sdelete with the parameter Bogus.txt and then wait until the application is finished.
More Info: https://doc.qt.io/archives/qt-4.8/qprocess.html#start
Edit from OP : I found that using the following worked for me with the argument being passed in being a QString.
QProcess::execute("sdelete -s path");
I'm trying to write a rake task that can perform a guided search on the user's system for specific system libraries. The basic idea is simple enough (in semi-pseudo-code):
def find_lib names, paths
foreach name, path do
return { :name => name, :path => path } if File.exists? File.join(path, name)
end
return false
end
find_lib ['mylib1.2', 'mylib12'], ['/usr/lib', '/usr/local/lib']
My actual implementation is a little more elegant, but this shows the basic idea. However, I would like to make this OS agnostic, which throws a few big wrenches into the gears. Each operating system has potentially different prefixes and extensions for a library. For instance, a shared library could be ".dll", ".so', or ".dylib" depending on the current system. So far, I've come up with a solution that involves building a map of prefixes/extensions based on the current operating system:
settings = {}
settings[:dylib_ext] = OS.windows? && ".dll" ||
OS.mac? && ".dylib" ||
".so"
This works to some extent, although it only covers the dynamic library case, and also relies on an external gem "OS", which I was trying to avoid.
Does anyone know a better way of accomplishing such a task, or if it is a solved problem (via another gem perhaps)? The main thing I'm concerned about is the map, which could get very cumbersome (not to mention that detecting the correct operating system is rather tedious at best, especially if you were to throw in cygwin or mingw).
After some thought, it seems that I have been too specific as to the user's current operating system, while what I really have wanted to determine has always been what functionality the user's system supports... The approach that I ended up using was to determine a list of possible prefix/suffix combinations, and to check each of those.
I am working on a plugin which will have its own plugins to handle various events.
Now I'm thinking of enabling this plugins to add their own "commands". But I wonder how to treat that most efficiently. I have a list of my own commands which I search in the article anyway. Should I then just trigger a DoWhatYouWant($article)-event - or, since I do the searching (and parsing of params) anyway, perhaps I could build a global command-list and then trigger an "ExecuteCommand($article,$cmd,$params)"-event? Sounds nicer, but then (I think) I'd have to build this command-list (so that my program know what to look for), so every plugin would have to somehow 'advertise' what it could do, i.e. the names of commands it could handle - and I have no idea how that could be done.
Or is there a better (more standardized?) approach?
If you import your plugins trough the plugin helper
JPluginHelper::importPlugin('mycmdplugins');
then you can get all available commands which are supported by your sub plugins like
$cmds = JDispatcher::getInstance()->trigger('onMyAwesomeCmds');
With the $cmds variable you know now which commands are supported by the sub plugins and you can parse the article for them. Then you can do
foreach ($cmds as $cmd) {
preg_match_all("{".$cmd."*}", $article->text, $matches, PREG_SET_ORDER);
if (!empty($matches)) {
JDispatcher::getInstance()->trigger('onMyAwesome'.ucfirst($cmd), array($article, $params));
}
}
To eliminate more repeating tasks I suggest that the additional plugins will extend a base class from your plugins folder.
So I'm trying to make use of a GtkSourceView in C++ using GtkSourceViewmm, whose documentation and level of support give me the impression that it hasn't been very carefully looked at in a long time. But I'm always an optimist :)
I'm trying to add a SourceView using some code similar to the following:
Glib::RefPtr<gtksourceview::SourceLanguageManager> source_language_manager = gtksourceview::SourceLanguageManager::create();
Glib::RefPtr<gtksourceview::SourceLanguage> source_language = Glib::wrap(gtk_source_language_manager_guess_language(source_language_manager->gobj(), file, NULL));
Glib::RefPtr<gtksourceview::SourceBuffer> source_buffer = gtksourceview::SourceBuffer::create(source_language);
gtksourceview::SourceView* = m_source_view = new gtksourceview::SourceView(source_buffer);
m_vbox.pack_start(*m_source_view);
Unfortunately, it spits out the warning
(algoviz:4992): glibmm-WARNING **:
Failed to wrap object of type
'GtkSourceLanguage'. Hint: this error
is commonly caused by failing to call
a library init() function.
and when I look at it in a debugger, indeed the second line above (the one with the Glib::wrap()) is returning NULL. I have no idea why this is, but I tried to heed the warning by adding Glib::init() to the begining of the program, but that didn't seem to help at all either.
I've tried Google'ing around, but have been unsuccessful. Does anyone know what Glib wants me to init in order to be able to make that wrap call? Or, even better, does anyone know of any working sample code that uses GtkSourceViewmm (not just regular GtkSourceView)? I haven't been able to find any actual sample code, not even on Google Code Search.
Thanks!
It turns out, perhaps not surprisingly, that what I needed to init was:
gtksourceview::init();
After this, I ran into another problem with one of the parameter to gtksourceview::SourceLanguageManager, but this was caused by a genuine bug which I subsequently reported and was promptly fixed. So everything's working great now!
I use gtkmm. Typically you have to initialize things with something like :
_GTKMain = new Gtk::Main(0, 0, false);
Of course do not forget :
delete _GTKMain;
Check here for details :
http://library.gnome.org/devel/gtkmm/2.19/classGtk_1_1Main.html
(Sorry but the link option does not work ...)