Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Cross-Platform Makefile for Swift

DZone's Guide to

Cross-Platform Makefile for Swift

Check out how the author uses a Makefile so he can build and test directly on OS X rather than a virtual machine.

· Mobile Zone
Free Resource

Launching an app doesn’t need to be daunting. Whether you’re just getting started or need a refresher on mobile app testing best practices, this guide is your resource! Brought to you in partnership with Perfecto

I'm mostly building Swift applications for deployment to Linux, but sometimes it's easier to build and test directly on OS X rather than spinning up a VM. To facilitate this, I use a Makefile that means that I don't have to remember the compiler switches.

It looks like this:

# This Makefile assumes that you have swiftenv installed
# To get going, start with `make init`

SWIFT_VERSION = DEVELOPMENT-SNAPSHOT-2016-04-25-a

# OS specific differences
UNAME = ${shell uname}
ifeq ($(UNAME), Darwin)
SWIFTC_FLAGS =
LINKER_FLAGS = -Xlinker -L/usr/local/lib
endif
ifeq ($(UNAME), Linux)
SWIFTC_FLAGS = -Xcc -fblocks
LINKER_FLAGS = -Xlinker -rpath -Xlinker .build/debug
PATH_TO_SWIFT = /home/vagrant/swiftenv/versions/$(SWIFT_VERSION)
endif


build:
swift build $(SWIFTC_FLAGS) $(LINKER_FLAGS)

test: build
swift test

clean:
swift build --clean

distclean:
rm -rf Packages
swift build --clean

init:
- swiftenv install $(SWIFT_VERSION)
swiftenv local $(SWIFT_VERSION)
ifeq ($(UNAME), Linux)
cd /vagrant && \
 git clone -b experimental/foundation https://github.com/apple/swift-corelibs-libdispatch.git && \
 cd swift-corelibs-libdispatch && git submodule init && git submodule update && \
 sh ./autogen.sh && \
 ./configure --with-swift-toolchain=/home/vagrant/swiftenv/versions/$(SWIFT_VERSION)/usr \
 --prefix=/home/vagrant/swiftenv/versions/$(SWIFT_VERSION)/usr && \
 make && make install
endif


.PHONY: build test distclean init


Let's go through it.

SWIFT_VERSION = DEVELOPMENT-SNAPSHOT-2016-04-25-a


This simply sets which version of Swift this project uses. It's that ever changes.

# OS specific differences
UNAME = ${shell uname}
ifeq ($(UNAME), Darwin)
SWIFTC_FLAGS =
LINKER_FLAGS = -Xlinker -L/usr/local/lib
endif
ifeq ($(UNAME), Linux)
SWIFTC_FLAGS = -Xcc -fblocks
LINKER_FLAGS = -Xlinker -rpath -Xlinker .build/debug
endif


This section allows for different compiler and linker switches for each operating system.

We're compiling libdispatch on Liux, so we need to enable the blocks language feature in clang. This is done by using the -Xcc switch to tell the compiler to pass the next switch (-fblocks) to clang.

For linking on OS X, I nee to pick up the Homebrew Mysql library in /usr/local/lib. This isn't needed on Linux as apt puts the relevant library in the right place. However, on Linux we need to link against a library in our own .build/debug directory, so we pass the switches for that. In the same way as -Xcc, -Xlinker passes the next parameter to the linker (ld). We need to pass -rpath .build/debug, but as we can only pass one argument at a time with -Xlinker, we do it twice.

build:
swift build $(SWIFTC_FLAGS) $(LINKER_FLAGS)

test: build
swift test

clean:
swift build --clean

distclean:
rm -rf Packages
swift build --clean


These are the standard make targets for building, testing and cleaning up intermediate files. By using the standard names, working on different projects is very easy and predictable as the same make commands work everywhere.

init:
- swiftenv install $(SWIFT_VERSION)
swiftenv local $(SWIFT_VERSION)
ifeq ($(UNAME), Linux)
cd /vagrant && \
 git clone -b experimental/foundation https://github.com/apple/swift-corelibs-libdispatch.git && \
 cd swift-corelibs-libdispatch && git submodule init && git submodule update && \
 sh ./autogen.sh && \
 ./configure --with-swift-toolchain=/home/vagrant/swiftenv/versions/$(SWIFT_VERSION)/usr \
 --prefix=/home/vagrant/swiftenv/versions/$(SWIFT_VERSION)/usr && \
 make && make install
endif


The init target is specific to my Swift projects. It sets the correct local Swift version for this project using swiftenv. The - before the swiftenv install command ensures that make continues even if this command fails (which it will if the version is already installed).

We then do something that's specific to Linux and install lib-dispatch which we need for GCD. It's included already in OS X, which is why this is guarded by the ifeq ($(UNAME), Linux).

That's it. This is a simple Makefile which leaves me to think entirely about my code, rather than my build system.

Keep up with the latest DevTest Jargon with the latest Mobile DevTest Dictionary. Brought to you in partnership with Perfecto.

Topics:
swift ,makefile

Published at DZone with permission of Rob Allen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}