Sunday, August 19, 2012

Ruby on OS X

A few weeks ago I decided to try (once again) to learn Ruby and Rails.  In the past, I never got far in this endeavor, on account of getting confused and/or bored. This time, I haven't gotten far because I haven't been able to get the damn language working the way I need it to.

Allow me to elaborate. I am using several pieces of dated but still useful reference material.  The good thing is that they were all published around the same time, meaning they all use the same (or similar) version of Ruby, Rails, and Rubygems.  The bad thing is that all of these tools have received major upgrades in the years since.  Version mismatches usually lead to incompatibilities, and sure enough, the commands listed in my Rails book are flat out broken when used with Ruby 1.9 and Rails 3.  I needed the old stuff, and I needed it configured properly.

My quest to to achieve this perfect development environment was a monumental pain in the ass, redeemed only by the fact that it taught me a ton about Ruby, the Ruby community, and the innards of OS X.

My first major hurdle came while trying to compile Ruby 1.8.5 from scratch.  It turns out that as of Mountain Lion (or maybe Lion, I forget), OS X has no pure version of GCC.  It's all LLVM, with either a Clang or GCC front end.  Suffice to say that only the most bleeding edge version of Ruby compiles nicely with these tools.  Everything else simply craps out at one point or another.   At this point, I decided to look for some alternatives.  RVM is a popular tool for managing different versions of Ruby, so I tried to give it a shot.  It failed spectacularly.  Unbeknownst to me,  RVM installs different versions of Ruby by compiling them.  Obviously it failed just as hard, no matter which version I tried to install.

I went back to the Internet to look for solutions.  The most common suggestion was to install Apple's pre-Lion version of GCC4.2 using Homebrew.  I don't like Homebrew (or Macports or Fink), and I wasn't excited about using it just for the compiler I needed.  So instead I found a wonderful guide to building GCC from scratch on OS X.  The instructions worked perfectly, and they left me with a working, up to date compiler that was installed to a sane location.

I didn't know it yet, but at this point, I had all the tools I needed to get Ruby up and running.  Yet I still struggled when building from source.  One issue is that the Ruby source has some glaring issues (at least in version 1.8.5).  For example, I found one file that had #define where it needed #defined,and another which tried to pass a const char* to free() (which, at least on my system, requires a void* argument.  Then there was the file which defined two constants which already existed in OS X's version of stdlib.h.

The second issue was getting make to use my hand build version of GCC.  It was easy enough to put it on my PATH, but that wasn't enough.  Some parts of Ruby's build process use the generic
cc command, and on OS X this is a symbolic link to /usr/bin/clang.  I only discovered this last part today.  A week ago, I had what looked to be a working version of Ruby which failed to install gems.  When I googled the error messages, all of the hits were concerning the aforementioned issues with compiling Ruby using LLVM and Clang.  I kept thinking "but I'm not using them.  I have GCC4.7.  I can see that it's being used by make. "  Only it wasn't being used by make. At least, not during the entire build process.  When I finally changed the cc symlink, the build finally succeeded.

Just kidding.  It failed again.  For whatever reason, several of the modules in the ext/ folder of the source tree had empty Makefiles.  I'm still unsure as to how this happened, but the issue went away after running make distclean, and then another make.  This time, I had a fully working copy of Ruby 1.8.5.  After that, everything fell into place.  Rubygems. Rails 1.2.  It's all working fine, as do the book examples.

At first, my takeaway from this ordeal was that Apple was doing a fine job fucking up OS X as a legitimate environment for programmers. By the end of it, my tune changed.  I still don't like the loss of GCC (and now I won't have to worry about it either), but if FreeBSD can get their system running with Clang and LLVM, I hesitate to say that either tool is a problem.  Rather, the issues seemed to stem  from the way Ruby is/was written.  I'm not saying it isn't worthy of being used in production environments, but I don't expect (and don't encounter) such sloppiness in any other major programming language.

I also learned a lot about the Ruby community.  Specifically, I decided that the concept of "convention over configuration" espoused by Rails developers extends into the community at large.  Did you know that RVM will change the way the cd command behaves on your system?  Even if the change isn't problematic for 99.9999999% of users, it is still something I'd like to be told about at installation.  I also grew frustrated at how so many of the proposed solutions to my problems boiled down to using a tool that would automagically download and configure the tools I needed in order to build and install the tools I wanted to use.  In other words, they wanted you to paste a few commands into a shell and hit enter, regardless of whether or not you knew what it would do to your system. To be fair, this isn't exclusive to the Ruby community, but I grow tired of it in general.

Don't worry though; I still have a Ruby specific gripe.  Before I installed Rubygems, I had a sneaking suspicion that the latest version would not be compatible with old versions of the language.  This is in fact true, but good luck finding this information out on the Rubygems homepage.  It may very well exist, but the only place I found the answer was an old question on Stack Exchange. Without that hunch, who knows how much more time I would have spent struggling.

Ruby'ers - I get it.  I really do.  Configuration sucks.  It's boring, error prone, and compared to writing actual code, is no fun at all.  But dammit, sometimes it's necessary.  If you ignore configuration, you will have no idea where to look when something goes wrong.  And despite the fact that these languages and frameworks ask us to trust them, they can and will make mistakes.  The only way to deal with them is to know what the heck is going on in the first place.

Sunday, August 12, 2012

Core Image Fun House on Mountain Lion

All in all, I'm torn on what I think about OS X Mountain Lion.  If I'm lucky, I'll write a more detailed post explaining my personal pros and cons, but this post has to do with one of my biggest cons - the loss of Core Image Fun House (which I just wrote about in my last post).

The problem stems from Xcode 4.4.  It seems that Apple made some major changes to the IDE since the last version I had, including removing the /Developer folder, which was where Fun House, along with several other utility apps, resided.  The other utilities were retrievable through optional downloads from Apple's Developer site, but none of them seemed to contain Fun House.  I scoured Google for some sort of answer, and was able to confirm that it is, in fact, not being offered with newer versions of Xcode.  I still have no idea as to why, nor have I found anyone else who's wondering where it went (which was a reminder that the Internet doesn't always pounce upon every single change in the state of the world).

Thankfully, I did manage to find a solution. Fun House is an incredibly simple program, and it looks like Apple used to include it as sample code back with Leopard.  The code is still archived, meaning you can build it yourself a fresh copy of the executable.  Here are some general steps on how to do so:

1) Download the source code from the above link (look for the button labeled "Download Sample Code").

2) Unzip the archive, and open the project in Xcode (you should just be able to select File -> Open and open the folder itself).

3) Once the project is opened, it isn't runnable right away.  If you're on Mountain Lion, you're going to have project configuration errors to resolve.  If you click on the yellow exclamation point in the top-center of the IDE, it should bring up a list of errors in the left hand column.  Here's an image of what you should be seeing:

4) Double clicking on the second of the two errors will allow you to fix the settings.  You'll get a popup stating all of the changes Xcode will make.  It will look like this:
Click "Perform Changes".  If you get a message about enabling snapshots, choose whatever option you want.

Once the changes are made, the code should be runnable, with one final caveat. You have to run Fun House as a 32 bit app, rather than 64.  Most likely it'll be set to 64 bit by default, and you'll need to change that. In the top left corner, near the run button, you should see the something labeled "Fun House -> something something 64-bit".  Click on this to change it to 32 bit.  Then you can hit the run button.  If all goes well, Core Image Fun House will launch.

If you get a successful launch, you can move on to the final step - creating a .app file that you can run when you're not in Xcode.  In the left hand column, if you select the little folder icon, you'll get a resource view of your project.  Under the products folder, you should see the .app file.  Right click it, select "Open in Finder", and you can then copy the file to wherever you'd like.

Tuesday, July 24, 2012

Changing Icon Colors


Recently I was looking for a way to change the color of an application's icon in OS X.  The idea I had was to run two separate instances of Eclipse - one for Android development, and one for other work (this is probably unnecessary, but I've already done the work).  In order not to confuse the two instances, I wanted to change the color of the Eclipse icon, so that the Android installation would be colored Android green, to tell them apart.  The only trouble is that I'm terrible with anything related to graphics or image processing, so a I had no idea where to start to make this idea a reality.

Fortunately, I stumbled upon the solution.  If you install the OS X developer tools, you get a program called Core Image Fun House.  You can use it to apply all sorts of effects to an Icon (.icns) file, including changing the color.  Here's what I did:


  • Find the folder where your Eclipse installation is.
  • Right click on the Eclipse.app file and choose "Show Package Contents".  Now you'll be navigating within the package, to get into the guts of the application.
  • Open the "Contents" folder, then the "Resources" folder.  You should see a file named "Eclipse.icns".  That's your icon.  Make a copy of it somewhere, and open the copy up in Core Image Fun House.
  • Core Image allows you to add filters to the icon in question. Click on the plus sign in the "Effects Stack" menu to bring up all the filter options.  Under the "Color Effect" section, you should find a filter called "Color Monochrome".  Apply this filter, and you'll see a color picker in the Effects Stack menu.  Use this to change the color of the entire icon.
  • When the icon looks right, go to File -> Export.  Choose a name and a save destination.  Lastly, change the file type from "JPEG Image" to "Apple Icon Image".
  • Take the newly saved .icns file and drop it into the resources folder of the Eclipse package (this will overwrite the original, so you may want to make a backup of it first).  If you do it right, OS X will recognize the new icon and replace it just about everywhere (you may have to add a new copy of the icon to the dock, if you have a permanent dock icon).

Saturday, June 23, 2012

Android Development: How to get GPU Acceleration for your AVDs

I was quite excited when I first read the news that the Android Emulator now supports using your PC's GPU for better graphics performance.  Trouble is, the aforementioned announcement doesn't contain any information on how it works.  I only discovered the answer thanks to Google's revamped developer site, wherein I stumbled across an emulator setup guide I had never seen before (I'm assuming that it actually was there before, and that it isn't a brand new page.  I could very well be wrong on that).

Anyway, the answer is found in the settings page for your virtual device. In the hardware section, you can click "New", and choose the "GPU Emulation" property.  Set it to yes, and your graphics card will be put to work (provided it is supported; I'm not sure how well it works in all environments).

Click the 'New' button in the 'Hardware' section, and you'll be able to add GPU emulation as a property (It's shown at the bottom of the property list here).
So far, the results are impressive.  The virtual device still takes a while to load up (though not as long as it did when I first tinkered with the SDK, years ago), but once it's on, it is very smooth and responsive, enough so to make it worthwhile for testing.  This could make it much easier to test future projects on multiple device types.

The guide above also explains how to configure Virtual Machine acceleration, using the VM extensions  supported by modern processors.  This is another welcome feature for improving emulator performance, but it looks more complicated to setup.  Namely, you have to enable the VM extensions for your CPU via the BIOS, and install extra virtualization drivers.  The drivers are the real showstopper, as the guide warns that they can conflict with the drivers for other VM software like Virtualbox.  The fix is to only enable one set of drivers at a time - this is easy enough in a *nix environment, but I'd have to go and find out what Vitrualbox installs.

Once you've got your drivers under control, there's one last caveat; to use VM acceleration, your virtual device has to be running an x86 CPU, rather than the traditional ARM chip.  This isn't really a problem - Intel has already put out an x86 based phone, and the support is there.  You just have to remember to take the extra step, because these AVDs go to ARM by default.

If I dip my toes into this CPU virtualization, I'll come back here with my findings.

Sunday, June 17, 2012

Notepad App: The Rest

With the Scratchpad finished, the next step was to get the regular notepad functionality working.  Since I already had a working example, all I had to do was fit it into my existing codebase.  This turned out to be fairly easy, and I had a half-working example after no more than an hour's work.  Getting it working well was another matter entirely.

For one, the text on the main screen was small, and only the text itself was responsive to touch input.  If the title of a note was small, it was almost impossible to open (and if there was no title, it was completely inaccessible).   This fix taught me just how important it is to understand the built in Android layout rules.  The "wrap_content" rule, for instance, can be a bad choice for setting the width of a view. So can "match_parent" if you aren't aware of what the parent view's width is set to.  This is yet another area in which blindly following sample code can get you in trouble, when all of a sudden your GUI is lined up all wrong and you don't know why.  I ended up re-evaluating the width and height of every View in every XML file in the app, since this forced me to justify each and every setting.  By the end, I had everything looking the way I wanted it, and more importantly, I understood why.

My initial porting attempt also broke a small (but handy) feature from the sample Notepad app; if there were no saved notes, a special "no notes" message was displayed instead.  In my app, however, this message was displaying even when there were notes present.  It turns out that this feature requires your app to be designed in a very specific fashion, which happened to be the case for the sample app, but not mine.  Specifically, the Activity in question needs to:

  • Subclass Android's ListActivity class.
  • The layout file associated with the Activity needs to contain one ListView and one TextView, and they must be id'ed using two of Android's standard View names - "list" and "no_notes".

Looking at my app, I knew that my layout file used different id names, and that my class only extended  Activity. An easy fix to be sure, but there was another problem - could I still cram the Scratchpad 
button onto the page?  If I added it to the layout file, would it display?  And even if it did, would the ListActivity accomodate the code responsible for handling click input?

The answer to both of these questions is "yes" and "yes".  By using a ListActivity, you benefit from having a built-in ListView object to use, but you aren't married to it.  Remember that you can technically associate any layout file to a ListActivity.  It helps if some of the Views defined in the layout are structured in such a way to work well with the class, but even then you can still add more on top of it.  Then, once you add extra buttons and gizmos, you simply write a click handler for each one. For me, this translated into an extra layout entry (for the Scratchpad button), and a single, small click handler.  Nice and easy all around, and I learned a ton about how views and activities relate to each other.


After that, it was just a matter of making a few final touch ups, such as having the cursor appear at the end of the title when opening a note, and giving notes a default title when none is entered. All told, this phase of the work took almost as long as the last, but I got far, far more done.

I'd like to end this entry with a list of additional lessons learned.   All told, this was a very rewarding experience, and I feel more motivated than ever after achieving this small success.
  •  For the first time, I used version control on a personal project.  I'm using git, as I'm used to it from work, and it worked like a charm.  When I tried to refactor the app to use a ListActivity, I created a new branch: it was nice to know that, should it not work, I could revert back to a working state.
  • I'm planing on going back to this app at a later date, to make some improvements. Specifically, it could use better error handling, and it would be nice to have more flexible controls for adding/deleting/editing content.  Perhaps even a home screen widget for displaying the Scratchpad.
  • I ran into an issue using StringBuffer; namely, I was trying to reuse the same StringBuffer instance without cleaning it out, so it kept preserving its previous content.  Ideally, what I should have been doing was creating a new object every time, but sometimes I still think like a C coder, and I considered that a waste of memory.  Yeah yeah, there's garbage collection, I know, but wiping the buffer was trivial, and now I feel like I can go to sleep tonight.
  • Next up, a tasks app.  It'll be far more complicated, but even more useful too.

Saturday, June 16, 2012

Notepad App: Scratchpad

I've finally a useable part of my personal app.  The Scratchpad function is working fully.

I made a serious mistake when working on this part, by trying to store the Scratchpad data in a SQLite database.  Such a DB makes sense when you are storing multiple notes, but the Scratchpad is just one big note, a text dump for storing quick thoughts that I don't want or need to create a full, separate note for.  There's no need to wrestle with database queries and row integrity.  I lost several hours struggling to get things working, to the point where I almost gave up.

Thankfully, I sat back down and researched alternative storage methods.  After all, this kind of data could easily be stored in as a text file, and as it turns out, Android has tools for doing this.  You can create storage files that are viewable and readable only by the app itself.  Using this technique, I got the Scratchpad working very quickly, and while I am happy it works, I'm also more frustrated with the fact that I'll never get those wasted hours back.

This reveals a major flaw in my skills as a programmer.  I rely on sample code too much, to the point where it holds me back.  I needed to store data; what I should have done is look through the reference documents for ways to do this.  Instead, I looked through the samples I had previously read through.  Since all of these samples were dealing with ListViews, they all used SQLite tables.  It wasn't the only storage choice available, but it was the only one I was exposed to.  Thus my tunnel vision set in.

The other problem with using sample code is that sometimes the only thing it can teach you is how certain parts of the API work within the context of this specific example.  Unless you can read the code and understand how to use a featured method  in any given situation, then you don't really understand how to use it.  If you then proceed to copy and paste that code into a completely different context, what will you do if it breaks?  Scramble, of course, because you don't know enough about how it works.

I made these mistakes with the Scratchpad, and for my own sake, I need to learn from them if I am to get the remainder of the app completed without experiencing this level of frustration.


The Moral of the Story: Use sample code to get a feel for how a complete program reads and flows.  But when it's time to do something yourself, figure out what it is you want to do, and look through the API to find pieces that will help you do that.  Work with them until you find out what it really does, and if it isn't suiting your purposes, start looking again.  By the time you have a working prototype, you will be able to explain why it works (and if it turns out there's a better way you could have done it, don't worry.  That can come in a new version, when your skills have improved).

Notepad App: Intro

My first attempt at an Android App is to make a notepad application.  As it turns out, the Android sample code has a fully functioning notepad in its sample code folder.  It's simple, but if all you want is to write and save notes, it's perfect.

However, I want to do slightly more than that. Namely:

- I want to be able to write individual notes, with titles, that I can save (this is what the Android sample project already offers).
- I want to have a single, giant note, called the "Scratchpad", which I can access quickly, and fill with quick bits of text.  The point here is not organization, but to allow me to just get things down before I forget.

In theory, this should be a simple job.  Just take the existing example, add a new button on the screen for the Scratchpad, and an additional, super basic text editing window for modifying it.

Let's see just how simple it will be for me in practice. Consider this a developer diary of sorts.