Compiling the C30 gcc compiler on Mac OS X (Leopard)

UPDATE July 23, 2009: I’ve added a build transcript to the tarball so that you can compare your build output to mine, and also added the full path to sed in the script. Get it here.

I switched to Mac a couple of years ago, but still find myself dependent on MS Windows for electronics and embedded software development. Fortunately more tools are getting available for Linux and hence Mac as well, which is good (AVR tools are a great example).

This week I’ve been fiddling with a dsPIC33 device from Microchip. It works fine in MPLAB (apart for the occasional crash or USB hang for the programmer) but I get tired of having to work with MS Windows. So I started searching for a C30 compiler for Mac. Unfortunately, I haven’t found (a free) one yet, but I discovered that the MPLAB C30 compiler is actually based on the gcc compiler, so it should be possible to make it work on OS X.

Microchip has published the gcc and binutils source code on their website (which they have to do due to the GPL) so that’s an easy start. After some googling I also found the debian packages made by John Steele Scott.

Compiling gcc and using the patches from the debian packages made me come close to a working compiler, but not completely. These were the problems I still had to address before getting a working compiler:

  • binutils: I got configure errors due to the fact that conftest.dSYM directories were left in the way. Apparently this is due to a new default option with Xcode when compiling with debug option on. To fix it I would have to regenerate the configure files with a newer autoconf/automake.  Instead I solved it by compiling without the debug option (removed -g from the CFLAGS).
  • gcc: at startup gcc would crash in some internationalization init code. I solved this one by compiling with –disable-nls, which disables the internationalization in gcc. I think I can do without compiler warnings in dutch…
  • gcc: crash at startup in some default library path juggling code. I found out that gcc would start up without crashing when I moved it out of the install directory. Fixed it by patching out the offending code.
  • gcc: at install it would put double target strings in executable names (like pic30-elf-pic30-elf-gcc), fixed with an extra sed command after installing.

The build script and patches are based on version 3.10 of the compiler and binutils.

Download the build scripts and patches tar ball here.

Make sure you read the README file, it contains more info than written down here.

To build, you’ll need to do the following:

  1. Unpack the tar ball in a suitable location.
  2. Get an installation of MPLAB C30 on a Windows machine. Find the MPLAB C30 directory in the MPLAB installation directory and zip it. Make sure the resulting zip file is named “MPLAB C30.zip” and copy it to the same directory as where the build script is located.
  3. Download mplabalc30_v3_10.tar.gz (binutils) and mplabc30v3_10.tar.gz (gcc) from the MPLAB website. Look for the C30 compiler and then archived versions. Put the two tar.gz files in the same directory as where the build script is located.
  4. Run the build script. It will unpack, patch, compile and install the files into the directory “install” (residing in the same directory as the build script).
  5. Review the installation in the install directory. Now you can do three things: a. add the install directory to your path and call it a day, b. manually copy everything over to another place or c. change the PREFIX variable at the top of the build script and run it again (maybe you’ll need to sudo depending on the permissions in the PREFIX directory)

Now the next challenge will be to incorporate it into Xcode…

Tags: , , , ,

20 Responses to “Compiling the C30 gcc compiler on Mac OS X (Leopard)”

  1. Leo Says:

    Hey, thanks for posting this. I tried out your instructions but a crash dialog came up while building the GCC toolchain. Nonetheless, the build script runs through to completion. However, any time I try to run the compiler it says things like this:

    main.c:1: error: Invalid -mcpu option. CPU 30f3013 not recognized.

    no matter what value of -mcpu I pass in.

    Here is the contents of the Crash Reporter dialog box:

    Process: as [10915]
    Path: /opt/pic-mac/install/pic30-elf/bin/as
    Identifier: as
    Version: ??? (???)
    Code Type: X86 (Native)
    Parent Process: sh [10914]

    Date/Time: 2009-01-10 21:41:54.951 -0500
    OS Version: Mac OS X 10.5.6 (9G55)
    Report Version: 6

    Exception Type: EXC_BAD_ACCESS (SIGBUS)
    Exception Codes: KERN_PROTECTION_FAILURE at 0×0000000000084318
    Crashed Thread: 0

    Thread 0 Crashed:
    0 libSystem.B.dylib 0×9471a7c4 strcpy + 52
    1 as 0×0006c95b process_resource_file + 59
    2 as 0×0006d012 pic30_update_resource + 258
    3 as 0×0003c30d bfd_init + 29
    4 as 0×00004ae7 main + 183
    5 as 0×00001dd6 start + 54

    Thread 0 crashed with X86 Thread State (32-bit):
    eax: 0×0000002f ebx: 0×0006c28b ecx: 0×00084327 edx: 0×00000008
    edi: 0×00084318 esi: 0×00084335 ebp: 0xbfffeec8 esp: 0xbfffee88
    ss: 0×0000001f efl: 0×00010206 eip: 0×9471a7c4 cs: 0×00000017
    ds: 0×0000001f es: 0×0000001f fs: 0×00000000 gs: 0×00000037
    cr2: 0×00084318

    Binary Images:
    0×1000 – 0×85fe7 +as ??? (???) /opt/pic-mac/install/pic30-elf/bin/as
    0×8fe00000 – 0×8fe2db43 dyld 97.1 (???) /usr/lib/dyld
    0×906dd000 – 0×906e1fff libmathCommon.A.dylib ??? (???) /usr/lib/system/libmathCommon.A.dylib
    0×946ef000 – 0×94856ff3 libSystem.B.dylib ??? (???) /usr/lib/libSystem.B.dylib
    0×95815000 – 0×9581cfe9 libgcc_s.1.dylib ??? (???) /usr/lib/libgcc_s.1.dylib
    0xffff0000 – 0xffff1780 libSystem.B.dylib ??? (???) /usr/lib/libSystem.B.dylib

  2. admin Says:

    Hi Leo,
    Looks like something didn’t build correctly on your system. What crash dialog did you see when running the build script? Or better:
    would you be able to do a complete build from scratch with the build script, and send its output to a file, like this:

    ./build >& build.out

    and send the build.out file to me?

  3. Leo Says:

    I’ll try that next. Meanwhile, I got it to build by skipping the patches that change the search paths for .h and .inc files. I am mostly using the default support directory layout from Microchip’s C30 distribution. As far as I can tell, everything is working except for lines inside linker scripts that look like this:

    OPTIONAL(-lp33FJ256GP710)

    This line appears to instruct the linker to include the library that contains definitions of functions from uart.h, etc. The linker complains that this directive is a “syntax error.” If I comment out that line in the linker script and manually add the flag “-lp33FJ256GP710″ to my invocations of pic30-coff-ld, then my builds work.

    Do you know why the linker would complain about that linker script directive?

  4. bas Says:

    Leo: now that you mention it, I recall having the same problem with the linker script as well.

    if you include the pic30-rules.mk file in your Makefile (see makefile_example) it will automatically add the “-lp33FJ256GP710″ (depending on the processor you mention in your own makefile) so I didn’t bother looking into it.
    The OPTIONAL keyword is not mentioned in the gnu documentation for the linker, so maybe it is something Microchip added in their Windows version? I don’t know.

  5. Leo Says:

    It appears the trick is that you have to ‘touch’ all of the .y and .f files in the “acme” directory before building binutils. Once you do this, pic30-ld will recognize those linker scripts. I appear to now have a fully functional C30 toolchain, using a stock “support” folder from the MPLAB C30 distribution. I’ll try to clean up what I did so I can send you the modifications I made to your build script.

    I’m very grateful for the instructions you posted. I have been using C30 under Wine for some time, and though it was very reliable it was also very slow. It used to take several minutes for me to build the firmware on the device that I am working on; with the new toolchain I built it takes about two seconds (on a MacBok Pro, 2.16 GHz Intel Core 2 Duo).

  6. bas Says:

    Ah! The acme directory! I did touch the .y files in the gcc build, but forgot to do that in the acme build!

    Thanks for finding this. I’ll update the script. I’m curious to see what other changes you made for building!

  7. Antoine Says:

    Hi.

    Thanks a lot for your effort, this is much needed!

    I happen to have the same crash than Leo (first comment), what ever I do. Simply calling “pic30-elf-as” leads to the crash, with similar log. “pic30-elf-gcc” seems to rely on pic30-elf-as, and thus wont work (indicating that pic30-elf-as crashed).

    Any idea how to fix that?

    Thanks a lots
    Antoine

  8. bas Says:

    Hi Antoine,

    Did you follow the build script exactly or did you make changes for your own setup?

    Can you try again from scratch and send me a log of the build?

    (like above:

    ./build >& build.out

    and send me the build.out file)

    Thanks!

  9. Leo Says:

    How do I attach a file to this page? I want to send my build script.

  10. Antoine Says:

    bas,

    I’ve followed pretty much exactly your instruction for the build. I’ll send you an email asap with a log and further details on what breaks.

    Thanks again for your efforts!
    Antoine

    @Leo: I guess you can use the email address at the bottom of this page

  11. bas Says:

    Based on the feedback from Leo and Antoine (thanks!) I’ve updated the build script in the tar ball. Click here to get it (same link as in the text above).

    I’ve added a command that touches all .y and .l files in the binutils before building, so that the lex and yacc scripts will be rebuild, and I’ve added a

    --disable-nls

    option to the configure script of binutils (appearantly not only gcc suffers from this problem, but also binutils). This avoids a failing linker binary for users with different locale settings/libraries than me.

  12. Antoine Says:

    “Side side note”: the RSS feed for these comments does not seem to work. It’s a shame, because I would not want to miss anything :)

  13. Leo Says:

    It appears that the GNU license permits redistribution of this compiler in binary form. Would it be legal to distribute a Mac OS X installer for pic30-gcc and binutils? I don’t see any reason why not.

    The standard library, headers, and linker scripts would have to come separately, of course. That wouldn’t be a big problem because any user that has any kind of license, whether the full professional version or the free educational version, for Microchip C30 has a copy of the standard library already.

    I have been using Xcode with SCons for cross-platform embedded development for about a year. However, I see no reason why one couldn’t use Xcode directly for building PIC30 projects. Xcode should be able to parse debugging symbols from C30 object files, for auto-complete.

    I am tempted to take a stab at a set of Xcode project templates for C30.

  14. Leo Says:

    Here’s a page that has some info on how to put together Xcode plugins:
    http://maxao.free.fr/xcode-plugin-interface/index.html

    However, the compiler spec appears to be outdated. For one, the “.pbcompspec” files that they talk about are replaced by “.xcpsec” files in Xcode 3. Some reverse engineering would be required to make an Xcode plugin for PIC30.

  15. bas Says:

    Sounds like a nice plan!

    Until now lack of time has held me back of trying to plug it into Xcode (I’m using textmate right now).

    Now if we could implement remote debugging via Xcode, that would be code nirvana :-D

  16. bas Says:

    @Antoine: did you subscribe to the feed linked just above the start of the comments (at the end of the text) or did you use the RSS icon in the address bar? The former should track changes to the comments on this page, the latter tracks changes to the blog itself.

  17. Antoine Says:

    Oh. Strangly enough, firefox wont show any content for the feed, but my feed reader (actually Mail.app) shows the correct content. (I was using the correct link.) It’s all fine now, thanks!

  18. Leo Says:

    So I symlinked all the pic30-coff-* executables to pic30-* because my build scripts all use the pic30-* variants. I put the symlinks in a separate directory from the executables. When I tried building my project, the compiler crashed. This was because it was looking for the file “c30_device.info” relative the symlink I made.

    Bas, many of your patches relate to the resource paths and hard-coding them into the compiler. Microchip’s convoluted path parsing code is clearly designed to handle the situation where the whole packing is copied to a folder specified by the user, long after the package was built with “make install”. Is Microchip’s technique for doing this worth keeping? Someone should try moving the base folder of their pic30 installation and see if it still works. If it does, then Microchip’s relative paths might make creating an installer much simpler.

    Also, I realized that my patch for the file “c30_resource_paths.h” was only necessary because in Microchip’s distribution there are two copies of the .gld and .inc files: with the assembler and with the compiler. There are two ways to handle this: 1) modify the toolchain’s hardcoded relative search paths or 2) symlink/copy resouces the the appropriate locations so that the directory layout is identical to Microchip’s. Which would be preferable?

  19. bas Says:

    That’s right, the resource path handling leaves a lot to be desired.
    The resource path stuff built by Microchip is probably targeted towards the windows platform, and probably not tested for unix like file systems, hence the crash.
    Anyway, my goal (and others, who actually made the patches – I just copy pasted mostly) was simply: ‘make it compile, get it to work’. Hence the shortcut taken by hardcoding the paths during the build process.

    I think resolving this with symlinks feels a bit like a ‘last resort’. It would be better to fix the relative resource path code and include a couple of standard places where to go look for resource files (and gracefully fail if not found rather than crash). Those standard places should follow the way Apple organizes resource paths (for example for iPhone, or find out how it was done for the AVR gcc compiler).

  20. LnddMiles Says:

    The best information i have found exactly here. Keep going Thank you