There’s a good chance your iOS app includes a number of open source frameworks in its codebase, and Loose Leaf is no different. Many of these dependencies’ licenses require that you include a copy of the license in your final build. Some require other attribution or URLs. Even with just a few includes, it can quickly become difficult to manage.
Last week, we talked through how to automate our app’s version numbers, and this post will automate our bundled licenses.
The Goal: Include Licenses in our Settings
This walkthrough will help us create a custom sub-menu in our Settings.bundle to show all of our bundled licenses.
Step 1: Prepare The Settings Bundle
First, we need to define where that section will appear in our settings bundle.
In your Settings bundle, create a new file Acknowledgements.plist:
Since the contents of this file will be auto-generated each time we compile, there’s no reason to add it into your git repo. I suggest adding the path to Acknowledgements.plist into your .gitignore file.
Next,you’ll need to add 2 items to your Root.plist – a Title and a Child Pane:
The first item creates the “LICENSE” title item, and the second creates the link to our sub-menu. It references the file “Acknowledgements.plist” to use as the child pane.
Step 2: Add License Files
Next, we need to define the licenses that we’ll be wanting to include in our Settings bundle. For each license, create a separate .license file in your project contents. No need to copy these into your built product, we only need them in our source tree – we’ll be using them to generate the contents of our Acknowledgements.plist file in the next step.
Each license file should be in the following format:
Name of the Licensed Object, eg. "JRSwizzle License" etc contents of the license here - copy of the MPL or MIT License, etc
Step 3: The Build Script
I’m using the perl script from this Stack Overflow answer, and I’ve saved it as “generateLicenses.pl”. This perl script will be modifying the Acknowledgements.plist file for us.
#!/usr/bin/perl -w use strict; my $out = "Settings.bundle/en.lproj/Acknowledgements.strings"; my $plistout = "Settings.bundle/Acknowledgements.plist"; system("rm -f $out"); open(my $outfh, '>', $out) or die $!; open(my $plistfh, '>', $plistout) or die $!; print $plistfh <<'EOD'; StringsTable Acknowledgements PreferenceSpecifiers EOD for my $i (sort glob("*.license")) { my $value=`cat $i`; $value =~ s/\r//g; $value =~ s/\n/\r/g; $value =~ s/[\t]+\r/\r/g; $value =~ s/\"/\\\"/g; my $key=$i; $key =~ s/\.license$//; my $fullstr = ""; my $cnt = 1; my $keynum = $key; for my $str (split /\r\r/, $value) { if ($cnt == 1){ print $plistfh "\n"; print $plistfh "Type\n"; print $plistfh "PSGroupSpecifier\n"; print $plistfh "Title\n"; print $plistfh "$keynum\n"; print $outfh "\"$keynum\" = \"$str\";\n"; }else{ $fullstr .= "\n\n" . $str; } $keynum = $key.(++$cnt); } $fullstr =~ s/^\s+//; $fullstr =~ s/\s+$//; print $outfh "\"$keynum\" = \"$fullstr\";\n"; print $plistfh "FooterText\n"; print $plistfh "$keynum\n"; print $plistfh "\n"; print $plistfh "\n"; print $plistfh "Type\n"; print $plistfh "PSGroupSpecifier\n"; print $plistfh "FooterText\n"; print $plistfh "\n\n"; print $plistfh "\n"; } print $plistfh <<'EOD'; EOD close($outfh); close($plistfh);
Important!
Make sure the Run Script is near the top of your Phases section. This script needs to be run before the Copy Resources item in your Build Phases.
Step 4: Build your project!
That’s it! Just build and run your project, and all of the licenses should be auto-included into your Settings bundle automatically. If you ever need to add or remove more licenses, just add or remove more .license files from your project’s directory and they’ll be automatically included in the next build. Easy!
This process has been incredibly helpful for Loose Leaf‘s build process. I include a number of different open source frameworks, and this has been incredibly helpful for organizing those licenses into the build. Of course, I also have a number of frameworks that I’ve open sourced as a part of Loose Leaf’s development, so maybe I’ll see one of those included in your project too!