使用 cgo、LuaJIT 和 musl 构建静态二进制文件

Build static binary with cgo, LuaJIT and musl

看完Statically compiled Go programs, always, even with cgo, using musl I'm trying to use described method to statically link LuaJIT

我尝试构建的 Go 代码:

package main

import "github.com/aarzilli/golua/lua"
import "fmt"

func test(L *lua.State) int {
    fmt.Println("hello world! from go!")
    return 0
}

func test2(L *lua.State) int {
    arg := L.CheckInteger(-1)
    argfrombottom := L.CheckInteger(1)
    fmt.Print("test2 arg: ")
    fmt.Println(arg)
    fmt.Print("from bottom: ")
    fmt.Println(argfrombottom)
    return 0
}

func main() {
    L := lua.NewState()
    defer L.Close()
    L.OpenLibs()

    L.GetField(lua.LUA_GLOBALSINDEX, "print")
    L.PushString("Hello World!")
    L.Call(1, 0)

    L.PushGoFunction(test)
    L.PushGoFunction(test)
    L.PushGoFunction(test)
    L.PushGoFunction(test)

    L.PushGoFunction(test2)
    L.PushInteger(42)
    L.Call(1, 0)

    L.Call(0, 0)
    L.Call(0, 0)
    L.Call(0, 0)

    // this will fail as we didn't register test2 function
    err := L.DoString("test2(42)")

    fmt.Printf("Ciao %v\n", err)
}

使用参数和输出构建命令:

$ CC="/usr/local/musl/bin/musl-gcc" go build --ldflags '-linkmode external -extldflags "-static"' basic.go
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running /usr/local/musl/bin/musl-gcc failed: exit status 1
/usr/bin/ld: cannot find -lluajit-5.1
collect2: error: ld returned 1 exit status

使用 LD_DEBUG=all 我可以获得 more information(8000 多行)。

我的问题:问题是什么以及如何解决?我想可能会有一些提示,但我不太明白。

我采取了以下步骤:

1。使用 musl 构建静态 LuaJIT 库。

$ make STATIC_CC="/usr/local/musl/bin/musl-gcc" CCOPT="-static -fPIC" BUILDMODE="static"
...
==== Successfully built LuaJIT 2.0.4 ====

2。使用 musl 构建动态 LuaJIT 库。

$ make DYNAMIC_CC="/usr/local/musl/bin/musl-gcc" BUILDMODE="dynamic"
...
==== Successfully built LuaJIT 2.0.4 ====

3。检查构建。

$ find . -iname *.a -o -iname *.so
./src/libluajit.a
./src/libluajit.so

4。安装它。

$ sudo make install
...
==== Successfully installed LuaJIT 2.0.4 to /usr/local ====

5。检查安装。

$ pkg-config luajit --cflags
-I/usr/include/luajit-2.0
$ pkg-config luajit --libs
-lluajit-5.1

6。修改 golua lua.go 文件以使用硬编码 cgo 参数。

我在覆盖这些值时遇到了问题,所以我只是修改了源代码。

C 评论 cgo 参数:

/*
#cgo CFLAGS: -I ${SRCDIR}/lua
#cgo llua LDFLAGS: -llua
#cgo luaa LDFLAGS: -llua -lm -ldl
#cgo linux,!llua,!luaa LDFLAGS: -llua5.1
#cgo darwin,!luaa pkg-config: lua5.1
#cgo freebsd,!luaa LDFLAGS: -llua-5.1
#cgo windows,!llua LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32
#include <lua.h>
#include <stdlib.h>
#include "golua.h"
*/
import "C"

新:

/*
#cgo CFLAGS: -I/usr/include/luajit-2.0 -I${SRCDIR}/lua
#cgo LDFLAGS: -lluajit-5.1
#include <lua.h>
#include <stdlib.h>
#include "golua.h"
*/
import "C"

7。建立一些例子

如问题开头所示。

安装 LuaJIT 的位置:

$ find / -iname libluajit* 2> /dev/null
/usr/local/lib/libluajit-5.1.so.2
/usr/local/lib/libluajit-5.1.a
/usr/local/lib/libluajit-5.1.so
/usr/local/lib/libluajit-5.1.so.2.0.4
/usr/lib/libluajit-5.1.so.2.0.5
/usr/lib/libluajit-5.1.so.2
/usr/lib/libluajit-5.1.a
/usr/lib/libluajit-5.1.so
/usr/lib/libluajit.s

编辑 1

我已关注 @putu's 评论并将 #cgo LDFLAGS 更改为

#cgo LDFLAGS: -L/usr/local/lib -lluajit-5.1

现在我有

$ CC="/usr/local/musl/bin/musl-gcc" go build --ldflags '-linkmode external -extldflags "-static -fPIC"' basic.go
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running /usr/local/musl/bin/musl-gcc failed: exit status 1
/tmp/go-link-916770907/000000.o: In function `printf':
/usr/include/x86_64-linux-gnu/bits/stdio2.h:104: undefined reference to `__printf_chk'
collect2: error: ld returned 1 exit status

@putu 为我指明了正确的方向,我所要做的就是调整 CFLAGS 以包含 musl.

清理了 C lua.go 中的评论:

/*
#cgo CFLAGS: -I/usr/include/luajit-2.0 -I/usr/local/musl/include/
#cgo LDFLAGS: -L/usr/local/lib -lluajit-5.1
#include <lua.h>
#include <stdlib.h>
#include "golua.h"
*/
import "C"

看起来一切正常:

$ CC="/usr/local/musl/bin/musl-gcc" go build --ldflags '-linkmode external -extldflags "-static"' basic.go
$ file basic
basic: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
$ ./basic 
Hello World!
test2 arg: 42
from bottom: 42
hello world! from go!
hello world! from go!
hello world! from go!
Ciao [string "test2(42)"]:1: attempt to call global 'test2' (a nil value)