Professional Documents
Culture Documents
V1.23
Author .......................................................................................................................... 3 Motivation .................................................................................................................... 3 Results ......................................................................................................................... 3 The Release Folder .................................................................................................. 3 The Framework ........................................................................................................ 3 The Version Information ........................................................................................... 4 The Documentation .................................................................................................. 5 Status ....................................................................................................................... 6 Creating the Xcode project .......................................................................................... 7 Framework and Versioning Run Scripts ...................................................................... 9 Building .................................................................................................................... 9 Additional Files .......................................................................................................... 17 Re/Sources............................................................................................................. 17 Making use of that Version information...................................................................... 23 Main definition file preprocessor Define .............................................................. 23 Main implementation file constant String............................................................. 23 The Build Process ...................................................................................................... 24 Debugging .............................................................................................................. 24 Distribution ............................................................................................................. 24 Rendering a Documentation ...................................................................................... 25 Building .................................................................................................................. 25 DoxyGen .................................................................................................................... 30 Create a DoxyGen config file using the DoxyGen GUI frontend Wizard ................ 30
Author
Till Toenshoff ttoenshoff@cellular.de
Motivation
Creating highly polished, complete and useful binary modules for reuse within Xcode projects. Plain static libraries would not be sufficient as those are not produced for both, simulator and device compatibility. Creating both flavors manually and joining them using lipo is feasible but takes many manual steps. As that process can be automated, why not going the extra mile and creating a proper framework together with a real docset, usable from within Xcode. And now, that we intend to automate the entire process, why not including an automated versioning scheme allowing us to identify the exact version of the resulting framework.
Results
The
Release
Folder
You will receive a folder consisting of the Framework and the DocSet.
The
Framework
The resulting Framework pretty much looks, feels and works like one of the Applesupplied Frameworks. But unlike Apples Frameworks, this one contains a static, universal library.
The
Documentation
The DoxyGen generated DocSet is usable just like any other DocSet supplied with Xcode. For more information regarding DoxyGen and its syntax for automated documentation generation, see one of those DoxyGen manual pages. Navigate to Xcode Help->Documentation and API Reference.
Now click on that Eye-Button and select your freshly created DocSet.
Alt-Click on any documented symbol within any opened source-file and your new documentation will be used right within the Xcode quick-reference feature.
The linked symbol will lead you right into the full context and description of that symbol.
Documentation showing the Release-Tag, the Patch-Level, the Build-Counter (and the GIT-Commit-Hash)
Status
The current solution is, in parts, a bit cumbersome and has its caveats the biggest being a lot of initial preparation. I feel that this initial work is totally worth it, especially considering that it is a one-time-investment.
Select the project root item and switch to the project main target
Now drag this Run Script to the second build-phase, just after Target Dependencies.
#####################[ part 2 ]################## # # IF this is the original invocation, invoke WHATEVER other builds are required # # Xcode is already building ONE target... # # ...but this is a LIBRARY, so Apple is wrong to set it to build just one. # ...we need to build ALL targets # ...we MUST NOT re-build the target that is ALREADY being built: Xcode WILL CRASH YOUR COMPUTER if you try this (infinite recursion!) # # # So: build ONLY the missing platforms/configurations. if [ "true" = ${ALREADYINVOKED} ] then echo "RECURSION: I am NOT the root invocation, so I'm NOT going to recurse" else # CRITICAL: # Prevent infinite recursion (Xcode sucks) export ALREADYINVOKED="true" echo "RECURSION: I am the root ... recursing all missing build targets NOW..." echo "RECURSION: ...about to invoke: xcodebuild -configuration \"${CONFIGURATION}\" -target \"${TARGET_NAME}\" -sdk \"${OTHER_SDK_TO_BUULD}\" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO" xcodebuild -configuration "${CONFIGURATION}" -target "${TARGET_NAME}" -sdk "${OTHER_SDK_TO_BUILD}" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO fi ACTION="build" #Merge all platform binaries as a fat binary for each configurations. CURRENTCONFIG_DEVICE_DIR=${SYMROOT}/${CONFIGURATION}-iphoneos CURRENTCONFIG_SIMULATOR_DIR=${SYMROOT}/${CONFIGURATION}-iphonesimulator CURRENTCONFIG_UNIVERSAL_DIR=${SYMROOT}/${CONFIGURATION}-universal # ... remove the products of previous runs of this script # NB: this directory is ONLY created by this script - it should be safe to delete! rm -rf "${CURRENTCONFIG_UNIVERSAL_DIR}" mkdir "${CURRENTCONFIG_UNIVERSAL_DIR}" # echo "lipo: for current configuration (${CONFIGURATION}) creating output file: ${CURRENTCONFIG_UNIVERSAL_DIR}/${EXECUTABLE_NAME}" lipo -create -output "${CURRENTCONFIG_UNIVERSAL_DIR}/${EXECUTABLE_NAME}" "${CURRENTCONFIG_DEVICE_DIR}/${EXECUTABLE_NAME}" "${CURRENTCONFIG_SIMULATOR_DIR}/${EXECUTABLE_NAME}" echo "Done with creating a universal library
######################## # FRAMEWORK ######################## # original: http://www.cocoanetics.com/2010/05/making-your-own-iphone-frameworksin-xcode/ echo "Building framework..." # name and build location FRAMEWORK_NAME=${PROJECT_NAME} FRAMEWORK_BUILD_PATH="${PROJECT_DIR}/build/Framework" # these never change FRAMEWORK_VERSION=A FRAMEWORK_CURRENT_VERSION=1 FRAMEWORK_COMPATIBILITY_VERSION=1 # Clean any existing framework that might be there if [ -d "$FRAMEWORK_BUILD_PATH" ] then echo "Framework: Cleaning framework..." rm -rf "$FRAMEWORK_BUILD_PATH" fi # Build the canonical Framework bundle directory structure echo "Framework: Setting up directories..." FRAMEWORK_DIR=$FRAMEWORK_BUILD_PATH/$FRAMEWORK_NAME.framework export FRAMEWORK_DIR mkdir -p $FRAMEWORK_DIR mkdir -p $FRAMEWORK_DIR/Versions mkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSION mkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSION/Resources mkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSION/Headers echo "Framework: Creating symlinks..." ln -s $FRAMEWORK_VERSION $FRAMEWORK_DIR/Versions/Current ln -s Versions/Current/Headers $FRAMEWORK_DIR/Headers ln -s Versions/Current/Resources $FRAMEWORK_DIR/Resources ln -s Versions/Current/$FRAMEWORK_NAME $FRAMEWORK_DIR/$FRAMEWORK_NAME echo "Framework: Copying library..." cp "${CURRENTCONFIG_UNIVERSAL_DIR}/${EXECUTABLE_NAME}" "$FRAMEWORK_DIR/Versions/Current/$FRAMEWORK_NAME" echo "Framework: Copying assets into current version..." cp ${SRCROOT}/*.h "$FRAMEWORK_DIR/Headers"
echo "Fetching build version info" versionPlist=${SRCROOT}/Version.plist buildVersion=$(/usr/libexec/PlistBuddy -c "Print CFBuildVersion" $versionPlist) buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBuildNumber" $versionPlist) buildHash=$(/usr/libexec/PlistBuddy -c "Print CFBuildHash" $versionPlist) echo "Rendering info.plist" buildPlist=$FRAMEWORK_DIR/Resources/Info.plist cat "${SRCROOT}/Framework.plist" | sed 's/${PROJECT_NAME}/'"${PROJECT_NAME}"'/' > $buildPlist /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildVersion.$buildNumber" $buildPlist /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $buildVersion.$buildNumber" $buildPlist /usr/libexec/PlistBuddy -c "Set :CFBuildHash $buildHash" $buildPlist echo "Copying results" if [ ! -d "${CELLULAR_FRAMEWORKS_PATH}/${PROJECT_NAME}" ]; then mkdir -p "${CELLULAR_FRAMEWORKS_PATH}/${PROJECT_NAME}" fi cp -rf $FRAMEWORK_DIR "${CELLULAR_FRAMEWORKS_PATH}/${PROJECT_NAME}" exit 0
Note: This script will install the framework within your CellularFrameworks folder as defined below. Go to Xcode->Preferences->Source Trees and add a new variable using that plusicon on the bottom of the screen.
CELLULAR_FRAMEWORKS_PATH should point towards the location you intend to use for keeping a distributable version of your framework
Additional
Files
Re/Sources
Name it Framework.plist
Name it Version.plist
Add a new Header file named version.h to your project actually, this step is optional as the file will be created/rendered by the build-process. This is just for making sure that you make a note of that header-file and the ongoing changes within. Just make sure that you do not enter anything of value into this header as it will be rewritten on each and every build.
Your project browser should now look somewhat like the following
FRAMEWORK_VERSION
Distribution
For distribution. build an Archive version (Build For Archiving). Note: It does not matter whether you select Device or Simulator building as the buildscripts will always build both.
Rendering
a
Documentation
Building
Select the new Targets Build Phases Add a new Build Run Script as done before.
# Run doxygen on the updated config file. # Note: doxygen creates a Makefile that does most of the heavy lifting. echo "running doxygen..." $DOXYGEN_PATH $TEMP_DIR/doxygen.config # make will invoke docsetutil. Take a look at the Makefile to see how this is done. echo "make doxygen html install..." make -C $SOURCE_ROOT/DoxygenDocs.docset/html install exit 0
Make sure the variable DOXYGEN_PATH is setup properly in your Xcode preferences. Go to Xcode->Preferences->Source Trees and add a new variable using that plusicon on the bottom of the screen.
DOXYGEN_PATH should point towards the doxygen executeable normally located at /Applications/Doxygen.app/Contents/Resources/doxygen Add another Run Script
## ## Copy results to public location ## echo "Copying results..." cp -rf "/Users/${USER}/Library/Developer/Shared/Documentation/DocSets/de.cellular.$PROJE CT_NAME.docset" "${CELLULAR_FRAMEWORKS_PATH}/${PROJECT_NAME}" echo "Done copying results"
This script bundles the Framework with its documentation within the installation folder.
DoxyGen
Create
a
DoxyGen
config
file
using
the
DoxyGen
GUI
frontend
Wizard
Enter a proper working directory, project name, project synopsis. Enter . for the Source code directory.
Select Use built-in class diagram generator Now switch over to the Expert tab and select HTML.
Make sure that GENERATE_DOCSET is checked. You may now specify proper DOCSET-metadata like FEEDNAME, BUNDLE_ID, PUBLISHER_ID and PUBLISHER_NAME. Save the DoxyGen configuration file within your source-root-folder and name it doxygen.config.
For an initial test, you may now select Run within DoxyGen. The results should look somewhat like the following;
If all went smooth, you may now go ahead and try to full monty