Getting start with Buck build System

If you want an option to Xcode builds, the Buck build system can be a good solution. I’ll show you in this guide how to get started and why to use an alternative build system. You can use Buck as a project generator too, but it’s not the main idea. If you are looking only for a project generator, you can use other easier options.

For first, you need to understand the build system concept. Xcode isn’t a build system, it’s an IDE, that contains a build system. Build systems have the rules of compiling code and packaging it. Like an iOS build system, it calls swiftc to compile swift code, ibtool to compile xibs (…) and after it, creates the .app, the binary in the correct structure.

Now, clean your mind and forget Xcode for now…

Think about your project structure, the modules, files, resources… Go to the finder and start creating folders to organize your code.

Let’s setup Buck

What you’ll install:

  • Command line tools;
  • Java 8;
  • Buck;

I recommend you use HomeBrew.

To install The command line toolsxcode-select —install

Buck is written in Java, then you will need to install Java in your machine. Not, let’s install Java using AdoptOpenJDK:

brew tap AdoptOpenJDK/openjdk
brew install --cask adoptopenjdk8

Let’s install buck now:

brew tap facebook/fb
brew install buck

If you receive a error like Error: /usr/local/Cellar/buck/2021.01.12.01 is not a directory Run  brew link buck

For the last step, run: brew install watchman

You can see the complete guide here.

Let’s buck!

Before using Buck, I recommend you read this article. Will help you to understand how a .app or .ipa is generated.

Understanding the structure

The most benefit of Buck is modularization. Then, stop thinking in your app as a BIG code, start to think in a LOT of small parts of code. Each module needs to work “alone”, with dependencies of course, but you need to can use the module in another app without bringing all other modules.

Each module needs a BUCK file. It’s a file without an extension named BUCK. In this file, you will teach buck how to build the module.

Config

To use buck, some default configs are needed. See the file .buckconfig . This file contains the default configs and some paths needed.

App module

To generate a .app, or using the correct term, a Bundle, you need a Binary. A Binary is an executable file with your code. And pay attention here, a saw your CODE. Assets, xibs, and storyboards aren’t code!

Go to VeryCoolApp/BUCK. You’ll see a code like this:

apple_binary(
    name = “VeryCoolAppBinary”,
    visibility = [“PUBLIC”],
    srcs = glob([‘**/*.swift’]),
    ...
    is_main_run_destination = True,
)

The command apple_binary will generate a binary (oh a Sherlock Holmes here…). This binary by self doesn’t do anything, you will need to put it inside a Bundle.

apple_bundle(
    name = “VeryCoolApp”,
    visibility = [“PUBLIC”],
    extension = “app”,
    binary = “:VeryCoolAppBinary”,
    product_name = “VeryCoolApp”,
    info_plist = “Info.plist”,
    ... 
)

Finally, the Bundle is the app! A Bundle is in the resume a folder that contains all compiled sources.

All of the parameters you can find at buck documentation.

“Ok, but my app has assets and xibs and storyboards, where did I put it?”

As I saw before, the BUCK file is how we teach buck to build our files. Let’s see how to compile assets:

apple_asset_catalog(
    name = “VeryCoolAppAssets”,
    visibility = [“PUBLIC”],
    dirs = [“Media.xcassets”],
)

After added the apple_asset_catalog to your buck file, you need to use it as a dependency in your app:

apple_binary(
    name = “VeryCoolAppBinary”,
    visibility = [“PUBLIC”],
    srcs = glob([‘**/*.swift’]),
    deps = [“:VeryCoolAppAssets”],
)

Ok, the next step is to compile de xibs and storyboards, the resources:

apple_resource(
    name = “VeryCoolAppResources”,
    visibility = [“PUBLIC”],
    files = glob([
        “**/*.xib”
    ]),
)

If you need to compile storyboards too, just add them to files . Now, let’s use it as a dependency:

apple_binary(
    name = “VeryCoolAppBinary”,
    visibility = [“PUBLIC”],
    srcs = glob([‘**/*.swift’]),
    deps = [“:VeryCoolAppResources”,
            “:VeryCoolAppAssets”],
)

Congratulations!!! Now, a buck can build your app! Try to make: buck build VeryCoolApp

Library

Yeah, finally we will create a Module! An independent module. Please, go to VeryCoolLibrary/BUCK.

Here is more simple, it’s a apple_library :

apple_library(
    name = “VeryCoolLibrary”,
    visibility = [“PUBLIC”],
    srcs = glob([‘*.swift’]),
    tests = [“:VeryCoolLibraryTests”],
)

It’s an independent library. This library has a tests module inside:

apple_test(
    name =  “VeryCoolLibraryTests”,
    ...
    deps = [
        “//VeryCoolLibrary:VeryCoolLibrary”,
    ],
    srcs = glob([
        “Tests/Sources/*.swift”,
    ]),
)

Using the library

Now, to use the library is too easy, do you remember de deps ?

apple_binary(
    name = “VeryCoolAppBinary”,
    visibility = [“PUBLIC”],
    srcs = glob([‘**/*.swift’]),
    deps = [“:VeryCoolAppResources”,
            “:VeryCoolAppAssets”,
            “//VeryCoolLibrary:VeryCoolLibrary”],
)

Congratulations!!! Now, a buck can test your library! Try to make: buck test //VeryCoolLibrary -n “iPhone 12

Makefile

The make file is only to help you with the commands.

To use, just create a new file named Makefile and add:

build:
	@-BUCK build //VeryCoolApp

Just run make build for example.

Xcode

Yes, Buck can create an Xcode project for you. Run:

BUCK project VeryCoolApp && open VeryCoolApp/VeryCoolApp.xcworkspace

DONE! Now you are building a iOS Project without Xcode!

You can find all code in this repository:

https://github.com/narlei/buckstartersample