Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: explain when to use -ldflags=-extar when cross-compiling #45395

Open
mewalig opened this issue Apr 5, 2021 · 6 comments
Open

doc: explain when to use -ldflags=-extar when cross-compiling #45395

mewalig opened this issue Apr 5, 2021 · 6 comments
Labels
Documentation help wanted NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@mewalig
Copy link

mewalig commented Apr 5, 2021

What version of Go are you using (go version)?

go version go1.16.3 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

darwin + amd64

What did you do?

I am compiling Go into a static archive to be called with C code. It works when I compile for the native platform. It does not work when I try to cross-compile for Windows using mingw64

Works:

  • cross-compile C for Win using mingw64 (no Go code) (to confirm that my C cross-compile toolchain works)
    x86_64-w64-mingw32-gcc only_c.c -o only_c.exe

  • native compile: Go to static archive, exporting a function myExportedFunction, called by C executable:
    go build -buildmode=c-archive test.go # ( exports myExportedFunction )
    clang test.c test.a -o test # ( test.c calls myExportedFunction )

No errors or warnings:

  • compile Go to static archive targeting Windows (cross-compiled on OSX for use with mingw64)
    CC=x86_64-w64-mingw32-gcc GOOS=windows CGO_ENABLED=1 go build -o test.w64a -buildmode=c-archive test.go
  • I have also tried using the below to build the archive (no change-- yields the same error below)
    CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ CPP=x86_64-w64-mingw32-cpp RANLIB=x86_64-w64-mingw32-ranlib AR=x86_64-w64-mingw32-ar LIBTOOL=/opt/mingw64/bin/libtool GOARCH=amd64 GOOS=windows CGO_ENABLED=1 go build -o test.w64a -buildmode=c-archive test.go

Fails:

  • compile executable: C code to call exported Go function, cross-compiled on OSX targeting Windows using mingw64
    x86_64-w64-mingw32-gcc test.c test.w64a -o test.exe
  • error:
    /.../x86_64-w64-mingw32-ld: /.../ccmb8owx.o:test.c:(.text+0x29): undefined reference to "myExportedFunction"

What did you expect to see?

No error message, and test.exe file created

What did you see instead?

Error message

@ianlancetaylor
Copy link
Contributor

Can you show us the code that you are trying to build?

@mewalig
Copy link
Author

mewalig commented Apr 5, 2021

Here's a simple example that has the same problem (at least for me).

test.go:

package main

// #include <stdlib.h>
import "C"

import (
	"fmt"
	"os"
	"unsafe"
)

//export myExportedFunction
func myExportedFunction(c_str *C.char) C.int {
	fmt.Println("hi")
	return 0
}

func main() {
	if len(os.Args) < 2 {
		println("Usage: test <any_string>\n")
	} else {
		arg1 := os.Args[1]
		arg1_c := C.CString(arg1)
		defer C.free(unsafe.Pointer(arg1_c))
		myExportedFunction(arg1_c)
	}
}

test.c:

#include "test.h"

int main(int argc, char **argv) {
  if(argc > 1)
    myExportedFunction(argv[1]);
  return 0;
}

@ianlancetaylor
Copy link
Contributor

What happens if you use go build -buildmode=c-archive -ldflags=-extar=x86_64-w64-mingw32-ar ... ? (Keep all the environment variable setting also, just add the -ldflags=-extar flag.)

@mewalig
Copy link
Author

mewalig commented Apr 6, 2021

That worked. You are the man! Thank you.

BTW: is there documentation that describes this necessary step, which I missed? In case it answers any other future questions/issues I might otherwise run into

@mewalig mewalig closed this as completed Apr 6, 2021
@ianlancetaylor
Copy link
Contributor

I'm going to reopen this to get better documentation.

We should also consider supporting an AR environment variable.

@ianlancetaylor ianlancetaylor reopened this Apr 6, 2021
@ianlancetaylor ianlancetaylor changed the title Unable to cross-compile static library called by C, when building on OSX for Windows doc: explain when to use -ldflags=-extar on Windows Apr 6, 2021
@ianlancetaylor ianlancetaylor added this to the Backlog milestone Apr 6, 2021
@ianlancetaylor ianlancetaylor changed the title doc: explain when to use -ldflags=-extar on Windows doc: explain when to use -ldflags=-extar when cross-compiling Apr 6, 2021
@dmitshur dmitshur added the NeedsFix The path to resolution is known, but the work has not been done. label Apr 6, 2021
@AlexRouSg
Copy link
Contributor

AlexRouSg commented Apr 7, 2021

We should also consider supporting an AR environment variable.

There appears to already be an AR env var?

env = append(env, cfg.EnvVar{Name: "AR", Value: envOr("AR", "ar")})

Looks like it might just be a few lines change to get ld to use the AR env

if *flagExtar == "" {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation help wanted NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

4 participants