Compile a swift package to a binary to be used from linux

I made a super small package

// Package.swift
import PackageDescription

let package = Package(
    name: "HelloWorld",
    dependencies: [
        .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .executableTarget(
            name: "HelloWorld",
            dependencies: [
                .product(name: "ArgumentParser", package: "swift-argument-parser"),
            ]
        ),
    ]
)

which does this very simple bit of code:

import ArgumentParser

@main
struct HelloWorld: ParsableCommand {
	@Argument var name: String?

    mutating func run() throws {
		if let name {
			print("Hello, \(name)!")
		} else {
			print("Hello, world!")
		}
    }
}

When I attempt the run the binary from a different machine running linux, I get an error with this message: cannot execute binary file: Exec format error.

I'm guessing that the executable needs to be compiled for a different architecture. Is there a way to compile something from this that will work for both macOS and linux as a binary or simply to at least get it to work on linux alone?

You need to build a binary separately for each platform.

I figured that might be the case. Is it possible to compile for a linux arch (compatible for something like a github linux runner) from my local machine? I've looked a bit online, but I'm having trouble finding anything for this.

You can use Swift SDK Generator to generate an SDK for the specific Linux distribution and its version and then build an executable with that SDK. With --static-swift-stdlib it will link the Swift standard library into it statically, but it still links to Glibc dynamically, since Glibc doesn't support static linking. That's why you need to be mindful that you target the same exact Linux distribution version or newer, otherwise your binary will try to load an incompatible version of Glibc after it's deployed.

3 Likes