Step 2 : Create a new package

Now let’s suppose you want to create a new package:

cd <pid-worskspace>
pid create package=my-first-package author="My Name" institution="LIRMM"

The package has been created and is purely local to you workspace (nobody knows about it and can access to it except yourself). One of the first thing to do is to connect it to a remote repository on the gitlab server. To do so:

  • create a gitlab project (in your account or in a group if you have the adequate rights in this group). Simply push the New Project button in gitlab dashboard. You must give to this repository the same name as your newly created package : in this example my-first-package !

  • Once created your server repository is empty but it has an address like You must now connect it to the PID package you just created:

cd <pid-worskspace>
pid connect package=my-first-package

Well done ! The package is now connected to the remote repository on the server ! You can now start developping the package.


You can do a all in one command to create and connect the newly created package:

cd <pid-worskspace>
pid create package=my-first-package

2.1 Look at git branches

A PID package has two standard git branches:

  • master branch always reflects the last released version of the package. This branch is used only to get and publish updates of the package.
  • integration branch is where developpers actually work. This branch is used to directly develop new functionnalities or to merge patches coming from feature specific branches.

After creation the package repository is on integration branch, just do:

cd <pid-worskspace>/packages/my-first-packages
git branch -a

You should see a star * in front of the integration branch indicating that this is the current branch. From developper perspective, they should always work on integration branch or on feature specific branches but never directly on master branch.

2.2 Look at git remotes

A PID package has two standard git remotes defined:

  • official remote is the online repository (in your project server) that is referenced inside the workspace. It is used to update package and to release its versions using tags. The address bound to the official remotes is the address defined with the url argument in connect and create commands. It is also the address defined in the root CMakeLists.txt file of your package (see next section).

  • origin remote is the online repository you are currently working with. Most of time, and after creation, origin has exactly the same value than official. But sometimes you need to work on an isolated online repository (typically after a fork of the official repository) that you can update. Keep in mind that even if you work with a different origin, updates and releases of the package always target the official repository.

After these preliminary explanations, let’s code !

Step 3 : Write code and describe package content

For the remaining of this section we name <my-first-package> the path to the newly created package for the sake of readability.

3.1 Edit package content description

The first thing to do is to edit the package meta-information. This is achieved by editing the root CMakeLists.txt file of the package.

At the beginning, your package’s root CMakeLists.txt file should look like this:

cmake_minimum_required(VERSION 3.15.7)
set(WORKSPACE_DIR ${CMAKE_SOURCE_DIR}/../.. CACHE PATH "root of the packages workspace directory")
list(APPEND CMAKE_MODULE_PATH ${WORKSPACE_DIR}/cmake) # using generic scripts/modules of the workspace
include(Package_Definition NO_POLICY_SCOPE)


PID_Package(AUTHOR 		    My Name
            YEAR 		      2015
            LICENSE 	    CeCILL
            DESCRIPTION   TODO: input a short description of package toto utility here
            VERSION       0.1.0

#now finding packages


As you may see the PID_Package function (equivalent to declare_PID_Package) is the function used to set the CMake project as a PID package and contains arguments whose values are set according to arguments you passed to the creation command (see previous sections). You may have to change some arguments that have default values if you do not set corresponding argument in the command. For instance, you can decide:

  • to apply a given license (CeCILL is acually the default license when packages are created) by changing the value of the LICENSE argument.
  • set the main author name by changing the value of the AUTHOR argument. By default the name is the name of your workstation current user if you do not set the author argument with the create command.
  • add (beside INSTITUTION line) a line to specify the email of the person to contact to have information about this package (well, yourself we presume): MAIL
  • provide a short description of the package replacing the line beginning by TODO.

There are many way to better document and formalize you package but these basic informations are sufficient.

The call to PID_Package also sets the current version using the VERSION argument. At beginning the version is 0.1.0. If the patch version is not specified, then it is considered as 0.

Finally, the last line of the package’s root CMakeLists.txt must be the call to build_PID_Package() macro. To be short, this macro does all the job for configuring the package adequately so never forget it.

As long as your package has no dependency you have nothing more to do in this root CMakeLists.txt file. Now, let’s add components to your package !

3.2 Create a library

Let’s suppose you want to create a very simple library printing an “Hello World” message in console by calling a function called, print_Hello(). We want this library to be a static (or shared) library, it will so need to have a header file and a source file.

3.2.1 Create folders containing sources

With PID, source files are not targeted directly, but instead you have to specify a folder that contains source and header files. When creating a static or shared library you basically have to create a folder that contains the sources, both in the include and in the src folders. Let’s call this folder hello.

cd <my-first-package>
mkdir src/hello
mkdir include/hello

3.2.2 Define the library in PID

Now to inform the PID system that you want to create a library you have to edit the CMakeLists.txt file contained in the src folder. Write the following code:

PID_Component(STATIC_LIB NAME hello-static DIRECTORY hello)

You just specify that the source code of the static library named hello-static is in the hello folder of both include and src folder (using the DIRECTORY keyword).

3.2.3 Write the code

Now you have of course to write C/C++ code of your library.

  • Edit a file named hello.h in the include/hello folder and paste the following code:
#include <string>

void print_Hello(const std::string& user_input);
  • Edit a file named hello.cpp in the src/hello folder and paste the following code:
#include <hello.h>
#include <iostream>
static std::string output_string = "Not Hello ";
static std::string output_string = "Hello ";

using namespace std;

void print_Hello(const std::string& user_input){

Now your library is completely defined.

3.2.4 Define another library, with the same code

With PID it is quite simple to define another component built from the same code ! As an example we will define a shared library from the exact same code as previously. To do this, you have to edit the CMakeLists.txt file contained in the src folder and write the following code at the end of the file:

PID_Component(SHARED_LIB NAME hello-shared DIRECTORY hello

The things that changed are:

  • the name of the component (here hello-shared). You just have to remember that components name are unique in the context of a package.

  • the type of component (here a shared library using the SHARED_LIB keyword).

  • a definition has been added to the compilation of the library code, using INTERNAL DEFINITIONS keywords. DO_NOT_PRINT_HELLO is so defined for this library only, this way the shared library will print “Not Hello “ as prefix of the output, instead of “Hello “ (look at hello.cpp).

3.3 Create an example application

Now let’s suppose we want to write an application using the previous library. The process is more or less the same.

3.3.1 Create the folder containing sources of the application

As previously, you have to create a folder that contains source of the application, but this time in the apps folder. We simply call this folder hello.

cd <my-first-package>
mkdir apps/hello

3.3.2 Define the application in PID

To inform the PID system that you want to create an application you have to edit the CMakeLists.txt file contained in the apps folder. Write the following code:

PID_Component(hello-app APPLICATION DIRECTORY hello)

As with libraries you just specify that the source code of the application named hello-app is in the hello subfolder of apps folder (using the DIRECTORY keyword).

Now as this application uses a library we have to define a dependency between the application and the library. Let’s suppose we use the static library hello-static defined previously.

PID_Component_Dependency(COMPONENT hello-app DEPEND hello-static)

Here the important part is the DEPEND keyword followed by the name of the component in use (hello-static). It specifies that the hello-app component depends on a component called hello-static. Another way to define such a dependency is to use the DEPEND argument of the component declaration command, allowing so to define a component and its dependencies in the same time:

PID_Component(hello-app APP DIRECTORY hello
              DEPEND hello-static)

This is far more convenient to use when the dependency is simple to specify. Sometimes, more things have to be defined (e.g. preprocessor definitions) and then it is required to use the PID_Component_Dependency command that provides arguments to precisely set all aspects of the dependency.

3.2.3 Write the code

Now you have of course to write C/C++ code of your application. Edit a file named hello_main.cpp in apps/hello folder and paste the following code:

#include <hello.h>
#include <iostream>

using namespace std;

int main(int argc, char* argv[]){
    if(argc == 1){
	cout<<"Only one argument ... error !! Please input a string as argument of the program"<<endl;
	return 1;
    return 0;

Now your application is completely defined. It simply takes the arguments passed to the program and passed them to the call of the print_Hello() function so that they in turn will be printed on standard output after the prefix “Hello “ message.


More complete explanations about the usage of the PID API can be found here and an example giving deeper explanations is provided here.

Step 4 : Build and install a first version of your code

Now you have to build your code to get the resulting binaries.

cd <my-first-package>
pid build

The build folder is used to perform out of source build with cmake. The build command perfoms build (compile + link) and install, all in one !! Depending on the option you choose the command may perform much more things. To know and set these options use the standard CMake configuration tool by doing:

cd <my-first-package>/build
ccmake ..

All options and their influence on the build process are explained here.

The install process puts the generated files in the adequate places, in a folder corresponding to the current version. With the current settings of the package (see the root CMakeLists.txt file) it puts them in the folder <pid-workspace>/install/<platform>/my-first-package/0.1.0. You may see the resulting artefacts:

  • libhello-static.a and can be found in the lib subfolder.

  • hello-app can be found in the bin subfolder.

To run the application simply do:

cd <pid-workspace>/install/<platform>/my-first-package/0.1.0/bin
./hello-app "this is my message"

The console should print :

Hello this is my message

Now let’s see how to release your package.