Building a Grand Unified Xcode 4.4 installer for both Lion and Mountain Lion
Apple has released Xcode 4.4 through the Mac App Store for all Macs running 10.7.4 and higher, including Mountain Lion. This application, on first launch, then installs the other Xcode tools. The command line tools can be installed separately through the Xcode preferences, in the Downloads section.
For my users who are developers, I wanted to include Xcode 4.4 in their new machine builds and also install the command line tools automatically. I also wanted to build one Xcode 4.4 installer that worked for both 10.7.x and 10.8.x. The Xcode 4.4 application itself runs fine on both Lion and Mountain Lion, but the command line tools are OS-specific.
To do this, I used a modified form of the methodology referenced in this post to repackage Xcode 4.4 for distribution without needing an Apple ID. See below the jump for the procedure.
Building the package
Install Xcode 4.4 from the Mac App Store onto your build machine.
Update – 7-31-2012: I’ve seen Apple ID-related issues with updating the Mac App Store’s Xcode since posting this, where I was signed into the App Store using a different Apple ID than the one used to install Xcode. To avoid this problem, download and use Xcode 4.4 from the Apple Developer site.
Download the latest Lion and Mountain Lion Command Line Tools for Xcode disk images from the Apple Developer site
Verify that the permissions on the Xcode application in /Applications are correct by running the following command:
sudo chown -R root:wheel /Applications/Xcode.app
Set up a new Iceberg project. Since we’ll need to run this installer with root privileges, I recommend setting the project type to Darwin: Package. That will open the project with the installation privileges automatically set to root.
In this case, I’m naming the project Xcode 4.4.
In the Files section, click on the Applications folder in the listing.
Go to the Archive menu and select Add Files…
Select the Xcode application in /Applications
Verify that it’s now showing up under Applications in your Iceberg project
Select the Lion and Mountain Lion Command Line Tools for Xcode disk images and drag them into the Additional Resources section of your Iceberg project.
The last pieces are removing any previous Xcode.app from /Applications and telling the correct Command Line Tools for Xcode installer to run.
To remove any previous Xcode.app from /Applications, I’m using the following preflight script:
#!/bin/sh # Remove existing /Applications/Xcode.app from machine if [ -d /Applications/Xcode.app ]; then rm -rf /Applications/Xcode.app fi
To install the command line tools, I’m using the following postflight script:
#!/bin/sh # Determine OS version osvers=$(sw_vers -productVersion | awk -F. '{print $2}') if [[ ${osvers} -eq 7 ]]; then # # Installing the Xcode 4.4 10.7 Command Line Tools # # Create /tmp/Command Line Tools (Lion) mountpoint in /tmp /bin/mkdir "/tmp/Command Line Tools (Lion)" # Mount the latest command line tools disk image as /tmp/Command Line Tools (Lion) /usr/bin/hdiutil attach "$1/Contents/Resources/xcode44cltools_10_76938107a.dmg" -mountpoint "/tmp/Command Line Tools (Lion)" -nobrowse -noverify -noautoopen # Install the Xcode command line tools /usr/sbin/installer -dumplog -verbose -pkg "/tmp/Command Line Tools (Lion)/Command Line Tools (Lion).mpkg" -target / # Clean-up # Unmount the command line tools disk image from /tmp/Command Line Tools (Lion) /usr/bin/hdiutil eject "/tmp/Command Line Tools (Lion)" # Remove /tmp/Command Line Tools (Lion) from /tmp /bin/rm -rf "/tmp/Command Line Tools (Lion)" fi if [[ ${osvers} -eq 8 ]]; then # # Installing the Xcode 4.4 10.8 Command Line Tools # # Create /tmp/Command Line Tools (Mountain Lion) mountpoint in /tmp /bin/mkdir "/tmp/Command Line Tools (Mountain Lion)" # Mount the latest command line tools disk image as /tmp/Command Line Tools (Mountain Lion) /usr/bin/hdiutil attach "$1/Contents/Resources/xcode44cltools_10_86938106a.dmg" -mountpoint "/tmp/Command Line Tools (Mountain Lion)" -nobrowse -noverify -noautoopen # Install the Xcode command line tools /usr/sbin/installer -dumplog -verbose -pkg "/tmp/Command Line Tools (Mountain Lion)/Command Line Tools (Mountain Lion).mpkg" -target / # Clean-up # Unmount the command line tools disk image from /tmp/Command Line Tools (Mountain Lion) /usr/bin/hdiutil eject "/tmp/Command Line Tools (Mountain Lion)" # Remove /tmp/Command Line Tools (Mountain Lion) from /tmp /bin/rm -rf "/tmp/Command Line Tools (Mountain Lion)" fi
Once you’ve got the preflight and postflight script built, run the following commands to make the scripts executable:
sudo chmod a+x /path/to/preflight
sudo chmod a+x /path/to/postflight
Last step, go ahead and build the package. (If you don’t know to build, check the Help menu for the Iceberg User Guide. The information you need is in Chapter 3 – Creating a package.)
Testing
Once the package has been built, test it by taking it to a test machine running 10.7.4 or higher that doesn’t have Xcode 4.4 and install it. The end result should be that Xcode 4.4 installs along with the correct command line tools for the host without requiring an Apple ID.
Aren’t you going to face problems by re-packing the App Store version? specially now that 10.8 will open the App Store automatically when an update is available
I usually use the version from developer.apple.com
I haven’t seen issues so far with the Mac App Store version. That said, getting it from the developer site also works.
I’ve now seen issues, so I’m updating the post to recommend using Xcode from the Apple developer site.
It is not clear to me whether an Xcode user must have admin rights or not in order for Xcode to be useful. Nevertheless, in using this process, and after deployment, the end user is asked to install Device tools which requires admin rights. Is this expected behavior in 4.4; should I also include the Device tools, or should Xcode only be deployed to admin users?
You can update the postflight script to include installing the Mobile Device tools if desired. The path to the package is “/Applications/Xcode.app/Contents/Resources/Packages/MobileDevice.pkg” (no quotes).
For non-admin users, they should be able to work with Xcode once they’ve been added to the “_developer” group. They can be added individually with the following command:
sudo dscl . append /Groups/_developer GroupMembership “username”
If you want to add a group (like “staff” or “everyone”) to the “_developer” group, you can run the following command:
sudo dseditgroup -o edit -a “group name” -t group _developer
You will still need to turn on developer security mode; (DevToolsSecurity -enable) or you will continue to be prompted for admin access.
From the DevToolsSecurity manpage:
“When the Xcode developer tools are installed, the post-install script automatically runs this DevToolsSecurity tool to change the authorization policies, such that a user who is a member of either the admin group or the _developer group does not need to enter an additional password to use the Apple-code-signed debugger or performance analysis tools.”
Sounds like the postinstall, paired with Rich’s tip above, should cover it, right
Great Blog!
1) I found that when you first start xcode you are prompted to install a Device package
To get around that I added these two lines at the end of your postflight script:
/usr/sbin/installer -dumplog -verbose -pkg “/Applications/Xcode.app/Contents/Resources/Packages/MobileDeviceDevelopment.pkg” -tgt /
/usr/sbin/installer -dumplog -verbose -pkg “/Applications/Xcode.app/Contents/Resources/Packages/MobileDevice.pkg” -tgt /
although probably only the 2nd line is needed.
2) I see that when installed and you look in Xcode > Preferences > Downloads tab
there are several simulators that can be installed. Any idea if it’s possible to install them from the command line and where the packages are located for them?
Ok – seems like the simulators live in the following location:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs
Seems that all that is necessary is for you to copy the iPhoneSimulatorxx.sdk folder from one installation to another. I guess that could be either downloaded already and in that case it would be part of the Xcode.app. Otherwise they could be used in another installer for people who needed it later.
David, that’s correct – although Apple has occasionally provided patches for the Simulators after they’ve been released, and checks for these when Xcode launches.
The Simulators are also available as standard packages to install, although they require some modifications to install to the correct location, and they don’t actually use receipt version numbers to check whether they’re installed. Some more info is here in a blog post:
http://macops.ca/xcode-deployment-the-dvtdownloadableindex-and-ios-simulators
Why are we not able to install the command line tools from the mpkg file? That would be easier than mounting/unmounting the dmg, but I can’t get it to work. When I drag the mpkg out of the dmg, the file size is way too small.
Also, are both MobileDevice.pkg and MobileDeviceDevelopment.pkg required to eliminate the prompt to install them when you run Xcode for the first time?
I love this site and have found lots of useful information so far.
Pete,
There’s two ways you can set up a metapackage. The first is with all of the installer packages stored inside the metapackage, so that everything you need is copied over when you copy the metapackage to a new location.
The second way is to have the installer packages stored outside the metapackage, and that’s the situation here. The metapackage is actually referencing installer packages stored in an invisible directory on the disk image named Packages. By mounting the disk image and running the metapackage from the disk image, the install can run because the metapackage can access the installers in that hidden directory.
But how can one convert a metapackage of the second kind (with pkgs located outside the mpkg) into a metapackage of the first kind (with all the pkgs stored inside the mpkg)?
I’ve tried running pkgutil –expand on the mpkg, editing the Distribution file (specifically the file URL in the pkg-ref), and rebuilding the mpkg with pkgutil –flatten. I can never get the resulting mpkg to show a file listing of all the incorporated pkgs.
Any