Generating, Compiling, and Running Code

This chapter describes how to generate, organize, compile, and run the code for a PhAB application:

PhAB automatically generates everything that's required to turn your application into a working executable, including:

By doing all this, PhAB lets you get on with the job of writing the code that implements your application's main functionality.


Note: The way you build PhAB projects depends on whether you're running PhAB standalone or from the IDE. This chapter describes building and generating code using PhAB standalone, and indicates where there are differences when using the IDE. For more information on building and generating code in the IDE, see the Building Projects section in the Developing Programs chapter of the IDE User's Guide.

For most code generation, you can use the Build menu. However, you can also generate some C and C++ stub files on the spot when using various dialogs to develop your application; use the icons located next to function or filename fields:

Edit icon

This means you're free to edit a callback function while still in the process of attaching it to the widget. You don't have to go into the Build menu, generate code from there, and then come back to write the function.

Using the Build menu

If you are using PhAB from the IDE, you can use PhAB's Build menu to generate the application's user interface code. All other build and run functions are handled by the IDE.

In standalone PhAB, the Build menu is the development center for building your applications. From this menu you can:

Build menu

Building your application

To build your application in standalone PhAB:


Note: Depending on the state of the application, PhAB may skip some of the above steps. For instance, if you've already built your application, but just changed a resource for one of the widgets, PhAB may only save your application to update the changed widget and then rebind the widget files into your application; it will skip code generation, compilation, and linking.

Generating application code

When you make changes to your application, even within your own source files, you may need to generate the application code. Doing so ensures that the prototype header file, proto.h, is up to date. You can safely generate the code at any time — PhAB won't overwrite any code you've added to the stubs it generated earlier.


Note: When you use PhAB from the IDE, PhAB regenerates the application code every time you save the project.

Before generating the code, PhAB saves your application if you've modified any modules. To minimize compile time, PhAB compiles only the files that have changed.


Note: If you plan to use a global header in your application, you should set up the header before generating any code. For more information, see Setting project properties in the Working with Applications chapter, and Global header file in the Working with Code chapter.

To generate your application code, select Generate UI from the Build menu. PhAB generates any required files any time you build your application.

What PhAB generates

PhAB generates various files and stores them in the application's src directory.


Caution: Any filename that starts with ab is a PhAB file and shouldn't be modified at any time. If you try to edit an ab file, you could lose work (when PhAB overwrites the file) or experience incorrect behavior (when files get out of sync).

You can modify any other files that PhAB generates, with few conditions. These conditions are described in the following sections.

Here are the files that PhAB generates:

appname/Makefile
Used to compile and link the application
appname/common.mk
Contains traditional makefile options, such as compiler options and link options.
src/Usemsg
A usage message for the application
src/abHfiles
Contains a list of header files that PhAB knows about.
src/abLfiles
External PhAB references in the Makefile
src/abSfiles
Contains a list of source files that PhAB knows about, for example source files with callbacks used in the PhAB project.
src/abWfiles
Contains a list of PhAB modules that are part of your application.
src/abdefine.h
Contains all the PhAB-generated manifests. PhAB includes this header in all C files.
src/abevents.h
Contains all the application's callbacks
src/abimport.h
The extern reference header that's included in all C files. See Function prototypes, below.
src/ablinks.h
Contains all the application's module definitions
src/abmain.c
The application's main-line C file. This file starts with ab, so don't modify it.
src/abmain.cc
If PhAB detects any C++ functions in your application, it generates abmain.cc instead of abmain.c. This file also starts with ab, so don't modify it.
src/abplatform
Contains a list of the platform directories for the application
src/abvars.h
Contains all the PhAB-generated global variables
src/abwidgets.h
Contains all the PhAB data references
src/indHfiles
Contains additional header files not contained in abHfiles.
src/indLfiles
Contains additional options for the linker.
src/indSfiles
Contains additional source files not contained in abSfiles.
proto.h
Contains the application's prototypes — see “Function prototypes”, below. Don't rename this file.

Version control

Here are the files you need to save if you're using version-control software (PhAB can generate some of them, but it's a good idea to save them all):

abapp.dfn
Callbacks and other information — this is a binary file.
abapp.wsp
Widget lock status — this is a binary file.
wgt/*
Widget resources — these might look like text, but they're binary.
src/*.{c,cc,cpp,C,h}
Source files and headers.
src/*files, src/Usemsg
Files that list non-PhAB source files. Be sure to save the non-PhAB source, too.
Makefile, common.mk
The make files.
target_directory/Makefile, target_directory/*/Makefile
The target files and their content.
application_name.ldb
Your application's language database. Save any translation files as well.

You'll need to keep a matched set of all the files that PhAB generates; save the same version of the abapp.dfn, src/ab*, and wgt/*.wgt? files.

Tips on using CVS

It's easier to save a PhAB application in CVS than RCS. Here are some things to keep in mind:

Function prototypes

PhAB generates function prototypes used by the compiler to check that your functions are called correctly. These prototypes are placed in abimport.h and optionally in proto.h. Here's how these files compare:

proto.h abimport.h
Generated by parsing your source code. Generated by looking at your application's settings.
Prototypes for all functions are generated. Only prototypes known to PhAB (callbacks, setup functions, pointer-to-function resources) are generated.
You can have problems with preprocessor directives (see Potential problems with generating proto.h), unusual C constructs, syntax errors, and C++ code. Prototypes don't depend on the source code.
Doesn't work with C++. Contains the appropriate #ifdefs and extern "C" declarations required by C++.
Prototypes match what the functions look like. Prototypes match what the functions are supposed to look like—if the source code is different, the compiler can detect it.

To suppress the generation of prototypes in proto.h:

  1. Press F2 or from the Project menu, choose Properties to open the Project Properties dialog.
  2. Click the Generate Options tab.
  3. Disable the Scan Source Files for Prototypes option.

Potential problems with generating proto.h

In the interests of speed, the program that scans your source files for function prototypes ignores preprocessor directives. This can cause some problems in proto.h.

For example, say we have the following code:

#ifdef DOUBLE
    for (i = 0; i < 18; i++, i++) {
#else
    for (i = 0; i < 18; i++) {
#endif
        x += 2 * (i + x);
        y += x;
    }

Since preprocessor directives are ignored, the prototype generator sees:

    for (i = 0; i < 18; i++, i++) {
    for (i = 0; i < 18; i++) {
        x += 2 * (i + x);
        y += x;
    }

The two opening braces cause it some confusion, and an incorrect prototype is generated. Look for this kind of thing if the prototype generator is creating incorrect prototypes.

To fix the example above, we could remove the opening braces and put an opening brace on the line after the #endif. Or we could do the following:

#ifdef DOUBLE
#define ADDAMOUNT   2
#else
#define ADDAMOUNT   1
#endif

    for (i = 0; i < 18; i += ADDAMOUNT) {
        x += 2 * (i + x);
        y += x;
    }

How application files are organized

PhAB stores each application as a directory structure. This structure consists of a main directory that holds the application-definition file, two subdirectories that store the module files and application source code, and, potentially, directories for different development platforms:


Application directories


Directories for a PhAB application.

At the top of the application's directory structure are the wgt and src directories. The wgt directory contains the application's widget files (files with extension .wgt* that PhAB uses to store information about your modules that are part of your application). The src directory contains header and source files needed to compile your application. At the same level as src and wgt are the platform directories (e.g. x86, mips, and arm). Their structure is the same as the structure generated by the addvariant command. The reports directory contains the files created when you choose the Generate Report command from the Project menu.

This directory structure is called the “Eclipse PhAB project” structure, because it is allows you to create an application in PhAB and then load it in Eclipse as an “Eclipse PhAB project”. Conversely, an application created in Eclipse can be loaded in PhAB.


Note: If you first generated your application with an earlier version of Photon, it might have been created as a single-platform application. In this case, the placement of files is slightly different, as described in the sections that follow.

You can choose the target platforms on which to compile your application. You can edit your target configuration by choosing Targets from the Build menu.

Multiplatform applications

Here's what each directory contains for a multiplatform application:

appl
The name of this directory is the same as your application. It contains the application-definition file, abapp.dfn. Because this file is proprietary to PhAB, you shouldn't try to modify it.
appl/src
The src directory contains the source code, headers, and a Makefile generated by PhAB, as well as any code you create yourself.

For detailed information on the files stored in this directory, see What PhAB generates in this chapter.

appl/src/platforms
These directories contain the Makefile, object files, and executables for the chosen platforms. The Makefile in the src directory runs those in the platform directories.
appl/wgt
The wgt directory contains your application modules. Because each type of module has a different file extension, it's fairly easy to recognize the exact modules you want when importing modules from another application. For more info, see the handy tables in the Module types section in the Working with Modules chapter.

Caution: Always use PhAB to edit the module files in the wgt directory. Don't try to edit these binary files with another editor.

Never modify any files prefixed by ab.


Single-platform applications

Here's what each directory contains for a single-platform application:

appl
The name of this directory is the same as your application. It contains the application-definition file, abdefn.app. Because this file is proprietary to PhAB, you shouldn't try to modify it. After you've compiled and linked the application, the executable is also placed in this directory.
appl/src
The src directory contains the source code, headers, object files, and Makefile generated by PhAB, as well as any code you create yourself.

For detailed information on the files stored in this directory, see What PhAB generates in this chapter.

appl/wgt
The wgt directory contains your application modules. Because each type of module has a different file extension, it's fairly easy to recognize the exact modules you want when importing modules from another application. For more info, see the handy tables in the Module types section in the Working with Modules chapter.

Caution: Always use PhAB to edit the module files in the wgt directory. Don't try to edit these binary files with another editor.

Never modify any files prefixed by ab.


Converting to Eclipse

If you have a single-platform application built with an earlier version of Photon, it is converted to “Eclipse Project” format when you load it for the first time. When converting an application, PhAB moves any existing Makefile to src/default/Makefile.old.

If you have a multiplatform application built with an earlier version of Photon, it is loaded by PhAB as is. You can choose to convert it to Eclipse Project format by selecting Project-->Convert to Eclipse Project.

Editing source

You can edit source files from an external editor, which you can configure in PhAB. If you're using PhAB from the IDE, you can use an editor in the IDE to work with source files as well.

You can open source files for editing within PhAB from the Browse Files palette. If the Browse Files palette isn't visible, select Window-->Show Project. The Browse Files palette looks like this:


Browse Files palette


Browse Files palette.

To edit, view, or delete source code from within PhAB:

  1. Click the source-code file.
  2. Click the appropriate action button (Edit, View, Delete, ...).

    You can also edit a file by double-clicking its name.

Choosing an editor or browser

To choose which external editor or browser the Edit and View buttons invoke, see Customizing your PhAB environment in the PhAB's Environment chapter.

Creating a source module

To create a new source-code module:

  1. Click Create to open the Create File dialog, then type the name of the new file.
  2. If you wish to create the file using a template (for a header file or widget callback), select a format from the Template combobox.
  3. Click Create. You'll see a terminal window that displays either an empty file or a file that contains the template.

If you create any files, click Refresh to reread the application directory and refresh the list of files in the Browse Files palette.

Changing the file display

To control which files are displayed in the Browse Files palette, use the following:

The Filter line at the bottom of the palette allows you to filter the list of the files the Browse Files palette displays. For instance *.[ch] displays subdirectories and filenames ending in .c and .h.

Compiling and linking

This section applies to standalone PhAB. For information about compiling and linking applications using the IDE, see the Building projects section in the Developing Programs chapter of the IDE User's Guide.

After generating the application code, you need to:

Specifying additional libraries

By default all PhAB applications link against libAp and libph. You can specify addtional libraries libraries for your application in the Link Libraries field of the Build and Debug Options dialog.

You can also specify how libraries are linked against your application:

The default is shared libraries. To specify how libraries are linked, use the -B option in the Link Libraries field of the Build and Debug Options dialog. For example, consider the following Link Libraries line: -Bstatic -lphexlib -Bdynamic -lmylib -Bstatic. This links against libphexlib.a, mylib.so, and since the default libraries are considered being after the end, libAp.a and libph.a.

You can also specify a list of library callback functions when you start PhAB. For more information, see appbuilder in the Utilities Reference.

Running make

Once you've chosen the library type, you're ready to compile and link.

The first time you generate your application, PhAB creates Makefile and common.mk files in the project directory (plus a Makefile for each platform selected for multiplatform development) so you can make the application. Subsequent generations don't modify the file directly; instead, they update external files referenced in the common.mk.

Once the common.mk is generated you can modify it, though you should only do so when there's no way to set options from within PhAB.

By default, the Makefile is compatible with the installed make command. You can convert the file to a format that suits the make command you prefer—just ensure the external file reference method is still compatible.

For more information, see Including non-PhAB files in your application,” later in this chapter.

To make your application:

  1. Select Build-->Build to open the Make Application dialog and start the make process.
  2. If any errors or warnings are detected during the make process, PhAB enables the Edit and Restart buttons.

    To edit the first file that contains errors, click Edit. After fixing the problems, click Restart to run make again.

    To stop make at any time, click Cancel.

  3. Once the application has been compiled and linked, PhAB enables the Make dialog's Done button. Click Done to close the dialog.

    The Done button is also enabled when you click Cancel.

Modifying the make command

By default, PhAB uses the installed make command to make your application. If you need to change this command in any way, click Build Preferences.


Note: Any changes you make to Build Preferences settings are saved with the application itself rather than as a global preference.

Customizing the build process

You can customize the build options on the Build and Debug Options tab on the Project Properties dialog. Open the Project Properties dialog by selecting Project-->Properties. For a description of this dialog, see Build and Debug options in the Working with Applications chapter.

When you use PhAB from the IDE, PhAB handles the code generation for the user interface, while the IDE manages the build process. Therefore, only items in this dialog that affect generation are available when you run PhAB from the IDE.

The first time you generate your application, PhAB creates a Makefile and a common.mk in the top level directory. Subsequent generations don't modify the file directly. You can customize your build process by changing or adding compile and link flags in common.mk.

Once the Makefile is generated you can modify it, though you should only do so when there's no way to set options from within PhAB.

By default, the Makefile is compatible with the installed make command. You can convert the file to a format that suits the make command you prefer—just ensure the external file reference method is still compatible.

For more information, see Including non-PhAB files in your application,” later in this chapter.

Running the application

How you run an application developed in PhAB depends on whether you're running PhAB standalone or from the IDE. When running PhAB from the IDE, you set up launch configurations for targets through the IDE. For more information, see the Preparing Your Target chapter and Running projects section of the Developing C/C++ Programs chapter in the IDE User's Guide.

From standalone PhAB, once your application has been compiled and linked without errors, it's ready to run. Just follow these steps:

  1. Select Run from the Build menu. The following dialog appears:

    Run Options

  2. If you've used PhAB to create a multilingual application, you can choose the language from the Language list. For more information, see the International Language Support chapter.
  3. If your application needs command-line arguments, type them into Run Arguments.
  4. Click OK.

Note: When your application runs, its working directory is the platform directory (i.e. the directory containing the executable).

If you check Do not show this dialog again, the Run Options dialog doesn't appear the next time you run the application. To reenable the dialog, check the Ask for run arguments option on the General tab of the AppBuilder Preferences Settings dialog.

If you check Always use these settings, then the settings are saved and used any time you run this application. You can change the run arguments or language on the Run Options tab of the Project Properties dialog.


If you use functions such as printf() in your application, the output goes to your console if you run your application from PhAB. To see this output, open a pterm and run the application from there instead of from PhAB.

PhAB is still active while your application is running. To switch between the two, use the Window Manager's taskbar.


Note: If the target you chose to build your application for is not the same as the one you run PhAB on, you'll have to transfer your application's executable to your target in order to run it.

Debugging

You can run your application with a debugger, which can be handy if your application crashes or behaves incorrectly.

When running PhAB from the IDE, you use the debug features in the IDE. For more information, see the Debugging Programs chapter in the IDE User's Guide.

=>> To debug your application in standalone PhAB, choose Build & Debug from the Build menu. This launches the application in your preferred debugger.

Note: In order to debug an application, you have to compile a debug-build version. To do this, select Build & Debug from the Build menu.

To switch between the debugger and the application, use the Window Manager's taskbar.

Managing targets

You can add or delete target platforms using the Manage Targets dialog. To open this dialog, select Build-->Targets.


Manage Targets dialog


Manage Targets dialog.

To add a target, click Add target.


Note:
  • If you select a target that is already added to your application, the Makefile in the target directory is overwritten.
  • Targets on which Photon doesn't run are greyed out and can't be selected. The targets which don't support Photon are defined in a configuration file, $QNX_HOST/usr/photon/appbuilder/nonphoton_targets.def.

To delete a target, select it and click Delete target.

Only the targets selected in this dialog are built.

The Build menu

Here's a description of all the items in the Build menu:

Build & Run
Standalone PhAB only. Builds the current application and then runs it. This command saves any changed files before building the application.
Build & Debug
Standalone PhAB only. Builds your application and then debugs it. This command saves any changed files before building the application.
Rebuild All
Standalone PhAB only. Rebuilds all files for all selected targets.
Build
Standalone PhAB only. Builds the application for selected targets.
Make Clean
Standalone PhAB only. Removes the executable and object files from the target directories before running Make.
Generate UI
Generates files related to the user interface, but doesn't build the application's executable.
Run
Standalone PhAB only. Runs the last built executable.
Targets
Standalone PhAB only. Opens the Manage Targets dialog.

* For these commands, “all your selected targets” means the building process will take place only for selected targets. To change the currently selected targets simply choose Targets from the Build menu and change the selection in the target list. You can also select targets from the Build and Debug Options tab of the Project Properties dialog.

Including non-PhAB files in your application

Your application can include files that aren't created with PhAB, but you need to tell PhAB how to find them.

Eclipse Project applications

To add non-PhAB source files to an application, place them in the project's src directory.

Multiplatform applications

PhAB generates empty lists in the following files in the src directory, and you can edit them:

indHfiles
Non-PhAB header files. For example:
MYHDR = ../header1.h ../header2.h

indOfiles
Non-PhAB object files. For example:
MYOBJ = file1.o file2.o

indSfiles
Non-PhAB source files. For example:
MYSRC = file1.c file2.c


Note: Remember to specify the filenames relative to where the Makefile is found. For a multiplatform application, that's relative to the platform directory:
  • Header files and source files are usually in the parent directory, src, so their names start with ../ .
  • Object files are usually in the same directories as the Makefiles.

Single-platform applications

A single-platform application from an earlier version of Photon doesn't have the indHfiles, indOfiles, and indSfiles files. Instead, you'll find MYHDR, MYOBJ, and MYSRC in your Makefile, and you can specify filenames there.


Note: Remember to specify the filenames relative to where the Makefile is found. For a single-platform application, that's relative to the src directory.

Adding libraries

If your application uses a library that isn't included by default in the Makefile, you can add it with the Link Libraries line on the Build and Debug Options tab of the Project Properties dialog. Open this dialog by selecting Project-->Properties.

For instance, if you want to link against the socket library, put the following in the Link Libraries line:

-l socket.

You can also add it by editing the LDFLAGS variable in common.mk:

Making a DLL out of a PhAB application

You can make a PhAB application into a DLL, but there isn't a PhAB option that will do it for you. PhAB doesn't know anything about building DLLs; it's the PhAB library that lets you turn a PhAB application into a DLL.


Note: The application that loads your DLL must be a PhAB application so that the PhAB library is properly initialized.

Even though PhAB lets you set up an initialization function and windows to open at startup, they're ignored when your application is a DLL. That's because this regular PhAB startup is done by main(), and the main() function of a DLL isn't called. (Don't attempt to call it from your own code, either.)


Compiling and linking

In general, you can turn any application (whether created by PhAB or not) into a DLL by adding -shared to the compiler and linker flags (and most likely adding a dll extension to the filename). You should also give the -Bsymbolic option to the linker to make sure that locally defined symbols that your DLL uses aren't overridden by any symbols in the executable with the same name.

To make these changes for a PhAB application, run the addvariant command at the top level directory for the application. For example:

addvariant x86 dll

For more information, see addvariant in the Utilities Reference, and the Conventions for Recursive Makefiles and Directories appendix of the QNX Neutrino Programmer's Guide.

Initializing your DLL

Typically, a DLL defines an initialization function that an application calls after it calls dlopen() to load the DLL. Your DLL's initialization function needs the full path to the DLL.

Before calling any PhAB code, the initialization function must call ApAddContext(), like this:

ApAddContext( &AbContext, fullpath );

The arguments are:

AbContext
A global data structure that PhAB puts in abmain.c.

Note: This structure has the same name in every PhAB application or DLL, so you must link your DLL with the -Bsymbolic option mentioned above.

fullpath
The full path of your DLL, suitable for passing to open().

You can call ApAddContext() more than once, but you need to keep track of how many times you called it.

ApAddContext() returns zero on success, or -1 on failure. Don't call any Ap* functions if ApAddContext() fails.

AbContext holds, among other things, the location of the executable or DLL that it's contained in, and the language translation files currently loaded for that file. At any time, one of the registered contexts may be “current”; a few libAp functions implicitly refer to the current context, and some require a current context when you call them. At program startup, the program's context is made current. You can unset it or change it to a different context by calling ApSetContext():

ApContext_t *ApSetContext( ApContext_t *context );

This makes the given context current, and returns the previous current context. Both can be NULL; but if you pass a non-NULL pointer, it must point to a registered context.

So, for example, your initialization code would look something like this in your main application (with error checking removed for clarity):

void *handle = dlopen( path, 0 )
int (*entrypnt)() = ((int(*)()) dlsym( handle, "myentrypoint" );
(*entrypnt)( path, ABW_dll_pane );

And the initialization function in the DLL would look something like this:

int myentrypoint( const char *path, PtWidget_t *panewgt ) {
    ApAddContext( &AbContext, path );
    ApCreateModule( ABM_dll_contents, panewgt, NULL );
}

Unloading your DLL

When an application is about to unload a DLL, it typically calls a cleanup function in the DLL. In your DLL's cleanup function, you must:

You must call ApRemoveContext() the number of times that you successfully called ApAddContext(). After you've called ApRemoveContext(), your DLL must not call any PhAB functions.