alpha version, October 2000
The most important thing of the XSdk project system is that you do not need to know anything of it: all the work is done automatically by the ProjectBuilder and the XSdk bundles, and you need not be even aware there are some makefiles, not speaking of their contents.
There are some reasons why this documentation is provided even so:
A standard make (or more precisely the portable gnumake) system is used. That means that in each project there is a Makefile, which contains all the information relevant to the project. For technical reasons, there is another file, Makefile.xsdk, which contains some auxiliary information; it is created automatically by the main Makefile, and you can more or less ignore it.
All the information of the project is stored in a PB.project file (described below). The makefiles are generated using the information from the PB.project; therefore, you can freely delete the Makefile.xsdk, and you don't need to keep the Makefile up to date (actually, the only reason you cannot delete the Makefile as well is that then there would not be anything to start the make process with).
The precise usage of the makefiles:
This way, all projects will remain to be fully moveable between any XSdk implementations.
Somewhat differently from traditional systems, the Makefile (or Makefile.xsdk) does not contain any rules to make the project. Its sole purpose is to define which files are part of the project, and which attributes are to be used when the project is built. All the rules are in a set of comprehensive makefiles, which are included into the Makefile when make is run. These makefiles are described below.
The PB.project file is the centre of all the project information. Luckily, it features a flexible and extensible format, allowing to store just any information needed. First we shall describe the file format, and then we shall look at the particular variables and settings used by XSdk.
The PB.project file uses a generic dictionary (or, rather, property list) file format, invented by NeXT ages ago. It is a recursive hierarchical system of information, structured in dictionaries and arrays, with scalar values of string type (numeric or date values are simply coded as strings).
| Type | Meaning | Representation |
|---|---|---|
| string | plain (potentially Unicode) string | Just the string, quoted if contains special characters, whitespaces or if empty. Unicode characters are represented by standard \U<n> tags. |
| array | an array of other objects; they need not to be of the same type | comma-delimited list of objects, enclosed in parentheses |
| dictionary | a dictionary of pairs <key,value>, where the key is a string, and value can be any object | a list of pairs (<key>=<value>), each terminated by a semicolon, enclosed in {} braces |
For example, the following property list defines a dictionary, containing a string "Hello" for a key "Greeting", an array of strings "World", "Symbian", "Psion", and "All developers" for a key "To whom", and another array, containing one string, one (nested) array, and one (nested) dictionary for a key "Deeper structure":
{
Greeting = Hello;
"To whom" = (World, Symbian, Psion, "All developers");
"Deeper structure" = (
"ThisStringIsQuotedDueToSpecialChar:@",
("A nested array with just one string"),
{ what = NestedDictionary; }
);
}
Note that whitespaces are ignored (unless inside quoted string).
Using the dictionary format, the PB.project file can contain just anything, provided the top level dictionary keys do not clash. All the XSdk-specific keys have a "XSdk" prefix to ensure that. Besides, some standard keys (not specific for the XSdk, but maintained by the ProjectBuilder) are used as well.
The best way to describe them is to present an example of a real PB.project file (with the keys not used by XSdk deleted out for better readability):
{
FILESTABLE = {
CLASSES = (boss.cpp);
FRAMEWORKS = (XConversion.framework, XFoundation.framework);
H_FILES = (boss.h);
OTHER_LIBS = (euser, efsrv, estor, gdi, apparc, print, ws32, cone, eikon);
OTHER_LINKED = (ftest.f);
OTHER_RESOURCES = (Readme.txt);
OTHER_SOURCES = (
Makefile,
cpp.template,
h.template,
Makefile.postamble,
Makefile.preamble,
Makefile.xsdk
);
PUBLIC_HEADERS = (boss.h);
SUBPROJECTS = (bosseng.engine, bossview.engine);
};
MAKEFILEDIR = "$(NEXT_ROOT)/Local/Developer/XSdk/Makefiles";
PROJECTNAME = Boss;
PROJECTTYPE = "Epoc Application";
XSdkAppCapabilities = {Embeddable = YES; Hidden = NO; NewFile = YES; };
XSdkAppCaption = "Boss Game";
XSdkAppDocName = "just for sample";
XSdkApplicationIcon = XApplicationIcon.mbm;
XSdkApplicationIconNoForStupidAif = 4;
XSdkAssistantDefaultHumanLanguage = 1;
XSdkAssistantDefaultLanguage = CPP;
XSdkCreated = "2000-10-20 20:46:11 CEST";
XSdkMimeTypes = ({priority = 0; type = text/html; });
XSdkPlainResources = (boss.rss);
XSdkUID1 = 268435577;
XSdkUID2 = 268435564;
XSdkUID3 = 268436051;
XSdkUsingExtendedApi = NO;
XSdkVersionBeta = YES;
XSdkVersionBuild = 7;
XSdkVersionBuildTime = "2000-10-22 05:15:12 +0200";
XSdkVersionMajor = 1;
XSdkVersionMinor = 0;
XSdkWasImportedBy = MmpImport;
}
<<<description of the particular keys forthcoming: they are understandable somewhat even so, aren't they>>>
The XExportPB tool serves for creating makefiles automatically, using the information stored in the PB.project file. It can prepare more or less any file, using the PB.project and a template...
<<<detailed usage and template description forthcoming:
This excerpt is not quite up to date!
The template can contain:
- just any line which starts with '#'; it is copied to the generated makefile;
- just any line which does not contain exactly one '='; it is copied to the generated makefile;
- any number of lines in format <X>=<Y>, they are described below:
<X> is just a variable name. Unless there are strong reasons not to do so, it should have the prefix XSDK_, and it should be in uppercase. It is copied to the makefile exactly as is, ie. including any leading or trailing delimiters.
<Y> is the appropriate value. Firstly, it is stripped all the leading and trailing spaces and tabs. Then, its prefix is checked:
- $ means the XSdk defaults are checked, and the value of the default of the name (<Y> without the prefix '$') is used;
- @ means the value (<Y> without the prefix '@') is searched for in project (PB.project) recursively, ie. if not found in the current project, is searched for in its superproject, till the root project is reached;
- # means special target. There must be another hash, and between hashes the tagret is specified. After it can be any of the other prefixes.
- if the target contains a %, the value is a number ([xxx intValue]), and target is the format wanted (like #%d#, or #0x%06X#);
- otherwise, the target is filename, to which the property will be stored as a plist (and the file name will be in the makefile)
- ? means it is filename, and it will be added in case it exists
- no prefix means the value is searched for in the current project (PB.project).
The value can be in format XXX.YYY, which means "XXX" is searched for, the result should be a dictionary with a key YYY. This can be recursive (XXX.YYY.ZZZ.TTT). In case the object is *not* a dictionary, the part after dot is just ignored.
There can be more values on line: UNIMPLEMENTED YET
The value can be an array: UNIMPLEMENTED YET
If no value is found, nothing is written to the makefile, and the next template line is processed. Otherwise, the <X>=value is written out (for value being used the [value description] in case the object is not a NSString).
>>>
Since the project makefiles are generated from the ` file, there would be no need to describe them. But, (a) currently for a short time the Linux users have to edit the Makefile manually, and (b) you might want to understand the makefile system eg. to add your own targets.
Since it is updated automatically, you should never edit Makefile, not even in Linux: edit the PB.project instead. Though, we provide a list of its variables for case you would want to use them in your own targets (in the Makefile.postamble).
The Makefile always sets a few standard variables, then it includes the platform.make, Makefile.preamble, root project makefile for the concrete project type, Makefile.postamble and Makefile.dependencies makefiles in this order. Have a look at the Makefile in any XSdk project for an example.
The make variables relevant to the XSdk, which are set in Makefile, are:
| variable | contains |
|---|---|
| NAME | The name of the project. It is used in different places: eg. a generated application will be NAME.app, with resource file NAME.rsc and Aif file NAME.aif; analogically a generated library will be NAME.dll, etc. Therefore, the NAME has to be a valid file name. (The application caption is set thru the application inspector.) |
| PROJECT_TYPE | The type of the project. Currently, it can be "Epoc Application", "Epoc Framework", "Epoc EXE", "Epoc Bundle", "Epoc View", or "Epoc Engine" for the appropriate project types. The name is unquoted. |
| CPPFILES | List of all the C++ source files, which implement classes. |
| OTHERLINKED | List of the remaining C++ source files. |
| CFILES | List of the plain C source files. |
| HFILES | List of the headers used in the project. |
| PUBLIC_HEADERS | For framework, list of those headers which are to be exported to the installed framework (ie, to be available for projects which just use the framework). |
| GLOBAL_RESOURCES | Names of all unassigned files in the project which are to be copied to the result. Currently, it is used mainly for the application help files, but any file or folder can be placed here. |
| LIBS | Names of all the Epoc standard libraries the project is to be linked against. For a historical reasons each of the names must have a "-l" prefix (the prefixes are stripped out in the makefile suite, but the ProjectBuilder would not understand had the prefixes be not used). |
| FRAMEWORKS | Names of all the frameworks used in the project. Again, for historical reasons each framework has to have a "-framework " prefix (note the space). |
| SUBPROJECTS | Names of all the linked-in subprojects. CURRENTLY UNSUPPORTED BY XSDK |
| BUNDLES | Names of all the subprojects which generate results of their own (like engine DLLs). |
| MAKEFILEDIR | The path where all the standard makefiles are to be found. |
| MAKEFILE | The project makefile for this project type (like epocapp.make for Epoc Application). |
<<<XSDK_LIBS, XSDK_FRAMEWORKS>>>
Note that in a makefile maintained by a ProjectBuilder there are a number of other variables set--ProjectBuilder does that to support a proper building of many different flavors of projects. In Linux, just leave anything you do not understand alone: generally, it have no influence to the XSdk, but it might raise problems when the project is opened in the ProjectBuilder.
Since it is updated automatically, you should never edit Makefile.xsdk, not even in Linux: edit the PB.project instead. Though, we provide a list of its variables for case you would want to use them in your own targets (in the Makefile.postamble).
| variable | contains |
|---|---|
| XSDK_UID1/2/3, XSDK_XUID1/2/3 | All the three project UIDs, both decimal (XSDK_UID1, XSDK_UID2, XSDK_UID3) and hexadecimal (XSDK_XUID1, XSDK_XUID2, XSDK_XUID3). The hexadecimal forms have no "0x" prefix nor "h" suffix: use tem directly should you need to. |
| XSDK_VMAJOR, XSDK_VMINOR | The project version. Both values are numeric (decimal), and there is no limit for them (but the integer range). |
| XSDK_VBUILD, XSDK_VBUILDTIME | The number of build (of the current version), and the time of the last build. With ProjectBuilder, these values are not set by user; they are supplied automatically instead. |
| XSDK_VBETA | "YES" or "NO" depending on whether the project is in the beta stage or not. |
| XSDK_RESOURCES | List of the resource source files in the project. With legacy Symbian projects, they will contain the NAME.rss as well; the native XSdk projects generate the main resource automatically, and do not need this. |
| HFILES | List of the headers used in the project. |
| XSDK_APP_CAPTION | A few following variables are set for application projects only. This one contains the (default) application caption. |
| XSDK_DEFAULT_DOC_NAME | The default application document name. For legacy Symbian projects, you have to ensure it is used in the main resource file manually; the native XSdk projects place the name into the main resource automatically. |
| XSDK_APPCAP_EMBEDDABLE | The application capabilities; possible values are "NO", "YES", or "ONLY". |
| XSDK_APPCAP_HIDDEN | The application capabilities; possible values are "NO" or "YES". |
| XSDK_APPCAP_NEWFILE | The application capabilities; possible values are "NO" or "YES". |
| XSDK_MIME_TYPES | Name of a file, which contains list of the application MIME types and their attributes. |
| XSDK_APP_ICON | Name of the MBM file of the application icon. There is also an auxiliary XSDK_APP_ICON_NO_FOR_STUPID_AIF value, which contains the number of bitmaps in the file. It is used only when a Symbian AIF source is generated, for their aiftool cannot even check itself for the contents of the MBM file! All the X.soft tools are able to do that, and thence do not need the value. |
| XSDK_APP_COMMANDS | For native XSdk application projects, this is the name of a file containing the application menu, hotkey list and toolbar, generated and maintained by a GUI editor. |
| XSDK_EXTENDED_API | "YES" or "NO", depending on whether the project was generated using the XSdk extended API. |
| XSDK_LANGUAGE | The number of the default (human) language used for the project. The numbers are the same Symbian uses. |
| XSDK_TEMP | The path where temporary files can be placed. |
DEPENDS_ON, BLASTEDSHEET, ASMONLY=YES, OPTIMALIZE={number|NO}
<<<documentation forthcoming>>>
<<<sorry the text below is not absolutely up to date (although still very good a description of the current state): root.common.make includes commands.make and commands.OS.make; they export all commands, and are NOT included from common.make. Besides, "commands" are renamed to "settings", since they set paths as well>>>
The standard makefiles (included by Makefile, and containing all the rules for building Epoc executables) are placed in the $(NEXT_ROOT)/Local/Developer/XSdk/Makefiles folder. You should never need even to look at them, unless you are interested...
Besides, the standard Makefile includes platform.make, Makefile.preamble (if any), the appropriate project makefile, Makefile.postamble (if any), and Makefile.dependencies (if any).
This is the very first makefile (but the main Makefile, which includes it) to be processed for each project. It sets one variable only:
| variable | contains |
|---|---|
| OS | Symbolic value which represents the platform XSdk is currently running on. Currently two values are supported: MACOSX for Mac OS X and Mac OS X Server, and WEBOBJECTSNT for WebObjects for NT. Linux is currently recognized as a MACOSX; that will probably change in future. |
The platform.make tries to recognize the platform automatically. Currently, it checks whether there is an enviroment variable SystemDrive; of so, WEBOBJECTSNT are presumed.
This makefile is processed only once for each hierarchical project. It is included from the root project makefiles, as the first include; thence, only the Makefile, platform.make and Makefile.preamble are processed before it. It sets the project-wide variables and rules; the most important ones are:
| variable | contains |
|---|---|
| ROOTDIR, ROOTDISK | The directory of the root project. Since the XSdk works in M$ Windoze as well, the path management gets somewhat tricky: the problem is that the absolute path there begins by a drive letter and colon. That can be quite a problem in makefiles, naturally! Thence, the path is divided to two parts, the disk (including the colon), and the rest of the path (including the first slash). Of course, in any decent environment the disk variable will be always empty. There is analogical support with more variables below. |
| GENROOTDIR, GENROOTDISK | All the generated files (but a small number of exceptions, like the Makefile.xsdk) are placed to this directory and its subdirectories. |
| RELEASEDIR, RELEASEDISK | The directory where the build result will be placed. Normally subpath of the GENROOTDIR, but the user can specify a different value by setting the variable RELEASEPATH when the make is run. |
| SUBNAME | The path-name of the currently built (sub)project. For the root level it is defined to be equal to NAME (which is set in the Makefile), but for each nested subproject it is automatically changed to that subproject's path name. |
| SUBPATH | The full path name, beginning from the root level SUBNAME all subsequent SUBNAMEs are added with path separator. |
This makefile is included from each project makefile. It contains all the variables and rules for the project system, but the ones which needed to be placed in the root.common.make. The first thing it does is to include the Makefile.xsdk (if any), so as its variables are available to the rest of the build system.
The most important varaibles defined in the common.make are:
| variable | contains |
|---|---|
| XSDKROOTDIR, XSDKROOTDISK | The directory where the XSdk support (like these makefiles, the XSdk-specific tools, XSdk frameworks and others...) is placed. |
| XSDKTOOLDIR | XSdk tools directory. In windoze, contains the disk part (there is no harm). |
| BUILDROOTDIR | Just a conveniency--this is always a subdirectory of GENROOTDIR, named by the current build mode. It does not contain the disk part (for it is the GENROOTDISK). |
| BUILDDIR | The particular place where the generated files (like modules) are put. It is a subpath of the BUILDROOTDIR, specific for each subproject (the SUBPATH is appended). |
| SRCROOTDIR | The root directory where generated and preprocessed sources are put; a subdirectory of BUILDROOTDIR. Again, no disk part. |
| SRCDIR | The particular place where the generated and preprocessed sourcesare put. It is a subpath of the SRCROOTDIR, made the same way as BUILDDIR. |
| ALLSOURCENAMES | Names of all source files in the project. It is combination of the CPPFILES, OTHERLINKED, and CFILES contents (all three variables are set in the Makefile). |
| FRAMEWORKDIR, FRAMEWORKDISK | The directory where the XSdk frameworks are stored . |
| FRAMEWORKNAMES | Names of all the frameworks used in the project. |
| OBJ | The object file suffix (ie. "o" or "obj", depending on architecture used). |
Beside that, the common.make imports all the remaining general makefiles: the commands-$(OS).make for the platform-depenedent commands and rules, and recursive.make, compile.make, and export.make.
Note that the makefiles are included after all the variables are defined. Therefore, should any of the variables in common.make use any of the variables defined in the included makefiles (like the EPOCLIBS, which uses EPOCLIBDIR, defined in the commands-$(OS).make), it must be defined using '=', not ':='!
There are some general usage targets defined in the common.make as well:
| target | usage |
|---|---|
| .mkbdir | To be called from the project makefiles. The target just makes the output directories (BUILDDIR, RELEASEDIR, HDRDIR, and SRCDIR) in case they do not yet exist. |
| .tellme... | A number of reporting targets; they just ECHO some information to the console. |
| .checkexport | Checks whether the RELEASEPATH variable was set, and if so, calls the target .export. |
| .stdclean | Removes the GENROOTDIR directory. |
| all | Placed so that is performed when make is called without argument. Writes out the valid targets to console, otherwise does nothing. |
| debug | Sets the BUILD variable to debug, and calls target .builddb. |
| marm | Sets the BUILD variable to marm, and calls target .build. |
| target | Sets the BUILD variable to clean, and calls target .clean. |
| export | Sets the BUILD variable to export, and calls target .checkexport (see above, the net result is calling of target .export). |
Particularly interesting are the last targets (the ones without dot, but the all). They ensure that whenever the make is called with the appropriate target, the target is set into the BUILD variable, and one of the targets .builddb, .build, .clean, or .export is performed. Therefore, the project makefiles do hardly more than specifiyng the appropriate actions for these targets (see below).
A number of commands and rules which are platform-dependent is placed into a makefile apart, commands-$(OS).make. Note incidentally that this makefile is included from the common.make after its own definitions are made, so that it can--should need be--use and change any of them.
The most important varaibles defined in the commands-$(OS).make are:
| variable | contains |
|---|---|
| EPOCROOTDIR, EPOCROOTDISK | The directory where the standard Symbian files (headers, libraries,...) are placed. On windoze, they can be almost anywhere. Therefore, one of two variables can be set in the Makefile.xsdk, or Makefile.preamble, or wherever:
In case no variable is defined, the Symbian files are presumed to be in D:/epoc32. |
| EPOCHDRDIR | Where the Epoc stores include files. No disk part (on EPOCROOTDISK). |
| EPOCLIBDIR | Where the Epoc stores libraries. No disk part (on EPOCROOTDISK). |
| CD, RM, LN,... | A number of tools for different tasks. All are specified by the full path, in windoze including the disk part (there is no harm). |
The header.make makefile sets all the header-relevant variables (but some which have to be set in the platform-specific makefile commands-$(OS).make). They are pretty plain:
| variable | contains |
|---|---|
| HDRDIR | Into this directory all the preprocessed and generated headers are placed. There is no disk part, for the directory is always part of the GENROOTDIR hierarchy. |
| ALLHDRDIRS | Names of all directories, containing header files relevant for the project. That includes the HDRDIR, but there are also directories with the Epoc and the framework headers. None of these paths contains a disk part, each lay in GENROOTDISK. |
<<<documentation forthcoming>>>
| target | usage |
|---|---|
| .preparelocalhdrs | To be called from the project makefiles. The target prepares all the local headers (ie. preprocesses them, and places them to HDRDIR). |
| .preparehdrs | Ditto. Prepare all the makefiles, including the local ones above. For Epoc or framework headers it can possibly mean some copying. |
The libraries.make makefile sets all the link-relevant variables (but some which have to be set in the platform-specific makefile commands-$(OS).make). They are no more complex:
| variable | contains |
|---|---|
| LOCALLIBS | Proper paths (not just names) of all the libraries generated locally (ie. those from subprojects, and those referenced by teh DEPENDS_ON variable). None of these paths contains a disk part, each lay in GENROOTDISK. |
| ALLIBS | All the library name this project is to be linked against. None of these paths contains a disk part, each lay in GENROOTDISK. |
<<<documentation forthcoming>>>
| target | usage |
|---|---|
| .preparelibs | Prepares all the non-local libraries (the local ones are to be built). For Epoc or framework libraries it can possibly mean some copying. |
All the project makefiles have a similar structure. Firstly, root project makefiles include the root.common.make makefile; then all project makefiles set the target-specific variables, then include common.make (which includes all the remaining general makefiles).
Finally, they set the appropriate behaviour for the standard targets (see the common.make above)--for example this way:
.build: .tellmeproject .recursive .mkbdir .preparehdrs .buildrsrcs .preparelibs .buildproject .tellmedoneSome particular project makefiles of course can contain specific targets to be performed, or some other tricks. If interested, see the epocbundle.make how to prepare a makefile which would work both as a root project and as a subproject.
<<<documentation forthcoming>>>
| target | usage |
|---|---|
| .preparersrcs | Prepares the source form (*.rss) of all the project's resources. The reason of this subservice is published is so that the RSS files can be exported without compilation. |
| .buildrsrcs | Makes all the project's resources. |
both "normal" resources from XSDK_RESOURCES and the generated one from XSDK_APP_COMMANDS
In the compile.make makefile there is the core of the whole project system: it ensures compilation and building of the projects. It exports just one target, .buildproject, to be called from the project makefiles.
Still, it is relatively simple: firstly, the .buildproject target is defined; it just calls one target defined inside the compile.make, which preprocesses all the headers (.preparehdrs), and the target .dobuild, which is imported from the build-$(OS)-$(BUILD)-$(TGTTYPE).make makefile, described below.
<<<documentation forthcoming>>>
<<<defined macro names for compiler>>>
<<<documentation forthcoming>>>
Note that when you use the build-$(OS)-$(BUILD)-$(TGTTYPE).make with the specific target, it is more or less just an extension of the project makefile. In principle there is no difference whether you place some targets, needed for building, to the project makefile (to be called from the .build target), or to the build-$(OS)-$(BUILD)-$(TGTTYPE).make makefile (to be called from the .dobuild target). Generally it is considered better to keep the project makefile lightweight and place as many commands as possible into the build-$(OS)-$(BUILD)-$(TGTTYPE).make makefile.
<<<documentation forthcoming>>>
The export.make makefile converts the XSdk projects to the Symbian-compatible ones. Since the Symbian project system is extremely simple, it is not that easy: eg. so as the hierarchical projects can be exported reasonably, a batch file has to be prepared to automate the building of the projects in the proper order.
<<<documentation forthcoming>>>
Copyright © 1999-2000 X.soft, all rights reserved