Posts Tagged ‘Objective-J’

Cappuccino 0.7 Now Available

Wednesday, May 20th, 2009

We’re pleased to announce the immediate release of Cappuccino 0.7, the latest update to the Cappuccino web framework. This release has been five months in the making, and it marks a significant step forward for the project.

0.7 By The Numbers

As of version 0.6, Cappuccino had 9 total contributors. Version 0.7 more than triples that number with 29 total contributors. And thanks to the inspiration and hard work of Xavier Noria and José Espinal, we’ve got a slick new website that keeps up to date tallies on all of the contributors to the project. Check it out here. If you find a mistake, be sure to let us know in the comments.

contributors

This release includes over 100 bug fixes, thanks in part to all the new contributors, and to the hard work of users taking the time to file quality bug reports. If you hadn’t noticed already, we’ve moved to github’s new issue tracking for bug reports, so check out the new system, and vote on issues that are important to you.

New Look

aristo

The biggest new feature of Cappuccino is our new new theme: Aristo. Aristo is the new look and feel for Cappuccino applications. Created by the talented designers at Sofa, Aristo is designed specifically to look good in the browser, and in any browser, whether it’s Firefox, Safari, or even Internet Explorer, Mac and Windows. We’ve also open-sourced the PSD file used to create Aristo. All the controls have been updated to use the new style, and we’ve added a few new controls as well, like checkboxes, radio buttons, and segmented controls.

Theming

We didn’t just build one new look for Cappuccino, though. Instead, we built an entirely new theme engine which will let anyone create a theme for Cappuccino. All the properties of the standard controls are fully themeable in all the different “theme states” (like “pushed”, “disabled”, “normal”, etc.). In the coming months, we’ll be sharing new themes with the community, and building a site for users to post their own themes for others to download and use.

Interface Builder

Those of you who come from a Cocoa background are used to using Apple’s Interface Builder tool to layout your Cocoa applications. Thanks to a technology in 0.7 called nib2cib, you can use Interface Builder to layout Cappuccino applications too. All of the classes supported in Cappuccino 0.7 that have Cocoa analogues are included. So, you can drag checkboxes, sliders, text fields, buttons, and lots more. You can even instantiate custom top level objects, or custom view subclasses, which will be converted to the right class in Cappuccino by the nib2cib tool. Once you’re done laying out the UI of your application with Interace Builder, you can use it’s target-action and outlet technology to build up its logic as well.

making a cappuccino application using interface builder

nib2cib is a powerful tool that drastically reduces the amount of code you need to write to build an interface with Cappuccino. The starter package now includes both a nib/xib based application template, and a standard, code based template, so you can choose which is best for you. From the command line you can use the new capp tool to generate a nib/xib project by typing “capp gen -t NibApplication MyApp”.

The Rest

As if that wasn’t enough, there are a lot more changes. First off, improved support for debugging in Cappuccino and Objective-J, thanks to some contributions to WebKit. For more details, see Francisco’s post on the topic.

We now build on top of Rake instead of ant, which has helped us create a much better build system that can improve quickly. Objective-J has improved support for deploying code to multiple platforms, like server (e.g. rhino) and browser. And we’re including the new Narwhal JavaScript standard library in Cappuccino as an external dependency.

Narwhal is still in the early stages, but eventually it will be a set of standard JavaScript APIs that work consistently across many different JavaScript implementations, making it easy to work on any JavaScript interpreter you have available. We’ll write more about all these new features as time goes on, especially all the new tools and APIs in 0.7, so stay tuned. In the mean time, you can check out information we’ve posted to the wiki.

Thanks again to everyone who’s contributed to Cappuccino for the 0.7 release, and to everyone using Cappuccino!

- Ross

Cappuccino Casts

Saturday, February 7th, 2009

Thomas Balthazar, who’s been doing the recent “This Week in Edge Cappuccino” series (read this week’s post), also started a new site to host screencasts of Cappuccino & Objective-J tutorials. So far he’s created a screencast for the starter tutorial

We’re all looking forward to seeing more screencasts on the site, and if you want to contribute your own screencast, get in touch with Thomas and he’ll add it to the site. Thanks Thomas!

On Leaky Abstractions and Objective-J

Monday, December 8th, 2008

In a recent post by John Resig, and in many of the comments, there seems to be the mistaken belief that Objective-J was designed to allow existing Objective-C programmers to write code that runs on the web. It’s been compared to GWT, where developers program almost exclusively in Java and are allowed to “circumvent” JavaScript. This however is not the case with Objective-J at all. For starters, Objective-J is simply a language addition to JavaScript, and exists separately from the actual Cappuccino framework (which I’ll discuss a little later). It does not directly have anything to do with the DOM or AJAX, etc. The purpose behind Objective-J was to facilitate the development of Cappuccino, and when we originally set out to do that we simply wanted to add a few key missing features to the existing JavaScript “standard”. In other words, Objective-J is our take on JavaScript 2.0.

Now, this is usually the point at which someone chimes in that JavaScript is perfect, and that I just don’t understand it (you know, despite the fact that I’ve been using it for upwards of 10 years and have worked on its implementation in a major shipping browser). However, I think most people in the community can agree that there are some pretty big holes remaining in JavaScript. JavaScript is being used in increasingly larger projects, and in these projects some of its weaknesses are beginning to show. This is precisely why we have things like the (now dead) ECMAScript 4 proposal, Harmony, and Adobe’s ActionScript. And the truth is, had JavaScript 2.0 come around and been widely implemented and supported, we would have built Cappuccino without Objective-J. But the problem is that JavaScript 2.0 didn’t come around. I started working on what would eventually become Objective-J and Cappuccino three years ago, and in that time there have been no significant improvements or changes to the JavaScript language. Yes, certain browsers have taken it upon themselves to add a few nice features here and there, but for people writing real applications that need to run on most browsers, its simply not practical to rely on them. For the most part, we’re writing the same JavaScript today (language-wise at least) that we were 5 years ago. And that doesn’t seem like its going to change anytime soon.

Everybody is writing “abstractions” around JavaScript

And I don’t just mean projects like Pyjamas and GWT. I mean EVERYBODY, including Prototype, Dojo, and jQuery.  Yes, you read correctly, all the major JavaScript frameworks are essentially doing the same thing we are to some degree or another — we’re really not that original. The sole difference between their approach and ours is that when they add new language features to JavaScript, they’re not taking the extra step of introducing new syntax. Don’t believe me? Take a quick look at an example right out of the Prototype tutorials:

// when subclassing, specify the class you want to inherit from var Pirate = Class.create(Person, { // redefine the speak method say: function($super, message) { return $super(message) + ', yarr!'; } });

What we’re seeing here is the introduction of classical inheritance to the JavaScript language. This has always traditionally been a language feature, but due to its absence in JavaScript, the folks at Prototype have chosen to make it a library feature. The important thing to realize here is that it requires as much work to learn about the Class function as it would to learn about a new class keyword. And the same is true of Dojo:

dojo.declare("Employee", Person, { constructor: function(name, age, currentResidence, position) { // remember, Person constructor is called automatically this.password=""; this.position=position; }, login: function() { if (this.password) alert('you have successfully logged in'); else alert('please ask the administrator for your password'); } });

Once again, dojo.declare might as well be a new keyword since its shoehorning classical inheritance right into JavaScript. The jQuery UI widgets do something very similar to this with the “widget” factory method:

$.widget("ui.sortable", $.extend({}, $.ui.mouse, { _init: function() { var o = this.options; this.containerCache = {}; this.element.addClass("ui-sortable"); //...

At the end of the day, it doesn’t really matter if you’re a JavaScript expert, all these libraries have quite the learning curve and if its your first time with any of them, you’re going to have be referring to documentation a lot. And that’s not a bad thing. My point is simply that in JavaScript, more so than anywhere else, libraries need to first define what is essentially a new mini-language before they can begin to do anything useful.  This is a bit unfortunate, because it ends up tying language additions to library features, despite there being no necessary connection between the two. This makes it particularly hard to use the different libraries together in an efficient way. Sure, you can use all three in the same project, but there are some clear walls between them since each one decides to do classes a little bit differently. Not to mention the fact that you now have pretty redundant code your site. This is what happens when a language is clearly missing features. Individual frameworks in the .NET, Objective-C, Java, and so forth world don’t suffer from core incompatibility in the way they choose to do something as fundamental as defining class hierarchies. This is part of the reason we built Objective-J as its own standalone entity.  If all you want is some of the cool language features that Objective-J adds (without any of the design patterns in Cappuccino) then you can just use Objective-J, there is no “all or nothing” contract.

OK, so how is Objective-J different?

As we’ve now seen, there is a general tendency to add language features to JavaScript. Now, in my personal opinion, I prefer language features as fundamental as these to be part of the syntax, not part of a library. Let’s look at what Objective-J inheritance looks like:

@import "Animal.j" @implementation Snake : Animal { Number miceEaten; } - (String)speak { return "hisss!"; } @end

To me this code reads a little more naturally, and at the very least it’s no harder to pick up than the numerous library functions required in the other libraries. This approach also has the added benefit of making it absolutely trivial to write new syntax modules so that my text editor of choice can actually know what is going on in my code. You’ll also notice that creating a new syntax gives us great flexibility and allows us to add a few nifty features that wouldn’t otherwise be possible, such as optional static typing and code importing. But again, this isn’t as “out there” as some people would have you believe. It has even more benefits as we’ll soon find out, but before we do, let me answer the question that I’m sure many of you are asking right now:

Why Objective-C style syntax?

Again, we didn’t start off saying “lets port Objective-C”!  In fact, our first versions of Objective-J looked very similar to Java or C++:

class Snake extends Animal { Instance.speak = function() { return "hisss!"; } }

However, this approach had some serious issues. To better understand them, we have to take a look at what the principal design goals of Objective-J actually were:

  1. First off, it had to be a strict superset of JavaScript – meaning all existing JavaScript had to work. Believe it or not, we do like JavaScript, and we didn’t want to break it or create a trade-off of features.  Not to mention we wanted the existing plethora of libraries to still work.
  2. Secondly of course, we wanted to add a number of “key” features.  Some things as crucial as being able to import code and built in support for classical inheritance.  We also wanted some features inspired by languages like Ruby, such as method_missing.
  3. And lastly, we wanted to keep the ease of use of JavaScript, which meant not adding an extra “compilation” step, but instead allowing developers to still pound out some code and hit refresh and see it run.

The problem with adding language features in a way that would be more “familiar” to most developers, like the Java approach above, is that it would break backwards compatibility with existing JavaScript. This is because a lot of the keywords we wanted to use are actually reserved words in JavaScript, despite not being currently used. There is good reason for this though, because at some point they may actually mean something, and we wanted to make sure Objective-J kept working when JavaScript (finally) got a real update. Of course, we could have just chosen different keywords, like “Class” instead of “class” for instance. This however also breaks backwards compatibility because someone may have used the Class identifier in their code already.

The other problem with this approach is that it made it next to impossible to add harder features like optional static typing or dynamic dispatch of methods (thus allowing for method_missing) without having a full blown compiler. There’s no way to “intercept” a method call in JavaScript.  So once again, we were stuck.

Luckily for us however, a group of people ran into these same issues about 25 years ago when trying to improve the C language. These were the folks at Stepstone who developed Objective-C. Just like in our case, Objective-C had to be a strict superset of C (unlike C++ which does NOT always play nice with C). Also lucky for us is that JavaScript syntax is very close to C syntax, so their language additions translated very naturally to JavaScript. And perhaps now it is obvious why our keywords start with the “@” symbol, because in this manner there is no possibility of ever clashing with future JavaScript keywords or predefined user variables and functions. In other words, we can now add to the language as much as we want without the fear of breaking compatibility with existing JavaScript.

Similarly, the new method passing syntax allows us to have firmer control of how messages are sent:

object.jsMethod(); [object objjMessage];

This is the famous bracket syntax. What you may not realize is that this makes it perfectly clear when you are using Objective-J style message dispath, allowing us to “hook in” and add things like method_missing, etc. There are a whole bunch of other cool things that this enables which are outside the scope of this post, but I encourage you to check out the other tutorials on our site to learn about them. All this, without breaking any existing libraries and without requiring the user to compile before every run. Pretty impressive for a langauge that is supposedly “completely different” from JavaScript.

The Part About Leaky Abstractions

On top of Objective-J, we’ve built the Cappuccino framework, which is designed to help developers write desktop class applications on the web. One of the many things Cappuccino does is “abstract away” the DOM, and I’ll get into why we do this in a moment.  But before I do, I think I should take a second to address this whole “leaky abstractions” business, because there seems to be a fair bit of confusion regarding this as well. If you haven’t already read it, or even if you have, I recommend you take a look at Joel Spolsky’s original article on the subject.

When people refer to this article, it is usually to criticize some “abstraction” because it will “inevitably” be leaky, and then oh boy you better watch out! But this was not Spolsky’s thesis. He didn’t end the article with “and thus avoid abstractions at all costs”. He was not somehow suggesting that we stop abstracting altogether. Quite the contrary, its clear that although these “leaks” are an unfortunate and unavoidable consequence, abstractions are still incredibly worthwhile: hence the conundrum. In every single example given in the article, it was never implied that the abstraction was somehow bad or invalid because of its leak: Just because certain SQL queries are slow doesn’t mean you should manually read in tab delimmeted files and scan them yourself. Just because TCP can fail if you unplug your computer doesn’t mean you should do IP transfers yourself.  It just turns out that, big surprise, nothing is perfect. Joel put it best himself:

Indeed, the abstractions we’ve created over the years do allow us to deal with new orders of complexity in software development that we didn’t have to deal with ten or fifteen years ago, like GUI programming and network programming.

And the truth of the matter is that the problem of leaks is overstated. I find it particularly hilarious when JavaScript programmers bring this up, since JavaScript, being a garbage collected dynamic interpreted language, is quite possibly one of the biggest abstractions of all. And yet, most of us can see that the benefits of JavaScript far outweigh the “leaks”. I think few JavaScript programmers have had to learn “the whole stack” once they’ve encountered one of JavaScript’s many leaks, whether it be performance issues (from being interpreted) or perhaps large memory consumption (from being improperly garbage collected in some browsers). No one has had to go and open up WebKit’s source code to figure out these problems. Most of the time you simply Google your concern and learn the workaround. Not that big a deal.

Leaks are just something we all have to learn to deal with in every facet of programming, because programming is abstraction. Abstraction is basically all programmers ever do, from pushing electrons across a wire, to turning C into assembly, to interpreting JavaScript in your browser, every step in computer science has been an exercise in abstraction. There is nothing inherently wrong with abstraction. I can understand if someone disagrees with a particular abstraction for well defined reasons, but simply waving your hands and referring me to the law of leaky abstractions is not a valid argument.

To suggest that we shouldn’t abstract because of Joel Spolsky’s Law that all abstractions are inherently leaky is to suggest that we shouldn’t debug because of Murphy’s Law that all code will remain inhrerently buggy.

Back to Cappuccino and the DOM

Cappuccino doesn’t just abstract away the DOM, it abstracts away HTML, CSS, VML, the JavaScript DOM API, etc. Why? Because as you can see there are just too many technologies with overlapping responsibilities. It’s never really clear whether you should create a button in HTML or in JavaScript code, and whether you should style it in a CSS files or apply styles manually in JavaScript, or whether you should just use Canvas to draw everything. Not to mention that on top of having to sort through all these technologies, you have the additional challenge of having to accomodate for every slightly different flavor that exists in every browser. Sometimes its relatively simple, but othertimes it can be quite complex, as is the case with Canvas and VML. The other problem is that these technologies were simply not originally designed to handle the tasks they are now performing.  HTML was designed for laying out documents, not creating applications.

We look at these technologies completely differently.  To us, HTML, CSS, Canvas, the DOM, etc all represent the “rendering engine” of the web, in the same way that graphics cards are the rendering engines for your computer. It’s too difficult to learn the intricacies of every graphics card on the market, so developers instead use technologies that hide these details like OpenGL. In the same way, Cappuccino defines a common way to “draw” for the web. Internally, it figures out whether its more efficient to make a div, or draw to a canvas, or use VML. This is a fantastic time saver today, because it allows Cappuccino to worry about things like performance and allows you to just get a button on the screen. But its going to be even better as time goes on. This is not only because the underlying code will get better, but because web applications today look like this:

But tomorrow, when enough browsers finally support SVG, they may look like this:

Or, for all we know, like this:

The important thing is that when this happens, and it will eventually happen, people who invested heavily in todays technologies will have to spend a great deal of effort updating, but we will just swap out the guts of Cappuccino and your code will inherit the benefits of SVG or whatever new technology is out there.

Conclusion

To me what we’ve done with Objective-J and Cappuccino seems inevitable. Even the most conservative major JavaScript libraries can’t get away without adding features to the language, and we’ve simply taken the next logical step with Objective-J. Similarly, Cappuccino is a tool that allows you to stop thinking about web pages and browser incompatibilities, and instead focus on the complex problems presented by the challenge of creating full-on applications on the web. As we’ve said countless times, Cappuccino isn’t for everything. All of this abstraction isn’t necessary if you’re simply trying to add dynamic elements to a site like bankofamerica or digg. Cappuccino is for building rich applications in the browser, a small minority in the web world today. We believe that this is where things are headed, and we designed Cappuccino specifically to get us there.

- Francisco

Synthesizing Accessor Methods

Sunday, October 26th, 2008

Yesterday, Francisco and Tom checked in a new feature to the Cappuccino git repository, called accessor synthesizing. This is a new language feature for Objective-J, and its designed to reduce the amount of boilerplate code developers have to write in a custom class. Normally, when you write a custom class in Objective-J, you also write a pair of getter and setter methods for each instance variable (ivar) that you want to expose. This usually means writing repetitive code that hardly ever changes each time you write it. With accessor synthesizing, developers will only have to write getter and setter methods when something truly interesting needs to happen in those methods.

Accessor synthesizing adds a new keyword to the Objective-J language, @accessors. When declaring your list of ivars in the @implementation block of your class, adding this one keyword will tell the Objective-J preprocessor to implement accessors for you. Let’s see an example of a simple class written using the old method, and then the same class using @accessors.

This Person class has two ivars, firstname and lastname. Before @accessors, the class looks like this:


@implementation Person : CPObject
{
    CPString firstName;
    CPString lastName;
}

- (void)setFirstName:(CPString)aString
{
    firstName = aString;
}

- (CPString)firstName
{
    return firstName;
}

- (void)setLastName:(CPString)aString
{
    lastName = aString;
}

- (CPString)lastName
{
    return lastName;
}

@end

Using the new @accessors keyword, we can eliminate four methods:


@implementation Person : CPObject
{
    CPString firstName @accessors;
    CPString lastName @accessors;
}
@end

This second version is much more succinct than the first, and less tedious to program. We think this will be helpful for developers, and will increase productivity and code readability.

It’s important to note that this doesn’t change the way you use a class. For our Person class, in both cases, the code for getting the first and last names of a person (in the myPerson variable) would look something like this:


var fullName = [myPerson firstName] + " " + [myPerson lastName];

Similarly, setting an ivar looks like this:


[myPerson setFirstName:"Winston"];
[myPerson setLastName:"Smith"];

Like any key-value-coding compliant class, the name of the instance variable becomes the “property” or “key”, and that key name is used in the setter and getter methods. If your key is firstName, the getter for that key will be firstName, and the setter will be setFirstName:. The same pattern applies to any other key.

Configuration

There are a few configuration options when using the new @accessors technique. Perhaps most importantly, is the ability to change the name of the property. For example, if you declared an instance variable like this:


CPString _location @accessors;

Objective-J would generate two accessor methods called _location and _setLocation:. These are the expected accessor methods for a key called “_location”. In order to generate more friendly versions without the leading underscore, you can modify your declaration like this:


CPString _location @accessors(property=location);

The addition of the property=location tells Objective-J to use “location” as the new property name, instead of “_location”, which will generate location and setLocation: methods without the underscore. In addition, you can also specify the specific name of both the getter and the setter method, like this:


BOOL _hidden @accessors(getter=isHidden, setter=setIsHidden);

This code specified a boolean instance variable called _hidden; the getter method will be called isHidden and the setter method will be called setIsHidden:. One thing to keep in mind when specifying your own getter and setter method names is key-value-coding. Although we don’t yet have much documentation on the subject (you can read Apple’s documentation here), key-value-coding enables several important features in Cappuccino, so it’s important to maintain key-value-coding compliance. Normally, the rules are that for a given key, say “foo”, the getter is called foo, and the setter is called setFoo:. There’s an additional rule for boolean values, which says that you can use isFoo, and setIsFoo:, in addition to the usual method names. In our case, thats why our custom getter and setter names are still key-value-coding compliant.

There are two additional configuration options, readonly, and copy. By default, @accessors will generate both a getter and a setter. If you only want to expose a getter method to the world, you can add the readonly value in the arguments. The other option, copy, has to do with how the setter works. Normally, when you pass an object to a setter, it’s assigned directly. The generated setter looks like this:


- (void)setFoo:(id)aFoo
{
    foo = aFoo;
}

When you specify copy, the argument is first sent the message copy, and the return value of that message is assigned to the instance variable:


- (void)setFoo:(id)aFoo
{
    if (foo !== aFoo)
        foo = [aFoo copy];
}

This is useful if you want to ensure that an object you’re passing isn’t modified out from under you. Of course, it only applies to ivars that are both read and write, and cannot be combined with readonly. To summarize, you can use both of these options like this:


@implementation FooBar : CPObject
{
    id foo @accessors(readonly);
    id bar @accessors(copy);
}

History

Apple introduced properties in Objective-C 2.0, which added a new way to declare instance variables for your classes. The two key features were the ability to use what has become known as “the dot syntax” for accessing instance variables, and the second was the ability to have the compiler automatically generate accessor methods. Reducing code, especially code that doesn’t change every time you write it, is certainly a worthwhile goal, so we thought it would be a good idea to bring this new idea to Objective-J. There are a lot of things about the Objective-C 2.0 implementation of properties that don’t make sense for Objective-J, so we decided not to port them directly and instead developed a syntax that we believe makes the most sense.

The main goal we want to achieve is eliminating the need to write your own accessor methods. We don’t, however, support the “dot syntax” aspect of Objective-C 2.0. This makes the dual @property and @synthesize syntax of Objective-C 2.0 redundant. Furthermore, rather than just choose one or the other, we decided to use a new keyword, @accessors. This will lesson the confusion for existing Cocoa developers trying to learn Objective-J. It will also make sure we don’t have an incompatible syntax going forward, as we explore new ways to work with existing Objective-C code.

Conclusion

Accessor synthesizing will reduce the amount of boilerplate code that needs to be written, and make the language just a little bit easier to develop in. Overall, we think it’s a worthwhile addition to the language. If you have an opinion, we’d love to hear it, so sound off in the comments. Although this new syntax isn’t yet written in stone, we won’t expect to change it after version 0.6 of Cappuccino ships. Checkout the latest version of the git repository to start using this new feature.

We’re also considering other language features that might make it easier to program in Objective-J. If you’ve got an idea, or you’re interested in being part of the discussion, you should sign up for the mailing list, where we’ll be discussing some of the new proposals.

Cappuccino Tools: “objjc” and “steam”

Tuesday, October 14th, 2008

Note: please check the tools page on the wiki for the latest information on Cappuccino’s tools.

In our previous post on the Cappuccino build tools we summarized the purpose of four of the tools. In this article we’ll dive deeper into two of them, objjc and steam.

To review, the purpose of these tools is to prepare your application for deployment by pre-compiling all application Objective-J code into JavaScript, thereby reducing the load time for clients. Additionally, since most developers won’t need to modify Cappuccino itself, we always compile Cappuccino’s AppKit and Foundation frameworks to further reduce load time.

The only time you’ll need to run steam (which handles running objjc for you) is when you’re deploying your application, or if you’re making changes to the Cappuccino frameworks themselves. In the latter case, the easiest way to recompile the frameworks is to run the default ant task in the Cappuccino source tree:

cd /path/to/cappuccino
ant

To use the freshly built frameworks simply replace the “Frameworks” directory in your application with a symbolic link to the Release directory in the directory pointed to by your $STEAM_BUILD environment variable:

cd /path/to/your_application
mv Frameworks Frameworks-Original
ln -s $STEAM_BUILD/Release Frameworks

(if you’re loading your project through a webserver like Apache make sure to enable the FollowSymLinks option)

objjc

objjc, the Objective-J compiler, is the most important of the build tools, but you’ll likely never invoke it directly. objj can take any number of parameters as input filenames and output filenames (preceded by the “-o” flag). For example:

objj Class1.j -o Class1.o Class2.j -o Class2.o

This will invoke the Objective-J compiler (which is identical to the one used by Objective-J in the browser) on each input file, outputting JavaScript plus some metadata to each specified output file. Next we need to combine all of these individual output files into a single “.sj” archive that contains the JavaScript and import dependency metadata for the entire framework. It would be possible to do this by hand, but steam takes care of it for you.

steam

steam is the general Cappuccino build tool that manages the creation and compilation of your Cappuccino applications.

To create a basic Cappuccino application, simply run steam with the “create” command:

steam create ApplicationName

This will create a new Cappuccino application in the directory “ApplicationName”. This application can be modified and run (by opening index.html in the browser) without any further usage of the build tools.

When you’re ready to compile the application code for deployment, add a .steam file to your application, like the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Name</key>
    <string>YourApplication</string>
  <key>Targets</key>
  <array>
        <dict>
            <key>Name</key>
            <string>YourApplication</string>
        </dict>
  </array>
    <key>Configurations</key>
  <array>
        <dict>
            <key>Name</key>
            <string>Debug</string>
            <key>Settings</key>
            <dict>
                <key>PREPROCESS</key>
                <true/>
                <key>FLAGS</key>
                <string>-DDEBUG</string>
            </dict>
        </dict>
        <dict>
            <key>Name</key>
            <string>Release</string>
            <key>Settings</key>
            <dict>
                <key>PREPROCESS</key>
                <true/>
                <key>PREINTERPRET</key>
                <true/>
            </dict>
        </dict>
  </array>
</dict>
</plist>

This file defines the targets and configurations for your project. This one defines a single target, YourApplication, and two configurations, Release and Debug. To compile your application, simply execute steam with the build command, the .steam filename, and the configuration name:

steam build -f MyApp.steam -c Release

If a .steam filename is not provided it will look for a file with the extension “.steam”. Likewise, if a configuration name is not provided, it will use the first one defined in the file. The following will run the “Debug” configuration in your .steam file:

steam build

steam gathers all “.j” files in your application, compiles them, and combines them into a single “.sj” file (“static Objective-J”), along with a new “Info.plist” which tell Objective-J which files are contained in the “.sj”.

The results are placed in a subdirectory of $STEAM_BUILD named the same as the configuration, i.e. Debug or Release. Alternatively, pass the “-b” flag and a build directory to specify where it should be built.

The compiled application or framework can then be used in place of the original uncompiled collection of .j files. If it was an application, copy or symlink your Frameworks directory to it’s directory. If it was a framework, copy it to your application’s Frameworks directory.

Conclusion

This article covered the core Cappuccino build tools, objjc and steam. Remember that you will probably never want to call objjc directly, but rather rely on the “steam build” command to manage the build process for you. Additionally, remember the build process is entirely optional (except if you’re editing the Cappuccino frameworks themselves), and is only necessary as a deploy-time optimization.

In subsequent articles we’ll cover the remaining more advanced build tools, press and bake, as well as further deployment optimizations.

The Cappuccino and Objective-J Build Tools

Monday, October 6th, 2008

Note: please check the tools page on the wiki for the latest information on Cappuccino’s tools.

This article is a high level overview of the current Cappuccino and Objective-J build tools. Subsequent posts will cover each tool in more detail.

One of our primary design goals with Cappuccino and Objective-J was to keep the simple development cycle web developers are used to: edit your code, save, refresh the browser. At the same time we wanted to add powerful language features to JavaScript without requiring the user install a plugin like Flash or Silverlight. At first glance it seemed like only two of these three requirements could be satisfied simultaneously, until we had the key realization that we could simply write our compiler in JavaScript itself, and perform the compilation at runtime on the client.

In reality the Objective-J “compiler” is more like a preprocessor, performing a relatively simple transformation from Objective-J code to JavaScript code, which is then interpretted by the browser’s native JavaScript engine. We don’t do full parsing and compiling, nor do we have a separate interpreter on top of JavaScript. The result is that the compiler and resulting code run very fast.

This turned out to work great. Simply download the starter package, load index.html in your browser, and start editing away! If you’re just getting started with Objective-J and Cappuccino you don’t even need to worry about the build tools, they’re entirely optional.

When it comes time to deploy your application you may want to optimize it. There’s no reason for your customers to wait any longer than necessary, even if the overhead is minimal. That’s where the build tools come in. Each tool has a specific purpose, and they all work together to produce an optimized Cappuccino application:

  • objjc – the Objective-J compiler
  • steam – a general tool for managing the build process, creating new Cappuccino applications, etc.
  • press – code stripping and other optimizations
  • bake – deployment tool

objjc

At the lowest level is “objjc”, the Objective-J compiler. It’s equivalent to gcc or javac, except it converts Objective-J code to JavaScript. Because we can run the same JavaScript code in the browser and Rhino the core of objjc is identical to the in-browser compiler.

Currently objjc’s implementation is closer to a simple preprocessor than a compiler, much like the original Objective-C compiler was implemented as a preprocessor on top of C. The preprocessor simply looks for the few Objective-J syntax additions and replaces it with the raw JavaScript equivalent. A big reason this is possible is that Objective-J is a strict superset of JavaScript, thus all JavaScript code is valid Objective-J code.

Typically you don’t call objjc directly, but rather let steam manage the build process.

steam

Next up is steam, which is the main Objective-J and Cappuccino build tool. Currently it serves two purposes: “steam build” (similar to Xcode’s “xcodebuild”) and “steam create” (similar to Ruby on Rail’s “rails” command).

“steam build” runs the compilation process on an entire application or framework and outputs a single “.sj” file, vastly decreasing the number of HTTP requests required to load an application. These “.sj” files are archives of the compiled input “.j” files, along with information detailing each file’s required imports. This allows the Objective-J loading system to efficiently and asynchronously load a large application.

“steam create” copies all the files required for a new project to the directory specified.

press

The “press” tool takes in a full application and attempts to determine which code files are unecessary. It then strips those files and writes the results to another directory. This could be thought of as a “linker” though it works very differently than a traditional linker. On a simple project it will reduce the AppKit and Foundation frameworks size by approximately 30%, and we expect further improvements.

Optionally, it can run the pngcrush utility on all your png graphics, attempting to reduce their size. Eventually press will also automatically sprite images, further reducing the number of HTTP requests required to load your images.

bake

Finally, we have “bake”, the Cappuccino deployment tool (like “Capistrano” but specialized for Cappuccino applications). Bake orchestrates all the above tools to produce, and optionally deploy, a highly optimized Cappuccino application. First it can pull both Cappuccino and your application code from git, svn, or a local or remote directory via rsync.

It then copies pieces of the various “checkouts” to the “products” directory, first running a build process like “steam” or ant, if specified. For example, it can run steam on your application code, and copy the results to the product directory, then do the same for AppKit and Foundation, copying the results to the Frameworks/AppKit and Frameworks/Foundation directories to build the complete application.

Once an application is assembled, bake can run “press”, optimizing the application’s size.

Then bake sets up a directory structure and index.html file which allows for several important tricks: aggressive caching, keeping the client application in sync with the server backend, and atomic deployments, all while preserving a single user-facing URL for the application.

Finally, the application is archived and gzipped, scp’d to one or more servers, and atomically deployed to the specified path(s).

Conclusion

Cappuccino’s build tools are great at optimizing your deployed application, but there are further web server specific optimizations possible as well, including enabling gzipping and caching. These will be discussed in subsequent articles.

Download

Cappuccino and Objective-J are licensed under the LGPL. For more information, see our licensing page.

Copyright © 2009 - 280 North, Inc. Cappuccino and Objective-J are registered Trademarks of 280 North. Logo by Sofa. Hosting by Slicehost.