You have been rejected. Last Friday you thought you had hit bottom when you got rejected by the barista of the day in account of you flirting with the barista of a different day that showed up out of turn to, surprise, have a coffee. What can you say, you got confused.
But things just went down hill from there. On Sunday your main competitor, Mystery Bunny Games, publicly criticized you on their blog! They pointed out that all that Telnet business you were babbling about made your applications waste memory, increased the size of your binary, and misspent time initializing frameworks that were never used in the final release of your app. They called it a disservice to the users, that have to suffer slow, bloated apps cause some lazy developer decided to add thousands of lines of code just for his own convenience.
Ouch.
If that was not enough, this morning you got rejected again… by Apple! They discovered they could use your binary to upload Lua scripts and run all kinds of hacks on the device. Somehow they didn’t thought that was cool.
But you have learned the lesson: never follow any advice you get on the intertubes. Now, let me explain you how you can fix two of those three problems.
Debug/Release
Whenever you build your applications you always start with an Xcode project template that has the basis all setup for you. Between other things it comes with one Target representing the product you are building, and two Configurations with the settings appropriate for both a Debug build, and a Release one.
The Target contains between other things what files, libraries, and frameworks are linked and compiled. And that is your problem. Your Telnet debug server class, AsyncSocket and the CFNetwork framework it requires, plus all those files of the Lua runtime, should really not be in your Release build; they are Debug tools. How can you have the two different builds include different files? You only see two ways of doing this, and you don’t like either.
- To create different Targets for Debug and Build, and forget about the Configurations all together. But then for files that should be shared you will have to keep the targets in sync yourself, adding files to one then to the other.
- The old
#ifdef/#endif
trick: edit all those files so they end up empty if you are building a Release. But modifying 3rd party code? You will need to do it every time they update it! And what about that framework you are linking to? Even linking empty files takes time, especially since your development powerhouse is the cheapest Mac Mini you could find on eBay.
Chunking with static libs
The first thing you really need to do is separate all this code into chunks. On one side all the code that is required for both Debug and Release. On the other, all the code for your debug server. So you start by putting it all into its own project, and building one of those static libraries you have heard about. It is so easy these days… Apple even provides you with a project template out of the box to do this.
What? Don’t want to do it yourself? Gosh, you are so damn lazy. OK, I will give you the code! Just grab it, build it and you will end up with a libLuaDebugServer.a that contains all the stuff from the last time. Well… almost all.
Remember that CFNetwork framework we needed? Static libraries don’t… well, they don’t include frameworks so… I guess we still need to link to that in the main proj… Why are you looking at me like that? Man, I am getting there! Don’t worry! When have I failed you? Yeah, don’t answer that.
Otherworldly flags
So now that you have that library, you can delete all that code from the main project and add the library instead. If you want to get serious you could even do some of that cross-project referencing and target dependencies crap. But you know what? You will still have the same problem! Adding your static lib to the project will add it to the Target, and that will link and compile it in both Configurations!
So is time to rethink this. Linking is the problem, and you need to do it differently depending on your Configuration. Hey, what’s this?
Other Linker Flags? I know you never look at any of these arcane build settings unless it is to check the -O Turbo button. But you can pass to this one here parameters for things you want linked only in the configuration selected! How? Easy.
-framework NameOfFramework
-l NameOfLibrary
So in our case, this should be…
-framework CFNetwork
-l LuaDebugServer
By the way, notice is not CFNetwork.framework
or libLuaDebugServer.a
; it figures out the filenames on its own. Now that you have that you don’t need to add the files to the Target, so they will not be linked and compiled with the Release build. Except that if you try to build the project right now, you are just going to receive a bunch of gibberish errors.
Paths
Although Xcode has no problem finding that CFNetwork framework, it has no clue where the hell your static library is. Not only that, but it doesn’t know where the headers of your static library are either, so when you call any of the methods of your LuaServer class, is more bitter than your quadruple shot of the mornings.
I am sure that you saw this coming, but you will have to mess with build settings again. The two we need are Header Search Paths and Library Search Paths. Let’s imagine that you have your static library project in the same folder than your main project. Then the paths should be like this:
- Header Search Path:
"$(SRCROOT)/../LuaDebugServer/"
- Library Search Path:
"$(SRCROOT)/../LuaDebugServer/build/
$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/"
The important parts of those paths are the quotes (useful in case you have your projects in folders with names containing spaces), the $(SRCROOT)
(that points to the folder containing the main project), and the $(EFFECTIVE_PLATFORM_NAME)
(that makes sure to grab the correct version of your library whether you are building for the simulator or for the device).
Check?
There you have it. The same project than before, featuring Pancho the Begging Cat, built so it only uses the Telnet Debug Server and all the Lua code in Debug configuration, but not in Release. You don’t believe me? Is easy to check!
Debug
Et Release
Also, did you noticed how after building for the simulator, the firewall in your Mac didn’t bug you about accepting connections when running the Release build? I say you are ready for a nasty response to the Mystery Bunny Games people. If you only knew who they were…
LuaSockets Source Code! Again!
This time not one, but two Xcode projects! One containing all the Telnet server and Lua code that builds a static library, and one with the example project.
The static library only contains headers for the LuaSocketServer class. If you want to make any of the other AsyncSocket or Lua methods available to the main project, you will need to add those headers to the Target’s Copy Headers build phase.
If you check the main project you will see the debug server code and the CFNetwork framework are gone; the Target Settings of the Debug configuration contain the necessary linking flags.
Have fun!
Pingback: App Tweaking at Under The Bridge
George Sealy; July 29, 2010, 12:15 AM
Bob; July 29, 2010, 1:39 AM
Noel; July 29, 2010, 6:29 AM
Miguel A. Friginal; July 29, 2010, 6:57 AM
Nicolas; September 15, 2010, 11:17 AM
Dave Newman; December 7, 2010, 6:02 PM
Miguel A. Friginal; December 7, 2010, 11:24 PM
Dave Newman; December 8, 2010, 1:07 AM