Showing posts with label Mac OS X. Show all posts
Showing posts with label Mac OS X. Show all posts

2010-08-05

Reviving an Old Tiger

An old machine that proved its mettle on the line can be a handy development server, on a pinch. Especially if you're starting up by pulling your boot straps, as I currently am. I have this Blue & White G3 that served me faithfully for the last, say, 10 years. Bitrot, alas, is not a hardware problem: software version numbers climb and software authors drop support for older operating systems and configurations, and we misers are left struggling and scavenging for information to make things compile and install. So, for my own reference, here's what I did this time. This applies to Mac OS X 10.4.11, AKA Tiger:

Sybase 12
Get the latest EBF for Mac OS, EBF17473. It works beautifully.
XCode 2.5
I had to root quite a bit around the newly redesigned Apple Developer site. The image name is xcode25_8m2558_developerdvd.dmg
MySQL 5.1.49
A challenge for GCC 4.0.1, it kernel-panicked the machine once. I followed these fine instructions. I set it up to start up automatically on boot, via the following launchd script:

<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>KeepAlive</key>
 <true/>
 <key>Label</key>
 <string>com.mysql.mysqld</string>
 <key>Program</key>
 <string>/usr/local/mysql/bin/mysqld_safe</string>
 <key>RunAtLoad</key>
 <true/>
 <key>UserName</key>
 <string>mysql</string>
 <key>WorkingDirectory</key>
 <string>/usr/local/mysql</string>
</dict>
</plist>

Put it in /Library/LaunchDaemons/com.mysql.mysqld.plist.

Apache httpd 2.2.16
I followed these instructions. The layout I used is this:
<Layout DarwinLocal>
    prefix:        /usr/local/apache2
    exec_prefix:   ${prefix}
    bindir:        ${exec_prefix}/bin
    sbindir:       ${exec_prefix}/sbin
    libdir:        ${exec_prefix}/lib
    libexecdir:    ${exec_prefix}/modules
    mandir:        ${prefix}/man
    datadir:       /Library/Documents
    sysconfdir:    /etc/httpd
    installbuilddir: ${datadir}/build
    errordir:      ${datadir}/error
    iconsdir:      ${datadir}/icons
    htdocsdir:     /Library/WebServer/Documents
    manualdir:     ${datadir}/manual
    cgidir:        /Library/WebServer/CGI-Executables
    includedir:    ${prefix}/include+
    localstatedir: /var
    runtimedir:    ${localstatedir}/run
    logfiledir:    ${localstatedir}/log/httpd
    proxycachedir: ${runtimedir}/proxy
</Layout>

and the configuration is this (culled from here):

CFLAGS="-arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk" ./configure \
--enable-layout=DarwinLocal \
--enable-access \
--enable-actions --enable-alias --enable-asis --enable-auth \
--enable-auth_dbm --enable-auth_digest --enable-autoindex \
--enable-cache --enable-cgi --enable-dav --enable-dav_fs \
--enable-deflate --enable-dir --enable-disk_cache \
--enable-dumpio --enable-env --enable-expires --enable-fastcgi \
--enable-file_cache --enable-headers --enable-imap \
--enable-include --enable-info --enable-log_config \
--enable-log_forensic --enable-logio --enable-mem_cache --enable-mime \
--enable-mime_magic --enable-negotiation --enable-perl \
--enable-rewrite --enable-setenvif --enable-speling --enable-ssl \
--enable-status --enable-suexec --enable-unique_id --enable-userdir \
--enable-usertrack --enable-version --enable-vhost_alias --enable-so \
--enable-module=all --enable-shared=max

These instructions allow automatic launching of Apache at startup.

zlib 1.2.5
libpng 1.4.3
Beware, as the DLL gets installed with the wrong name: it should be libpng14.14.dylib.
jpegsrc v8b
freetype 2.4.1
gd-2.0.35
I configured it with the usual caveats.
libmcrypt 2.5.8
mhash 0.9.9.9
mcrypt-2.6.8
php 5.3.3
It took me quite a long while sort out the correct incantation to configure PHP. This is what worked for me:
export CFLAGS="-DSQLITE_ENABLE_LOCKING_STYLE=0 -DBIND_8_COMPAT"
./configure \
-prefix=/usr/local/php5 \
-with-config-file-path=/etc \
-with-zlib=/usr/local \
-with-xml \
-with-xsl \
-enable-ctype \
-enable-dom \
-enable-exif \
-enable-filter \
-enable-ftp \
-enable-gd-native-ttf \
-enable-libxml \
-enable-mbregex \
-enable-mbstring \
-enable-pcntl \
-enable-pdo \
-enable-posix \
-enable-shmop \
-enable-simplexml \
-enable-soap \
-enable-xml \
-enable-bcmath \
-with-bz2=/usr/bin \
-with-curl \
-with-freetype-dir=/usr/local \
-with-gd=/usr/local \
-with-iconv \
-with-jpeg-dir=/usr/local \
-with-ldap \
-with-mcrypt=/usr/local \
-with-mysql=/usr/local/mysql \
--with-mysqli=/usr/local/mysql/bin/mysql_config \
-with-openssl \
-with-pdo-mysql=/usr/local/mysql \
-with-png-dir=/usr/local \
-with-zlib=/usr/local \
-enable-dbx \
-enable-sockets \
-with-apxs2=/usr/local/apache2/sbin/apxs \
-with-kerberos=/usr \
-with-mysqlsock=/var/mysql/mysql.sock \
-without-pear

Don't forget to apply the patch described in this post. Be sure to make test!

Next, configure Apache to run phpMyAdmin, Drupal and Mantis (I won't have anything to do with either Python or Ruby, sorry). I expect this old Tiger to bend under the pressure but not break.

2008-10-15

Top Drawing

I wrote the last time about simple ways to "just get something onto the screen", and I ended by exploring a simple Top Draw program. I hinted at the ease with which Top Draw allows compositing a complex "painting", taking more or less by fiat the examples included with the program. I since took advantage of the basic rosette drawing subroutine to make a wallpaper that I could actually install:

A desktop wallpaper generated with Top Draw

In my opinion there are two advantages to using Top Draw:

  1. It abstracts the compositing paradigm with a Photoshop-like Layer object,
  2. It allows to interleave procedural drawing with arbitrary Core Image filters,

thus leveraging the built-in capabilities of Mac OS X Quartz subsystem.

I first refactored my script so that the drawing code is independent of the global transform being applied:


function wheel(m, n) {
  if (m < 1 || n < 5) return;
  var color = new Color();
  color.alpha = 0.3;
  var a = Math.PI / n;
  var k = Math.cos(a), s = Math.sin(a);
  var t = (k + s) / (k - s);
  var d = k + s * t;
  var r = Math.pow(k - s, m);
  for (var e = 0; e != m; e++) {
    color.saturation = 0.5*(1 + e/m); // 0.5 -- 1.0
    color.brightness = 0.5*(2 - e/m); // 1.0 -- 0.5
    for (var i = 0; i != n; i++) {
      var b = (2*i + e) * a;
      var x = r * Math.cos(b), y = r * Math.sin(b);
      color.hue = i / n;
      desktop.fillStyle = color;
      desktop.beginPath();
      desktop.moveTo(x, y);
      desktop.lineTo(d * (k * x - s * y), d * (k * y + s * x));
      desktop.lineTo(t * x, t * y);
      desktop.lineTo(d * (k * x + s * y), d * (k * y - s * x));
      desktop.lineTo(x, y);
      desktop.fill();
    }
    r /= k - s;
  }
}

Gone are centers and offsets in each parameter to the drawing commands, as gone is the global scaling of the drawing. Then, I use random number generators to place the rosettes all over the screen:

desktop.fillLayer(new Color(0));
var db = desktop.bounds;

var xrnd = new Randomizer(0, db.width );
var yrnd = new Randomizer(0, db.height);

In order to give some depth to the final result, I'll blur each drawing a bit so that newer rosettes are sharper than older ones:

var f = new Filter("CIGaussianBlur");
f.setKeyValue("inputRadius", 2);

I'll draw a number of rosettes, four in this case, in random places:

for (var i = 1; i <= 4; i++) {
  var cx = xrnd.intValue;
  var cy = yrnd.intValue;

I make sure that the rosette fits the screen with the given center:

  var sz = Math.max(cx, cy, db.width - cx, db.height - cy);

In order to isolate each drawing from the modifications to the global transform, I save the drawing context prior to changing scale and center:

  desktop.save();
  desktop.translate(db.x + cx, db.y + cy);
  desktop.scale(sz, sz);

I then draw the rosette and restore the context. I could easily give random parameters to the drawing routine, but I find that by having uniform shapes the rosettes nicely stack one over another:

  wheel(8, 10);
  desktop.restore();

Finally, I apply the prepared filter to the resulting image:

  desktop.applyFilter(f);
}

As you can see, it's really easy to get good results with remarkably little code. Keep hitting Command-R until you find a result you like, and install it on your desktop.

2008-10-13

Procedural Drawing

Pretty pictures, again. There are now a number of "toys" with which to "recreate" the experience of turning on the old computer (C-64, Spectrum, Apple II or what had you) and being greeted with a BASIC prompt. I've written before about how SDL can give you a simple, direct (!) buffer to which to write pixels; the problem it has is that it does not know anything about drawing any object more complicated than a pixel. I'd like to explore some alternatives.

I was inspired by this image and wanted to replicate it. I happen to have Mathematica at hand, and sometimes it's my fall-back choice. After some fudging, I came up with:

wheel[m_Integer?Positive, n_Integer?Positive] :=
 With[{a = Pi/n},
  With[{ka = Cos[a], sa = Sin[a]},
   With[{ta = (ka + sa)/(ka - sa)},
    With[{d = ka + sa*ta},
     Graphics[
      Table[
       With[{r = 1/(ka - sa)^e},
        Table[
          With[{k = Cos[a (2 i + e)], s = Sin[a (2 i + e)]},
          {Hue[i/n, 0.5*(1 + e/m), 0.5*(2 - e/m)],
           Polygon[
            r {{k, s},
             d {k*ka - s*sa, s*ka + k*sa},
             ta {k, s}, 
             d {k*ka + s*sa, s*ka - k*sa},
             {k, s}}]}],
        {i, 0,  n - 1}]],
      {e, 0, m - 1}]]]]]]

I won't delve into the semantics of this function, except to say that it is pure (it returns a Graphics object), and that I tend to use immutable bindings introduced by With as much as possible, but this not always affords me readable code. An invocation of wheel[12, 16] generates the following:

color daisy drawn with Mathematica

Pretty! I was satisfied with this for maybe twelve hours. I thought that it could be nice if it could be animated, or something. Doing this in OCaml was out of the question; I have no intention of installing Cairo and a host of dependencies and bindings just to be able to. Using Processing would have been an alternative; I find it, however, crude and unresponsive. Flash would have been ideal, as I'm impressed with Krazydad's wizardry. This would have the unfortunate prerequisite of me having to learn to program Flash in the first place, which is something I have not in my plans for the foreseeable future. I could have used Java, I could…

I remembered I had downloaded Top Draw. I don't think it has animation capabilities; it sits, I think, squarely in the category of "toys". It has, however, a strong graphics model, with filters and compositing inherited from Quartz. Its documentation is succint but informative, and it's Javascript, so I would feel at home. It turns out that Mathematica's retained model means that I could forget about scaling and layout; with Top Draw, those considerations must be taken into account:

var bounds = desktop.bounds;
var cx = bounds.x + bounds.width  / 2;
var cy = bounds.y + bounds.height / 2;

I had a choice between showing most of the graphic or filling most of the screen; it's a matter of a min over a max:

var sz = Math.max(bounds.width, bounds.height) / 2;

Again, the drawing should be generated with a simple call:

desktop.fillLayer(new Color(0));
wheel(12, 16);

The function wheel is where the fun begins (pun not intended). It takes two parameters, the number m of layers and the number n of rhombs to place around the circle. It starts by validating the inputs:

function wheel(m, n) {
  if (m < 1 || n < 5) return;

Each rhomb has a color determined by its position on the graphic. Each would be placed two n-ths of the way around the circle, or α = π / n. Some trigonometry shows that the diagonal of the rhomb is t = (1 + tan α)/(1 - tan α), and d is the distance to the center of the rhomb. As you can see, the rhombs grow exponentially with a factor of 1/(cos α - sin α); in order to make the entire drawing fit the prescribed size I must calculate the starting radius r accordingly:

  var color = new Color();
  var a = Math.PI / n;
  var k = Math.cos(a), s = Math.sin(a);
  var t = (k + s) / (k - s);
  var d = k + s * t;
  var r = sz * Math.pow(k - s, m);

Each tier of rhombs e has a particular saturation and brightness computed as a fraction of the total:

  for (var e = 0; e != m; e++) {
    color.saturation = 0.5*(1 + e/m); // 0.5 -- 1.0
    color.brightness = 0.5*(2 - e/m); // 1.0 -- 0.5

The rhombs spiral out of the center, since each tier is started at an angle of α from the previous one. This makes the new rhombs interlock between a pair of preexisting rhombs at the current point x, y:

    for (var i = 0; i != n; i++) {
      var b = (2*i + e) * a;
      var x = r * Math.cos(b), y = r * Math.sin(b);

(As you might have noticed, all angles are relative to the semicircle; that is, they are actually half-angles). The hue is relative to the position around the circle:

      color.hue = i / n;
      desktop.fillStyle = color;
      desktop.beginPath();

Two of the rhomb's four corners are aligned with the current point; the two others are at an angle of α at either side. Instead of computing six sines and cosines, I use the formulas for the sum and difference of angles:

      desktop.moveTo(cx + x, cy + y);
      desktop.lineTo(cx + d * (k * x - s * y), cy + d * (k * y + s * x));
      desktop.lineTo(cx + t * x, cy + t * y);
      desktop.lineTo(cx + d * (k * x + s * y), cy + d * (k * y - s * x));
      desktop.lineTo(cx + x, cy + y);
      desktop.fill();
    }

As I've indicated above, the drawing is done relative to the center of the desktop. And that's it. It only remains to scale the radius for the next tier:

    r /= k - s;
  }
}

Now it is clear that is important that n > 4 so that 0 < cos α - sin α < 1. The result of this program is essentially identical to the previous one:

color daisy drawn with Top Draw

With the added bonus that now I can start playing with filters and tweaks in real-time until I'm satisfied, or tired, or both. Let the games begin!

2008-03-03

ocamlsdl on MacOS X 10.5 "Leopard"

I've found that there a number of pitfalls that make getting ocamlsdl up and running on Leopard a less than straightforward experience. For the record, here are a number of fixes I found I needed to apply. I'm reconstructing the process after the fact, so I apologize if anything is missing.

0. Prepare your environment

You'll need to set up some environment variables first. I'm a tcsh user, while the default in Leopard is bash; hence, you'll have to modify the environment yourself depending on your shell.

Include X11 in your executable path
libpng and freetype2 live inside /usr/X11. The standard way to pass linker options is to use libpng-config and freetype-config, these are in /usr/X11/bin. Add this to your binary path.
Fix broken Leopard linker
Set and export LDFLAGS with value
-dylib_file \
  /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:\
  /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib

(this is one long option, broken into lines for ease of reading.)

1. Get SDL to compile

SDL proper builds and installs without problems; however, the tests need manual intervention.

  1. Enter the test directory and ./configure.
  2. Then manually edit Makefile and append $(LDFLAGS) to CFLAGS (line 7).
  3. Finally make and run the tests. A good test to try is testwm.

2. Compile attendant libraries

For some strange reason, SDL_image won't find the built-in libpng. Build and install it, together with libtiff. Then, build and install SDL_image, SDL_ttf and SDL_mixer. Everything should work; if not, check that the variables above are correctly set in your session's environment.

3. Compile ocamlsdl

I assume you're using ocamlfind; if not, you'll probably not find trouble with the last step.

  1. Start by doing ./configure; it should say that it'll build SDL_image, SDL_ttf and SDL_mixer.
  2. Then, edit makefile.config.gcc so that lines 29 and 30 read -framework Cocoa instead of the original -Wl,-framework,Cocoa.
  3. Also, edit src/Makefile so that line 89 reads $(RANLIB) $$($(OCAMLFIND) query sdl)/*.$(A) instead of the original $(RANLIB) $$($(OCAMLFIND) printconf destdir)/*.$(A).
  4. Finaly make it.

If you've installed a previous version of ocamlsdl and you're using ocamlfind, you'll need to manually remove the installation directory (ocamlfind query sdl) prior to sudo make install.

3. Test ocamlsdl

I've found a great "hello world"-type of walk-through., but it needs some tweaking for MacOS X, as the ocamlsdl README explains. Use the following Makefile:

RESULT        = testsdl_1
SOURCES       = testsdl_1.ml
PACKS         = bigarray sdl
OCAMLBLDFLAGS = -custom

include OCamlMakefile

and make sure that the example built with make nc (native code) and make (bytecode) both work. Again, I assume you're using ocamlfind.

Good luck!

2008-02-02

Codeless Language Module for OCaml

Since I couldn't find a ready-made syntax highlighting definition to edit OCaml code in BBEdit, I pieced together one from information and examples I found around. So, for the record, here is an OCaml Codeless Language Module that does the job:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>BBEditDocumentType</key>
  <string>CodelessLanguageModule</string>
  <key>BBLMColorsSyntax</key>
  <true/>
  <key>BBLMIsCaseSensitive</key>
  <true/>
  <key>BBLMKeywordList</key>
  <array>
    <string>and</string>
    <string>as</string>
    <string>assert</string>
    <string>asr</string>
    <string>begin</string>
    <string>class</string>
    <string>constraint</string>
    <string>do</string>
    <string>done</string>
    <string>downto</string>
    <string>else</string>
    <string>end</string>
    <string>exception</string>
    <string>external</string>
    <string>false</string>
    <string>for</string>
    <string>fun</string>
    <string>function</string>
    <string>functor</string>
    <string>if</string>
    <string>in</string>
    <string>include</string>
    <string>inherit</string>
    <string>initializer</string>
    <string>land</string>
    <string>lazy</string>
    <string>let</string>
    <string>lor</string>
    <string>lsl</string>
    <string>lsr</string>
    <string>lxor</string>
    <string>match</string>
    <string>method</string>
    <string>mod</string>
    <string>module</string>
    <string>mutable</string>
    <string>new</string>
    <string>object</string>
    <string>of</string>
    <string>open</string>
    <string>or</string>
    <string>parser</string>
    <string>private</string>
    <string>rec</string>
    <string>sig</string>
    <string>struct</string>
    <string>then</string>
    <string>to</string>
    <string>true</string>
    <string>try</string>
    <string>type</string>
    <string>val</string>
    <string>virtual</string>
    <string>when</string>
    <string>while</string>
    <string>with</string>
  </array>
  <key>BBLMLanguageCode</key>
  <string>Caml</string>
  <key>BBLMLanguageDisplayName</key>
  <string>Objective Caml</string>
  <key>BBLMScansFunctions</key>
  <true/>
  <key>BBLMSuffixMap</key>
  <array>
    <dict>
      <key>BBLMLanguageSuffix</key>
      <string>.ml</string>
    </dict>
    <dict>
      <key>BBLMLanguageSuffix</key>
      <string>.mli</string>
    </dict>
  </array>
  <key>Language Features</key>
  <dict>
    <key>Comment Pattern</key>
    <string><![CDATA[(?x:
(?> \(\* (?s: .*? ) (?> \*\) | \z ) )
    )]]></string>
    <key>Function Pattern</key>
    <string><![CDATA[(?x:
^[ \t]*
(?P<function>
  \b(?: let | and )\b [ \t]+
  (?: \brec\b [ \t]+ )?
  (?P<function_name>
    [A-Za-z]['0-9A-Za-z_]* | \([^)]+\)
  )
  (?:[ \t]+ [^ \t=]+)+ [ \t]*
  =
)
    )]]></string>
    <key>String Pattern</key>
    <string><![CDATA[(?x:
(?>
  (?<!') " (?: [^"\\] |
    (?P<escape>
      \\ (?: ['"ntbr\\] | \d{3} | x[0-9A-Fa-f]{2} )
    )
  )*
  (?> " | \z ) ) |
(?> ' (?: [^'\\] | (?P>escape) ) ' )
    )]]></string>
    <key>Identifier and Keyword Character Class</key>
    <string>\w</string>
    <key>Skip Pattern</key>
    <string><![CDATA[(?x:
(?> \(\* (?s: .*? ) (?> \*\) | \z ) )
|
(?> (?<!') " (?: [^"\\] | \\ (?: ['"ntbr\\] | \d{3} | x[0-9A-Fa-f]{2} ) )* " )
    )]]></string>
  </dict>
</dict>
</plist>

The function pattern could use some work, and the comments pattern doesn't recognize nested comments, but it's a start. I hope you will find it useful.

2008-01-28

GD on Leopard

As a once-again proud owner of a feline, I'm building my development environment. I've found an excellent walk-through for installing MySQL, and another instalation guide for GD (PDF) for PHP use. The MacBook Pro is the fastest machine I've ever used, bar none. Such a pleasure, well-worth the investment.

For the record, I'll mention the configure parameters I used to compile GD with full graphics support:

./configure --x-includes=/usr/X11/include \
  --x-libraries=/usr/X11/lib \
  --with-freetype=/usr/X11/

As in the linked-to tutorial, I assume you've installed the full X11 development libraries. With that, the result is:

** Configuration summary for gd 2.0.34:

   Support for PNG library:          yes
   Support for JPEG library:         yes
   Support for Freetype 2.x library: yes
   Support for Fontconfig library:   yes
   Support for Xpm library:          yes
   Support for pthreads:             yes

I hope somebody finds this useful.