<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: gerwert</title>
    <description>The latest articles on Forem by gerwert (@gerwert).</description>
    <link>https://forem.com/gerwert</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F97021%2F6bcf449e-efc9-443e-aa50-d0c84fa01386.png</url>
      <title>Forem: gerwert</title>
      <link>https://forem.com/gerwert</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gerwert"/>
    <language>en</language>
    <item>
      <title>Calling Swift from Go</title>
      <dc:creator>gerwert</dc:creator>
      <pubDate>Wed, 30 Jan 2019 20:03:30 +0000</pubDate>
      <link>https://forem.com/gerwert/calling-swift-from-go-5dbk</link>
      <guid>https://forem.com/gerwert/calling-swift-from-go-5dbk</guid>
      <description>&lt;p&gt;Both Swift and Go are modern compiled languages. They have their own typical use cases, &lt;a href="https://medium.com/@gerwert/notes-on-building-and-distributing-a-small-cross-platform-cli-tool-3eddc07b8449"&gt;strengths and weaknesses&lt;/a&gt;. Would it not be great to combine strengths of both languages in a single project? &lt;/p&gt;

&lt;p&gt;One possible use case is when you want to use Cocoa API's (native to macOS) such as &lt;code&gt;NSUserNotificationCenter&lt;/code&gt; in an existing Golang code base. This can be done via Objective-C as intermediate language. But I very much prefer Swift over Objective-C. &lt;/p&gt;

&lt;p&gt;This "best of both worlds approach" has some caveats of course, but we'll come to that later. First the fun part.&lt;/p&gt;

&lt;h2&gt;
  
  
  A library as a bridge
&lt;/h2&gt;

&lt;p&gt;There is no direct interoperability between Swift and Go. But what we can do, is using a generic way to link binaries written in arbitrary languages: shared libraries. Or more specific in this case: dynamic libraries.&lt;/p&gt;

&lt;p&gt;Prerequisite is that both languages support the same &lt;a href="https://en.wikipedia.org/wiki/Calling_convention"&gt;calling convention&lt;/a&gt;. Both Golang and Swift support creating and linking to libraries that use the &lt;code&gt;cdecl&lt;/code&gt; calling convention, which originates from the C programming language. If we build a Swift library that exports functions with cdecl calling convention, we should be able to call those functions from Go.&lt;/p&gt;

&lt;p&gt;We have to make sure to explicitly export functions with the cdecl convention in Swift. Calling Swift functions in a "normal" Swift library from Go is not possible, because Swift and Golang have their own (and different) calling conventions. &lt;/p&gt;

&lt;p&gt;But even if both languages would use the same calling convention, we would need some way of converting argument and return types from one language to the other. For example, a &lt;code&gt;string&lt;/code&gt; in Golang is completely different from a &lt;code&gt;String&lt;/code&gt; in Swift. So we would not be able to simply pass strings between Swift and Golang without some kind of layer in between.&lt;/p&gt;

&lt;p&gt;In our case that layer is a dynamic C library. Thus, we'll use C as lingua franca, which is common when bridging programming languages.&lt;/p&gt;

&lt;p&gt;Now, let's look at the steps needed create a C library from Swift code that can be called from Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Swift library
&lt;/h2&gt;

&lt;p&gt;Let's create a very simple Swift library, that exports a single function that prints a string. First step is initialise our project using Swift Package manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ swift package init --type library
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create a Swift file that contains our function: &lt;code&gt;./Sources/go-swift/go_swift.swift&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this file we declare one function: &lt;code&gt;sayHello&lt;/code&gt;. This function&lt;br&gt;
accepts a pointer to a C string as the only argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;@_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sayHello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// export to C as `sayHello`&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namePtr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UnsafePointer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;CChar&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;    
    &lt;span class="c1"&gt;// Creates a new string by copying the null-terminated UTF-8 data (C String) &lt;/span&gt;
    &lt;span class="c1"&gt;// referenced by the given pointer.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;namePtr&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Welcome, &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make this Swift function accessible from C, we have to add a &lt;code&gt;@ _cdecl&lt;/code&gt; attribute to it.&lt;br&gt;
&lt;code&gt;@_cdecl&lt;/code&gt; is an &lt;a href="https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829"&gt;undocumented and unsupported attribute&lt;/a&gt; (so might not be available anymore in future Swift versions), which gives a Swift function a "C name" in the resulting library. It tells the compiler not to mangle the function name (as it does by default), ensuring our function name is exported as if it had been written in C.&lt;/p&gt;

&lt;p&gt;Also notice that we can't use the build-in Swift &lt;code&gt;String&lt;/code&gt; as type for our argument, because that is not a C compatible type. Therefore we're dealing with raw pointers to C-style null-terminated strings: &lt;code&gt;UnsafePointer&amp;lt;CChar&amp;gt;?&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Call library from Go
&lt;/h3&gt;

&lt;p&gt;After building the swift library via &lt;code&gt;$ swift build&lt;/code&gt;, we can try to call the &lt;code&gt;sayHello&lt;/code&gt; function in that library.&lt;/p&gt;

&lt;p&gt;To call our function from Go, we need &lt;a href="https://golang.org/cmd/cgo/"&gt;cgo&lt;/a&gt;. Cgo acts as a bridge between C and Go.&lt;/p&gt;

&lt;p&gt;But before we can link the Swift library to our Go program using cgo, we need to create a C header file: &lt;code&gt;./include/go_swift.h&lt;/code&gt;. Otherwise our Go program is not aware of the C function signature of &lt;code&gt;sayHello&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since we only have a single function, our header file can consist of a single line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;$ swiftc -emit-objc-header &amp;lt;swift file&amp;gt;&lt;/code&gt; you can generate an Objective-C header automatically. But as far as I'm aware, there is no automatic generation for plain C header. So we'll have to create the C &lt;br&gt;
header file manually. &lt;/p&gt;

&lt;p&gt;For simple functions this is relatively straightforward. For more complex functions you might need (lots of) trial and error. I didn't go as far for example to test if it's possible to pass a pointer to a function as parameter.&lt;/p&gt;

&lt;p&gt;After defining the header, it's time to write a small Go program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="c"&gt;/*
#cgo CFLAGS: -I./include
#cgo LDFLAGS: -L.build/debug/ -lgo_swift
#include &amp;lt;stdlib.h&amp;gt;
#include "go_swift.h"
*/&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"unsafe"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Copy Go string to C string&lt;/span&gt;
    &lt;span class="n"&gt;cstr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Call Swift function `sayHello`&lt;/span&gt;
    &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// The C string is allocated in the C heap using malloc.&lt;/span&gt;
    &lt;span class="c"&gt;// Therefore memory must be freed when we're done&lt;/span&gt;
    &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our Go file, we import the C package and declare a preamble. From the cgo documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To use cgo write normal Go code that imports a pseudo-package "C". The Go code can then refer to types such as C.size_t, variables such as C.stdout, or functions such as C.putchar.&lt;/p&gt;

&lt;p&gt;If the import of "C" is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package. For example:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the preamble, we need to set some linker flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cgo CFLAGS: -I./include&lt;/code&gt;: set path to header files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cgo LDFLAGS: -L.build/debug/ -lgo_swift&lt;/code&gt; sets the location in which to look for library files, and which libraries to link to. &lt;code&gt;go_swift&lt;/code&gt; is library the name from &lt;code&gt;Package.swift&lt;/code&gt;. The library location is path that contains the output from the Swift build process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we can build an run our Go program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go build -o hello
$ ./hello
Welcome, Bob!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works fine! But, as mentioned before, there are several issues with this approach, compared to "normal" development in either Golang or Swift.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory management
&lt;/h3&gt;

&lt;p&gt;Both Swift and Go have automatic memory management, such as memory allocation and garbage collection. Therefore, normally when writing code in Swift or Go we don't need to worry about things like memory leaks and buffer overflows.&lt;/p&gt;

&lt;p&gt;In order for automatic memory management to work, a runtime needs to be fully in charge of all memory allocated and to know the location of all pointers. That means Swift's runtime can't manage pointers created by Go's runtime, and visa versa.&lt;/p&gt;

&lt;p&gt;Because of this, there are restrictions when passing pointers via a shared library. Go pointers passed to C code must be pinned for the duration of the C call, and C code must stop storing the Go pointer when the C function returns. If you don't strictly adhere to these and other rules, things can become messy quickly.&lt;/p&gt;

&lt;p&gt;Bottom line is you must be careful and cautious about memory management. That's a big disadvantage, because you'll lose the convenience and safety of automatic memory management when using functions from a shared library. The type name &lt;code&gt;UnsafePointer&lt;/code&gt; we have to use in the Swift code says it all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Using C as an intermediate language means we need to convert Go types to C types, C types to Swift types, and back again. This, amongst other things, causes overhead that will impact application performance. For simple programs this might not be a problem at all. But when performance matters, there is always a better solution than bridging languages via a shared library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-platform support
&lt;/h3&gt;

&lt;p&gt;While Go is available on many platforms, Swift is not. By linking a Go program to a Swift library you'll loose the broad platform support that Golang offers.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, is this a good idea?
&lt;/h2&gt;

&lt;p&gt;"Yes", because it's fun (!) and bridges a gap between Golang and native MacOS frameworks. But also "No", because, because calling Swift from Go creates issues that would not be there when using a single language. &lt;/p&gt;

&lt;p&gt;In other words, whether or not choosing the Golang/Swift route is for you, depends on your project and if there is another way to achieve what you want. For example, MacOS APIs can be called using Objective-C as intermediate language instead. &lt;/p&gt;

&lt;p&gt;But, that aside, it is something definitely worth experimenting with.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Repository with example code &lt;a href="https://github.com/onderweg/swift-from-go"&gt;available on Github&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The other way around: 

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youngdynasty.net/posts/writing-mac-apps-in-go/"&gt;Writing Apps in Go and Swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf"&gt;Calling Go Functions from Other Languages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>swift</category>
      <category>c</category>
    </item>
    <item>
      <title>On building a small cross-platform CLI tool in C, Go &amp; Swift</title>
      <dc:creator>gerwert</dc:creator>
      <pubDate>Fri, 25 Jan 2019 13:03:28 +0000</pubDate>
      <link>https://forem.com/gerwert/on-building-a-small-cross-platform-cli-tool-in-c-go--swift-45d4</link>
      <guid>https://forem.com/gerwert/on-building-a-small-cross-platform-cli-tool-in-c-go--swift-45d4</guid>
      <description>&lt;p&gt;A great thing about being a programmer is that if you need specific, customised, tooling, you can just write it yourself. Often there are existing options, but of course it’s a lot more fun to write your own tools, especially when you have room for some experimentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5G3ULnVL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AGw0ATlzGnZnFFYky_w7HyQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5G3ULnVL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AGw0ATlzGnZnFFYky_w7HyQ.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how I came to write a simple tool.. 3 times, in different languages.&lt;/p&gt;

&lt;h4&gt;
  
  
  The experiment
&lt;/h4&gt;

&lt;p&gt;My goal was to write a very simple command line tool that can generate one-time passwords compatible with &lt;a href="https://en.wikipedia.org/wiki/Google_Authenticator"&gt;Google Authenticator&lt;/a&gt;. Google authenticator uses the &lt;a href="https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm"&gt;Time-based One-Time Password algorithm (TOTP)&lt;/a&gt; to generate codes. Instead of writing my own implementation, I wanted to use an existing TOTP library, since there already are many good ones.&lt;/p&gt;

&lt;p&gt;Essentially, all I want my tool to do, is accept a secret as single input, then call an exiting TOTP library to generate a code, and print the generated access code to the standard output.&lt;/p&gt;

&lt;p&gt;The question I was asking myself was: suppose I would like to use the tool on several platforms (Mac, Windows, Ubuntu), and would like to&lt;br&gt;&lt;br&gt;
distribute the tool amongst a small group of — not necessarily technical — people (e.g. colleagues), what programming language would be the most pragmatic/viable/fun option?&lt;/p&gt;

&lt;p&gt;Of course you can look at this question from many angles. Let’s focus on building and distributing the tool. Then, these were my “should have” requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It should be possible to distribute the tool as single executable that works “out of the box”, meaning the user does not have to install dependencies like runtimes, frameworks, libraries, etc.&lt;/li&gt;
&lt;li&gt;With the same code base (but possibly different toolchains) it should be possible to produce builds for multiple platforms.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Language choice
&lt;/h4&gt;

&lt;p&gt;I wanted to create a binary for this specific experiment, that’s why I did not consider interpreted languages like Node.js, Ruby, and Python for this specific tool. Although, of course in general these languages would all make perfectly viable options to use for writing a cross-platform command line tool.&lt;/p&gt;

&lt;p&gt;There is also a disadvantage to those languages, being that the end user needs to have a runtime (e.g. Node.js) installed. Although many platforms come with common runtimes pre-installed, the user might need to install a different version. That is not always a trivial task for non-technical users.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I’m aware that there are tools to compile interpreted languages to stand-alone executables, but that feels a bit like cheating here)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the end, my choice was to experiment with &lt;strong&gt;C&lt;/strong&gt; , &lt;strong&gt;Go&lt;/strong&gt; and  &lt;strong&gt;Swift&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I decided to stay in my “programming language comfort zone”, because learning a new language was not part of my experiment. Therefore I did not experiment with (in opinion) very interesting other languages, such as &lt;strong&gt;Rust&lt;/strong&gt; , which I will try out in the future (feel free to leave a comment with your Rust experiences). Also good to note maybe: for this experiment I considered &lt;strong&gt;C++&lt;/strong&gt; overkill (or actually maybe, my C++ knowledge is just lacking).&lt;/p&gt;

&lt;h4&gt;
  
  
  What I learned
&lt;/h4&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;C&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Typically, executables build with C are linked dynamically. That means that end users need to install dependencies (linked libraries) in order to run the tool. That's definitely not ideal.&lt;/li&gt;
&lt;li&gt;There are ways around this, but these all come with some disadvantages:
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static linking:&lt;/strong&gt; create single binary that will hold all required binary code. But, that requires that all libraries that you use (for example a TOTP library) support static linking. This is definitely not always the case. Furthermore, Apple&lt;a href="https://developer.apple.com/library/archive/qa/qa1118/_index.html"&gt;does not support statically linked binaries on Mac OS X&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distribute linked dynamic libraries with your application&lt;/strong&gt;. This means that for every target OS you’ll have to pre-build all linked libraries, make sure these libraries can be found by the executable (e.g. changing rpath on macOS), and bundle them with the app. In other words you need compile and bundle .dll (Windows), .dylib (macOS) or .so (Linux) files with your app.&lt;/li&gt;
&lt;li&gt;C does not have a runtime that needs to be bundled with the application. Therefore the resulting executable is quite small. The only dependency (dynamic library) is the C standard library libc, which is by default available on the OS'es I would like to target.&lt;/li&gt;
&lt;li&gt;Building a single C code base on different platforms can be a pain. I generally prefer to use the “default”, or most widely supported, build chain for a platform. In my opinion that is Visual Studio on Windows, Xcode on Mac (or GCC on Mac command line) and GCC on Linux. But that means that for every platform you need to install and setup a completely different build environment (project file, build scripts, etc).&lt;/li&gt;
&lt;li&gt;Compiling dependencies from source for multiple platforms is hard. Like I mentioned above, setting up build chain for your &lt;em&gt;own&lt;/em&gt; code on different platforms can be difficult already. It is even more difficult to compile &lt;em&gt;third party&lt;/em&gt; libraries from source for multiple platforms. Some are relatively easy to work with cross-platform, but others are a real pain because they lack support for, or documentation on, cross-platform building.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Executables build by Golang are statically linked by default. This means users don’t have to install any dependencies, and you don’t need to distribute dynamic libraries with your application. For a small command line application, the only thing you need to distribute is the executable.&lt;/li&gt;
&lt;li&gt;Unfortunately, because of the static linking, the &lt;a href="https://golang.org/doc/faq#Why_is_my_trivial_program_such_a_large_binary"&gt;resulting executable is relatively large&lt;/a&gt;. That is because a Go binary includes the Go runtime, so that the end user does not need to have Go installed. (but, as &lt;a href="https://medium.com/u/333bfa9d9c3"&gt;Dotan Nahum&lt;/a&gt;, points out, there are ways to &lt;a href="https://hackernoon.com/a-story-of-a-fat-go-binary-20edc6549b97"&gt;trim down some fat&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Go is available as a binary distribution on all target platforms I was interested in. That makes setting up a build environment and building on these platforms painless.&lt;/li&gt;
&lt;li&gt;A great thing about Go, is that you can &lt;a href="https://medium.com/@georgeok/cross-compile-in-go-golang-9f0d1261ee26"&gt;easily compile for multiple platforms&lt;/a&gt; on one machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Swift&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is recommended to statically link to the Swift standard library, so that the resulting executable is not bound to the specific version of Swift that it was built with. This results in a large binary (more than 10 MB for a simple tool). The need for static linking is due to &lt;a href="https://developerinsider.co/what-will-be-new-in-swift-5/"&gt;Swift lacking ABI stability&lt;/a&gt;. That is on the roadmap to be solved in a future Swift version though. (In comparison, Objective-C does have ABI stability by the way).&lt;/li&gt;
&lt;li&gt;Cross-platform support has not yet matured. You can compile a Swift program on both on Mac and Linux (there is no official Windows release yet), but the cross-platform build system — &lt;a href="https://swift.org/package-manager/"&gt;Swift Package Manager (SPM&lt;/a&gt;) — is not nearly as mature as Xcode on MacOS. Furthermore, many libraries that are available on CocoaPods or Carthage (MacOS only) don’t support SPM (cross-platform) yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;When it comes to building cross-platform and distributing the tool, &lt;strong&gt;Go&lt;/strong&gt; gave me the best developer experience.&lt;/p&gt;

&lt;p&gt;Thanks to the default static linking, it is easy to create a single executable for distribution.&lt;/p&gt;

&lt;p&gt;Building a Go program on different platforms is also really easy. There is no need for writing platform specific build scripts, or using platform dependent tool chains.&lt;/p&gt;

&lt;p&gt;Downside is that the resulting executable is relatively large (several megabytes), but in my situation that was not a real issue.&lt;/p&gt;

&lt;p&gt;Next up is &lt;strong&gt;C&lt;/strong&gt;. Writing in C always gives me a pleasant sense of control and a feeling of freedom due to the lack of constraints from a runtime. Of course the downside to this is that you can easily shoot yourself in the foot. But the biggest problem here was that there is no single toolchain for building that works just as flawlessly cross-platform as Go.&lt;/p&gt;

&lt;p&gt;And finally, &lt;strong&gt;Swift&lt;/strong&gt;. While I really like Swift as a language, and I would only consider Swift as obvious choice when writing command line tools specifically for macOS. Swift is too much of a &lt;a href="https://www.altexsoft.com/blog/engineering/the-good-and-the-bad-of-swift-programming-language/#tt16"&gt;“moving target”&lt;/a&gt; for me. That has several implications, an important one is that it is not straightforward to use Swift on other platforms. Another issue for me is that Windows is not yet officially supported.&lt;/p&gt;

&lt;p&gt;As a final note: I wanted to share my experiences, but in the end, what language suits you best comes down to personal preference and current state of languages. Next year might be different.&lt;/p&gt;

</description>
      <category>node</category>
      <category>go</category>
      <category>cli</category>
      <category>c</category>
    </item>
  </channel>
</rss>
