Get Equipped with Bjam -j8
Saturday December 22, 2012 17:31:53

Macaroni for C++ uses Macaroni for C++ to generate code and then Boost Build to build itself.

I wrote Macaroni for C++ out of a desire to bring the speed at which I could code .NET and Java to C++. Unfortunately, one of the things I ran into is the classical problem that large C++ projects can quickly take forever to build if you aren't careful. From scratch, Macaroni takes between eight and ten minutes to build on my old core 2 duo laptop. On my new, top of the line i7 desktop it builds in over five minutes. On my netbook it takes an hour.

Boost Build is an incredible tool which is hurt not so much by its documentation but by the fact that its complexity is necessary to provide features that are hard to appreciate. Boost Build handles the discrepancies of building code with different compilers, operating systems, and configurations, making it possible to use a single build script that can compile an application linked to shared libraries with Visual C++ in debug mode, then a statically compiled version using MinGW, and finally build a Ubuntu version of the app in a VM.

The ability to choose on the fly the way to compile an application, rather than having to think ahead when writing the build script, is liberating. It's like using a nice multi-platform library such as Boost Filesystem instead of writing the code to access files and directories yourself from scratch for every operating system. Boost Build, along with the Boost libraries, enabled me to quickly create a Linux version of Macaroni, which makes me wonder if any person who advocates something like autotools or make on the basis that they are “universal” has bothered trying a different OS or development environment in the past ten years.

However, Boost Build has a price to pay in the form of it's learning curve. I've spent the last three years figuring it out, and at times have been frustrated to the point where I nearly dropped it. When I first discovered Boost Build, I decided to make it the required build system of Macaroni. After several months of bitter experience I realized instead I needed to find a way to represent the physical layout of the files generated by Macaroni, so that while I would mainly focus on generating files for Boost Build I could create build scripts for other tools if I or anyone else ever wanted to (this was also to generate Visual Studio projects to take advantage of VS's debugger, which is the only reason I start up Visual Studio anymore).

I feel as if I still can't claim to know Boost Build, as I'll find out new things constantly that seem so useful I wonder how I could ever get work done without them. An example of this is the “-j” flag, which I found today.

Normally when Boost Build executes, you can see it calling the compiler once for every object file (in Macaroni there is going to be a one-to-one correlation between classes and object files… I've thought of ways to customize this but so far every idea seems to add too much complexity). On a multicore beast of a machine like my new one that is clearly too boring for the CPU, which sits at 20%.

Enter the “-j” flag, which tells Boost to call multiple processes simultaneously. So “bjam -j4” will invoke four processes simultaneously. This has sped up the build times of Macaroni dramatically.

I wanted to time the differences, so I installed ptime, a useful program that spits out the time taken to invoke some process. I then tested bjam's performance without the -j flag, then with -j4 and finally -j8. Each time I first deleted the bin/msvc-11.0 directory so it would build from scratch, then I invoked it again to see if there was any speed up.

\________________________________________/
|         |   normal |     -j4 |     -j8 |
+---------+----------+---------+---------+
| build   | 310.510s | 94.594s | 69.813s |
| rebuild |   1.067s |  1.060s |  1.059s |
""""""""""""""""""""""""""""""""""""""""""

It turns out there is no speed increase for the parsing process Bjam does initially, so if nothing needs to be built the -j flags add nothing. However, moving to “-j8” made the build four and a half times faster. Its also the only process I've yet seen cause my CPU to jump to 100%.

This flag feels like some kind of unbelievable secret, like when I figured out there was a hidden ending in Link's Awakening, or discovered the #line directive which allowed compile errors to reference Macaroni source code. If it's in the Boost Build docs then it must be buried (though contributions are welcome, so maybe I should shut up and add it). When I, right now, Google specifically for “bjam -j” or “bjam -j4” I see nothing mentioning this flag on the first page of Google results.

The way I discovered the flag initially is by stumbling into an ancient page where someone had pointed out that the “-j” flag interspersed output from the commands it called in parallel. When I read it, I did a double take because I couldn't believe such a useful piece of functionality was real and being referenced so nonchalantly. After bjam seemed to work with the flag, I ran the experiments listed above to prove it to myself that “-j” did would I hoped and that it wasn't some illusion. I've since Googled “bjam -j4” and the only webpage I could find referencing this incredibly useful bit of functionality is this one).

Maybe the flag is officially unsupported? All I know is that I'm grateful it works now and has dramatically decreased the time it takes me to build from scratch.



Lubuntu Turns Netbooks into Rocket Ships
Sunday December 16, 2012 20:06:37


For years I've owned an Acer Aspire One netbook using Windows XP. While I've stayed fond of the idea of using it, for roughly half that time Windows XP and the certain programs such as web browsers have become degraded in performance to the point that using the system is no longer enjoyable (this is in spite of several reinstalls of Windows - maybe Service Patch 3 for XP has a feature which drastically decreases performance on Netbooks?).

I installed Ubuntu, but while faster, it didn't quite feel great either. For one thing, the Unity UI left-hand dock takes up an unforgivable amount of real estate on the netbook screen. For another, while Ubuntu loads fast and generally was a bit zippier than XP, there was still noticeable pauses as I switched between tasks or opened up new programs. My biggest pet peeve was the update center popping up and stealing focus from every other program a few minutes into each session despite the fact it then took a few seconds more to fully load.

Thankfully, there are other distros of Ubuntu with lighter-weight UIs meant for older hardware. I was assumed I'd be using Xubuntu, due to its important feature of having a mouse for a logo. But after reading some benchmarks, I settled on Lubuntu, which uses LXDE, a thin layer on top of X11 with little inbetween.

Lubuntu is just a rocket ship compared to everything else I've run on this netbook. It loads fast, switches apps fast, and so far everything just works. It has some failings, such as the inability to snap Windows to a grid using a keyboard shortcut, but most of these are more forgivable on a Netbook where I usually keep apps full screen and switch between them.

After that, I just had to tweak a few things to get an environment I was comfortable on. Here's a list of steps I recommend if you're planning on running Lubuntu:

  • As always, install Launchy. While some bemoan where a start menu is or isn't placed, others use Launchy and forget details like that.
  • Disable the ALT+SPACE keyboard binding, so Launchy can use it.
  • Make Launchy start at boot. Here's a good article on how to accomplish this.
  • Install the incredible Sublime Text 2.
  • In order for Launchy to detect programs, such as Sublime, you'll need to add shortcuts to the desktop menu, even though you won't be using it. Here's how I did it:
    $ cd /usr/share/applications
    $ sudo vi sublime.desktop
    

    Then I added the following in VI:
    [Desktop Entry]
    Type=Application
    Name=Sublime Text 2
    GenericName=
    Comment=
    Icon=/home/tim/Tools/sublime/SublimeText2/Icon/48x48/sublime_text.png
    Exec=/home/tim/Tools/sublime/SublimeText2/sublime_text
    Terminal=false
    Categories=Office;IDE;
    


  • Similar to when I'm in Windows, I like to have a bash script that runs every time I start up a terminal. I used to edit bash.bashrc directly, but now I simply add a line to bash.bashrc to source a script that lives somewhere under ~/Tools.

    In Windows, the main purpose of the analogous bash script was to set the path to use various command line utilities, though in Linux its better not to defy convention and instead let most programs live where the debian package says they should. However, a start up script can still be useful for certain programs that don't have packages as well as programs that do have them but which you wish to install from source in a directory of your choosing. An extra start up script can also do fun things like displaying tips fortune on startup. For example, here is my current script:

    MPATH=~/Tools/Common/U/macaroni/macaroni-0.1.0.25-ubuntu
    alias macaroni="$MPATH/macaroni generatorPath $MPATH/Generators \
        libraryRepoPath $MPATH/Libraries messagesPath $MPATH/"
    export BOOST_ROOT=~/Tools/Local/boost/boost_1_52_0
    export PATH=$PATH:$BOOST_ROOT
    fortune | cowsay
    date
    


I'm not being hyperbolic when I say Lubuntu has made my Netbook feel like a whole new machine. If you're in a similar situation with an older Netbook or Laptop, I highly recommend it. It's amazing to me that there's still software out there that's this fast on old hardware.



Getting started with Macaroni on Ubuntu
Wednesday December 12, 2012 05:15:29


I recently got Macaroni compiled in Ubuntu and passing all the unit tests. The integration tests weren't so lucky, perhaps due to configuration issues in how I'm using Boost Build. Despite that, I've released the Ubuntu build on Macaroni's homepage. Here's a little tutorial on how to use it in Ubuntu, which I'm writing as I run Macaroni for the first time in a fresh virtual machine.

First, download Macaroni from this link. I unzipped mine to ~/Tools/macaroni, so the final directory was ~/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64.

The Macaroni binary won't have the execute permission set, so fix that with:

$ chmod 700 ~/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64/macaroni

Macaroni needs a settings file to be present at ~/Macaroni. This is for global settings which need to be changed on a per-machine basis, though for this project we won't need it all.

$ mkdir -p ~/Macaroni
$ echo "properties={}" > ~/Macaroni/init.lua

Unlike the Windows version, we'll need to specify each path to the various Lua scripts (the ability to avoid this might be coming to the Linux version soon, but currently it seems a little complicated). So we'll create an alias to do all this for us.

$ MPATH=~/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64
$ alias mcpp="$MPATH/macaroni generatorPath $MPATH/Generators \
    libraryRepoPath $MPATH/Libraries messagesPath $MPATH/"

At this point typing “mcpp” will run Macaroni.

Create a new directory for an example project. Mine is ~/Work/mexample. In that directory, create the following file called “project.lua”:

import('Macaroni', 'ProjectTemplates', '1')
require 'SimpleProject'
GenerateCpp{group='Junk', project='Junk', version='0'};

This project file is simple to the point of absurdity. It uses the “GenerateCpp” function, which does nothing other than parse Macaroni files in the directory “src” and write C++ files to the directory “target”. If you want, you can change these directories with the “src” and “target” named arguments to GenerateCpp.

Of course, we'll need a Macaroni source file in the “src” directory. First, create the “src” directory, and then create the following file in that directory named “Example.mcpp” (actually, it can be called anything at all so long as it ends in .mcpp).

~import std::cout;

class Class1 { public Class1() { cout << "Class1!" } };

class Class2 { public Class2() { cout << "Class2!" } };

Finally, generate C++ code by running the following:

$ mcpp generate
Macaroni for C++
Version 0.1.0.25 built at 2012-12-11-10:45:52

Creating new Environment with the following AppPaths:
Message file : /home/tim/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64/
Library Paths : [/home/tim/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64/Libraries/home/tim/Macaroni/Libraries]
Generator Paths : [/home/tim/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64/Generators]
LoadProjectEnvironment
Parsing file project.lua...
Running /home/tim/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64/Libraries/Macaroni/Project-Lua/0/src/project-init.lua...
Running /home/tim/Macaroni/init.lua...
LoadProjectEnvironment
Parsing file /home/tim/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64/Libraries/Macaroni/ProjectTemplates/1/project-final.lua...
Running /home/tim/Tools/macaroni/macaroni-0.1.0.25-ubuntu-64/Libraries/Macaroni/Project-Lua/0/src/project-init.lua...
Running /home/tim/Macaroni/init.lua...

Program finished.

$ ls -la target
total 24
drwxrwxr-x 2 tim tim 4096 Dec 12 00:07 .
drwxrwxr-x 4 tim tim 4096 Dec 12 00:07 ..
-rw-rw-r-- 1 tim tim 1329 Dec 12 00:07 Class1.cpp
-rw-rw-r-- 1 tim tim  366 Dec 12 00:07 Class1.h
-rw-rw-r-- 1 tim tim 1329 Dec 12 00:07 Class2.cpp
-rw-rw-r-- 1 tim tim  366 Dec 12 00:07 Class2.h
$ cat target/Class1.h
#ifndef MACARONI_COMPILE_GUARD_Class1_H
#define MACARONI_COMPILE_GUARD_Class1_H

// This class was originally defined in Example.mcpp
// Forward declaration necessary for anything which also depend on this.
class Class1;

// Define class Class1
class  Class1
{
	public    : Class1();

}; // End of class Class1

#endif // end of MACARONI_COMPILE_GUARD_Class1_H

Hurray! You've now used Macaroni. If all you're interested in is getting rid of the duplication between header and implementation files, then you're good.

Hopefully I'll soon find time to write more blog posts soon detailing how to use Macaroni to do other things such as build projects using Boost Build, write glue code for Lua, as well as some other entries explaining the ideas behind Macaroni for anyone who's interested in writing their own code generators.



Installing MinGW and Boost on Windows XP
Friday November 23, 2012 14:40:17

MinGW is the premiere free non-Microsoft compiler for Windows. Even if you're primarily using Microsoft's compiler, compiling with MinGW, which is based on GCC, can give you a great head start to making your code compile with Unix. Additionally, if you want to use C++11 features, you can forget about doing it from a Windows XP box using a Microsoft compiler. Their cool new tools will compile to Windows XP, but can only be used on Windows 7 and up.

Installing MinGW it is fall off a log simple, but as I'm doing it on my old netbook right now I thought I'd document the process.

First, visiti the getting started page on MinGW's official website and download and run mingw-get-inst (you'll see it linked in the first few steps). Select “Download the latest repository catalogues” during the installation. Keep the default directory of C:\MinGW (the short path and lack of spaces helps with some tools). You can also select various compilers during the graphical installer, but don't, to relish the wonderful experience of installing these components from the command line.

Now add “C:\MinGW\bin” to the path.

Now install the following:

mingw-get install gcc
mingw-get install g++
mingw-get install mingw32-make

Working with Boost

The best way to work with Boost is to download the code and compile the libraries yourself. It's not easy, but controlling it yourself can offer insight into how these libraries are created and an appreciation for how portable it is.

Boost uses a special tool called Boost Build. You can think of this as an extremely flexible Make- once you've created your build script, you can build multiple configurations. For example, you can create a release version using Microsoft Visual C++ by invoking Boost Build one way, and then create a debug version with Gcc by invoking it another. Given that so much of C++ (and C) centers around how you build your code, it's nice that Boost Build abstracts this decision away from you until the end.

When you compile Boost itself, you need to be aware though that some options aren't configurable. One is whether or not you use the C++11 extensions for Gcc- Boost Build currently is not aware of this feature, so you need to remember it yourself. If you compile Boost for GCC without the C++11 flags set, it won't work with anything you compile using the C++ flags. So however you choose to use GCC, be consistent!

I recommend you use the GNU extensions because it works a little better with the Boost libraries. This involves passing the argument “-std=gnu++11” to the gcc compiler.

Building Boost

Download Boost from the official site. I have a program for all my tools, which I creatively named “C:\Tools”. Under this, I have a directory named “Boost”, and under that there's directories for every version of Boost I've downloaded.

I'm downloading Boost 1.52, so it's going to live in C:\Tools\Boost\boost_1_52_0.

Set the environment variable BOOST_ROOT to this path (again, ]I use a batch file to set up all these environment variables to avoid polluting the path). That's because Boost Build needs to have this set to work properly.

Now, in a command prompt enter that directory and type the following:

bootstrap.bat gcc
b2 --toolset=gcc cxxflags=-std=gnu++11 --build-type=complete stage cxxflags="-include cmath "

Again, gnu++11 is to make sure you build Boost with the C++11 features plus certain Gnu compiler extensions for maximum compatibility with Boost. The “-include cmath” works around a current issue building parts of Boost Python.

At this point go defrost a turkey because building Boost takes forever.

Once it's finished, congratulations! You can now take advantage of Boost in your programs.





<---2013-02-03 21:45:19 history 2012-11-05 03:25:21--->



-All material © 2007 Tim Simpson unless otherwise noted-