NAV

Discussion about PidPath objects

The rpathlib library provides a PidPath object that is used to describe and manage path to runtime resources in the context of a PID workspace. We can distinguish 3 main types of pid path:

absolute path

They have the classical form /home/user/dir/file.

Their use is really not recommanded.

static relative path

They are expressed as classical relative path in unix filesystem : dir/file. They are static because they must have been declared as dependent resources at build time using for instance:

  • Declare a direct runtime dependency to a file or folder:
     PID_Component(your_component_name SHARED DIRECTORY your_directory
                          RUNTIME_RESOURCES	folder1 folder2/file1 ...)
    
  • Declare a runtime dependency to an application:
    PID_Component_Dependency(your_component_name DEPEND an-application PACKAGE other_package)
    
or directly within component declaration:
     PID_Component(your_component_name SHARED DIRECTORY your_directory
                          DEPEND other_package/an-application)
    
  • Declare a runtime dependency to a module library:
    PID_Component_Dependency(your_component_name DEPEND a-module-library PACKAGE other_package)
    
or directly within component declaration:
    PID_Component(your_component_name SHARED DIRECTORY your_directory
                         DEPEND other_package/a-module-library)
    

dynamic relative path

They are unknown at build time so the dependency is not explicit until runtime. This way it is possible for a component to retrive a resource from arguments passed by to the program or from configuration files. They have a specific syntax decomposed in the following sequence of items:

  • a target package description with format <package name,version constraint>. The package name is a simple string naming the target package and version constraint specifies the search constraint. If the constraint is not respected (no version of the package was found wit hmatching requirements) then it throws an exception. Version constraints can specify:

    • an exact version, for example <pid-rpath, 1.7.0> searches for the exact version 1.7.0 of package pid-rpath.
    • a minimal version, for example <pid-rpath, +1.7.0> searches for the maximum version that is greater or equal than 1.7.0.
    • a maximal version, for example <pid-rpath, -1.7.0> searches for the maximal version that is less or equal than 1.7.0.
    • an interval of versions, for example <pid-rpath, 0.5.4~1.7.2> searches for the maximal version that is the interval
    • any version, for example <pid-rpath, any> searches for the maximal version available.

Please refer to the API doc of PidPath class to learn possible constraints.

  • a relative path expressed as classical relative path in unix filesystem : dir/file. This path is so made relative to the target package.

Specific modifiers

Whatever the type of path, PidPath also provides modifiers to be used at beginning of the expression:

  • the write modifier + specifies that the target resource does not have to exist (i.e. it will be written by the program).
  • the module modifier @ is used to specifiy a runtime component that is a module library (a dynamically loadable shared object).
  • the executable modifier # is used to specify a runtime component that is an application (an executable program).

All three modifiers are mutually exclusive. So anytime you define a runtime path to a runtime component (module or executable) this later must exist.

Using modifiers @ and # requires:

  • to define no path but to give only their name (as declared in the CMakeLists.txt file of the package that contains them).
  • to define the package they belong to (even if it is the same package as the one containing the source file) using a header like for a dynamic path.

So a static runtime path to a module looks like : @<package>component, while a dynamic runtime path looks like @<package,constraint>component. Same logic for executables.

The basics of static relative runtime resources

Any time you declare a static relative runtime resource for a given component (cf. previous section ), then:

  • All these runtime resources can be accessed by the component at runtime using static relative path. Futhermore the component will export all these resources so components that use it will be able to access these resources in turn.

  • if you use this resource in the code of the component (typically you will use path or file names), then you have to:

1) declare the component dependent from rpathlib:

#to be able to manage runtime path to resources in a clean way, include the rpathlib
PID_Component_Dependency(
				COMPONENT your_component_name				
				DEPEND 		rpathlib
				PACKAGE		pid-rpath)

or directly define it in component declaration using short signature.

PID_Component(your_component_name SHARED DIRECTORY dir				
				      DEPEND   pid/rpath) # we use framework and alias names here instead of package and real name

2) include the rpathlib include in your source code:

#include <pid/rpath.h>

3) use the pid-rpath API to manage all these path. It simply consists in using the dedicated “all-in-one” macro that does the whole job of finding for you:

std::string bad_path_to_resource = "folder1/file"; //BAD IDEA :(
...
std::string good_path_to_resource = PID_PATH("folder1/file"); //WELL DONE !!
std::string good_path_to_executable = PID_PATH("#<package>runtime_component_name"); //WELL DONE !!
...
std::string not_advised_path_to_resource = PID_PATH("/home/user/dir/file"); //absolute path are not recommanded
  • if you DO NOT use this resource in the code of the component (you use path or filename nowhere in its code), then you have nothing to do. This later case is simply used to allow components to export some resources even if they do not directly use them.

Remark: Using static relative runtime resource is far safer than with dynamic alternative as you know that these resources exist by construction (i.e. at build time) and will so be usable at runtime with adequate package version. Using dynamic relative path should be used only when it is not possible to know which runtime resources are required at build time (for instance when using a plugin based mechanism to dynamically load module libraries at runtime).

Exceptions

Be aware that PID_PATH may throw exceptions if the target files or folders do not exist in the file system. All exception thrown are of type std::logic_error, simply catch them as usual if you want to keep the program running.

Nevertheless, when you use static relative path like PID_PATH("a/path") there should not be any exception in your program as all target resources should have been referenced before either directly (using RUNTIME_RESOURCES in PID_Component) or undirectly (recursively, by dependencies of the component). So these runtime resources are known at build time (nevertheless their content or even their existence in filesystem is unknown until execution) and so an exception should not be allowed in a debugged program…

Discussion about executable

Any time an executable that directly or undirectly (via libraries) uses runtime resources it should always begin like:

#include <pid/rpath.h>
int main(int argc, char* argv []){
PID_EXE(argv[0]);//DON'T FORGET THAT LINE ON WINDOWS !!!!!
...

The PID_EXE command initialize the system to let it know how to find relative runtime resources. Without this you will face exceptions. Its use can be omitted for most recent UNIX platforms.

Discussion about modules

Any time you want to use module library (in a plug-in based approach) you should always use the PID_MODULE macro:

  • when module is loaded use PID_MODULE(true,"path/to/the/module"). This must be done before any call to this module API (for instance just after a dlopen or equivalent call).
  • when module is unloaded use PID_MODULE(false,"path/to/the/module"). This must be done just after all call to the module API have been performed (for instance just after a dlclose or equivalent call).

As module are most of time used to dynamically add new functionnalities to an executable, they are unknown at executable build time. So static runtime resources they use are unknown in the executable context. The call to PID_MODULE configures the executable so that it will also look into modules context to solve static relative runtime resources.