Building Qt/Mac with CodeWarrior

This is a log of my efforts in trying to build a Qt/Mac 3.2.0b1 application with CodeWarrior 8.3.

My earlier log working with Qt/Mac 3.1.0 is here.

Compile Qt source under CW.

Create the Qt/CW project

cd to the Qt src directory. Then qmake -spec macx-mwerks qt.pro file, to generate an XML file that CW can import. This will give you a CodeWarrior project. Since I have Qt configured as multi-threaded, my XML file is qt-mt.xml and I named the subsequent CW project file qt-mt.mcp. I have left these in the Qt src directory for now.

When CodeWarrior imported the XML file, I got three errors about incorrect access paths. I cleaned these up to make them point to the appropriate directories. The first two look like problems with soft links or aliases.

{OS X Volume}System/Library/Frameworks/OpenGL.framework/Headers ->
{OS X Volume}System/Library/Frameworks/OpenGL.framework/Versions/A/Headers

{OS X Volume}System/Library/Frameworks/AGL.framework/Headers ->
{OS X Volume}System/Library/Frameworks/AGL.framework/Versions/A/Headers

The third is probably due to the fact that my home directory is on an external disk.

{OS X Volume}Users/trygve/Documents/<various subdirs here>/frameworks/qt/include ->
{OS X Volume}Documents/<various subdirs here>/frameworks/qt/include

With these three changes, the project opens without any error messages.

Fix compilation errors in project settings and Qt source

(The following details are applicable to Qt/Mac 3.2.0b1 -- later versions may have incorporated some or all of these changes.) There are some compilation errors when compiling the Qt source, but they are relatively few and have simple fixes. Some require little tweaks in the source code, but the first one is a project config change.

Access Paths

The first error that was encountered was in the first source file to be compiled, qsound_mac.cpp, and was a problem in the project in general, preventing many files from compiling.

Error: the file 'mw_stdarg.h' cannot be opened.

That file is located here:

{Compiler}MacOS X Support/Headers/PPC Specific/mw_stdarg.h

I added that directory path to the Access Paths panel below the others. This allowed qsound_mac.cpp to compile without error, and I then compiled the next group of files—the Mac-specific Qt files. All but 1 compiled, so we fix the next problem....

Compile errors in qfont_mac.cpp

Lines 159-160 - Can't declare array size with variable, must use constant. I decided that the most expedient but clear fix would be to change line 158 into two lines so that the constant feat_guess is declared as a manifest constant rather than a local variable:

int feat_guess=5, feats=0;

change to:

#define feat_guess 5
int feats=0;

The next error was an illegal implicit conversion from 'QFontEngine *' to 'QFontEngineMac *' on line 316 (line 315 before the feat_guess fix above).

engine = (QFontEngineMac*)engineData->engine = e;

A clearer way of writing this that also satisfies the compiler is:

engineData->engine = e;
engine = (QFontEngineMac*) e;

Now all the xxxx_mac.cpp files compile, as do all but 4 of the remaining Qt files.

Compile error in png.c

Line 147 in src/3rdparty/libpng/png.c:

Error: illegal implicit onversion from 'void *' to 'png_struct_def *'

The fix is to cast it:

png_structp p = (png_structp) png_ptr;

Compile error in qfile.cpp

Line 530 in src/tools/qfile.c:

Error: function call 'operator+=({lval} QCString, {lval} int)' is ambiguous

Ambiguous QCString operator reference. It's using += with an int, which could imply several += interfaces. Quick fix is to cast/coerce to the intended type. Change the rhs to construct a QChar before appending:

ungetchBuffer += QChar(ch);

Compile errors in qglobal.cpp

Lines 409-411 in src/tools/qglobal.cpp:

Error : illegal implicit conversion from 'unsigned char *' to 'const char *'
qglobal.cpp line 409 const char *p = p_str(msg);

Error : function call 'DebugStr({lval} const char *)' does not match 'DebugStr(const unsigned char *)'
qglobal.cpp line 410 DebugStr(p);

Error : function call 'free({lval} const char *)' does not match 'free(void *)'
qglobal.cpp line 411 free(p);

These are const/unsigned/char conflicts in types causing conversion errors. The simplest fix is to change Line 409 to declare p as unsigned char* instead of const char*:

unsigned char *p = p_str(msg);

Compile error in qrtlcodec.cpp

Line 540 in src/codecs/qrtlcodec.cpp:

Error : function call 'operator+=({lval} QCString, const unsigned char)' is ambiguous
'operator+=(const char *, int)'
'QCString::operator+=(char)' (non-static)
qrtlcodec.cpp line 540 rstr += unkn;

Same problem as with qfile.cpp noted above. Ambiguous call to QCString operator +=, solved by constructing explicit type on the rhs:

rstr += QChar(unkn);

Link Qt library.

Once the compile errors were solved, there were some link errors while trying to link my library libqt-mt.dylib. Most were PNG-related:

Link Error: _png_pass_start is undefined
Link Error: _png_pass_inc is undefined
Link Error: _png_pass_ystart is undefined
Link Error: _png_pass_yinc is undefined
Link Error: _png_pass_dsp_mask is undefined
Link Error: _png_libpng_ver is undefined
Link Error: _png_pass_mask is undefined

I'm not sure what the ideal solution is, but it was sufficient to go into src/3rdparty/libpng/pngconf.h, and before line 1151, add this line:

#define PNG_USE_LOCAL_ARRAYS

This got those symbols to be compiled into with the PNG source rather than being ifdef'ed out.

This left the last 4 link errors to be solved. They didn't happen when I went through this process with Qt 3.1.0. They are:

Link Error : __Z22sched_get_priority_mini is undefined
Link Error : __Z22sched_get_priority_maxi is undefined
Link Error : __Z19qInstallPathPluginsv is undefined
Link Error : __Z12qInstallPathv is undefined

The first two are referenced in lines 316-317 of src/kernel/qthread_unix.cpp, unmangled as sched_get_priority_min and sched_get_priority_max. They are defined in <sched.h> in /usr/include. Seems like there is a missing library or like CodeWarrior does not have these in its libraries. For now I am getting around this by adding my own harmless stub versions of these functions, and I don't think that I need them at the moment. I added the following three lines to qthread_unix.cpp:

int sched_yield(void) { return 0; }
int sched_get_priority_min(int) { return 0; }
int sched_get_priority_max(int) { return 1; }

The last two link errors are referenced in lines 1654-1659 of qapplication.cpp and line 529 of qsettings.cpp, unmangled as qInstallPathPlugins and qInstallPath. These are defined in src/tools/qconfig.cpp so I'm not sure why they aren't found by the linker, but they contain hardcoded paths of my particular installation anyway, so they are not something that should be compiled in and actually used by my users! I can create stub definitions of these. Hopefully they are just being used by qmake, qconfig, and the Qt toolchain anyway.

After further inspection, I see that the reason for this error is that qconfig.cpp is not in the CodeWarrior project. Dropping qconfig.cpp into the project solves this error.

The library links!

I decided to set the project settings to place the output in a subdirectory of the Qt lib directory, so I end up with this path for my Output Directory under Target Settings:

{Project}../lib/mwerks

Now we have to get a Qt application to link to this library.

Compile and link an application.

In my application's home directory, where its .pro file lives, I did qmake -spec macx-mwerks client.pro to create the client.xml file for import, which resulted in my CW project file client.mcp.

There were compile errors right off the bat.

Access Paths

Just like in the library project, an access path was needed.

Error: the file 'mw_stdarg.h' cannot be opened.

That file is located in this directory:

{Compiler}MacOS X Support/Headers/PPC Specific

I added that directory path to the Access Paths panel below the others.

Compiler Options

I use exceptions routinely and RTTI when necessary, but these are turned off in the project generated by qmake. So in the project's C++ Language settings panel, I checked Enable C++ Exceptions and Enable RTTI. In addition, I checked ANSI Strict because, well, one should write clean code.

Other Compile Errors

I had two places where I was including the obsolete STL header <algo.h> instead of the current <algorithm>, so I fixed that to make CodeWarrior happy.

Link Errors

The project was set up to link with the gcc-built qt-mt.dylib, and this caused a handful of link errors because of undefined symbols. Replacing that dylib with the one built in the CW project earlier, made the application link successfully.

The application links!

Run and debug the application.

(No luck yet...trouble finding the dylib at launch time, version mismatch message appears on command line when run from there, bouncing app quits when run from the Finder....)