PBTOMAKE -- Xcode to Unix
by Jim Schimpf04/20/2004
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:
[Pandoras-Computer:TOMAKE10.3/Source/PBTOMAKE] jim% pbtomake -i PBTOMAKE.pbproj
PRODUCT IS [pbtomake]
FILE [main.cp]
FILE [CPBPROJ.cp]
FILE [CBufFile.cp]
FILE [CSymbol.cp]
FILE [CLexFile.cp]
FILE [CpbxLexFile.cp]
FILE [CTokFile.cp]
FILE [CMaker.cp]
FILE [cutil.cp]
FILE [CBufFile.h]
FILE [tgtypes.h]
FILE [CSymbol.h]
FILE [CLexFile.h]
FILE [CpbxLexFile.h]
FILE [CTokFile.h]
FILE [CMaker.h]
FILE [base.h]
FILE [cutil.h]
FILE [CPBPROJ.h]
[Pandoras-Computer:TOMAKE10.3/Source/PBTOMAKE] jim%
This would generate the makefile in a file called makefile. The makefile could be used by typing make in this directory. This would build a new copy of pbtomake using make and the makefile.
[Pandoras-Computer:TOMAKE10.3/Source/PBTOMAKE] jim% make
/usr/bin/g++3 ../main.cp -c -I../BASE_PC -I../BASE_PC/Dohickies -I.. -o main.o
/usr/bin/g++3 ../CPBPROJ.cp -c -I../BASE_PC -I../BASE_PC/Dohickies -I.. -o CPBPROJ.o
/usr/bin/g++3 ../BASE_PC/CBufFile.cp -c -I../BASE_PC -I../BASE_PC/Dohickies -I.. -o CBufFile.o
:
:
/usr/bin/g++3 ../CMaker.cp -c -I../BASE_PC -I../BASE_PC/Dohickies -I.. -o CMaker.o
/usr/bin/g++3 ../BASE_PC/cutil.cp -c -I../BASE_PC -I../BASE_PC/Dohickies -I.. -o cutil.o
/usr/bin/g++3 \
main.o\
CPBPROJ.o\
CBufFile.o\
CSymbol.o\
CLexFile.o\
CpbxLexFile.o\
CTokFile.o\
CMaker.o\
cutil.o\
-o pbtomake
[Pandoras-Computer:TOMAKE10.3/Source/PBTOMAKE] jim%
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:
###################################################
## Makefile for pbtomake
# Creator [Xcode -> Makefile Ver: 3.00]
# Created: [Sat Mar 6 07:48:15 2004]
#
###################################################
#
# Macros
#
CC = /usr/bin/g++3
CC_OPTIONS =
LNK_OPTIONS =
#
# INCLUDE directories for pbtomake
#
INCLUDE = \
-I../BASE_PC\
-I../BASE_PC/Dohickies\
-I..
#
# Build pbtomake
#
pbtomake : \
main.o\
:
:
cutil.o
$(CC) $(LNK_OPTIONS) \
main.o\
:
:
cutil.o\
-o pbtomake
#
# Build the parts of pbtomake
#
# Item # 1 -- main --
main.o : ../main.cp
$(CC) $(CC_OPTIONS) ../main.cp -c $(INCLUDE) -o main.o
:
:
# Item # 9 -- cutil --
cutil.o : ../BASE_PC/cutil.cp
$(CC) $(CC_OPTIONS) ../BASE_PC/cutil.cp -c $(INCLUDE) -o cutil.o
##### END RUN ####
Program Internals
Project Files
The Xcode project file PBTOMAKE.pbproj is really a directory containing two files (do ls -als PBTOMAKE.pbproj at the command line):
0 drwxrwxrwx 4 jim staff 136 7 Mar 07:03 .
0 drwxrwxrwx 18 jim staff 612 6 Mar 07:51 ..
40 -rwxrwxrwx 1 jim staff 17747 7 Mar 07:03 jim.pbxuser
32 -rwxrwxrwx 1 jim staff 12708 7 Mar 07:03 project.pbxproj
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.
|
Related Reading Mac OS X Panther for Unix Geeks |
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.
Return to MacDevCenter.com.
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 23 of 23.
-
*** ERROR no executiable target found
2008-09-04 09:38:59 jimschimpf [Reply | View]
Sorry I never thought about porting apps written ObjC to other systems needed makefile. I have an ObjC command line program I did recently and will try to adapt the program convert that project.
One point a lot of ObjC programs use frameworks that would not exist on Linux or other UNIX systems and that is a problem that this program couldn't event begin to solve.
In any case I will look into this over the next few days.
-
*** ERROR no executiable target found
2008-09-03 11:26:24 jimschimpf [Reply | View]
This message comes from the CPMaker.cp code where it is trying to read your project file and cannot find a target it knows about. If you point at your project in the FINDER and say show package contents. You will see a number of files in there if you open the pbxproj file (in a text editor) and look for the section PBXFileReference you will see all the files in your build. In there it has to find the string explicitFileType = "compiled.mach-o.executable" and that is the target executable for this project. If you aren't building that sort of thing then the program is a little confused and fails with this error.
You can see this search in the CPMake.cp file in the method
void CMaker::gatherline(). If you are not building a dylib or command line executable then PBTOMAKE will not find an executable it understands. If you are trying to build something else then send me a note directly (jim.schimpf@gmail.com) and we can see if this is possible. -
*** ERROR no executiable target found
2008-09-04 02:43:12 quentin.arnault [Reply | View]
Hi,
Thanks for your quick reply. So I checked the project.pbxproj file and I found the tag explicitFileType = wrapper.application.
To test what will happans, I changed wrapper.application to compiled.mach-o.executable. And a new error was raised:
-- Parse Done --
*** ERROR no C/C++ files found
** Parse failed **
As my project is coded in Objective-C (it is an iPhone project). Does pbtomake support Objective-C ?
Best regards,
Quentin ARNAULT
-
Problem 'no executable target'
2008-09-03 10:18:08 quentin.arnault [Reply | View]
Hi,
First of all thank you for this tool. I have the folowing error while launching the pbtomake tool:
-- Parse Done --
*** ERROR no executiable target found
** Parse failed **
I do not see what to do and where I'm wrong. Could you help ?
Best regards,
Quentin ARNAULT
-
New Version for Xcode 2.1
2005-06-16 03:36:16 jimschimpf [Reply | View]
I have posted a new version of pbtomake that works much better with the new style project files of Xcode 2.1. Apple radically changed the project structure and it made it MUCH easier to get it right. Get it at: (http://members.bellatlantic.net/~vze35xda/Load/TOMAKE-Xcode2.1.zip).
--jim
-
Thank you and question...
2004-07-02 08:31:17 iManu [Reply | View]
First, thank you, this really is helpful.
Second, I have a question.
The start is that I'm a beginner in C, and I just had a lecture on a PC on C programming. I already program in Fortran (yes, I'm THAT old...;-)
I was able to build all examples on my TiBook, except for an exercise where we had to build a dynamic library, because I don't know what to put in the makefile.
I can build a C dynamic lybrary with Xcode, though, so I was able to complete the exercise, but I wanted to find the correct options for a very basic dynamic library (and put that in the makefile).
This is why I tried PBTOMAKE.
Trouble is that the output makefile doesn't 'realize' that the goal is to build a dynamic library.
Is it because PBTOMAKE isn't meant to do that, or did I do something wrong?
My project is very simple, with only a .c and a .h file, and the xcode project give a functional .dylib file, so it seems to work from the Xcode side...
Thanks for your time :)
-
Suprising facts about the project file
2004-04-27 11:22:13 jimschimpf [Reply | View]
As GordonHenriksen and others have mentioned the Xcode and ProjectBuilder project file before it are really old style Next Plist files. Today I found about a utility called plutil that checks and can convert these files. It said the project file is a good Plist and I then converted it to the XML form. (plutil -convert xml1 <proj>.pbxproj). You can try this yourself. Then just for fun I put the pbxproj XML format file back into the original project and Xcode opened and used this file without a wimper. But when done (I did a couple of changes) the file is saved back to the original OLD plist format.
-
Access to code
2004-04-27 06:45:19 jimschimpf [Reply | View]
I can access it from work which is not the same ISP so I am not sure what the problem might be. If you want I can e-mail you the thing, it's < 700k.
-
Download page seems down for me
2004-04-26 22:19:48 timbat [Reply | View]
I've tried to download over the last few days and have had no success reaching the download site. Is it down ? -
Download page seems down for me
2004-04-27 05:37:02 timbat [Reply | View]
I'm still having problems both through versiontracker and the direct link, both at home and the office. I'm in the Southern Hemisphere, may that is the problem ! -
Download page seems down for me
2004-04-27 01:13:35 jimschimpf [Reply | View]
I cannot tell from here as the page is on my ISP and it works for me. I also have it listed on Versiontracker (www.versiontracker.com), go there and search for pbtomake and try that path. I will try later from work and see if the path works from there.
-
MakeFile -> XCode
2004-04-24 15:19:18 jimschimpf [Reply | View]
I think there is a discussion of how to do this in the help for Xcode. I vaguely remember the project sort of holding the make file.
-
Is there an utility for converting makefile or configure to Xcode project?
2004-04-24 11:14:27 jongampark [Reply | View]
Well.. for compiling and managing source codes in open source world, converting from makefile or config script to Xcode project is useful.
Is there such a program?
-
Is there an utility for converting makefile or configure to Xcode project?
2004-11-12 00:28:28 terry_teague [Reply | View]
Yes, there is a program that should do what you want. The program is ConvertMake.
http://homepage.mac.com/walisser/convertmake/
It currently only creates ProjectBuilder projects, but those can be imported into Xcode.
Hope this helps.
Regards, Terry
-
Looks like an old-school plist file
2004-04-24 08:58:40 GordonHenriksen [Reply | View]
Here's some documentation on working with them.
http://developer.apple.com/documentation/Cocoa/Conceptual/PropertyLists/Tasks/OldStylePListsTask.html
You shouldn't need to parse that yourself.
- G
-
Version 3.01
2004-04-24 03:07:32 jimschimpf [Reply | View]
I have put version 3.01 out and is available on the link above. This has a couple of fixes that should allow it to handle the very simple "Hello World" type project.
Remember this thing only works if ALL the file references in your project are made project relative. (Select get info on your sources directory and set it there). Second the created makefile is targeted to work in the same directory where the project is found. That is only if you cd there and make will it really build your code.
-
Not all is lost
2004-04-23 03:58:45 jimschimpf [Reply | View]
The good news is that there is nothing inherently different about Xcode vs converted ProjectBuilder projects. But my program does not like very simple projects, where the project and files are all in the same directory. If instead, you make a very simple hello world type project but put the c code in a SRC directory below where the project is created. (And use that main.c not the one Xcode creates for you with project relative addressing). Then it will create the makefile and it's Ok.
What I will do is change PBTOMAKE to handle this very simple case. It turns out that XCode doesn't put in a path key/value pair if the source/include file is in the same directory as the project. (I think it would have had the same problem with a ProjectBuilder file also).
--jim
-
Fixes for PBTOMAKE
2004-04-21 11:51:50 jimschimpf [Reply | View]
Very sorry, I should have an update very soon (look for 3.1...) and it will work with XCODE type files. I had tested this but somehow got fooled by XCode's conversion of old ProjectBuilder files. This also happened before when ProjectBuilder changed internal formats. Also going forward expect to hit potholes whenever Apple does updates of XCode.
I will try to send you e-mail when I get this, if you wish. Also the code is posted to Versiontracker in addition to the above link. That will show you a version change.
--jim
-
Problems in PBTOMAKE
2004-04-21 02:51:35 jimschimpf [Reply | View]
(1) It's very important that you set all file references in the project to PROJECT RELATIVE. (Select Sources, do GET INFO then set it there for all files).
(2) There seems to be a project with .xcode project types. I will fix this very soon. It does make the makefile but it seems to be a bit wrong. All ProjectBuilder files converted to Xcode seem to work but newly created Xcode files have a problem. (Look for version 10.4)
--jim -
Problems in PBTOMAKE
2004-04-21 11:41:59 windu2k [Reply | View]
I see. Apparently, Xcode preserves the basic structure of the ProjectBuilder files it converts while new Xcode files have a different enough structure. I did step (1) on the "Hello World!" project and that's what led me to conclude the project format was to blame. Hopefully, this is just a minor hurdle.
--Ryan
-
I just noticed a problem
2004-04-21 00:50:29 windu2k [Reply | View]
After trying repeatedly to use this utility (version 3.0) with Xcode files, I noticed your examples all use .pbproj files. Perhaps there is a difference to be found there. It works on old .pbproj files, but that doesn't do any good if you don't have those kind of project files. It chokes on .xcode files.
It is neat for what it does do, however.







char *values[] = {
"sourcecode.c.c",
"sourcecode.cpp.cpp",
"sourcecode.c.h",
"compiled.mach-o.executable",
"wrapper.framework",
"archive", // REF:JS12032006
"archive.ar",
"compiled.mach-o.dylib" // REF:JS10102006 Add dynamic lib
"sourcecode.c.objc" // REF:JS07092008 Add obj c
};
then change the switch statement below this to mark the ObjC files as source:
switch( j )
{
case 0:
case 1:
case 8: // REF:JS078092008 Add OBJ c files
// Source files just mark that we found it
line.file_type = true;
line.type = SOURCE_FILE;
break;
Re-build pbtomake and it should then build a make file for an ObjC project. Remember these usually use Frameworks and these are NOT portable to other OS's.