b2cloud

12th February 2013

Dynamic Headers in Xcode

Guides | Tutorial By 4 years ago

There have been a few very rare scenarios where I have actually required a dynamic header in a project. I mention Xcode in the title however this technique really applies to nearly any IDE or command line project.

If you are not using Xcode (which is what I’m most familiar with) and want to do this, you must have the ability to execute code before the compilation process. Simple if you build through the command line, perhaps a bit difficult depending on which IDE you use. If you use Xcode, go ahead and add a new native target to your application via “File > New > New Target…”. I say native because this will need to run on the same machine you are building the project on, this is most likely an OS X Command Line Tool linked to the Foundation framework (giving you the benefits of Objective C).

 

Xcode will create a main.m for this new target, this is where all the code to generate the dynamic header will exist. Now the last setup step is to make sure that whenever you build your primary target your DynamicHeader target is executed before compilation. In the project summary select your primary target and go to the build phases section. Open the “target dependencies” and drag the DynamicHeader target into the list.

And finally add a “run script” build phase to the end of the DynamicHeader target and enter the following script

  

cd "${BUILD_DIR}/${CONFIGURATION}"
resolvedpath=`readlink ${PRODUCT_NAME}`

if [ $resolvedpath ]
then
resolvedpath=`dirname $resolvedpath`
cd $resolvedpath
fi

exec "./${PRODUCT_NAME}"

This will essentially run the DynamicHeader target every time after it is compiled.

Now anything in DynamicHeader’s main.m will be compiled and run before our primary target (SomeProject in the images above).

The example I’m going to write here is simply just going to generate a random number into a .h header that will be compiled into the primary target, obviously this is a simple example, I will go through a real scenario I have found this useful for at the end of the blog post.

In the main.m, write the following

int main(int argc, const char * argv[])
{
	@autoreleasepool
	{
		//	String contents of the header file
		NSString* headerString = [NSString stringWithFormat:@"#define kRandomNumber %i", arc4random() % 10000];

		//	Where 'this' file is
		NSString* filePath = [[NSString stringWithUTF8String:__FILE__] stringByDeletingLastPathComponent];

		//	Where the header is saved to
		NSString* headerPath = [filePath stringByAppendingPathComponent:@"GeneratedHeader.h"];

		[headerString writeToFile:headerPath atomically:NO encoding:NSUTF8StringEncoding error:nil];
	}

    return 0;
}

Compile the project and a generated header will appear in the DynamicHeader target folder. Add this back to your project and import it into your primary target and use kRandomNumber somewhere. Now every time the project is compiled a brand new random number is generated.

Download what I ended up with here.

One real example I have used this for is a project where I encrypted a bunch of the strings used inside the app. Having a dynamic header meant I could code the plain strings into the pre-compiled target which would spit out a bunch of encrypted strings into #defines I could use in a header for my primary target, making it extremely easy to add more, change the encryption and make sure I never forget to encrypt a string.

Recommended Posts

Precompilation Run Script in Xcode 4

Post by 4 years ago

Shell scripts are very handy for custom actions after compiling an Xcode project, but unfortunately they can no longer be run before compiling, not as easily as before at least. To set this up now,...

Got an idea?

We help entrepreneurs, organizations and established brands from around
the country bring ideas to life. We would love to hear from you!