Saturday, October 31, 2009

mingw32, wine, library paths

Here is yet another thing I'm posting here just because Google searches turn up this blog sometimes and it might help someone save some time. Audience is people building Windows binaries on Linux with the mingw32 cross compiler and testing them in Wine. I do this sometimes for work on the Audacity project, which with a few minor modifications builds nicely with mingw32 -- it doesn't work exactly like a VS compile, but it lets me test wxMSW behavior, which is sometimes useful.

So you're running Linux, you've set up a mingw32 cross compiler (on Ubuntu just get all the mingw32 packages), and built some libraries with it. And you've built programs that use those libraries. But all the libraries are installed in places like /usr/i586-mingw32msvc/lib and /usr/local/i586-mingw32/lib. As far as I can tell, as of Wine 1.0, to get Wine programs to see libraries in those locations is to add them to PATH in a registry key. Typically Wine is configured so that your Unix root shows up at drive Z. So run regedit and go to HKLM/System/CurrentControlSet/Control/Session Manager/Environment and add to PATH, for example, ;Z:\usr\i586-mingw32msvc\lib;Z:\usr\local\i586-mingw32\lib (your paths may vary).

You'll also need to install the mingw32 runtime DLL to your Wine, which is usually something like gunzip -c /usr/share/doc/mingw32-runtime/mingwm10.dll.gz > ~/.wine/drive_c/windows/system32/mingw10.dll.

If you don't like having Z: point at root (for some people it's good for Wine to be highly integrated -- others would rather have it as far from their normal system as possible) you can point drives specifically at your library paths using winecfg, or other similar tricks. Symlinks from within ~/.wine/drive_c might be another appealing option.

Monday, October 5, 2009

Perl and JavaScript

I made a comment in my last post that I thought deserved more comment: "here, as usual, doing it right means doing it like Perl". I do like Perl a lot, but I came to it quite late in the game. In the beginning it wasn't much better suited to writing large programs than bash.

For a long time, C required that all variable declarations go at the top of a block. PHP, well, PHP is still a ridiculous mess, but it's getting better. To quote Pat V., "It's painful to watch PHP make all the same mistakes Perl made 10 years ago." C++ compilers still have some compatibility issues, but even a young guy like me remembers a time when it was even worse, where many compilers barfed on simple template code and the STL was slow and unreliable in many installations. And I can only imagine those poor early Lisp programmers that had to use S-expressions for everything... OK, scratch that last one.

All these languages had the freedom to get better. The programmer that wanted better features could get a new compiler or interpreter; the one that wanted his old code to work could stick with the old version. The language developers could break compatibility and improve the language because programmers had this power. The programmer didn't have control of processor or library bugs on user machines, but those things are usually taken pretty seriously. Adoption of better web standards can take a lot longer, and as long as old browsers are still around they have to be recognized and coded to. About all you can do is add. It wouldn't be hard to give JavaScript variables block-level scope and extent, but it would be really hard to get that adopted.

Sunday, October 4, 2009

Enlighten me on JavaScript

I am learning JavaScript because it will likely be a useful language for me in the future (it is a very popular language, and since I don't really want to move back to Silicon Valley it's hard to find jobs using languages I like). And there are things I just don't quite understand about the way it was designed, both about the language and about the DOM. I am open to the fact that there are things I just don't know about; I'm just a beginner. If anyone has good answers to any of these (meaning ways to make programming simple things as easy as they should be), let me know.

1. Why did they make the string concatenation operator the same as the numerical addition operator? In C++ using many string classes they're the same. But in C++ variables have types, so you know exactly what you're getting by looking at the types. In Perl variables don't (usually) have types, but the set of operators for numerical and string operations are completely different, so you know exactly what you're getting by looking at the operators. In JavaScript if you aren't sure what your variables' types are you have to do coerce them (unary + and concatenating an empty string are the easiest ways I know of). It's ugly and inconvenient, so people aren't as careful as they should be, and it bites them.

And, yeah, I have some idea why they may have done it. They wanted to keep all the C-style operators intact, and they use up so many symbols that you have to overload them. I don't think it's all that good of an excuse. It's nice that C-style syntax is familiar to lots of people, but honestly, who cares about bitwise operations in JavaScript? Few enough people that they could have just been made functions. As a C programmer learning JavaScript, trust me, it would not have been an obstacle to my learning the language.

2. How do you "pass-by-value" into anonymous functions? Yeah, closures are wonderful, in some unusual cases. But what if I want to just use the value? This is arguably more common than actually wanting a closure; for example, when creating anonymous event handlers that use the iterating variable of a for loop. To do this relatively simple thing you can create an external function taking the values as arguments and returning a function enclosing the copied arguments. Or you can use (function(a){return function(){doSomethingWith(a)};})(i). Which is, as Geordi La Forge says of Data's poetry, "clever". What it isn't is readable or easy to understand. Especially when so many of the people writing JavaScript aren't CS majors.

EDIT: One more note about this. This would seem to be a general problem in languages with closures, but it's not really so bad in some others. I don't know most of the languages that seem to generate most of the closure chatter (Lisp, Python, and the .NET languages) well enough to quickly test this, but I do know Perl, which does indeed have closures. Perl's lexical variables have block-level scope and extent, so you can enclose the iterating variable's current value by declaring one within the loop and using that in your anonymous function. JavaScript only has function-level scope/extent, so you can't do that -- you have to replicate the functionality with an immediately-executed anonymous function. Kool-Aid drinkers say it's a testament of JS's flexibility; I say it's a pain in the ass. As for the other languages, the Internet knows! Reportedly modern VBScript has block-scope variables with function extent, which strikes me as bizarre; C# does it right (here, as usual, doing it right means doing it like Perl). Python doesn't have block-level scope, and Lisp lets you have any kind of scope/extent you want; a let variable would give you what you wanted as long as the let was inside the loop. C and C++, of course, do it right, but they don't have closures. So it's a mixed bag.

3. Using the nice, proper DOM event functions, how do you replace one anonymous event handler with another? Why, addEventListener and removeEventListener, of course! But removeEventListener requires a reference to the handler you want to remove. So all those nice anonymous ones I just created? Useless. I have to keep track of them. It's nice that this makes it really easy to have multiple handlers for every event. But, again, that is an unusual thing to need. They've taken care of the unusual need and not the normal one. Yeah, there's the older onclick style, but I'm pretty sure it's deprecated now.

4. Why is there no call to clear all the children of a DOM node? Instead you have to write your own loop for it. It's not hard to write but it's a waste of time and an opportunity to make mistakes.