Friday, September 5, 2008

The Battle of Squawk

Last week was mostly setup, so nothing exciting happened. Lots happened this week, so I'll report on that.

We picked up this week knowing the following:
  1. Squawk vaugely supports POSIX-compliant systems.
  2. VxWorks uses the GCC toolchain to compile programs
  3. VxWorks is (supposedly) POSIX-compilant.
So, our goal was to get Squawk to run on VxWorks. That's not as easy as it sounds.

Step one was to tell the Squawk builder about VxWorks. It needed to know things like the endianness of the platform and where the toolchain lives. This would have been completely trivial, except that VxWorks has to be difficult. Instead of naming the gcc compiler gcc, it's ccppc. I'm pretty sure that calls some other tools, but for our purposes, it just needed to compile code. So instead of just extending the GCC Compiler class, we needed to override getToolsDir, compile, and link.

Okay, so the build system knows about the VxWorks compiler. All set, right? Not at all. The build system also needed to know about the VxWorks platform (things like what the executable extension was) and had to be told how to create a VxWorks compiler.

After much tinkering, mostly with tool paths, the builder ran. So, what's the first thing I do? I try running it. That was a huge failure. The first file had more than 100 errors all having to do with an invalid '*'. Turns out that problem was caused by the builder using the JDK's libraries on the include path. This would be harmless if we weren't trying to cross-compile. So, back to the build system to remove those include paths.

That fixed the '*' error, but then the type 'jlong' wasn't defined. Of course, it was defined in the same file that was causing the '*' errors. The solution to that one? Get rid of everything but the typedefs, and copy the offending header file to the platform-specific include folder (psif when I need to talk about it again).

Good, that fixed a lot of the errors... Except:
"Cannot find malloc.h". Seriously? Why not? VxWorks can't be helpful at all. Everything defined in malloc.h? Yeah, that's in memLib.h. So, wrapper file for that, and into the psif it goes.
"Cannot find sys/time.h". Everything has a sys/time.h, so I look at the include folder from VxWorks. There's a time.h (not in a sys folder), so that must be it. Drop that in, and... fail. There's no struct timespec defined. Why is this? Turns out there's time.h and sys/times.h. I needed the second one. Luckilly, this was only included in one of the platform-specific files, so a quick swap of the include saves the day.
"Cannot find netdb.h". This one was stupid. The netdb.h file isn't in the default include paths. It's stored in some other place, because apparently no one on VxWorks needs networking by default. But to add an include path... I have to change the builder.

That solved the missing files. What's left?
dlsym - This function gets used by Squawk when it needs to call a C function from Java. VxWorks happily defines the prototype, and doesn't implement it. It also has it's own symbol table that it uses. Add a wrapper function for that, and cross another error off the list.
open - VxWorks has an open function, but it takes 3 parameters instead of 2. Trying to add a wrapper resulted in complaints about it already being defined. My solution? Make it a macro. Now I have an open macro that calls the open function.

Finally, we have a build that works. Except the linking fails. Why does the linker fail? It doesn't need to do anything special, and it wasn't missing libraries. Well, I had accidentally left in a couple of the normal GCC linker options, and ccppc didn't like them. I think it was the -ldl option that broke it. Removed those, and... success! I have squawk.out and squawk.suite files in my working directory.

How do I get them onto the test system?

FTP makes the most sense. Let's try that. They can go in the system folder with all of the other .out files. Easy enough. Now, how do I run them? sp "squawk" failed epically, so I resorted to using the WindRiver Workbench to load up the file and execute it.

Did that work? No, of course not. We have this incredibly unhelpful exception detail (like pointers to memory unhelpful), and attaching a debugger gives me assembly code. After some Googling, I find the problem. VxWorks doesn't support argv/argc correctly. VxWorks has this clever solution where if your program needs three parameters, you have to write main(char* param1, char* param2, char* param3). Why can't these things ever be simple? Now Squawk has its own entry point for VxWorks (it currently only takes one argument) that maps the unhelpful variables into argv/argc.

So we're finally up and running... Sort of. squawk -X will happily give you usage instructions, but squawk com.sun.squawk.Test fails. Why? First, because it couldn't find the squawk.suite file. This was one of the more stupid things I've seen. VxWorks looks in the working directory for squawk.suite, but the working directory is set when you connect to the COM port and cd somewhere. There must be a way to set it from code, so I'll have to hunt for that. Once it could find squawk.suite, it immediately complained about the endianness of the suite file being wrong (it was generated as a little-endian file, but needs to be big-endian like the C part). We haven't gotten to that yet, so hopefully on Monday we'll have Squawk running Java 'Hello World' programs.

No comments:

Post a Comment