Using CodeWarrior on a Macintosh

This page is rather outdated as of December, 2005. However, see Converting from Carbon CFM to Mach-O for more recent tips.

CodeWarrior is a programming environment available from Metrowerks Corporation.CodeWarrior Pro 5 for Macintosh contains everything you need to develop Finale plug-ins both for Macintosh computers and Windows computers right on your Macintosh computer.

Most of the Finale PDK is not platform-specific. Files pertaining to a specific platform are segregated into folders called "Mac" and "Win" within the Source and Example folders. Coda seems not quite to have made up its mind whether to include all files in both the Mac and Windows downloads. As if this writing, the Mac download (Fin2K, released 8/27/99) does not include the Win files, whereas the Win download (released 8/31/99) does. I recommend that you consolidate the files into a single set from which to work, since Coda does not necessarily release the same version of the files in each download. I currently use the original Mac download for developing Finale 97/98 plugins and the new Windows download for developing Finale 2000 plugins.

In general, you should try to avoid platform-specific code. Sometimes you have no choice however. For more information, see Jari Williamsson's tips for plug-in developers. Both Apple and Microsoft have their APIs fully documented online. You can find the Apple documents at the Apple Developer Page. You can find the Microsoft's Win32 documentation at MSDN Online.

The following information assumes a good working knowledge of the CodeWarrior IDE and specifically how to set up and manipulate different Targets and their settings. You will probably end up with one project that includes 3 (possibly 4, see below) targets corresponding to the PPC, 68K, and Win32 versions of your plugin.

The Mac Platform

Since Coda uses CodeWarrior for it Macintosh development of Finale, creating your first Mac plugin is very simple. The Finale PDK comes with a project called TestExtension. that is ready to load and compile using CodeWarrior. The TestExtension project also illustrates how to include support for 68K Macs in your plugin. Apparently it was created with an earlier version of CodeWarrior than Pro 5, because it cannot find the correct 68K libraries as shipped. The libraries that have worked for me are the ones with suffix

Fa(4i_8d).A4

I chose the 8d libraries because they are the only libraries that also include 4i, which is in the names of the original TestExtension libraries. Here are my 68K target settings for 68K Code Generation:

Even though I am using the 8d libraries I do not have 8-Byte Doubles checked, because the TestExtension project did not have them checked. This could nevertheless be an error, but so far it is working. (I haven't used doubles anywhere yet either!)

Beyond this little problem, TestExtension builds successfully immediately, and you are ready to start working on your own plugin code.

The Windows Platform

For developing Windows versions of your plugins on your Mac, you should consider getting a Windows emulation program. I use Softwindows 95 from FWB Software, but there are other options as well. In addition, you will need to download the demo version of Finale for Windows from Coda's website. These two pieces of software allow you to test the Windows version of your plugin on your Mac.

Make sure you have installed the Win32 tools from your CodeWarrior disc. They do not install by default.

Creating the Windows Target

My approach is to set up a Win32 target within the same plugin project with the Mac targets. That way they can all share the same source code files.

Create a new target, empty except for the TestExtension source files, Testing.cpp and TESTEDAT.CPP. Set up the Target Settings like those in the Win32 C++ DLL.mcp project. It is located in the Metrowerks CodeWarrior:(Project Stationery):Win32 DLL:Win32 C++ folder. (If you don't use C++, there are corresponding C folders.) You are supposed to be able to open a New project using this as stationery, but every time I try it the system bombs. Opening it directly works fine, however.

This project has a bunch of extra libraries in it. The ones you you need are:

ANSICPPX86.LIB
ANSICX86.LIB
KERNEL32.LIB
Mwctrl.lib
USER32.LIB
ASVAPI32.LIB (for accessing the Registry)

Some settings need to be different than those in the Win32 C++ DLL.mcp project. Here are a couple of key panels containing different settings than those in the canned project.

Note that the file name is now ".fxt" rather than ".dll". Also notice the Heap and Stack parameters. These are copied from the Test.def file that ships with the Finale PDK.

Very important: notice the setting of Byte Alignment to 2. The template project has this value set to 8! If you do not set it to 2, your Windows plugin will not see the Enigma structures correctly.

Gluing Your Plugin to Finale

On the Mac, you simply add the fxmac.cpp file to your project, and that's all you need to do to link back into Finale. On Windows it is a little more complicated. You need three files for Windows. These files are all included in the Mac PDK download.

You can use Test32.def that ships with the PDK as a model for your .def file. You must comment out the HEAPSIZE and STACKSIZE statements and instead set these values in the x86 Target panel of the Target Settings. The name of the output file in the .def file must match the name of the target's output file.

The Fourth Target

With the original Fin98 PDK download, you needed to link with a different libarary to test with the demo version of WinFin98.The library was called findmo32.lib. I found it convenient to create a fourth target that produced the demo version of my plugin with a different name. The only difference between it and the normal Win32 target was that it used findmo32.lib rather than finale32.lib and it had a different .def file with the demo target's name in it instead of the normal target's name.

Coda may be moving away from the dual-library approach. In any case, no useable findmo32.lib has yet been released for the WinFin2K demo. Instead, I created a source file called fxwin.cpp that uses the Win32 calls GetModuleHandle and GetProcAddress to get the callback addresses for the FX_ routines.

At the top of fxwin.cpp I have:

#include <winbase.h>
#include "finextnd.h"

HMODULE hFinale = NULL; //Populated in FinaleExtensionInit. If null, the extension aborts.

inline FARPROC GetFXProc (ECHAR * func)
{
//MessageBox (NULL, func, "calling", MB_OK);
return GetProcAddress (hFinale, func);
}

Following this is a definition for each function in the PDK. For example, the definition of FX_LoadTGF is:

PUBLIC EXTGF * FINEXPORT FX_LoadTGF( CONST CMPER iuList, CONST twobyte staffSlot,
CONST twobyte meas, CONST twobyte layer, CONST tbool mirrorOK, CONST ELONG version /* = FXT_VERSION */ )
{
return CallFF_LoadTGFProc((FF_LoadTGFUPP)GetFXProc("FX_LoadTGF"), iuList, staffSlot,
meas, layer, mirrorOK, version );
}

The code in FinaleExtensionInit that populates hFinale is:

#if OPERATING_SYSTEM == WINDOWS
extern HMODULE hFinale; //defined in fxwin.cpp
hFinale = GetModuleHandle("FINALE.EXE");
if ( hFinale == NULL )
hFinale = GetModuleHandle("FINDEMO.EXE");
if ( hFinale == NULL )
{
MessageBox ( NULL, "Unable to locate FINALE program. This plugin will not be available.",
FINPI_NAME, MB_OK);
return NO;
}
#endif

Resources

The resource file for the Windows version of the TestExtension project is called Test.rc. Be sure to include it in both Win32 targets. Resources are the biggest pain in cross-platform development because the resource scripting languages are mutually incompatible, and you must maintain two separate scripts.

Compiling Your Code

The Finale PDK (at least as of Finale 98) has not been tested when generating Windows code using CodeWarrior. It contains a considerable number of places where it checks to see if the compiler is CodeWarrior and assumes the target must be Mac if so. Furthermore, if the target OPERATING_SYSTEM is WINDOWS, it issues some #pragmas for Visual C++ that cause errors in CodeWarrior. As a result, you may need to make the following modifications to the PDK files. Fortunately these changes are minor and have no adverse effect on the generation of your plug-in code. (Some have been corrected with the Finale 2000 version of the PDK.)

version.h

Both the FinPDK and the Win32 Headers directory released with CodeWarrior contain a version.h. This creates a potential conflict that can nevertheless be resolved by placing the PDK in the User Paths rather than the System Paths. The drawback to this is is that all PDK headers must be #included with "" rather than <>. Fortunately the PDK uses "" almost universally.

Here is an exception in version.h:

#include <win32.h>

must be changed to

#include "win32.h"

You will get a large number of illegal pragma warnings unless you uncheck the Illegal Pragmas option in the Error Reporting panel of Target Settings. However, one of the #pragmas in version.h then produces a syntax error:

#pragma warning(disable: 4001 4135_4018 4706 4010 4127)

You can safely comment out this #pragma.

#define STRICT

must be changed to

#ifndef STRICT
#define STRICT
#endif

DllEntry.cpp

DllMain() has a parameter that is not referenced in the body of the routine. CodeWarrior complains about this, so I commented out the parameter name. CodeWarrior's approach to DLL initialization is quite different than that of Microsoft Visual C++, which is what Coda uses for Windows development. This DllMain() function will not be called unless you precede it with the following prototype:

extern "C"
{
BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved );
}

I recommend copying DllEntry.cpp to your own location and making the change there. That way you will not be dependent on changes in the PDK.

Test.rc

#include <appinfo.h>
#include <ver.h>

must be changed to

#include "appinfo.h"
#include <winver.h>

If you are still having problems, please do not hesitate to contact me.