A tip about install_name_tool

Install_name_tool is a trick to hack up an executable so that it is using specific dynamic libraries. It is very handy for embedding libraries in the bundle. However, there might not be enough room in the binary for the new name. Here is a solution from Apple Developer Forums.

It's a linker option.  It's documented in the ld man page.
The idea is that install_name_tool is changing the contents of one of the Mach-O loader commands in the executable in place.  It's not completely rebuilding the executable.  So, the new install name needs to fit in the space that was already allocated for the existing loader command.  There's no guarantee that there's enough space for the new name if it's longer than the old name, unless you tell the linker to set aside additional space at the time the executable is built.  That's what -headerpad_max_install_names does.

Old skills still needed

Apple has once again, decided to reinvent the world. Unfortunately, they still haven’t finished with the last re-invention. It looks like people are going to have to start building things by hand again. Since I appear to have forgotten it, here is a command to show what dynamic libraries are liked to an object file:

otool -L /path/to/app/or/dylib

This is particularly important for C++, which is now apparently fully resurrected. It seems people were just getting too much done with dynamic languages and scripting. OS X (and iOS?) conveniently ship with multiple versions of the C++ standard library so that Apple can claim 100% compliance with the C++ standard.

So you want to do unit testing?

But not for regressions, of course. Then you would be just like those fresh-faced Apple programmers “coding to the test” and building a system that satisfies all tests, but doesn’t really work that well, and misses critical tests of functionality.

No. You want to do unit testing so you can validate the behaviour of classes in an environment that is much more simple that your final application. Once your prove your objects are working well, there will be little need to ever run the tests again.

But why aren’t your unit tests working? Or, rather, why aren’t your categories defined in a static library working? It finds the header. It is linking with the library. Your project is correctly using Apple’s crazy sibling workspace design. But your static library is missing at runtime?

Silly programmer. You forgot to include the “-all_load” flag to your linker flags to tell Xcode that you really do want to link to your libraries.

Edit: Apparently this is the result of two different linker bugs, from 2006 and 2010, of course. I’m sure the linked passed all the unit tests.

Pushing a local git repository to a remote ssh server

  1. Log on to the remote server
  2. Create a directory for the repository at /home/<me>/gitrep/repo.git
  3. Move into directory and create empty repository with “git init –bare”
  4. In the local repository, connect it to the remote with “git remote add origin ssh://<server>/home/<me>/gitrep/repo.git”
  5. Push local to remote with “git push -u origin master”

All done!

Debugging from a crash report

First, copy the submitted application binary and symbol file to somewhere handy like /tmp:

/tmp $ ls
EtreZip.app         launch-SS7kMq       launchd-343.Qidr35
EtreZip.app.dSYM    launch-duAAWh       launchd-523.GJ15q5
apr3yB4WN           launchd-1560.gDV25alaunchd-991.8pAEY8

Then find the address of the application in memory from Binary Images:

Binary Images:
 0x104717000 - 0x104919fef +com.etresoft.EtreZip (1.0.1 - 1.0.1)

Next, locate the crash in the backtrace:

Application Specific Backtrace 1:
0 CoreFoundation 0x00007fff8bbc725c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff89f9de75 objc_exception_throw + 43
2 EtreZip 0x00000001047381c5 EtreZip + 135621
3 EtreZip 0x0000000104739283 EtreZip + 139907
4 EtreZip 0x00000001047373e9 EtreZip + 132073
5 EtreZip 0x0000000104775434 EtreZip + 386100
6 libdispatch.dylib 0x00007fff85f9d1d7 _dispatch_call_block_and_release + 12

Now execute atos with this information to find the location. (Type this all on one line).

/tmp $ xcrun atos -arch x86_64 -o EtreZip.app.dSym/Contents/Resources/DWARF/EtreZip 
-l 0x104717000 0x00000001047381c5

got symbolicator for EtreZip.app.dSym/Contents/Resources/DWARF/EtreZip, base address 100000000
-[TCPListeningSocket readListeningPort] (in EtreZip) (TCPListeningSocket.m:191)

 

I guess we use git now

To create a local git repository of the current directory: git init

Add files with: git add *

Commit with: git commit

Now create a directory on Dreamhost: mkdir <reponame>.git

Create the remote repository: git init –bare

Now connect the two. From the local repository: git remote add origin ssh://path/to/<reponame>.git

Setup the link: git push -u origin master

Local Mail Server for MacOS X Lion

Download the UW IMAP software from http://www.washington.edu/imap/

Connect to ftp://ftp.cac.washington.edu/imap

Login as guest

Copy the file imap-2007f.tar.gz to your Desktop

Expand the archive with

tar zxvf imap-2007f.tar.gz

Fix the makefile. Open imap-2007f/Makefile and comment out line 422 that reads:

        EXTRACFLAGS="$(EXTRACFLAGS) -DMAC_OSX_KLUDGE=1" \

Build the software with:

make oxp SSLDIR=/usr SSLCERTS=/System/Library/OpenSSL/certs

Create a place to store the server:

sudo mkdir -p /usr/local/libexec

Copy the server into place:

sudo mv ipopd/ipop3d /usr/local/libexec

Create a PAM authentication module:

sudo cp /etc/pam.d/ftpd /etc/pam.d/pop

Create a self-signed certificate:

sudo openssl req -new -x509 -nodes -out /System/Library/OpenSSL/certs/ipop3d.pem -keyout /System/Library/OpenSSL/certs/ipop3d.pem -days 3650

Create launchd config files

sudo touch /Library/LaunchDaemons/edu.washington.pop3.plist
sudo vi /Library/LaunchDaemons/edu.washington.pop3.plist

Enter the following content:

<?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>Label</key>
 <string>edu.washington.pop3</string>
 <key>ProgramArguments</key>
 <array>
 <string>/usr/local/libexec/ipop3d</string>
 </array>
 <key>Sockets</key>
 <dict>
 <key>Listeners</key>
 <dict>
 <key>Bonjour</key>
 <false/>
 <key>SockServiceName</key>
 <string>pop3</string>
 <key>SockType</key>
 <string>stream</string>
 </dict>
 </dict>
 <key>inetdCompatibility</key>
 <dict>
 <key>Wait</key>
 <false/>
 </dict>
 </dict>
</plist>

Do the same for /Library/LaunchDaemons/edu.washington.pop3s.plist. changing Label to pop3s and SockServiceName to pop3s

Load the launchd config files:

sudo launchctl unload -w /Library/LaunchDaemons/edu.washington.pop3.plist
sudo launchctl load -w /Library/LaunchDaemons/edu.washington.pop3s.plist

Test your POP server:

openssl s_client -connect localhost:995
CONNECTED(00000003)
depth=0 <certificate stuff…>
emailAddress=<the e-mail address you used for the certificate>
verify error:num=18:self signed certificate
verify return:1
depth=0 <certificate stuff…>
emailAddress=<the e-mail address you used for the certificate>
verify return:1
---
Certificate chain
 0 s:<certificate stuff…>
   i:<certificate stuff…>
---
Server certificate
-----BEGIN CERTIFICATE-----
<certificate content in base64>
-----END CERTIFICATE-----
subject=<certificate stuff…>
emailAddress=<the e-mail address you used for the certificate>
issuer=<certificate stuff…>
emailAddress=<the e-mail address you used for the certificate>
---
No client certificate CA names sent
---
SSL handshake has read 1037 bytes and written 328 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID: <something…>
    Session-ID-ctx: 
    Master-Key: <something else…>
    Key-Arg   : None
    Start Time: 1311510626
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---
+OK POP3 localhost 2007f.104 server ready
user <your short user name>
+OK User name accepted, password please
pass <your login password>
+OK Mailbox open, 5 messages
quit
+OK Sayonara
read:errno=0

Edit the launchd config file for postfix:

sudo vi /System/Library/LaunchDaemons/org.postfix.master.plist 

Add the following:

<key>KeepAlive</key>
<true/>

Remove the following:

<string>-e</string>
<string>60</string>

Restart postfix master:

sudo launchctl unload -w /System/Library/LaunchDaemons/org.postfix.master.plist 
sudo launchctl load -w /System/Library/LaunchDaemons/org.postfix.master.plist 

Test your SMTP server:

telnet <your local host> 25
Trying fec0:0:0:fea9::1...
Connected to <your local host>.
Escape character is '^]'.
220 <your local host> ESMTP Postfix
EHLO <your local host>
250-<your local host>
250-PIPELINING
250-SIZE 10485760
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-BINARYMIME
250 CHUNKING
^]
telnet> quit

Construct a test message:

From: <your short user name>@<your local host>
To:  <your short user name>@<your local host>
Subject: This is a local test
This is a local test of the mail system.

Send your test message:

cat test.txt | sendmail -t

Setup Apple Mail to connect to:

Incoming Mail Server: <your local host>

User Name: <your short user name>

Password: <your login password>

Outgoing Mail Server SMTP: <your local host>

Use only this server: checked

Advanced:

Port: 995

Use SSL checked

Authentication: Password

Check your e-mail in Apple Mail. Accept the certificate. 

 

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.