Local web development on MacOS X Lion

Lion no longer creates personal web sites by default. To create one manually, enter the following:

mkdir ~/Sites
echo "<html><body><h1>My site works</h1></body></html>" > ~/Sites/index.html.en

PHP is not enabled in Lion. To enable it, do:

sudo vi /etc/apache2/httpd.conf

Uncomment line 111 that reads:

#LoadModule php5_module libexec/apache2/libphp5.so

to

LoadModule php5_module libexec/apache2/libphp5.so

Edit the launchd config file for Apache:

sudo vi /System/Library/LaunchDaemons/org.apache.httpd.plist  

Remove the following:

<string>-D</string>
<string>WEBSHARING_ON</string>

Restart Apache:

sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist 
sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist 

To turn on Apache, go to System Preferences > Sharing and enable Web Sharing.

In Safari, navigate to your web site with the following address:

http://<your local host>/

It should say:

It works!

Now try your user home directory:

http://<your local host>/~<your short user name>

It should say:

My site works!

Now try PHP. Create a PHP info file with:

echo "<?php echo phpinfo(); ?>" > ~/Sites/info.php

And test it by entering the following into Safari’s address bar:

http://<your local host>/~<your short user name>/info.php

You should see your PHP configuration information. This will be important for setting up MySQL later.

Download MySQL from http://www.mysql.com/downloads/mysql/. You want the Mac OS X ver. 10.6 (x86, 64-bit), DMG Archive. Open the archive mysql-5.5.14-osx10.6-x86_64.dmg. Install only the mysql-5.5.14-osx10.6-x86_64.pkg package. Ignore everything else.

Create the launchd config file for MySQL:

sudo vi /Library/LaunchDaemons/com.mysql.mysql.plist  

Use the following content:

<?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>KeepAlive</key>
    <true/>
    <key>Label</key>
    <string>com.mysql.mysqld</string>
    <key>ProgramArguments</key>
    <array>
    <string>/usr/local/mysql/bin/mysqld_safe</string>
    <string>--user=mysql</string>
    </array>
  </dict>
</plist>

Create a config file for MySQL that matches the Apple PHP build:

sudo vi /etc/my.conf  

Use the following content:

[client]
socket=/var/mysql/mysql.sock
[mysqld]
socket=/var/mysql/mysql.sock

Start MySQL:

sudo launchctl load -w /Library/LaunchDaemons/com.mysql.mysql.plist 

Download DBD::mysql from http://search.cpan.org/~capttofu/DBD-mysql-4.019/lib/DBD/mysql.pm

Extract the archive with:

tar zxvf DBD-mysql-4.019.tar.gz

Move into the directory:

cd DBD-mysql-4.019

First, fix the MySQL client library according to instructions in:

http://probably.co.uk/problems-installing-dbdmysql-on-os-x-snow-leopard.html

For Lion, type:

sudo install_name_tool -id /usr/local/mysql-5.5.14-osx10.6-x86_64/lib/libmysqlclient.18.dylib /usr/local/mysql-5.5.14-osx10.6-x86_64/lib/libmysqlclient.18.dylib

Next, build DBD::mysql with:

perl Makefile.PL --mysql_config=/usr/local/mysql/bin/mysql_config --testsocket=/var/mysql/mysql.sock --testuser=root
make
make test
sudo make install

If you want to add modules to PHP, I suggest the following site:

http://michaelgracie.com/2011/07/21/plugging-mcrypt-into-php-on-mac-os-x-lion-10-7/

I can’t explain it any better.

 

Apple Undocumentation

This used to be in Apple’s documentation about how to create flat executables (such as command line tools) that have Info.plist data. The information is gone from Apple’s site now. Still, it may be useful:

Putting Info.plist Files in a Flat Executable

Even if your program does not use the bundle structure, it should still include an information property-list file to identify key pieces of information to the system. For unbundled CFM executables, you can place the contents of the program’s Info.plist file in a ‘plst’ resource. For unbundled Mach-O executables, you can create an __info_plist section in the executable’s __TEXT segment and put the contents of your information property-list file there. To create an __info_plist section, you would create an Info.plist file as you would for a bundled program and then add the following linker options to your makefile or Xcode project:

-sectcreate __TEXT __info_plist Info.plist

To retrieve the Info.plist information, your unbundled program can use many of the CFBundle functions for accessing bundle properties. Although your program is not bundled, you can still get the “main bundle” and pass that object to any functions you call.

Update: It looks like it just got moved instead. It is now in the Code Signing Guide.

Hidden tricks in the Xcode editor

I’m quite fond of Xcode’s built-in editor. I have no problem with anyone trying to write the Next Great Programmer’s Editor, but the bar is pretty high. I use Xcode for almost all of my programming, including web sites and Perl.

In C, you can use the #pragma mark directive to add a comment to the function listing at the top of the window. In Perl, you can do the same with “TODO:” comments. However, I wanted to see if I could add a mark without having to use “TODO:”. I dug around and found the XcodeEdit private framework and discovered the syntax files for the Xcode editor. Here is the full list of marker codes:

  • TODO:
  • FIXME:
  • !!!:
  • ???:
  • MARK: This one is special. You don’t get the mark, just the text!

Back to work!

Xcode project and file templates

I’ve known about Xcode project templates for quite a while. I even wrote a little script once that would take an Xcode project and convert it into a template. All you had to do then was copy it to a magical place in your home directory and you had custom Xcode projects.

Unfortunately, there was no way to setup file templates. If you went to Xcode File -> New File, you would get the Xcode default files.

As of Xcode 3.1.2, there are improvements. You can now specify both project and file templates. Go to /Library/Application Support/Developer/Shared/Xcode. You can create Project Templates and a File Templates directories. Copy your favorite default set from /Developer/Library/Xcode/ and edit the files. Now, just like in New Project, there will be a set of User Templates in the New File dialog box in Xcode. Of course, none of this is documented.

Don’t forget to store your templates somewhere in your home directory and use symbolic links in the system directory. That will help with upgrading.

Thanks to the MacFUSE project for tipping me off.

Paths in MacOS X

A while back, I installed git to download some random open-source code that I’ve since forgotten about. I noticed this when hacking on my .bash_profile paths to add ImageMagick. I saw that git had been inserted into my path and I couldn’t figure out how. I thought they had been screwing around with my system bash scripts but no – something else was going on…

It seems MacOS X has a little known improvement to UNIX life on the desktop. Instead of adding paths login scripts, you can put them in the /etc/paths.d directory. Add a unique text file whose contents are the path to add. You don’t get control over the order of loading, but that (usually) shouldn’t be a big deal. There is also a /etc/manpaths.d as well.

I normally don’t like to put third party stuff in / directories. That is where things get lost when upgrading. I don’t know if I should use this or not, but I don’t want to forget about it.

MacOS X Application initialization and shutdown sequence

Perhaps this is it?

  1. main.m calls the NSApplicationMain function.
  2. init methods of classes in the main nib file
  3. awakeFromNib called on classes instantiated by the nib
  4. [NSApp run]
  5. [NSApp finishLaunching]
  6. Any windows in the nib that were marked as ‘visible at launch time’ are put on screen about now.
  7. applicationWillFinishLaunching:
  8. application:openFile:
  9. applicationDidFinishLaunching:
  10. <run main loop>
  11. applicationShouldTerminate:
  12. reviewUnsavedDocumentsWithAlertTitle:cancellable:delegate:didReviewAllSelector:contextInfo:
  13. closeAllDocumentsWithDelegate:didCloseAllSelector:contextInfo:
  14. <didReviewAllSelector>
  15. applicationWillTerminate:

Updated to add information from this post.

Going where you want

I know this blog is supposed to be about programming. But we programmers sometimes like to squirrel away files in odd places. The standard MacOS X file open dialog doesn’t let you get to those places. Or does it?

I remember long ago finding a keyboard shortcut that would pop up a little window in a file open dialog that would let you type in a path for a directory. Somehow, I managed to find it again. This time, I shan’t forget it.

The keyboard shortcut is Shift-⌘-G

Carbon to the rescue

There are some areas of MacOS X where Cocoa just doesn’t do it. Either the Cocoa version doesn’t have all the options you need or Cocoa just doesn’t have the function. In many cases, Apple has quietly updated some ancient MacOS Toolbox function to work in MacOS X. Here are a few of these:

FSFindFolder and FindFolder – Helps you find all those “special” directories.
All of Navigation Services – For when NSOpenPanel just doesn’t cut it.

Command-line Cocoa

It is possible to write command-line applications using Cocoa. However, you have to be careful. The only way to test such an app is by ssh’ing into your own box. You can’t just use the Terminal. Some APIs can only be called if they have access to the console or if root is running them. You won’t know that until you run your command-line app via ssh. if You get a message such as:
kCGErrorRangeCheck : Window Server communications from outside of session allowed for root and console user only
INIT_Processeses(), could not establish the default connection to the WindowServer.Abort
That is what’s going on.

The fix is simple, just don’t use the offending code. The offending code could be anything. I haven’t found a definitive list yet. Clearly anything related to the Window Server is out. Also verboten is anything related to the Process Manager.

To compensate, there is the little-known function “NSApplicationLoad” that will bootstrap enough of the Cocoa framework to run things that normally do not work until “awakeFromNib” in a GUI application. If you don’t want to call “NSApplicationMain”, go ahead and call “NSApplicationLoad”, create your own autorelease pool, and go forth on the command line.