Monday, September 27, 2004

From CodeWarrior 9.2 to XCode 1.5

This one comes from the darwin-development mailling list (Email address of Brad Oliver changed).

-------- Original Message --------
Subject: CodeWarrior to XCode
Date: Wed, 25 Aug 2004 23:59:53 -0700
From: Brad Oliver
To: darwin-development@lists.apple.com
CC: xcode-users@lists.apple.com
References: <20040826050031.5453.61096.mailman@lists.apple.com>

> Brad,
>
> is not that you have written an internal document - say -
> "How To's with Xcode: quirks explained" that could be distributed?

I haven't written anything more formal than an e-mail to my colleagues about the process. I'll summarize below. A lot of the "quirks" are not so easy to quantify as they involved getting used to the XCode IDE, which behaves very differently (to my eyes) compared to CodeWarrior.

Note that my perspective here is coming from years of work using CodeWarrior and porting code from Visual Studio to CodeWarrior. Also, these notes come specifically from our work moving Knights of the Old Republic (KOTOR) from CodeWarrior 9.2 to XCode 1.5.

1. "legacy" for-loop scoping (a variable defined in the for loop definition has scope outside the for loop) in theory works in gcc, but in practice breaks when the optimizer is enabled. You have use the ISO-standard for-loop scoping rules for this to work, i.e. move the variable declaration outside of the for-loop statement. gcc at least gives you warnings about this, so you can find and fix them in your code fairly easily.

2. Xcode's "CodeWarrior-style" inline assembly only works for the simplest cases, so it's best to avoid it if you can.

3. Passing a non-POD variable (where POD == Plain Old Data, e.g. C-style variables and structures rather than C++ structures that have vtables) to a routine that expects POD variables will generate a warning in gcc, and insert a "trap" instruction into your code, causing the app to abort in the debugger when that code is executed. I have no idea why gcc doesn't just generate an error for this case, since that code will fail to run.

This happens if, for example, you pass a custom string class structure to printf as a %s parameter. Under CW and Visual Studio, they will pass a pointer to the first chunk of non-vtable data (which in KOTOR is the actual char[] backing store for the string class out of blind luck). Under gcc, you must fix your code.

4. With the optimizer set to -O3 (the max), gcc does a lot of auto-inlining. As such, if you have some crappy code where a class defines a method as "inline" but the method is not actually inlined, gcc will give you a link error when you're done compiling. You have to remove the bogus "inline" statement in the function prototype to get it to work.

5. Single-precision floating-point functions like acosf, cosf, etc are not in the standard math library (libm). They are only available in 10.3+, in libmx. A similar situation exists for wchar support.

6. "bool" types are 32-bit in gcc, whereas they are 8-bit in CodeWarrior and Visual Studio. This causes substantial binary compatibility problems with data structures that are read to/written from disk. A "bool8" class can't be used to globally #define the problem away because it causes compile-time issues with templates. However, if you can identify the "bool" data structures that are being read/written to disk, you can change them to the "bool8" class and work around the problem that way.

7. We have routines that override standard library calls at link time, like fopen, etc. ZeroLink causes problems such that our overrides lose out, so it's best for us to keep ZeroLink off.

8. Dead-code stripping has a bug with C++ apps in XCode 1.5 whereby it tends to strip debugging symbols for used functions at link time. The end result is that you can't see the source code for a number of files in the debugger, nor can you set breakpoints in that code. Turning off dead-code stripping for the debug build fixes this, although you may have to work a bit to implement (or comment out) some routines that CodeWarrior would have otherwise stripped away. It's safe to use dead-code stripping in the release builds, as far as I can tell.

9. I write a lot of code that jumps past local variable initialization in C++, like so:

...
if (bad) goto bail;

int foo = 1;
do stuff here;
bail:
return;

This is not allowed by gcc; you have to change "int foo = 1;" to "int foo; foo = 1;". This is only if you're jumping past a local initialization, so it mainly comes up using the Apple debug macros like "require_noerr" and the like.

10. gcc doesn't recognize "\" as a path delimiter for #include statements, you have to change them to "/"

11. If you're using PPC intrinsics (like rlwinm or lhwbrx) you have to be sure to inlude "ppc_intrinsics.h" since they're not natively part of the compiler.

12. KOTOR casts a lot of class function methods as pointers for callbacks. gcc requires that you use a different syntax:

SetCallback ((CallBackPtr) classMethod);

becomes

SetCallback ((CallBackPtr) &Class::classMethod);

You can get away with just "&classMethod", but gcc will spew out a warning.

13. Build styles are fairly useless for our projects, since they don't allow us to easily have different libraries and source files for debug and release builds. It's fairly easy to clone XCode targets, so the best solution for us is to ignore/remove build styles from the projects and rely solely on different targets for debug and release builds.

I did run some performance tests on the game when we finished. On my Dual 2.5GHz G5, performance was almost immeasurably slower in the XCode build, by maybe .5 of a frame per second. It was well within the margin of error, enough so that I'd call it even with CodeWarrior.

I had some notes somewhere about compile times, but I can't locate them right now. Suffice it to say, CodeWarrior beat XCode/gcc pretty handily for the non-optimized build, but they were much closer on the optimized build. Surprisingly (at least to me) gcc's compile time using -O3 was almost identical to it's compile time for the non-optimized build. This also carries a big red asterisk - gcc does compile on both CPUs, so if you have a single-CPU Mac (or if CodeWarrior is ever updated to use 2 CPUs), then it's no contest in favor of CW.

I'd appreciate feedback from other people who have had experiences porting code from either VS/VS.NET or CodeWarrior to XCode. In our KOTOR test, the code had already been ported from VS.NET (VC7) to CodeWarrior, so it's unclear to me if there are any advantages that we'd see if we went directly from VS.NET to XCode.

--
Brad Oliver
xxx@xxx.com
_______________________________________________
darwin-development mailing list | darwin-development@lists.apple.com
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/darwin-development
Do not post admin requests to the list. They will be ignored.

No comments: