Difference between revisions of "Writing portable code"

From GNUstepWiki
Jump to navigation Jump to search
 
(33 intermediate revisions by 12 users not shown)
Line 4: Line 4:
  
 
== Porting Applications ==
 
== Porting Applications ==
 
You can generally convert NIB bundles from NeXTSTEP and OPENSTEP to
 
GNUstep using the nib2gmodel tool.
 
* nib2gmodel Something.nib Something.gmodel
 
* Open the gmodel file in Gorm on GNUstep and save it as gorm
 
  
 
=== Porting from NeXTSTEP (NX*) to GNUstep ===
 
=== Porting from NeXTSTEP (NX*) to GNUstep ===
  
For this you should have access to an old OPENSTEP installation, otherwise you're simply better off just rewriting the application from scratch.
+
For this you should have access to an old OPENSTEP installation, or find a friend who has one, otherwise you're simply better off just rewriting the application from scratch. There are some scripts which can be used to convert an application from NeXTSTEP to OPENSTEP located in <tt>/NextDeveloper/OpenStepConversion/ConversionScripts</tt>. They use a scripting language called "tops".  I haven't been able, as yet, to locate a version of tops for Linux or any other operating system other than Mac OS X or OPENSTEP/Mach or NeXTSTEP. There are a few conversion applications which basically just use the tops scripts to do the conversion.  They are actually two versions of the same program, but the second one doesn't run on NeXT, so here's both.  These are:
  
There are some scripts which can be used to convert an application from NeXTSTEP to OPENSTEP located in:
+
* [ftp://next-ftp.peak.org/openstep/mach/apps/devtools/Conversion.0.5.NI.tar.gz]
 +
* [ftp://next-ftp.peak.org/openstep/mach/apps/devtools/ConversionII.1.0.I.tar.gz]
  
  /NextDeveloper/OpenStepConversion/ConversionScripts
+
You should be able to point it at the project directory you wish to convert and start the conversion.  The GUI is very straightforward. You can also run the tops scripts on a Mac simply by saying:
  
They use a scripting language called "tops".  I haven't been able, as yet, to locate a version of tops for Linux or any other operating system other than Mac OS X or OPENSTEP/Mach or NeXTSTEP.
+
  tops -verbose -scriptfile {scriptfilename} {filestoconvert}
  
There are a few conversion applications which basically just use the tops scripts to do the conversionThey are actually two versions of the same program, but the second one doesn't run on NeXT, so here's both. These are:
+
All of the files are converted in place.  You must run all of the tops scripts in the ConversionScripts directory against the application code.  It is considerably simply to use the existing applicationsUnfortunately these scripts do not exist on Mac OS X, otherwise porting the Conversion application might be useful.
  
[ftp://next-ftp.peak.org/openstep/mach/apps/devtools/Conversion.0.5.NI.tar.gz]
+
When you start the scripts, if you're running them on black hardware you should go get a cup of coffee and watch a movie with your wife or go code something else for a while.   The conversion will take a good long while on an older machine.   I haven't timed it on the Mac, though. Once this is done, there is still a long way to go. Read on.
[ftp://next-ftp.peak.org/openstep/mach/apps/devtools/ConversionII.1.0.I.tar.gz]
 
  
You should be able to point it at the project directory you wish to convert and start the conversionThe GUI is very straightforward.
+
OPENSTEP4.2/Mach had a class called NSCStringText.  This class was primarily for apps which were converted from NeXTSTEP to use as a stop-gap measure in OpenStep.  This is one of the main reasons why it isn't in GNUstep.  You will need to make sure that any classes modified by the scripts to use NSCStringText will use NSText and it's related classes as appropriate. OPENSTEP4.2/Mac also had some other extensions on the OpenStep standard such as NXStreamsYou will also need to convert any and all instances of NXStream to use NSData instead in order to make your app work with GNUstep.
  
You can also run the tops scripts on a Mac simply by saying:
+
If your app is fairly small, you shouldn't be in for a great shock, but if your app is heavily reliant on the old Text object from NeXTSTEP, you have a lot of work ahead.  Other gaps which the scripts might leave are problems with NSUserDefaults which it can't fix on it's own.
  
  tops -verbose -scriptfile {location} {filestoconvert}
+
=== Porting from Cocoa or OPENSTEP (NS*) to GNUstep ===
  
All of the files are converted in place. You must run all of the tops scripts in the ConversionScripts directory against the application code.  It is considerably simply to use the existing applications.  Unfortunately these scripts do not exist on Mac OS X, otherwise porting the Conversion application might be useful.
+
Porting from Cocoa or OPENSTEP to GNUstep has different aspects. First there is the compatibility of the basic Foundation Kit and Application Kit. We support a lot of classes, but not all of them and the same is true for specific methods, specifically newly introduced classes and methods in Cocoa may still be missing as GNUstep started out aiming at OpenStep compatibility.
  
Once this is done, there is still a long way to go.
+
Second you have all the additional frameworks and libraries programmers on Mac OS X take for granted, for some of them free replacements exists, for most they are still missing. Mac OS X developers should try and avoid CoreFoundation as this will complicate your dependency situation on non-Mac hosts, even if that part of CoreFoundation has actually been ported. GNUstep Base and the FoundationKit offer many parts of the CoreFoundation functionality in a natural [[Objective-C]] manner. To be a bit more specific:
  
OPENSTEP4.2/Mach had a class called NSCStringText. This class was primarily for apps which were converted from NeXTSTEP to use as a stop-gap measure in OpenStep.  This is the main reason it isn't in openstep.  You will need to make sure that any objects modified by the scripts to use NSCStringText will use NSText and it's related classes as appropriate.
+
* don't use Core* (CoreFoundation, CoreSound, CoreAnimation, ...)
 +
* don't use KeyChain
 +
* don't use Carbon
 +
* don't use Quartz
 +
* don't use QuickTime
 +
* don't use WebKit (GCC 4.1 and up support ObjC++, but currently, there exists no WebKit port for GNUstep)
 +
* don't use altivec features or the vecLib.framework (a collection of functions for vector manipulation, an Apple specific extension)
 +
* don't use anything else we do not provide
  
OPENSTEP4.2/Mac also had some other extensions on the OpenStep standard such as NXStreams.  You will also need to convert any and all instances of NXStream to use NSData instead in order to make your app work with GNUstep.
+
If you committed none of these portability evils, the rest is relatively straightforward:
 
 
If your app is fairly small, you shouldn't be in for a great shock, but if your app is heavily reliant on the old Text object from NeXTSTEP, you have a lot of work ahead.
 
 
 
=== Porting from OPENSTEP (NS*) to GNUstep ===
 
  
 +
# [[Writing Makefiles|Write a new GNUstep make file]] for the project (very easy, still there is currently no automatic way to do so).
 +
# Make sure the Nib files are readable by GNUstep.
 +
## When saving a NIB file in project builder, ensure that "10.2 or later" format is selected. Also, ensure that "Use text archive format" is NOT checked, as this created problems.
 +
## Another option is to load them into Gorm and convert them into .gorm files. If they're from OPENSTEP or Mac OS X 10.1 or earlier, see [[#Porting_.nib_files_from_OPENSTEP_or_Mac_OS_X_10.1_and_earlier|below]].
 +
# Provide an Info.plist.
  
 
=== Porting from GNUstep to Cocoa ===
 
=== Porting from GNUstep to Cocoa ===
  
tbd.
+
This should be an easy transition since GNUstep implements most of Cocoa, except for the very Apple specific classes such as the scripting extensions. Since Gorm does not yet save .nib files, you will need to create the interfaces using IB.  Also there is a gorm reading/parsing framework for Cocoa in the works as well, so please stay tuned.
  
 +
Will need to:
  
 +
* Make a Project Builder project for your app or
 +
* an Xcode project for your app
  
=== Porting from Cocoa to GNUstep ===
+
Do the following:
  
Porting from Cocoa to GNUstep has different aspects.
+
* Open Xcode
 +
* Choose Application (if your project is an application)
 +
* Enter the name and location you wish the Project to reside at
 +
* Copy your files from your GNUstep application into the new project
 +
* Using the "Add Existing Files" option to add these files to your project
  
First there is the compatibility of the basic Foundation Kit and Application Kit. We support a lot of classes, but not all of them and the same is true for specific methods, Specifically newly introduced classes and methods may still be missing as GNUstep started out aiming at OpenStep compatibility.
+
You should preserve your original directory structure if you want to distribute one package for both GNUstep and Cocoa.
 
 
Second you have all the additional frameworks and libraries programmers on Mac OS X take for granted, for some of them free replacements exists, for most they are still missing.
 
 
 
Mac OS X developers should try and avoid CoreFoundation as this will complicate your dependency situation on non-Mac hosts, even if that part of CoreFoundation has actually been ported.
 
 
 
GNUstep Base and the FoundationKit offer many parts of the CoreFoundation functionality in a natural Objective-C manner.
 
 
 
==== The porting itself ====
 
 
 
short overview:
 
* write a makefile
 
* convert your NIB files to gmodel
 
* provide an Info.plist.
 
 
 
detailed instructions:
 
# you need to write a new GNUstep make file for the project (very easy, still there is currently no automatic way to do so)
 
# you need to convert the NIB files to GNUstep format. At some point in time GORM will be able to read NIB files, but currently you need to use the gmodel intermediate format for this and for this the above mentioned tools are used.
 
 
 
==== Don'ts ====
 
 
 
Don't use anything we do not provide:
 
 
 
* don't use CoreFoundation
 
* don't use KeyChain
 
* don't use Carbon
 
* don't use Quartz
 
* don't use QuickTime
 
 
 
gcc mainline currently doesn't support ObjC++ although it is already in the works somewhat (expected for gcc 4.1). that means:
 
 
 
* don't use WebKit (currently)
 
 
 
gcc mainline also does not support altivec, this is an apple specific extentsion, that means:
 
* don't use altivec features or the vecLib.framework (a collection of functions for vector manipulation).
 
  
 
== Stumbling Blocks ==
 
== Stumbling Blocks ==
  
* Apple's Cocoa.h
+
=== Apple's Cocoa.h ===
  
it is there to enable pre-compiled headers and speed up compile time thusly. Anyway, it contains just two lines:
+
It is there to enable pre-compiled headers and speed up compile time thusly. Anyway, it contains just two lines:
  
 
  #import <Foundation/Foundation.h>
 
  #import <Foundation/Foundation.h>
 
  #import <AppKit/AppKit.h>
 
  #import <AppKit/AppKit.h>
  
So you can easily work around this by providing your own or replace your include of <Cocoa/Cocoa.h> with just the above, which will also work on OS-X.
+
On older GNUstep systems, you may have to work around this by providing your own or replace your include of <Cocoa/Cocoa.h> with just the above, which will also work on OS-X.
  
* When you need to distinguish between Cocoa and GNUstep, you may use the following
+
=== Distinguishing Between Cocoa and GNUstep ===
  
 
  #ifdef GNUSTEP
 
  #ifdef GNUSTEP
Line 109: Line 85:
 
  #endif
 
  #endif
  
 +
=== Porting .nib files from OPENSTEP or Mac OS X 10.1 and earlier ===
  
=== Porting the .nib files ===
+
GNUstep can handle nibs from 10.2 or later of Mac OS X, but it can't read nibs made with NeXTSTEP, OpenStep or Mac OS 10.1 or earlier.  On the latest version of Mac OS X, this is a simple matter of loading the .nibs into Interface Builder.app and saving them in the 10.2 format.  Another possibility is using nib2gmodel, the only one when porting from OPENSTEP, and, mind you, you need to do the converting ''there''. First, get [http://freshmeat.net/projects/nib2gmodel/ nib2gmodel], follow the included instructions to build and install it.  Once that's done you're ready to begin:
 
 
First get [http://freshmeat.net/projects/nib2gmodel/ nib2gmodel], follow the included instructions to build and install it.  Once that's done you're ready to begin:
 
  
* Run the nib2gmodel program on your nib like so:
+
Run the nib2gmodel program on your nib:
  
 
   nib2gmodel mygui.nib mygui.gmodel
 
   nib2gmodel mygui.nib mygui.gmodel
Line 124: Line 99:
 
   rm mygui.ser
 
   rm mygui.ser
  
* Now you can either use the gmodel as it is, or you can convert it to a .gorm file.
+
Now you can either use the gmodel as it is, or you can convert it to a .gorm file.
  
 
==== Gmodel to .gorm conversion ====
 
==== Gmodel to .gorm conversion ====
Line 138: Line 113:
 
After you've defined all of the unknown classes, Gorm should complete the conversion.  Once this is done you should save the result to make sure you don't loose your work.
 
After you've defined all of the unknown classes, Gorm should complete the conversion.  Once this is done you should save the result to make sure you don't loose your work.
  
''' ''FIXME: add following:'' '''
+
==== .nib to .gorm conversion ====
* how to convert xCode project to GNUstep project (creating a GNUstep [http://www.gnustep.it/nicola/Tutorials/WritingMakefiles/index.html Makefile] or [[ProjectCenter]])
+
 
 +
Since it's possible to load nibs into GNUstep application now, it should be easy to convert 10.2 or later nibs by simply loading them into Gorm and saving them as .gorm files.  This is not strictly necessary since GNUstep can handle them natively.
 +
 
 +
NOTE: Our recommendation for this is not to use the nib2gmodel conversion and simply to use the nibs directly, if you can or to convert them as described above by loading them into Interface Builder and saving them as the newer nib format.
 +
 
 +
=== Xcode conversion ===
 +
 
 +
* how to convert Xcode project to GNUstep project (creating a GNUstep [http://www.gnustep.it/nicola/Tutorials/WritingMakefiles/index.html Makefile] or [[ProjectCenter]])
 +
 
 +
* [[pbxbuild]] - this program converts an Xcode project into a set of targets and directories in which you can build by simply using make.
 +
 
 +
* PBTOMAKE. [http://www.macdevcenter.com/pub/a/mac/2004/04/20/xcodetounix.html xcodetounix] (download at [http://members.bellatlantic.net/%7Evze35xda/software.html]) is a tool for converting Xcode and Project Builder files to generic Unix Makefiles.  It would probably be a good start for converting to a GNUstep makefile.
  
 
== Notes ==
 
== Notes ==
Line 149: Line 135:
 
* [[Foundation|GNUstep Base]] and the [[Foundation|FoundationKit]] offer some of this functionality "for free".
 
* [[Foundation|GNUstep Base]] and the [[Foundation|FoundationKit]] offer some of this functionality "for free".
 
* Try not to hard code paths and so on into your code, use macros (not recommended), or even better an abstraction mechanism.
 
* Try not to hard code paths and so on into your code, use macros (not recommended), or even better an abstraction mechanism.
* Avoid hard-coding system constants, or platform-specific ones where Posix or commonly-accepted ones exist (and we're not talking about glibc here :-)
+
* Avoid hard-coding system constants, or platform-specific ones where POSIX or commonly-accepted ones exist (and we're not talking about glibc here :-)
 +
* Try to avoid advanced features of the linker, such as weak symbols, which may not be present on non-ELF systems.  While this will work perfectly on most systems, it is not portable to all systems, most notably Windows.
 +
 
 +
=== When platform-specific code cannot be avoided ===
 +
 
 +
There are cases where you may need to write platform-specific code, especially in the case of desktop applications and services which make use of facilities not standardised by POSIX or by the FoundationKit and AppKit  specifications, at least use [[Identifying the target platform|standard platform macros]].
 +
 
 +
These platform-specific, or even desktop-specific requirements could be re-used by other projects - and even enhance desktop-integration efforts for GNUstep applications - by abstracting out common code into currently hypothetical [[PlatformKit]] and [[DesktopServicesKit]] frameworks.
  
 
[[Category:Project procedures]]
 
[[Category:Project procedures]]
 +
 +
=== Cross Compiling ===
 +
 +
See [[Cross_Compiling]]

Latest revision as of 12:12, 30 January 2009

GNUstep opens up some fairly interesting opportunities to target a number of platforms with the same source code, for example porting Mac OS X Cocoa applications to Linux, the BSDs, other Unices and (ultimately) Windows without significant re-engineering effort or degraded end-user functionality.

Some portability gotchas are listed below (please update when you run into a new one!):

Porting Applications

Porting from NeXTSTEP (NX*) to GNUstep

For this you should have access to an old OPENSTEP installation, or find a friend who has one, otherwise you're simply better off just rewriting the application from scratch. There are some scripts which can be used to convert an application from NeXTSTEP to OPENSTEP located in /NextDeveloper/OpenStepConversion/ConversionScripts. They use a scripting language called "tops". I haven't been able, as yet, to locate a version of tops for Linux or any other operating system other than Mac OS X or OPENSTEP/Mach or NeXTSTEP. There are a few conversion applications which basically just use the tops scripts to do the conversion. They are actually two versions of the same program, but the second one doesn't run on NeXT, so here's both. These are:

You should be able to point it at the project directory you wish to convert and start the conversion. The GUI is very straightforward. You can also run the tops scripts on a Mac simply by saying:

  tops -verbose -scriptfile {scriptfilename} {filestoconvert}

All of the files are converted in place. You must run all of the tops scripts in the ConversionScripts directory against the application code. It is considerably simply to use the existing applications. Unfortunately these scripts do not exist on Mac OS X, otherwise porting the Conversion application might be useful.

When you start the scripts, if you're running them on black hardware you should go get a cup of coffee and watch a movie with your wife or go code something else for a while. The conversion will take a good long while on an older machine. I haven't timed it on the Mac, though. Once this is done, there is still a long way to go. Read on.

OPENSTEP4.2/Mach had a class called NSCStringText. This class was primarily for apps which were converted from NeXTSTEP to use as a stop-gap measure in OpenStep. This is one of the main reasons why it isn't in GNUstep. You will need to make sure that any classes modified by the scripts to use NSCStringText will use NSText and it's related classes as appropriate. OPENSTEP4.2/Mac also had some other extensions on the OpenStep standard such as NXStreams. You will also need to convert any and all instances of NXStream to use NSData instead in order to make your app work with GNUstep.

If your app is fairly small, you shouldn't be in for a great shock, but if your app is heavily reliant on the old Text object from NeXTSTEP, you have a lot of work ahead. Other gaps which the scripts might leave are problems with NSUserDefaults which it can't fix on it's own.

Porting from Cocoa or OPENSTEP (NS*) to GNUstep

Porting from Cocoa or OPENSTEP to GNUstep has different aspects. First there is the compatibility of the basic Foundation Kit and Application Kit. We support a lot of classes, but not all of them and the same is true for specific methods, specifically newly introduced classes and methods in Cocoa may still be missing as GNUstep started out aiming at OpenStep compatibility.

Second you have all the additional frameworks and libraries programmers on Mac OS X take for granted, for some of them free replacements exists, for most they are still missing. Mac OS X developers should try and avoid CoreFoundation as this will complicate your dependency situation on non-Mac hosts, even if that part of CoreFoundation has actually been ported. GNUstep Base and the FoundationKit offer many parts of the CoreFoundation functionality in a natural Objective-C manner. To be a bit more specific:

  • don't use Core* (CoreFoundation, CoreSound, CoreAnimation, ...)
  • don't use KeyChain
  • don't use Carbon
  • don't use Quartz
  • don't use QuickTime
  • don't use WebKit (GCC 4.1 and up support ObjC++, but currently, there exists no WebKit port for GNUstep)
  • don't use altivec features or the vecLib.framework (a collection of functions for vector manipulation, an Apple specific extension)
  • don't use anything else we do not provide

If you committed none of these portability evils, the rest is relatively straightforward:

  1. Write a new GNUstep make file for the project (very easy, still there is currently no automatic way to do so).
  2. Make sure the Nib files are readable by GNUstep.
    1. When saving a NIB file in project builder, ensure that "10.2 or later" format is selected. Also, ensure that "Use text archive format" is NOT checked, as this created problems.
    2. Another option is to load them into Gorm and convert them into .gorm files. If they're from OPENSTEP or Mac OS X 10.1 or earlier, see below.
  3. Provide an Info.plist.

Porting from GNUstep to Cocoa

This should be an easy transition since GNUstep implements most of Cocoa, except for the very Apple specific classes such as the scripting extensions. Since Gorm does not yet save .nib files, you will need to create the interfaces using IB. Also there is a gorm reading/parsing framework for Cocoa in the works as well, so please stay tuned.

Will need to:

  • Make a Project Builder project for your app or
  • an Xcode project for your app

Do the following:

  • Open Xcode
  • Choose Application (if your project is an application)
  • Enter the name and location you wish the Project to reside at
  • Copy your files from your GNUstep application into the new project
  • Using the "Add Existing Files" option to add these files to your project

You should preserve your original directory structure if you want to distribute one package for both GNUstep and Cocoa.

Stumbling Blocks

Apple's Cocoa.h

It is there to enable pre-compiled headers and speed up compile time thusly. Anyway, it contains just two lines:

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

On older GNUstep systems, you may have to work around this by providing your own or replace your include of <Cocoa/Cocoa.h> with just the above, which will also work on OS-X.

Distinguishing Between Cocoa and GNUstep

#ifdef GNUSTEP
    /* GNUstep code goes here ... */
#else
    /* OS-X Cocoa native code goes here ... */
#endif

Porting .nib files from OPENSTEP or Mac OS X 10.1 and earlier

GNUstep can handle nibs from 10.2 or later of Mac OS X, but it can't read nibs made with NeXTSTEP, OpenStep or Mac OS 10.1 or earlier. On the latest version of Mac OS X, this is a simple matter of loading the .nibs into Interface Builder.app and saving them in the 10.2 format. Another possibility is using nib2gmodel, the only one when porting from OPENSTEP, and, mind you, you need to do the converting there. First, get nib2gmodel, follow the included instructions to build and install it. Once that's done you're ready to begin:

Run the nib2gmodel program on your nib:

  nib2gmodel mygui.nib mygui.gmodel

This should create the .gmodel as a plist. I recommend that you convert the gmodel to a "normal" plist instead of an XML plist. You can do that by doing this on OS X:

  pl < mygui.gmodel -output mygui.ser
  pl > mygui.gmodel -input mygui.ser
  rm mygui.ser

Now you can either use the gmodel as it is, or you can convert it to a .gorm file.

Gmodel to .gorm conversion

NOTE: Conversion from gmodel to .gorm is experimental and will probably remain so for a while. It currently works in the majority of cases, but there are still improvements which need to be made.

Conversion to a .gorm file is relatively straightforward:

  • Start Gorm.app.
  • Choose Gorm->Document->Open and find the gmodel you wish to load.
  • Gorm will prompt you to either define the superclass for classes it doesn't know about or to parse the headers.

After you've defined all of the unknown classes, Gorm should complete the conversion. Once this is done you should save the result to make sure you don't loose your work.

.nib to .gorm conversion

Since it's possible to load nibs into GNUstep application now, it should be easy to convert 10.2 or later nibs by simply loading them into Gorm and saving them as .gorm files. This is not strictly necessary since GNUstep can handle them natively.

NOTE: Our recommendation for this is not to use the nib2gmodel conversion and simply to use the nibs directly, if you can or to convert them as described above by loading them into Interface Builder and saving them as the newer nib format.

Xcode conversion

  • pbxbuild - this program converts an Xcode project into a set of targets and directories in which you can build by simply using make.
  • PBTOMAKE. xcodetounix (download at [3]) is a tool for converting Xcode and Project Builder files to generic Unix Makefiles. It would probably be a good start for converting to a GNUstep makefile.

Notes

Do not rely on tools available in development environment

All the world is not Linux or FreeBSD or Windows. System constants may be different on different platforms. Paths to command-line tools, the parameters they accept and locations of temporary directories may be different to what you are used to on your platform.

  • GNUstep Base and the FoundationKit offer some of this functionality "for free".
  • Try not to hard code paths and so on into your code, use macros (not recommended), or even better an abstraction mechanism.
  • Avoid hard-coding system constants, or platform-specific ones where POSIX or commonly-accepted ones exist (and we're not talking about glibc here :-)
  • Try to avoid advanced features of the linker, such as weak symbols, which may not be present on non-ELF systems. While this will work perfectly on most systems, it is not portable to all systems, most notably Windows.

When platform-specific code cannot be avoided

There are cases where you may need to write platform-specific code, especially in the case of desktop applications and services which make use of facilities not standardised by POSIX or by the FoundationKit and AppKit specifications, at least use standard platform macros.

These platform-specific, or even desktop-specific requirements could be re-used by other projects - and even enhance desktop-integration efforts for GNUstep applications - by abstracting out common code into currently hypothetical PlatformKit and DesktopServicesKit frameworks.

Cross Compiling

See Cross_Compiling