Add External Library¶
Add external library to the wscript of your experiment¶
To add an external library to your experiment, you need to modify the build script of your experiment, named
wscript. The standard way to do this is to create a new configuration file for the new dependency. In the
waf build system, this is done by creating a python script (
.py file), usually called
libname is the name of the library), in the same directory as your experiment.
to activate this script, you need to activate your experiment when configuring limbo:
./waf configure --exp your_exp
This new file should have the following structure:
#!/usr/bin/env python # encoding: utf-8 from waflib.Configure import conf @conf def check_libname(conf): # check if libname exists in the system try: res = check_if_libname_exists except: conf.fatal('libname not found') return
check_if_libname_exists is replaced with logic to find our library, as explained later. If the library is optional, the
conf.fatal line can be removed.
Then add the following lines in the
# imports, etc, ... # we assume that the configuration file is saved as libname.py import libname def configure(conf): conf.load('libname') conf.check_libname() # rest of the configuration # rest of code
Libraries usually have the headers and the lib files in two different directories. However, header-only libraries only have includes, in this case, you can ignore the following section named “Check for lib files”.
Check for headers¶
To check for the headers of the library, you can add the following code to the
# previous code @conf def check_libname(conf): # possible path to find headers includes_check = ['path1', 'path2'] try: conf.start_msg('Checking for libname includes') # include_files is a list with the headers we expect to find for file in include_files: conf.find_file(file, includes_check) conf.end_msg('ok') conf.env.INCLUDES_LIBNAME = includes_check except: conf.end_msg('Not found', 'RED') return # rest of check_libname # rest of code
Check for lib files¶
To check for the lib files of the library, you can add the following code to the
# previous code @conf def check_libname(conf): # possible path to find lib files libs_check = ['path1', 'path2'] try: conf.start_msg('Checking for libname libs') # lib_files is a list with the lib files we expect to find for file in lib_files: conf.find_file(file, libs_check) conf.end_msg('ok') conf.env.LIBPATH_LIBNAME = libs_check # list with the lib names the library has conf.env.LIB_LIBNAME = ['libname1', 'libname2'] except: conf.end_msg('Not found', 'RED') return # rest of check_libname # rest of code
Add configuration options¶
Additional configuration options are often needed when adding new libraries. For example, one useful option is to specify the location of the library headers and lib files. Adding options is easy: you only need to define a new function named
options in the
wscript and another one in the library configuration file. In the library’s configuration file (e.g.,
#imports, etc, ... def options(opt): # add options to the configuration opt.add_option('cmd_option', type='option_type', help='info message', dest='destination_variable') @conf def check_libname(conf): # access options if conf.options.destination_variable == 'yes': print 'destination_variable found' # rest of check_libname
The options in the waf build system are using the python’s
optparse. Check the official optparse documentation for more information.
Then add the following lines in the
wscript of your experiment:
# imports, etc, ... def options(opt): opt.load('libname') # rest of the options # rest of the code
Example: Add ROS as external library¶
Here’s a small and quick example to add ROS as an external library to our experiment. We assume the following file structure (where
main.cpp is C++ source code using limbo and ROS):
limbo |-- exp |-- example +-- wscript +-- ros.py +-- main.cpp |-- src ...
#!/usr/bin/env python import limbo import ros def options(opt): opt.load('ros') def configure(conf): conf.load('ros') conf.check_ros() def build(bld): libs = 'EIGEN BOOST ROS LIMBO' obj = bld(features = 'cxx cxxstlib', source = 'main.cpp', includes = '. .. ../../ ../../src', target = 'test_exec', uselib = libs, use = 'limbo')
#!/usr/bin/env python # encoding: utf-8 import os from waflib.Configure import conf def options(opt): opt.add_option('--ros', type='string', help='path to ros', dest='ros') @conf def check_ros(conf): # Get locations where to search for ROS's header and lib files if conf.options.ros: includes_check = [conf.options.ros + '/include'] libs_check = [conf.options.ros + '/lib'] else: if 'ROS_DISTRO' not in os.environ: conf.start_msg('Checking for ROS') conf.end_msg('ROS_DISTRO not in environmental variables', 'RED') return includes_check = ['/opt/ros/' + os.environ['ROS_DISTRO'] + '/include'] libs_check = ['/opt/ros/' + os.environ['ROS_DISTRO'] + '/lib/'] try: # Find the header for ROS conf.start_msg('Checking for ROS includes') conf.find_file('ros/ros.h', includes_check) conf.end_msg('ok') # Find the lib files libs = ['roscpp','rosconsole','roscpp_serialization','rostime','xmlrpcpp', 'rosconsole_log4cxx', 'rosconsole_backend_interface'] conf.start_msg('Checking for ROS libs') for lib in libs: conf.find_file('lib'+lib+'.so', libs_check) conf.end_msg('ok') conf.env.INCLUDES_ROS = includes_check conf.env.LIBPATH_ROS = libs_check conf.env.LIB_ROS = libs conf.env.DEFINES_ROS = ['USE_ROS'] except: conf.end_msg('Not found', 'RED') return
The configuration and compilation of the experiment follows the usual procedure (assuming that we are in the limbo root folder):
./waf configure --exp example ./waf --exp example