How to build with Golang archive?

A Golang project xxx/api has been built into an archive file api.a with command: go build -buildmode archive -o api.a a.go b.go

I’d like import package xxx/api and link against the api.a without accessing its source code in another main project. How to do this?

Guys, really need your help.

As far as I know, you can’t.

If can not, what is the purpose of -buildmode=archive ?

To build a statically linked/linkable archive to be used with other compiler toolchains.

Perhaps you can use cgo to create an interface that calls into the archive which you link statically, though it requires manual setup.

There is no native support for pre compiled libraries in go.

If it has been compiled with -buildmode=c-archive, it can not be linked to the go main package again with CGO :frowning:

Could you advise how to link the archive from -buildmode=archive to a C program? Then is it possible to link the c archive from gcc to the go main package using cgo?

I have no clue. I do not use such archives. For me they ever have been a measure of “reverse FFI”. I do not care for them. I just told you what I found in a very shallow google research.

But perhaps we have an XY problem here… What exactly do you want to achieve? Why do you want to link to the archive?

1 Like

Found this…about archive and how to use it in C…
Link here

What I want achieve is:

A golang static library without source code to be linked to another golang main package.

Why:

The library is the key part of our work and we do not want it open source for the extension developers. And shared library is not recommended for security (preventing someone from compiling another program based on the shared library) and easy distribution.

Does not work for what I ask

Golang had binary only packages since go 1.7 as an experimental feature, which would support exactly what you are asking for, though support has been dropped a couple of versions later (https://github.com/golang/go/issues/28152).

Perhaps you can redesign your “key component” in a way that consumers write plugins, instead of calling your code.

From my understanding of cgo, you should be able to use the files generated, though you need to write another go file, that wraps the c-headers in a go package.

I tried CGO and did not work. Could your advise how to write another go file?

I do not use CGO, though from what I read about it, you need to:

  1. import "C"
  2. #include "theGenerated.h"
  3. Write functions that call the C funtions from the header.

Thanks. Putting extended work into a plugin seems an acceptable solution for Linux, and macOS. But our app is cross-platform one using gioui for iOS and Android, too, and plugin does not work any more.

Plugins are linux only IIRC.

So your only bets are to release open source or write the C wrapper around the go lib that you then wrap in go again.

  • api.go
    package main
    import “C”
    //export Test
    func Test() {}
    func main() {}

  • build
    go build -buildmode=c-archive -o libapi.a api.go

  • main.go
    package main
    // #include “libapi.h”
    // #cgo LDFLAGS: -L. -lapi
    import “C”
    func main() {
    C.Test()
    }

  • build
    go build -o main main.go

  • Error
    duplicate symbol ‘__cgo_panic’ in:
    $WORK/b001/_cgo_main.o
    ./libapi.a(go.o)
    duplicate symbol ‘__cgo_topofstack’ in:
    $WORK/b001/_cgo_main.o
    ./libapi.a(go.o)
    duplicate symbol ‘_crosscall2’ in:
    $WORK/b001/_cgo_main.o
    ./libapi.a(go.o)
    duplicate symbol ‘__cgo_wait_runtime_init_done’ in:
    $WORK/b001/_cgo_main.o
    ./libapi.a(000006.o)
    ld: 4 duplicate symbols for architecture arm64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    make: *** [main] Error 2

To be more accurate, from the pkg documentation

Currently plugins are only supported on Linux, FreeBSD, and macOS.

Try with another package name, and without a main function (would be useless in none main package anyway)

c-archive only support main package with main function :frowning: