One of Bazel's best features is being able to easily write custom rules specific to your project. This is great for many use cases, but when what you really want is to enhance the behavior of existing rules, historically your options have been limited. What you would often do is wrap the existing rule in a macro, and add some number of custom rules to try and achieve the desired effect. When…
Apple platforms (macOS, iOS, etc), and specifically Mach-O binaries, have a slightly different approach to debug info than ELF binaries for Linux. If you are familiar with Xcode, you might have seen a few related settings that control what is produced and wondered what the trade-offs are. The goal of this post is to help you debug cases where these differences lead to a degraded debugging…
Once you've fully migrated a codebase to bazel, one of the many advantages is that you can easily inspect your build graph using bazel query . One of the many things you can do with queries is write scripts to enforce coding standards, or in today's example, find unused targets that can lead to discovering unused code. The simplest version of this query starts like this: let all_targets = //... in…
One of bazel's most attractive features is the ability for it to remotely cache artifacts to reduce unnecessary work for large builds. Unfortunately users quickly discover this comes with non-trivial financial and bandwidth implications. There are many ways, of varying difficulty, to try and improve your cache usage. From breaking unnecessary dependencies, to adding larger local storage for CI…
MachO binaries contain load commands to indicate to dyld where it should search for the libraries the binary depends on. These paths are often useful to inspect when debugging why your binary isn't discovering the libraries you'd expect. Previously you could discover these with: % otool -l `xcrun -f swiftc` \ | grep -A2 LC_RPATH \ | grep "^\s*path" \ | cut -d " " -f 11…
When working on bazel build infrastructure, something I often need to do is reproduce an action outside of bazel's infrastructure in order to debug it further. This debugging often involves changing flags or swapping out the tool itself for a custom built version. In many cases updating your bazel configuration as normal should work well enough. But sometimes when you're iterating on things that…
Auto linking is a feature that embeds information in your binaries' at compile time which is then used at link time to automatically link your dependencies. This allows you to reduce the duplication of flags between the different phases of your (or your consumers') builds. For example, with this Objective-C file: #include <Foundation/Foundation.h> int main () { NSLog ( @"Hello, World!" ); return 1…
When Apple transitioned to using os_log for system logs it seemed they also decided to open the floodgates for what logs were surfaced in our apps. This lead to a plethora of stackoverflow questions recommending you disable os_log entirely by setting OS_ACTIVITY_MODE=disable in your target's scheme. This is fine for some cases but might also silence some actually useful logs, or your own logs if…
For people who expect reproducible builds , Apple Silicon machines provide an interesting challenge. Apple Silicon requires arm64 binaries, including command line tools you build yourself, be codesigned. This change is mostly transparent to developers, because Apple updated their linker to automatically ad-hoc sign binaries 1 . Unfortunately, if you're interested in producing binaries that support…
When switching between multiple Xcode versions one way to globally update the version you want to use is by running xcode-select like this: sudo xcode-select -s /Applications/Xcode-12.5.1.app Then, if you want to automatically accept Xcode's license, and install any extra packages it requires (which should only be required the for the first time you run a new version), you can run: sudo xcodebuild…
When using bazel on a team, one of the things you quickly want to do is stand up a remote cache . This allows bazel to download build artifacts instead of spending CPU cycles reproducing things that have already been built by someone else. In order for bazel to guarantee that downloading the artifacts instead of building them will produce the same results, it must ensure that all the inputs of…
If you build your iOS app with an alternate build system such as bazel , it's likely that you use relative paths, instead of absolute paths, for compilation. Specifically, when building swift code, Xcode calls the compiler with something like: swiftc [ARGS] /path/to/srcroot/path/to/file1.swift /path/to/srcroot/path/to/file2.swift Where bazel will call the compiler with something like: swiftc…
One of the issues with shipping a tool that depends on SwiftSyntax is that it depends on a dynamic library that is provided with Xcode called _InternalSwiftSyntaxParser . This library provides some of Swift's logic for how to parse Swift code. When you run a command line tool that was built with a different version of Xcode than what you have installed locally, you hit this issue: <unknown>:0:0:…
If you distribute binaries for command line tools built with Swift Package Manager , you might have previously built your distribution binary with: % swift build --configuration release If you inspect the binary, you can see it was built for the current machine's architecture by default: % file .build/release/package .build/release/package: Mach-O 64-bit executable x86_64 Previously, this was…
Swift developers love to complain about LLDB. While there are many reasonable complaints, the important question is what can we do to make it better. Enter reproducers . Reproducers provide a way to run LLDB while also capturing information about your debugging session. With this information you can submit a more useful bug report to Apple with a reliable reproduction case. How? Although the steps…
After having a use for NSProgress I finally got a chance to dive in to its API. I found it to be less than understandable. So I wrote about it on the thoughtbot blog. You can find my post, NSProgress with Asynchronous Tasks, here .
After finally starting to use ReactiveCocoa I found integrating with Core Data to be a sore spot. I wrote about improving this integration on the thoughtbot blog here .
I haven't had anything to write in a while. Mainly because, as I've been working at thoughtbot , I've been writing everything I can on the thoughtbot blog . I spent a little while writing Clojure , and out of that came a few posts. Overall I wasn't a big fan of Clojure. I definitely lean more towards functional languages with types but I wanted to link these articles here regardless. Getting…
When working with large files in Vim, Tagbar has become an invaluable part of my workflow. It provides a succinct list of methods, modules, variables and other language specific constructs. When I started trying to spend more time in Vim writing Objective-C I was disappointed to see that, out of the box, it was not supported. Hopefully in the future it won't be difficult to set this up in Vim.…
After you buy a Raspberry Pi, or two, you need to figure out what to use them for. While you'll get a ton of interesting ideas from Googling "uses for a Raspberry Pi," I didn't particularly find them any more than a thought exercise . Making a VPN stood out as an actually useful configuration. Originally when I got my (accidentally chosen) Model A, I spent a little while going through this guide…
One of the great things about Vim's textual configuration is it's ability to contain logic based on outside factors. For the purpose of this post I'm referring to the ability to set your colorscheme based on the time of day with something like this . Having this functionality in Vim with the Solarized theme at night really made me want this in iTerm as well. Unfortunately iTerm's conifguration…
When starting a new web project one of the first things I do is download the most up to date HTML5 Boilerplate . It provides a great starting point for the HTML you need in a project. It also comes with an extremely complete .htaccess file. While this is very nice for a single site they recommend you do something different for multiple sites at the very top . (!) Using .htaccess files slows down…
As you may know I write a small OS X called Sail . Over the past few months that it has been available I've received a few crash reports about an issue I wasn't able to reproduce. Today I decided I wanted to dive into them and see if I could at least figure out the root of the issue and fix it with my next release. This lead me down the rabbit hole of symbolication , something I personally hadn't…
I'm tired of people asking about the 'best' IDE for xyz purpose. The answer to this question is there is no best. The answer is always 'it depends.' Not only does it depend on what you're doing but more importantly it depends on you. It depends on your work flow. It depends tons of other indiscernible factors. It seems like people think they work in exactly the same way as enough other people.…
Recently Travis added support for Objective-C and there for OS X and iOS projects for continuous integration testing. I gather that people have previously done this with self-hosted dedicated Jenkins machines but since Apple is so aggressive about dropping support for previous versions of the OS it seems like a pain to have to replace your build server every few years. Enter Travis, a great hosted…
For a long time people have talked about how horrible HFS+ is. Most notably, in my opinion, Linus Torvalds (the creator of Linux and Git) who said "Their file system is complete and utter crap, which is scary." John Siracusa also wrote about the problems with HFS+ in his 10.7 review along with talking about it on his podcast, Hypercritical in episodes 56 and 57 . The gist of all this really is…
One of my favorite defaults in some Linux distros is the ability to use CTRL+ALT+T to open a new terminal window. I wanted to enable this same functionality in OS X using Quicksilver . I did this using iTerm 2 but you can do it with the default Terminal if that's what you want. Enable the Terminal and iTerm2 Quicksilver plugins. Create a new custom hotkey trigger. Using the Home directory with the…
I spend a lot of time in my RSS Reeder (see what I did there?). I still find Google Reader to be the best and easiest way to manage my subscriptions, although I've been wanting to switch to Fever for a while. One thing I wanted to do when I launched my new site (the one you're reading) was to have a downloadable up to date export of my Google Reader OPML file (which of course I never did). I…
Working as a developer full-time can be very exciting. Dealing with new interesting problems gets me up in the morning. But I still find that after a few months of a specific project I find myself less and less interested with it. Not only projects but concepts and languages start to become less interesting. First it was websites then Objective-C then Ruby then C and now who knows. This scares me.…
I've been using Objective-C and C++ for a while now. While I feel like I know them pretty well I had absolutely no grasp on C itself. Obviously when using those languages you pick up a bit about data types and conditionals but you couldn't take that knowledge and completely write something non-trivial in C. Because of this I figured it might be worth some time so I started looking for viable…
I'm currently working on a OS X application that uses a few different NSTableViews to display user data. I was testing them out a bit to make sure multiple deletions worked correctly from my database and I found myself pressing 'j' and 'k' to try and move down and up. I decided it would be pretty cool to implement those two vim shortcuts into my table view just in case anyone else thinks like me.…
We all know not backing up has consequences . While losing sentimental files would definitely ruin your day, losing your web server's data could be even worse. I've mentioned before that I use Linode for my server hosting, and while they do offer an automated backup service I decided I'd rather setup my own solution to back up periodically to my local machine. Many people use rsync to do their…
I spend a decent amount of time these days helping maintain the CocoaPods specs repo by managing pull requests and issues. CococaPods is an awesome dependency manager similar to Rubygems for Objective-C projects. Unfortunately a lot of submitted podspecs haven't been correctly formatted or they're missing required information. CocoaPods has an awesome build in command pod spec lint that allows you…
I've recently been searching around for a good way to 'spawn' an iTerm window (no I don't use tabs in iTerm), at the pwd in my current iTerm window. I couldn't find any good way to do it so I jumped in to AppleScript Editor and made something happen. on run argv tell application "iTerm" set t to make new terminal tell t activate current session launch session "Default Session" tell the last…
For quite a while I was having trouble dealing with a global show/hide hotkey for windows in Objective-C. Global hotkeys are already hard enough . Although MASShortcut has solved that. Yes I know of ShortcutRecorder but it's very dated (MASShortcut even uses blocks!). I found that once I had the shortcut working I was having a hard time dealing with opening and closing, showing and hiding the…
I've been using Linode for about the past 4 months. I was previously using HostMonster for all of my hosting, while I would recommend them 80% of the time, Linode and the nature of a VPS allows many things you cannot do with shared hosting. I was looking around for some recommendations on how to deal with user accounts and permissions and ran across this great article that has almost every piece…
Something I've become very aware of lately is how difficult it is for me to ship. I have at least a dozen unfinished projects that I could probably ship, yet I find any excuse to hold them back. I could say forget it and ship it. Then depending on the amount of feedback I received, decide whether or not it was worth putting more time into. I often fall victim to "just one more feature here" or "oh…