dongqia0240 2017-06-04 20:02
浏览 204
已采纳

使用CGO,LuaJIT和Musl构建静态二进制文件

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

Go code I try to build:

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
", err)
}

Build command with parameters and output:

$ 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

Using LD_DEBUG=all I can get more information (8000+ lines).

My question: what is the problem and how to solve it? I think there can be some hint here but I can't quite grasp it.

I took following steps:

1. Build static LuaJIT library with musl.

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

2. Build dynamic LuaJIT library with musl.

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

3. Check build.

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

4. Install it.

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

5. Check installation.

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

6. Modify golua lua.go file to use hardcoded cgo parameters.

I had problems overriding those values so I simply modify source code.

old C comment with cgo parameters:

/*
#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"

new:

/*
#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. Build some example

As shown at the beggining of question.

Where LuaJIT got installed:

$ 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

EDIT 1

I've followed @putu's comment and changed #cgo LDFLAGS to

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

now I have

$ 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
  • 写回答

1条回答 默认 最新

  • dqydp44800 2017-06-05 09:26
    关注

    @putu pointed me to the right direction, all I had to do was tune CFLAGS to include musl.

    Cleaned up C comment in 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"
    

    Looks like everything builds just fine:

    $ 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)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿