PBTOMAKE -- Xcode to Unix

When I develop on Mac OS X, I usually use Xcode. Others obviously
differ about use of IDEs, but I prefer it. I do have a problem
when I wish to move an app from Mac OS X to other flavors of Unix or
Linux.

In most cases I am not attempting anything exotic, these
are usually CLI applications (e.g. a very specialized Lua interpreter
with extensions for my company's products). So moving to Linux or
Unix should be pretty much a slam-dunk, simply recompiling the
code. Easy in theory, but if the app in question has over 100 files in many different directories, and if it's an Xcode project, then there's no makefile.

I had hoped that Xcode would include this export function. But it doesn't, so I've created a free, open-source version and have made it available to you.

PBTOMAKE Version 3.0 Program

This program is freeware with source and can be
downloaded from the (PBTOMAKE Download page). It is run from the terminal command line and as an example run on its own project you would get:

Pretty simple really, and the idea is you run pbtomake on your project, copy the whole development tree to the Linux/Unix box and run make there. You will then get the application built on the other system without having to manually build a makefile with all the dependencies. Obviously you still have code porting to do, since, for example, under Mac OS X you link to frameworks while under other systems you have other ways. There's lots of other details involved in porting the code but pbtomake saves you the initial messy task of listing all the files and their paths to manually build a makefile.

makefile Details

The makefile created by the program is very simple and has everything
specified. It doesn't use rules or any other shortcuts. Each and
every file is separately specified, along with all the include
files. So the file created for this run is:

The jim.pbxuser is the per-user settings for the project and things like window
positions. The project.pbxproj file is the description of the files
and how to build the application. This is the file that pbtomake works on.

Knowledge of project.pbxproj is just by observation and trying to extract the information to build
the makefile. If someone reading this has deeper knowledge I
would appreciate hearing from you. The general form of both of
these files is a hierarchical structure based on keys/values and
lists. The usual form of things are:

key = value;

Now value can either be a single string/name or a list and lists written as:

{
thing,
thing1,
:
};

Where thing and thing1 can be either simple values or embedded lists.

Project File Analysis

The code modules CBPROJ, CpbxLexFile, CTokFile, CLexFile and CBufFile are used to convert the file structure into an in-memory tree representation of the text structure in the file. The form here is the conventional breaking of the input file into tokens; then CBPROJ.cp builds the tree.

For example, reading key = value; would turn into the token list:

key = value ;
<Token> <LINK> <Token> <END>

CBPROJ reads each of these tokens, stacking them up until a trigger is found, In this case an
<END> token, meaning that we have come to the end of an element in the
file. It then can package up the key and value as an element and
attach it to the tree structure of the file it's building. If you
want to see this tree use the -debug option of pbtomake and it will be dumped out.

Besides the tree structure being built, the program also needs a
reference table so it can search this tree for particular keys. A
direct search of the tree might work, but from experience this is very
slow. The module CSymbol is used to create a hashed symbol table of each of the keys found in
the file. In this way, a very quick search can find the nth
appearance of any key in the file.

makefile Construction

The module CMaker is where the
rubber meets the road and the actual makefile is constructed.
This module is run after the symbol table and tree representation of
the project file are completed. To build the makefile two things
have to be found: a list of the .H files and a list of the .C (or CP)
files. You can see these in the product makefile. Once you
know these, then:

The INCLUDE list comes from the path lists to the .H files.

The main dependency <name> : <Filename>.o comes from the list of .C/CP files.

The main link list and each of the individual file-builds come from the .C list.

I've found in the project file the VALUE of an isa key of PBXSourcesBuildPhase denotes the
list of .C files and PBXHeadersBuildPhase denotes the list of .H files. It is then a matter of finding these lists
in the memory tree representation of the project file and building file lists.

The rest of building the makefile is largely a matter of fprintf()s of
the lists of data in various forms to the output makefile. This
is also where, if you want another type of makefile it's quite easy to
change the output.

Jim Schimpf
does embedded software development for telecommunications test equipment and develops Mac freeware in his free time, while not doing his other job of tractor repair/general grunt work for his 200-acre farm.