DevGang
Авторизоваться

Скомпилируйте GoLang как мобильную библиотеку 

У вас есть проект GoLang, который нужно запускать в программе iOS. Вы можете все переписать на Swift, но вы надеетесь, что будет проще просто скомпилировать GoLang как модуль.

Хорошие новости: это возможно!

Программа go позволяет не только кросс-компиляции для различных платформ, но она также позволяет экспортировать методы и генерировать файлы заголовков C.

Примечание: Вы можете использовать для этого gomobile.

Функции экспорта

При компиляции GoLang как модуля вы потеряете доступ к функции main(). Вместо этого вы будете вызывать определенные методы из среды хоста.

Определить экспортируемые функции

Вы можете сделать это, создав специальный комментарий, который гласит //export <functionName>:

//export functionName
func functionName () {
  // do stuff
}

Мост к C

Теперь, когда вы можете экспортировать функции, вам нужно предоставить эти функции через мост C, что вы можете сделать, импортировав модуль «C»:

import "C"

Давайте создадим простой проект GoLang, который возвращает строку при вызове функции из внешней библиотеки. Мы можем назвать этот файл sayHelloLib.go:

package main

import "C"

//export sayHello
func sayHello() string {
  return "Hello"
}

Включить специальные функции для мобильных устройств

При экспорте на мобильный телефон необходимо учитывать несколько моментов. В частности, мы хотим убедиться, что мы используем cgo, что позволяет программам Go интерполировать с библиотеками C. Это важно для использования возможности запускать программы GoLang на Android или iOS.

Мы делаем это, устанавливая переменную окружения CGO_ENABLED=1

Другое соображение - размер двоичного файла. Поскольку мобильный телефон обычно имеет меньше памяти, чем обычный компьютер, Apple представила так называемый Bitcode, который использует некоторые хитрые приемы компьютерной инженерии для оптимизации двоичных файлов, например, путем упаковки нескольких типов данных в один 64-битный фрейм памяти.

Apple требует в своих программах двоичных файлов с поддержкой Bitcode, поэтому давайте включим это, установив переменную среды CGO-CFLAGS="-fembed-bitcode":

Собирая все вместе, мы получаем следующее:

$ export CGO_ENABLED=1
$ CGO_CFLAGS="-fembed-bitcode"

Компиляция

Основная команда для создания двоичного файла из проекта GoLang такова:

$ go build

Если вы компилируете определенный файл или файлы в папке, вы укажете go, какой файл или папку вы компилируете:

$ go build /path/to/gofile/or/folder

Изменить имя выходного файла

Вы можете указать GoLang, как назвать выходной файл, передав -o outputfilename параметр в go build. Обычно мобильным двоичным файлам присваивают расширение .a:

$ go build -o outputfilename.a /path/to/gofile/or/folder

Кросс-компиляция

Для кросс-компиляции вам необходимо указать go, какая ОС (GOOS), архитектура (GOARCH) и, в зависимости от вашей целевой платформы, ваш SDK (SDK), установив соответствующие переменные среды GoLang.

Например, если вы компилируете для устройства Android, вы должны установить переменные среды GOOS и GOARCH для Android / arm64.

$ export GOOS=android
$ export GOARCH=arm64

Если вы компилируете на устройство iOS, вы будете устанавливать переменные среды GOOS, GOARCH и SDK для Darwin / arm64:

$ export GOOS=darwin
$ export GOARCH=arm64
$ export SDK=iphoneos

Для симулятора iOS вы измените переменную SDK среды для симулятора iPhone.

$ export SDK=iphonesimulator

Затем вы можете запустить команду сборки:

$ go build -o outputfilename.a /path/to/gofile/or/folder

Вы должны увидеть новый файл outputfilename.a в рабочей папке.

Создать файл заголовка C

Cgo позволяет экспортировать файлы заголовков C с вашим двоичным кодом. Этот файл важен, потому что он позволяет вам вызывать функции из вашего проекта GoLang как модуль. Вы можете сделать это, передав в программу -buildmode=c-archive параметр go build:

$ go build -buildmode c-archive -o outputfilename.a /path/to/file

Вы заметите два новых файла:

  • outputfilename.a, скомпилированный двоичный файл.
  • outputfilename.h, заголовочный файл C.

Этот файл C-заголовка будет включать вашу экспортированную функцию:

// ...
#ifdef __cplusplus
extern "C" {
#endif
extern void sayHello();
#ifdef __cplusplus
}
#endif

Обрезать жир

Наконец, вы можете избавиться от некоторых неиспользуемых символов, передав -trimpath функции go build. Это удалит информацию о пути к проекту из окончательного двоичного файла:

$ go build -buildmode c-archive -trimpath -o outputfilename.a /path/to/file

Вы можете прочитать об этом в документации go help build, в разделе -trimpath:

 -trimpath
    remove all file system paths from the resulting executable.
    Instead of absolute file system paths, the recorded file names
    will begin with either "go" (for the standard library),
    or a module path@version (when using modules),
    or a plain import path (when using GOPATH).

Собираем все вместе

Теперь, когда вы все это прочитали, это должно иметь смысл:

$ export GOOS=darwin   // ios: darwin, android: android
$ export GOARCH=arm64
$ export SDK=iphoneos  // iPhone simulator: iphonesimulator
$ CGO_ENABLED=1
$ CGO_CFLAGS="-fembed-bitcode
$ go build -buildmode c-archive -trimpath -o outputfilename.a /path/to/file

Это создаст два файла, которые вы будете использовать в качестве модуля в своем проекте:

  • outputfilename.a, двоичный модуль
  • outputfile.h, который сообщает вашему компилятору, как использовать двоичный файл

Вы сможете включить эти файлы в проект, а затем вызвать метод sayHello(), например:

#include <stdio.h>
#include "outputfile.h"
// ...
void main() {
  printf(sayHello())
}
#Golang
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться