1.13. Creating a Static Library Project in a User-Defined Project on Wind River Workbench 3.x

In this tutorial we will create and build a static library project for the Wind River General Purpose Platform (GPP) for VxWorks. We have arbitrarily chosen to create a static library for Downloadable Kernel Module (DKM) projects; the process is almost exactly the same for Real-Time Process (RTP) projects.

There are two general approaches to building static libraries with GNATbench. The difference is whether the project type is defined by Wind River Workbench or by the user.

The first approach uses a Workbench-defined type of project, for example a DKM project. As such it uses the Workbench builder, and all the facilities provided by the type of project are available. The second approach does not use a Workbench-defined project type. Instead, it uses a “User-Defined” project type. Building and cleaning are still supported for user-defined projects, among other capabilities, but the specific facilities provided by Workbench-defined (e.g. DKM) projects are not available. The first approach is somewhat simpler to use, however. We will examine the second approach in this tutorial.

1.13.1. Workspace Configuration

These initial settings must be done for each new workspace used. You will only have to do this once per workspace unless the preferences are somehow reverted.

Start Workbench.

1.13.1.1. Perspective Selection

Use the Window menu entry and select “Open Perspective”, then select “Advanced Device Development”. Of course you may skip that step if you are already using that perspective.

1.13.1.2. Disabling “Standard” Managed Builds

As of Wind River Workbench 3.0, “Flexible” managed builds are used by default and “Standard” managed builds are deprecated. New GNATbench projects must employ Flexible managed builds.

Therefore, set the options on the Wind River “Build” preference page as shown below to disable Standard managed builds. You must also ensure the option to “Create default build targets for new projects using flexible managed build” remains enabled.

enabling standard build pref page

1.13.2. Creating and Configuring the Project

First, select the “User-Defined Project” wizard:

tutorial\_lib\_user\_defined\_proj\_wizard

In the resulting wizard, choose the “Wind River VxWorks” option in the pull-down menu:

tutorial\_lib\_user\_wiz\_page1

Press Next. In the next page, enter the name of the project. We name our project “staticDKMlib”:

tutorial\_lib\_user\_wiz\_page2

Press Next to configure build support.

tutorial\_lib\_user\_wiz\_page3

Ask to refresh current project after a build.

Press Finish. The new project will appear as shown below:

tutorial\_lib\_user\_proj\_init

Next we convert the new project to support Ada via GNATbench. To do this, we invoke the contextual menu on the new project node and select “New”, then “Other”, as shown below:

tutorial\_lib\_file\_new\_other

We then select “Convert to an Ada Project” in the resulting dialog and press OK.

conversion wizard for extending project

The first page of the conversion wizard will appear (shown in the next figure). We enter the name of the project to be converted and select the option to create a new GNAT project file.

tutorial\_lib\_user\_convert

Press Finish. A new wizard will activate to allow you to make the GNAT project file content choices.

The first page asks for the GNAT project unit name. This is not the gpr file name. Rather, it is the name of the unit (the project) within the gpr file.

Unlike the Eclipse project name, the GNAT project unit name must be a legal Ada identifier. The wizard will try to make a legal Ada name from the Eclipse project name, for example, by substituting underscores for dashes. If the Eclipse project name is already a legal Ada identifier that name is used unchanged, as in this case:

project conversion project unit name page

Select “Library Project” type and press Next.

The next page allows you to configure the ada library settings

tutorial\_lib\_ada\_library\_settings\_dialog

Click Next to take all the defaults. The next page allows you to configure the ada stand alone library settings

tutorial\_lib\_ada\_stand\_alone\_library\_settings\_dialog

Set interface to P and keep Generate the file(s) of the interface enabled to have a p.ads file automatically created. This code will be initially empty and we will edit it shortly.

Click Next.

The next page allows selection of the directories that will hold sources and intermediate products. We take all the defaults.

tutorial\_project\_dirs\_dialog.png

The final page allows selection of one or more toolchains to be available to the project.

Select the toolchain(s) to be used to build the static library.

Multiple toolchains can be convenient for a number of reasons. For example, a project baseline compiler version can be used to build the actual release but a newer version of the same toolchain can also be used for the sake of improved error analysis. This page also allows selection of a “production” and “debug” scenario, in which different switches are applied (e.g., debugging versus optimization) depending on the current development mode. Other build options are also available on the page. We take the defaults and simply press Finish.

tutorial\_lib\_project\_build\_settings\_dialog.png

Press Finish. The converted project will have new content:

tutorial\_lib\_user\_project\_converted

The GNATbench conversion wizard will generate the GNAT project file (“staticDKMlib.gpr”) with this content:

library project Staticdkmlib is

   for Languages use ("Ada");
   for Source_Dirs use ("src/**");
   for Object_Dir use "obj";
   for Library_Name use project'Name;
   for Library_Dir use "lib";
   for Library_Ali_Dir use project'Library_Dir;
   for Externally_Built use "False";
   for Library_Kind use "static";
   for Library_Standalone use "standard";
   for Library_Src_Dir use project'Library_Dir;
   for Library_Auto_Init use "False";
   for Library_Interface use ("P");

   package Compiler is
      for Default_Switches ("ada") use ("-g", "-gnato", "-gnatwa", "-gnatQ", "-gnat12");
   end Compiler;

   package Builder is
      for Default_Switches ("ada") use ("-g");
   end Builder;

   package Ide is
      for Gnat use "i586-wrs-vxworks-gnat";
      for Gnatlist use "i586-wrs-vxworks-gnatls";
      for Debugger_Command use "i586-wrs-vxworks6-gdb";
      for Compiler_Command ("ada") use "i586-wrs-vxworks-gnatls.exe";
      for Compiler_Command ("c") use "i586-wrs-vxworks-gcc.exe";
   end Ide;

end Staticdkmlib;

The Workbench wizard generated a file named “Makefile”. Originally it has the following content. The two targets (“all” and “clean”) are the hooks into the Workbench build infrastructure (the menus, in particular). In this original version the corresponding commands simply echo what the command would be doing.

all :
        @echo "make: built targets of `pwd`"

clean :
        @echo "make: removing targets and objects of `pwd`"

Modify the file to have the following content. Essentially you are replacing the entire content, although the two target names remain the same. Don’t forget to use tab characters to indent the commands under the targets – space characters will not work.

-include scenario.makefile

CONFIG_FILE = $(PLATFORM).cgpr

all :
        @echo "make: built targets of `pwd`"
        gprconfig --target=$(PLATFORM) \
                --config=ada,,$(RUNTIME), \
                --config=c,,$(RUNTIME), \
                --config=c++,,$(RUNTIME), \
                --config=asm,,, \
                --batch \
                -o $(CONFIG_FILE)
        gprbuild -p -P "$(GPRPATH)" \
                --config=$(CONFIG_FILE) \
                $(GNAT_SCENARIO_COMMAND)

clean :
        @echo "make: removing targets and objects of `pwd`"
        gprclean -r -P "$(GPRPATH)" \
                --config=$(CONFIG_FILE) \
                $(GNAT_SCENARIO_COMMAND);
        $(RM) $(CONFIG_FILE);

The new content will invoke “gprbuild”, a multi-language builder. In this case the GNAT project file directs gprbuild to create a static library. Note the various Makefile macros, such as “RUNTIME”.

Next we set the project build properties to define the “RUNTIME” macro. Right-click on the project node and select “Properties”, then select the “Build Properties” page.

We define a macro named “RUNTIME” to be associated with the project. “RUNTIME” stands for “run-time library”. We use “kernel-smp” to build a library for building a DKM client project on VxWorks 6 with SMP; make sure to use the proper value in your context. (The value will be passed by the Workbench builder invocation to the Makefile.)

Select the “$ Variables” tab. Then press the “New...” button and enter the new macro name and value, as shown below. Then press OK.

tutorial\_lib\_user\_new\_build\_macro

After doing so, the “Build Macros” tab will appear as follows:

tutorial\_lib\_user\_build\_props\_set

Press OK to close the Properties dialog.

Finally, we create some source files in the “src” folder:

Enter files content to get the following.

file p.ads

package P is
   procedure Q;
end P;

file p.adb

with GNAT.IO;
package body P is

  -------
   -- Q --
   -------

   procedure Q is
   begin
      GNAT.IO.Put_Line ("Hello from P.Q");
   end Q;

end P;

1.13.3. Building the Static Library Project

Select the “Build Project” menu entry.

Note the value passed to the Makefile for “RUNTIME” on the third line.

tutorial\_lib\_user\_proj\_build\_console

Click “No” to ignore index rebuild if a “C/C++ Index configuration potentially changed” dialog is displayed.

1.13.4. Client Projects Using the Library

Now that the library project is ready we can create and build a client project that uses the library. Strictly speaking you can build the client project first, making the necessary modifications to it after you build the static library project.

The client project is created via the new-project wizard just like any other DKM project. The project is also extended for GNATbench in the same manner. These construction and extension steps are described in great detail in the Creating and Building a General Purpose Platform Project on Wind River Workbench 3.x tutorial. Other than building it, follow those steps exactly. In this tutorial we have named the new client project “clientDKM”. The new main program is named “client_main” and we asked the wizard to generate the file for us.

The resulting new project will appear as follows:

tutorial\_lib\_both\_projects

The last required step is to associate the two GNAT project files so that the client project can make use of the static library when building the client’s Ada code. As always, this association is accomplished by placing a “with-clause” on the client’s GNAT project file (the “gpr file”) that references the static library’s GNAT project file. The fact that the static library gpr file is in a separate Workbench project does not matter.

with "../staticDKMlib/staticDKMlib.gpr";
project Clientdkm is

   for Languages use ("Ada");
   for Main use ("client_main.adb");
   for Source_Dirs use ("src/**");
   for Object_Dir use "obj";

   package Compiler is
      for Default_Switches ("ada") use ("-g", "-gnato", "-gnatwa", "-gnatQ", "-gnat12");
   end Compiler;

   package Builder is
      for Default_Switches ("ada") use ("-g");
   end Builder;

   package Linker is
      for Default_Switches ("ada") use ();
   end Linker;

   package Ide is
      for Gnat use "i586-wrs-vxworks-gnat";
      for Gnatlist use "i586-wrs-vxworks-gnatls";
      for Debugger_Command use "i586-wrs-vxworks6-gdb";
      for Compiler_Command ("ada") use "i586-wrs-vxworks-gnatls.exe";
      for Compiler_Command ("c") use "i586-wrs-vxworks-gcc.exe";
   end Ide;

end Clientdkm;

The “with-clause” on line one makes all the sources of the referenced GNAT project available, automatically, to the GNAT project file containing the clause. The clause must provide the path to the gpr file, but note that both absolute and relative paths are allowed. (This use of cross-project references is available generally, i.e., it is not limited to static library projects.)

The client main program can then reference the Ada package “P” provided by the static library:

with P;
procedure client_main is
begin
   P.Q;
end client_main;

1.13.5. Building the Client Project

Next we make the static library project a “sub-project” of the client project. We do this so that the Workbench builder will be separately invoked on the static library project, not just the GNAT builder as a result of the gpr file reference.

This step is accomplished by right-clicking on the static library project and selecting “Project References”, then “Add as Project Reference...”:

tutorial\_lib\_invoke\_project\_reference

In the resulting dialog box, enable the client project as a referencing “super-project”:

tutorial\_lib\_add\_proj\_ref\_dialog

Press OK and the Project Explorer will adjust to show the static library as a subproject of the client project:

tutorial\_lib\_nested\_lib\_project

Now, invoking the Workbench builder on the enclosing (client) super-project will also build, as necessary, the sub-projects. The other “build” oriented operations, such as project cleaning, will also now apply to the static library sub-project.

In the Project Explorer, select clientDKM project, right-click to bring up the contextual menu. Select “Build Project”.

A pop-up will appear the first time you build the project. Just press “Continue”.

Click “No” to ignore index rebuild if a “C/C++ Index configuration potentially changed” dialog is displayed.

tutorial\_lib\_user\_client\_build\_console

1.13.6. Congratulations!

You have created a static library in a user-defined project and used it with a client project.