Compiling Individual Files

Continuing the adventure of compiling Swift files without Xcode, you may have the need to compile individual files. I’m not sure if we can use this method to build up our own incremental builds for Swift as I don’t have any projects large enough to experiment with yet, but it could be interesting.

I’m going to start out with a couple of files: foo.swift and main.swift.

foo.swift

public func foo() -> String { return "Foo" }

main.swift

println("Hello, World!")

Now, if you simply run:

$ swiftc -sdk $(xcrun --show-sdk-path) -emit-object foo.swift -o foo.o

You’ll get a binary that will contain a main function as the compiler will add one in for your implicitly. When you go to link the files, you’ll end up with duplicate symbol collision.

$ nm foo.o 
00000000000000d8 s EH_frame0
0000000000000065 s L___unnamed_1
0000000000000010 T __TF3foo3fooFT_SS
0000000000000118 S __TF3foo3fooFT_SS.eh
                 U __TFSSCfMSSFT21_builtinStringLiteralBp8byteSizeBw7isASCIIBi1__SS
                 U __TFSsa6C_ARGCVSs5Int32
                 U __TFSsa6C_ARGVGVSs20UnsafeMutablePointerGS_VSs4Int8__
0000000000000030 T _main
0000000000000140 S _main.eh
0000000000000000 t _top_level_code
00000000000000f0 s _top_level_code.eh                     

Remember how I said that there are some interesting differences between swift and swiftc, well, here’s another one.

What we need to do is tell Swift to compile foo.swift but also let the compiler know that we have some other files. We can do that like this:

swift -frontend -c -sdk $(xcrun --show-sdk-path) -emit-object -primary-file foo.swift main.swift -o foo.o

NOTE!! You cannot use the -primary-file switch with swiftc; it’s only available when you use swift -frontend -c. What I believe is happening is that the primary file is getting compiled and the compiler is using all of the other input files for determining available symbols.

After updating the files to look like this:

foo.swift

public func foo() -> String {
    let message = testing()
    return "Foo - \(message)"
}

main.swift

public func testing() -> String { return "testing!" }
println("Hello, World!")

Then compiling foo.swift:

$ swift -frontend -c -sdk $(xcrun --show-sdk-path) -emit-object -primary-file foo.swift main.swift -o foo.o

We can see all of the goodies, including the all important missing main function definition.

$ nm foo.o
0000000000000268 s EH_frame0
00000000000001f2 s L___unnamed_1
0000000000000000 T __TF3foo3fooFT_SS
0000000000000280 S __TF3foo3fooFT_SS.eh
                 U __TF3foo7testingFT_SS
                 U __TFSS30convertFromStringInterpolationfMSSFtGSaSS__SS
                 U __TFSS37convertFromStringInterpolationSegmentfMSSFSSSS
                 U __TFSSCfMSSFT21_builtinStringLiteralBp8byteSizeBw7isASCIIBi1__SS
                 U __TFSa20convertFromHeapArrayU__fMGSaQ__FTBp5ownerBo5countBw_GSaQ__
                 U __TMdSS
                 U __swift_FORCE_LOAD_$_swiftFoundation
0000000000000218 S __swift_FORCE_LOAD_$_swiftFoundation_$_foo
0000000000000160 t _arraydestroy
00000000000002a8 s _arraydestroy.eh
0000000000000200 s _metadata
                 U _swift_allocObject
                 U _swift_deallocObject
                 U _swift_unknownRelease
                 U _swift_unknownRetain

There are a lot more options available to us, like:

  • -emit-module which would let us produce partial .swiftmodule files.
  • -emit-module-path for the path of the partial .swiftmodule files.
  • -emit-module-doc-path for the path of the partial .swiftdoc files.

Of course, this is only the tip of the iceberg. Next, you’ll need to merge the

swiftmodule files together and then link the object files together to actually create a usable executable or library.

That’s for another day.

Compiling Individual Files

swift vs swiftc

While working on [yesterday's post][yesterday], I noticed that Xcode uses the

swift command to perform its compiles rather than the swiftc command. What's odd, and maybe some others know more information here, is that swiftc is just a link to swift.

$ xcrun -f swift
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift

$ xcrun -f swiftc
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc

$ xcrun -f swift | ls -l swift*
-rwxr-xr-x  1 root  wheel  35546880 Nov 17 10:16 swift
-rwxr-xr-x  1 root  wheel    505488 Nov 17 10:16 swift-demangle
-rwxr-xr-x  1 root  wheel     46832 Nov 17 10:16 swift-stdlib-tool
lrwxr-xr-x  1 root  wheel         5 Nov 18 12:38 swiftc -> swift

However, it seems the swift tool itself is detecting how it's actually being run and switching modes internally.

This is obvious if you just run the two:

  1. swift – opens the Swift interpreter
  2. swiftc – prints an error <unknown>:0: error: no input files

So why am I bringing this up? Well, I found it interesting. =) In the end, I believe that swiftc is virtually the same as swift -frontend -c; however, I've not been able to confirm that fully and the error messages are slightly different between swiftc and swift -frontend -c, so the code path has to be at least a little different.

swift vs swiftc

Compiling Swift Without Xcode

Sometimes you want to compile code without Xcode and all it's glory. This can be advantageous in some respects, so let's dig into the different ways we can compile some Swift code and project types from the command-line using only

make and swiftc.

Project Types

Currently, as of Xcode 6.1.1, Swift is only officially supported in essentially two types of targets:

  1. An executable target.
  2. A dynamic library (Xcode only supports a framework project).

Also, if we take a look at the output of swiftc -help, we can see:

OVERVIEW: Swift compiler

USAGE: swiftc [options] <inputs>

MODES:
  -dump-ast        Parse and type-check input file(s) and dump AST(s)
  -dump-parse      Parse input file(s) and dump AST(s)
  -emit-assembly   Emit assembly file(s) (-S)
  -emit-bc         Emit LLVM BC file(s)
  -emit-executable Emit a linked executable
  -emit-ir         Emit LLVM IR file(s)
  -emit-library    Emit a linked library
  -emit-object     Emit object file(s) (-c)
  -emit-silgen     Emit raw SIL file(s)
  -emit-sil        Emit canonical SIL file(s)
  -parse           Parse input file(s)
  -print-ast       Parse and type-check input file(s) and pretty print AST(s)

The import items from above are -emit-executable and -emit-library. Those are the ones that will get us where we want to go.

Executable Target

For the executable, all you need is a main.swift file stored in a src directory.

main.swift

println("Building with make!");

And the Makefile looks like this:

# A simple build script for building projects.
#
# usage: make [CONFIG=debug|release]

MODULE_NAME = tool
SDK         = macosx
ARCH        = x86_64

CONFIG     ?= debug

ROOT_DIR    = $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
OUTPUT_DIR  = $(ROOT_DIR)/bin
TARGET_DIR  = $(OUTPUT_DIR)/$(SDK)/$(CONFIG)
SRC_DIR     = $(ROOT_DIR)/src

ifeq ($(CONFIG), debug)
    CFLAGS=-Onone -g
else
    CFLAGS=-O3
endif

SWIFTC      = $(shell xcrun -f swiftc)
CLANG       = $(shell xcrun -f clang)
SDK_PATH    = $(shell xcrun --show-sdk-path --sdk $(SDK))
SWIFT_FILES = $(wildcard $(SRC_DIR)/*.swift)

build:
    mkdir -p $(TARGET_DIR)
    $(SWIFTC) $(SWIFT_FILES) -emit-executable -sdk $(SDK_PATH) -module-name $(MODULE_NAME) -emit-module -emit-module-path $(TARGET_DIR)/$(MODULE_NAME).swiftmodule -o $(TARGET_DIR)/$(MODULE_NAME)

clean:
    rm -rf $(TARGET_DIR)

nuke:
    rm -rf $(OUTPUT_DIR)

This is a fairly simple Makefile that supports debug and release configurations, as well as cleaning or completely removing all of the built output.

This Makefile will produce three things:

  1. The executable binary for the tool.
  2. A swiftmodule file.
  3. A swiftdoc file.

All of the intermediate files are placed into temp directories. If you would like to see those, pass -v into swiftc.

Library Target

The library target is identical except for changing -emit-executable with

-emit-library.

Notice that once you make this change, main.swift will no longer compile properly. So change the file to this:

public func message() -> String {
    return "Building with make!"
}

Since the above method is public, when you consume this library, and because we are generating the swiftmodule file, the function will be available for you to call.

Summary

You'll probably not always want to use this technique and simply opt for the comfort of Xcode and its project configuration settings. However, if you need to setup a simple project and just want to use your favorite editor, copy this

Makefile, make a few adjustments, and you're good to go.

Compiling Swift Without Xcode

We Can Do Better

Abstraction.

It is the idea that we can break things down into nice, cohesive parts. Once we do that, we start to build more and more abstractions on top of what we have until we are left with what we have today: obscurity.

It saddens me that the we are equating “modern programming” as meaning we need to abstract away the fundamental parts of programming. Many languages coming out today are trying to get away from what programming fundamentally is: manipulating memory.

Now, I get it. Memory management can be a pain. However, as I reflect on where our industry has gone, it seems to be as if we’ve thrown the baby out with the bathwater. We’ve introduced highly involved and complicated systems to attempt to solve this memory management problem.

And have we succeeded?

For some domains, we have gotten “good enough”. So when I see languages coming out that are so focused on getting rid of memory management as a core principle, it just feels wrong to me. It feels like we are solving the wrong problem.

I think the problem comes down to two things:

  1. Clarity of expression – how well can we author our code, understand our code, and maintain our code?
  2. Introspective ability – how good are our tools that we use to help us diagnose our problems?

The first, I think it is a language problem. The second is a tooling problem. If we could track the lifetime of every allocation in our program, we could understand just exactly where and why memory is being leaked. We could track who is overwriting memory that they don’t own. We could know when memory is being accessed that has been reclaimed.

Yes, to some extent we’ve invested in some of these tools. But most of them suck and the language does little to help diagnose any of these problems. The language also does little to help you prevent these problems, and when they do try and help, those languages make doing many things much more difficult. High Friction.1

That’s what I want to try and do. Create a better language that allows you to be expressive, pragmatic, and get stuff done without handcuffing and treating you like a child.

Hello Proteus.

  1. The “high friction” term is something that Jonathan Blow talks about in his exploration of a new programming language for games. If you have not seen his videos, they are great; I highly recommend you check them out.
We Can Do Better

Static Wins! RAH RAH!

Warning: This is a bit of a rant; you’ve been warned.

Recently, the Swift team published this blog: What Happened to NSMethodSignature?

This is the first thought that went through my head:

Or which one of you, if his son asks him for bread, will give him a stone?

Matthew 7:9

Seriously, someone asks for the functionality for dynamic dispatch and you say you can do the same thing with static code! No, you cannot. You can mimic the behavior.

Instead, you showed someone how to build a static registration table. Then you make the statement that it’s “type-safe” while using Any as the arguments to the public API for dispatch and using type coercion… that’s not type-safety. And let’s be honest, it’s really not that different then the validation one does for dynamic dispatch either.

To make matters worse… no one writes that type of code for long without using MACROs because you end up with soooooo much duplicated, boiler plate code. But of course, Swift doesn’t support MACROs. Now you have two choices:

  1. Copy-paste for all the registration items.
  2. Build a custom tool to create the code from some metadata.

You see, and this is the trade-off that you never mention. You paint an extremely biased position without covering the full gambit of what is really needed to build and maintain a system like you are proposing. The reality, it sucks.

And that’s what really irked me about the post: you state the static registration table as the right and better way to solve the problem but speak to none of the drawbacks.

I’ve built systems using both static dispatch tables and dynamic invocation. I cannot say that I’m looking forward to building those same systems in Swift today.

Static Wins! RAH RAH!

Silently Failing

Over at Human Friendly there is a blog post about needing an AssertingNilCoalescing operator: !!. I get what is being said: you have an Optional that shouldn’t be nil (it’s an Optional for many reasons, typically outside of your control such as a bridged item from ObjC). Sounds reasonable, after all, no one likes crashing apps and the alternative is to use the if-let form to handle the case (or the shorthand ??).

So instead of writing this:

assert(opt != nil)
let foo = opt ?? safeValue

You use the shorthand version:

let foo = opt !! safeValue

Sure, it’s more terse. However, and this is the main reason I do not like this pattern: it is introducing a class of bugs that Swift has intentionally chose to make hard to get into and the very reason some are choosing to rewrite everything in Swift.

We did indeed see surprising patterns in the causes of these bugs. I found myself repeatedly saying to myself or Janie that a particular bug wouldn’t have even compiled under Swift, or would have thrown an immediate exception. When we totaled up bugs like this, we found that 40% of bugs shipped to customers in the last three years would have been caught immediately by using Swift. The primary classes of these bugs were:

  • Silent failures due to nil-messaging (emphasis added)
  • Improperly handled NSErrors, or other Objective-C error failures
  • Bad object typecasts
  • Wrong enum lookup tables being used for values

Source: http://www.sunsetlakesoftware.com/2014/12/02/why-were-rewriting-our-robotics-software-swift

This operator is introducing the same exact semantics that some are trying to run away from.

If opt is never supposed to be nil, then do an assert on it and log those errors using some sort of telemetry system or simply force unwrap it. The crash logs will help you find these issues and fix them, silently failing will not get you that information.

And you won’t find these issues in testing when using assert unless you also test against debug builds. If you are testing debug builds instead of release builds, then you really are not testing the product you’ll be giving your customers… but that’s a topic for another day.

Silently Failing

More on the Optionals!

We can chose to write stable code or we can hand-wave stuff that “shouldn’t fail”. I’m extremely wary of the pattern that I keep seeing from Apple about ! and Optional… I find it odd that Apple is promoting the use of the ! pattern.

An initializer defined with init can be made failable by adding a ? or a ! after the init, which indicates the form of optional that will be produced by constructing an object with that initializer. For example, one could add a failable initializer to Int that attempts to perform a conversion from a String:

extension Int {
    init?(fromString: String) { 
        if let i = fromString.toInt() {
            // Initialize 
            self = i
        } else {
            // return nil, discarding self is implied
            return nil
        }
    }
}

Source: Apple Developer Blog: https://developer.apple.com/swift/blog/

If we change the init? above to init! (which the description above tells us is perfectly valid)…

let value = Int(fromString: "abc")
return value + 1

BOOM! Hello my EXC_BAD_INSTRUCTION friend.

Look, sometimes your code really should only return nil in the most dire of circumstances, ok… but is the right behavior to crash your app? Even if it is, it should not be so easy to enable the return of nil from something that should practically never return nil, such as memory allocations handled by the system.

One of Swift’s goals is this: “Understanding and properly handling cases where objects are nil is fundamental to the frameworks, and Swift code makes this extremely easy.” (Source: https://developer.apple.com/swift/)

I truly believe this behavior is leading us away from that – I’d go so far to claim it’s the antithesis of it, but that may be too extreme for some.

As developers, we want to be able to write both safe and stable apps. The ! is leading us down the path of safe but crashy apps. We’re going to get there just as we got there with * and dereferencing null pointers. Of course, everyone knows not to do it… yet sometimes we forget. And to those new to the language, they might not know better.

See: Pointer fun with Binky.

I would much rather see APIs defined like this:

@unsafe_force_unwrap func init(fromString: String) { ... }

Give support for the feature when needed, but people will be much less prone to accidentally doing it. It needs to be marked as unsafe; currently there is no really indication other than experience with the language.

This also gives us the ability to have compiler warnings/errors when these are used so we can much easier audit those code usages.

More on the Optionals!

Optionals Beware

Update: 10/20/2014 I was inappropriately applying ? to the key lookup, which of course, does nothing. It is simply not needed.

Optionals… that pesky little safe, but sometimes dangerous, construct in Swift. It's not new or unique, but they do work a bit different than other languages.

GIVE ME THE VALUE!!! In John Siracusa's Yosemite review, there's a section on Swift. In it, while talking about safety and optionals, there's a trap in here.

let ages = [
    "Tim":  53,  "Angela": 54,  "Craig":   44,
    "Jony": 47,  "Chris":  37,  "Michael": 34,
]

let people = sorted(ages.keys, <).filter { ages[$0]! < 50 }

swift

Do you spot it? It's the use of !.

And that's the problem with the !, in some cases, it is safe to use it… until you start to modify the code around the area, then it might start to get dicey.

There is a safe way to write the code that will never cause your program to crash, regardless of the refactoring you do:

let people = sorted(ages.keys, <).filter { ages[$0] < 50 }

Removing the ! provides all the safety we need. The comparison operators already handle optionals. In the case of <, when the left hand side is nil, the result is always true.

Whenever you see the ! in your code, BE CAREFUL!!! I'd go so far as recommending to never use it. There are safer ways, though, they are sometimes it is a bit more verbose.

So instead of writing this:

func |||<T>(opt: T?, defaultValue: T) -> T
{
    return opt != nil ? opt! : defaultValue
}

swift

Write this:

func |||<T>(opt: T?, defaultValue: T) -> T
{
    if let opt = opt { return opt } else { defaultValue }
}

Update: Yes, you could use ??, that's not the point. The point is just showing how to write the forced unwrapped version in way that doesn't require forced unwrapping.

Beware of the optional!

Optionals Beware

Stop to Smell the Roses

I would love to build a better Objective C language. It would be a language that embraces the functional programming world and the imperative programming world, the world of dynamic runtimes and static types, and build a bridge to the future from the past.

The following is taken from some of my notes, so the code samples might be a bit rough.

Class definitions would be simple and straight forward:

' All classes derive from `NSObject` by default. Use the `derives <class>` syntax
' to subclass differently. Also, use `implements <type>, <type>, ...` for protocols.
interface Person
    ' The `let` keyword creates readonly properties.
    let firstName :: NSString
    let lastName :: NSString

    ' The `var` keyword creates read/write properties.
    ' The `[copy]` is the attribute applied to the property, in this case
    ' all writes to `emailAddress` will create a copy of the incoming value.
    var emailAddress :: NSString [copy]

    ' initializer with parameters, defaults to returning `instancetype` in ObjC
    def initWithFirstName::NSString lastName::NSString
        _firstName = firstName
        _lastName = lastName

    ' a message name with a single parameter, defaults to returning `void` in ObjC
    def say message::NSString
        log("\(firstName) says \"\(message)\"")

    ' A simple message that returns a `NSString`
    def fullName -> NSString
        return "\(firstName) \(lastName)"

All function definitions would allow for partial application:

def sum x: Number -> y: Number -> Number
    return x + y

let sum1 := sum 1
let sum2 := sum1 2
let full := sum 3 4
log "sum of 1 + 2 = \(sum2)"

Syntax would be light and free of unnecessary tokens:

' No difference between message calls and function calls
let david := Person newWithFirstName:"David" lastName:"Owens
david.emailAddress := "david@owensd.io"

' Use () to group nested calls for ordering
let sally := (Person alloc) initWithFirstName:"Sally" lastName:"Sue"
sally say:"Hello all the peoples!"

let ages = {
    "Tim":  53,  "Angela": 54,  "Craig":   44,
    "Jony": 47,  "Chris":  37,  "Michael": 34,
}

let people = filter (key => ages[key] < 50) (sort < (ages allKeys))

All of this code can be re-written to ObjC (by a tool). I have prototypes of some of it and manual constructions of others. I know it’s possible and it allows for full interop between this language dubbed Proteus and ObjC.

But… what’s the point?

I don’t mean to ask that as a submission or a throw-in-the-towel remark. But really, what’s the point? Where do I want to go with it? It would be fun to go through designing this out and getting all of the main scenarios working – I haven’t done that since my college days. I don’t even think it’s a super amount of work. But the edge cases will suck. The considerations of certain C constructs will get a bit dodgy. And in order to really get the performance up to par, I’m likely going to need to emit LLVM code instead of going through the ObjC source code, or worse (in my opinion), need to make changes to LLVM or Clang like the Eero project did. And this is before I even get into editor support, code highlighting, debugging, etc…

Swift has it’s warts. It’s a baby that’s trying to grow up quickly in a world that is harsh. The question I’ve been asking myself, both through these posts and throughout the weeks is really this: are Swift’s warts and ugly places worse than those of Objective C’s? Will they be tomorrow?

There will be a lot I miss about ObjC. Hopefully we’ll see more of that over time. But I think it’s time for this station to get back to it’s regularly scheduled program.

Stop to Smell the Roses

Building a Better Objective C

If you’ve been following along with my recent posts regarding enums and Objective C, you’ll notice a theme: Objective C is quite capable of expressing what we want, it’s just extremely verbose, especially compared to the improved syntax that Swift brings to the table.

There are many significant drawbacks to Swift, especially when you need to interop with ObjC code. In this world, we need something better. We need to be able to transparently bridge between the world of modern syntax and conveniences without being shackled to the days of C programming, while at the same time, being able to maintain 100% interop with all of our existing ObjC code.

We could continue to suffer through the ObjC syntax, or, we can do something about it.

Framing the Solution One solution to solving the problems I exposed in the series with enums is to use a bunch of MACROs. That works, but it doesn’t get us nearly where we want to be: a modern, sleek syntax that is both easy to write, and more importantly, easy to read and reason about.

This is where we want to be:

enum CompassPoint: North | South | East | West

That’s it. That’s all it should take to define one of the “traditional” enums.

enum Barcode:
  | UPCA(numberSystem :: int, manufacturer :: int, product :: int, checkInt :: int)
  | QRCode(code :: NSString)

And above is what the “associative value” enum looks like. I’d like to call out something here, we actually have more information encoded in the enum then Swift here – we capture the name of the components1. This adds much more clarity to what the values actually are.

And finally, the raw values:

enum ASCIIControlCharacter :: NSString:
  | Tab := "\t"
  | LineFeed := "\n"
  | CarriageReturn := "\r"

You might be wondering at how we are going to accomplish this. Well, it’s actually pretty straight forward. Here are the items we’ll be building:

  1. A parser for our enum syntax
  2. A tool to convert our parse tree to ObjC code

That’s it. We don’t actually need anything else2. I’ll show how we can leverage Xcode’s built-in extensibility points to give us nice error reporting and seamless integration of our new enum definition.

I will be calling this new language: Proteus.

Building the Parser There are basically two ways to generate the parser: handwrite one or use some tools to generate one from a grammar. I’m going to handwrite our parser, primarily because our enum grammar is quite simple and it’s really easy to provide very friendly error messages with a handwritten parser.

Note: I’ll only be showing building the most simple of parsers accepting only the basic version of the enum. The full github link will be posted at the end. Overtime I’ll continue to add support more features.

The work is going to be broken up into the following components:

  1. Scanner – this is going to break up the input file into a set of tokens.
  2. Analyzer – this is going to take the tokens from the Scanner and apply meaning to them, returning an array of Constructs.
  3. Construct – a representation of the different type of language constructs, such as enum or func.
  4. Rewriter – a function that can take a Construct and turn it into the appropriate Objective C header and implementation files.

I will be writing the components in Swift – I like the irony of building a better Objective C in a language that I think didn’t live up to that promise. =)

The full source for the project can be found here: https://github.com/owensd/proteus3.

If you take a look at the code for the scanner (in lexer.swift), the output for the CompassPoint declaration are the following tokens:

  1. Token(Keyword) “enum”
  2. Token(Identifier) “CompassPoint”
  3. Token(Colon) “:”
  4. Token(Identifier) “North”
  5. Token(Pipe) “|”
  6. Token(Identifier) “South”
  7. Token(Pipe) “|”
  8. Token(Identifier) “East”
  9. Token(Pipe) “|”
  10. Token(Identifier) “West”

This input is passed into the Analyzer which outputs an Enum construct.

Enum:
  typeName = "enum"
  identifier = "CompassPoint"
  options = [
    "North",
    "South",
    "East",
    "West"
  ]

Then there is the rewriteEnumToObjC rewriter function. The full code for that is below:

private func rewriteEnumToObjC(value: Enum) -> (header: String, implementation: String)
{
    var header = "@interface \(value.identifier) : NSObject\n\n"

    var implementation = "#include \"\(value.identifier).h\"\n\n"
    implementation += "#define RETURN_ENUM_INSTANCE() \\\n"
    implementation += "    static \(value.identifier) *instance = nil;\\\n"
    implementation += "    static dispatch_once_t onceToken;\\\n"
    implementation += "    dispatch_once(&onceToken, ^{\\\n"
    implementation += "        instance = [[\(value.identifier) alloc] init];\\\n"
    implementation += "    });\\\n"
    implementation += "    return instance;\n\n"

    implementation += "@implementation \(value.identifier)\n\n"

    for option in value.options {
        header += "+ (\(value.identifier) *)\(option.name);\n"
        implementation += "+ (\(value.identifier) *)\(option.name) { RETURN_ENUM_INSTANCE(); }\n"
    }

    header += "\n+ (NSArray *)values;\n"
    implementation += "\n+ (NSArray *)values\n"
    implementation += "{\n"
    implementation += "    static NSArray *values = nil;\n"
    implementation += "    static dispatch_once_t onceToken;\n"
    implementation += "    dispatch_once(&onceToken, ^{\n"
    implementation += "        values = @[ "

    for (idx, option) in enumerate(value.options) {
        implementation += "\(value.identifier).\(option.name)"
        if (idx != value.options.count - 1) {
            implementation += ", "
        }
    }

    implementation += " ];\n"
    implementation += "    });\n\n"
    implementation += "    return values;\n"
    implementation += "}\n"

    header += "\n@end\n"
    implementation += "\n@end\n"

    return (header, implementation)
}

swift

The basic concept is to literally just write the header and implementation files as you would normally.

With each of those components in place, it’s time to hook it up!

Integration with Xcode If you download the project I linked, there will be a command-line tool called protc. It takes two parameters:

  1. -file – the path to the .prot file that contains our enum definition
  2. -output – the path that the .h and .m files will be written to

So here’s the magic… Xcode has these things called “Build Rules”. It’s basically how anything gets compiled within Xcode. Well, we can create our own build rules for our .prot files.

Step 1: Build Rules To do that:

  1. Select your project in the project navigator
  2. Select the target for your app/tool
  3. Select the “Build Rules” tab in the project editor
  4. Add a new build rule

The script will be filled in with this content:

rm "${DERIVED_FILE_DIR}/${INPUT_FILE_BASE}.h" 2> /dev/null
rm "${DERIVED_FILE_DIR}/${INPUT_FILE_BASE}.m" 2> /dev/null
/Users/owensd/Library/Developer/Xcode/DerivedData/protc-ecehehjngfljckcirxwdltnqqayl/Build/Products/Debug/protc -file ${INPUT_FILE_PATH} -output ${DERIVED_FILE_DIR}

Then be sure to set the “Output Files” to:

  1. $(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).h
  2. $(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).m

Here’s a screenshot of what it looks like:

Custom build rules allow us great flexibility.

: .caption

Step 2: Create your .prot file Next, create your .prot file just as you would any file. The trick is to add it to your “Compile Sources”.

  1. Select your project in the project navigator
  2. Select the target for your app/tool
  3. Select the “Build Phases” tab in the project editor
  4. Add your .prot file to the list of “Compile Sources”

Don’t forget this step or nothing will seem to be working!

: .caption

Step 3: Use your new enum! That’s really it. Now when you build your project, the .prot will be processed and in turn the generated .m file will be compiled into your project’s target.

To use it, simply add the header file as normal:

#import <Foundation/Foundation.h>
#import "CompassPoint.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        for (CompassPoint *point in CompassPoint.values) {
            if (point == CompassPoint.North) {
                NSLog(@"direction is north");
            }
            else if (point == CompassPoint.South) {
                NSLog(@"direction is south");
            }
            else if (point == CompassPoint.East) {
                NSLog(@"direction is east");
            }
            else if (point == CompassPoint.West) {
                NSLog(@"direction is west");
            }
        }
    }

    return 0;
}

objc

If you set your “Output Files” to be ${DERIVED_FILE_DIR}, the header paths have no trouble finding the generated header.

Step 4: Handling Build Errors Of course, sometimes you might make a mistake in your .prot file. It would suck if there was no way to handle this or to be notified of this… but of course that’s not the case!

Change your .prot file to this:

enum CompassPoint North | South | East | West

Notice the missing : between CompassPoint and North. Re-build your project, and voila!

Errors are reported and clickable!

: .caption

Not only can the error be reported, but it will cause your project to report a build failure. Those errors are also linked back to your source, so double-clicking will open your .prot file and show the error there.

Pretty cool.

The only missing thing is code completion and colorization. Unfortunately, to the best of my knowledge, those two features require full-blown Xcode plug-ins – way out of scope for this blog entry.

Next Steps Over the years, Objective C has attempted to get facelifts. Way back the 1997 timeframe, there was a project to create a “modern syntax” for ObjC. It didn’t go well. Then there was the ObjC-Java bridge that came in 2001. That also didn’t go well.

However, in 2006 we got ObjC 2.0. That was pretty good step forward for the Objective C language. And of course, in 2014, we got Swift.

I think the biggest disservice we can do to the Cocoa developer community is remove the underpinnings of the ObjC runtime. It is the language’s, and I truly believe, the platforms’ greatest strength.

I believe if we hide the complexities of C from our source code and focus on letting the power of the ObjC runtime shine through in our code, we can create a new language that provides of the great flexibility of the ObjC runtime while still accomplishing many of the goals that Swift is attempting to solve – namely safer code by default.

So I guess this is the start of the project I’m calling Proteus. We’ll see how far it gets.

  1. Note that you can put labels here in Swift as well, they just are not required.
  2. Now, we could go the extra mile on step #2 and simply emit the LLVM code, but honestly, I don’t have time to go down that route. It’s also not necessary for what I want to accomplish here.
  3. Here’s the repo link for the state at the time of authoring this blog entry: https://github.com/owensd/proteus/tree/78d0b2ad729948fcef7e6da80e966574b372cc91.
Building a Better Objective C