user17471643
user17471643

Reputation:

Golang & CGO – link to a DLL dynamic library

Go language positions itself as a cross-platform language. To me a cross-platform language is that kind of language which is usable on all the supported platforms.

I would like to use its ability to link to a DLL dynamic library. DLL libraries are used on Windows operating systems, and Golang is known to support Windows O.S.

Golang's GitHub repository does not allow me to post questions there, they redirect me to StackOverflow (https://github.com/golang/go/wiki/Questions), so let it be so.

The library was written in C language. Golang is known to support the C language using the so called "CGO" feature.

I know about the syscall package. I would like to use the "CGO" feature on purpose.

I know that Golang provides a method to specify a C compiler for CGO using the CC variable. I want to know what is the proper way to use CLang compiler (https://en.wikipedia.org/wiki/Clang) in Go's CGO for my purpose.

So, my questions to the creators and maintainers of the Go language are following.

  1. How do I link to a C language DLL in Go ?
  2. How do I use CLang compiler for CGO ?
  3. How do I see the output (stdout for C people) of the compilation and linkage process in CGO ?

Thank you.

UPDATE

 go env -w CC="D:\Program Files\LLVM\bin\clang.exe"

sets the C compiler.

go env CC
D:\Program Files\LLVM\bin\clang.exe

but when I try to compile something it says:

... build constraints exclude all Go files in ... 

I fix this by setting environment variable CGO_ENABLED to 1 in my IDE.

Then a new error jumps out:

cgo: C compiler "D:\\Program" not found: exec: "D:\\Program": file does not exist

Looks like Go is still not supporting spaces in CC ?!

cmd/go: CC variable misparsed when set to a path containing spaces #41400
https://github.com/golang/go/issues/41400

@gopherbot gopherbot closed this as completed in 742dcba on Aug 16, 2021.

go version
go version go1.20.3 windows/amd64

I use the native go tool to add double quotes to my CC variable:

go env -w CC="\"D:\Program Files\LLVM\bin\clang.exe\""
go env CC
"D:\Program Files\LLVM\bin\clang.exe"

Alternative way will be to use native Windows tool to set the variable manually.

SET CC="D:\Program Files\LLVM\bin\clang.exe"

ECHO %CC%
"D:\Program Files\LLVM\bin\clang.exe"

go env CC
"D:\Program Files\LLVM\bin\clang.exe"

Looks like success ? Not yet.

go build .
# test/sdl-wrapper
D:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running D:\Program Files\LLVM\bin\clang.exe failed: exit status 1104
LINK : warning LNK4044: unrecognized option '/-tsaware'; ignored
LINK : warning LNK4044: unrecognized option '/-nxcompat'; ignored
LINK : warning LNK4044: unrecognized option '/-major-os-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-os-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-major-subsystem-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-subsystem-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-dynamicbase'; ignored
LINK : warning LNK4044: unrecognized option '/-high-entropy-va'; ignored
LINK : warning LNK4044: unrecognized option '/T'; ignored
LINK : warning LNK4044: unrecognized option '/-start-group'; ignored
LINK : warning LNK4044: unrecognized option '/-end-group'; ignored
LINK : fatal error LNK1104: cannot open file 'SDL2.lib'
clang: error: linker command failed with exit code 1104 (use -v to see invocation)

OK. I add SDL2.lib and SDL2.dll to the current folder.

go build .
# test/sdl-wrapper
D:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running D:\Program Files\LLVM\bin\clang.exe failed: exit status 1104
LINK : warning LNK4044: unrecognized option '/-tsaware'; ignored
LINK : warning LNK4044: unrecognized option '/-nxcompat'; ignored
LINK : warning LNK4044: unrecognized option '/-major-os-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-os-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-major-subsystem-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-subsystem-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-dynamicbase'; ignored
LINK : warning LNK4044: unrecognized option '/-high-entropy-va'; ignored
LINK : warning LNK4044: unrecognized option '/T'; ignored
LINK : warning LNK4044: unrecognized option '/-start-group'; ignored
LINK : warning LNK4044: unrecognized option '/-end-group'; ignored
LINK : fatal error LNK1104: cannot open file 'mingwex.lib'
clang: error: linker command failed with exit code 1104 (use -v to see invocation)

I do not see any signs of mingwex.lib in the source codes of SDL2 library.
My code is not using this file also.
What does this error mean then ?

build: cgo with clang and -buildmode=c-shared failures on Windows #42146
https://github.com/golang/go/issues/42146

I saw some people making merge requests to the Golang's source code to fix this mistake. But these attempts are being blocked by Google. https://github.com/golang/go/pull/54811

Wikipedia says that

LLVM currently supports compiling of Ada, C, C++, D, Delphi, Fortran, Haskell, Julia, Objective-C, Rust, and Swift using various front ends. Widespread interest in LLVM has led to several efforts to develop new front ends for a variety of languages.

Wikipedia also notes that CLang is primarily supported by Apple.

I guess now I know why Google is stopping all the attempts to make the language really cross-platform. But ... this is not smart at all.

Either they support LLVM sooner or later, or they will lose this war of formats.

Let's try to dig this thing out and see what it is

It looks like the only usage of mingwex text in Golang's source code comes from the src/cmd/link/internal/ld/lib.go file. This file has a super intersting comment in its top:

// Inferno utils/8l/asm.c
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/asm.c
//
//  Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
//  Portions Copyright © 1995-1997 C H Forsyth ([email protected])
//  Portions Copyright © 1997-1999 Vita Nuova Limited
//  Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
//  Portions Copyright © 2004,2006 Bruce Ellis
//  Portions Copyright © 2005-2007 C H Forsyth ([email protected])
//  Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
//  Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

OK, here we see that this piece of software is provided as is and we can do whatever we want to do with it. Let it be so.

I am searching for a hard-coded name of a GCC library used on Linux O.S. in a cross-platform language Golang, which should be working on Windows O.S. Let's check this thing out.

First of all, my eye sticks to the following moment. The mingwex is not used in constants like in common sense programming practice, but it is hard-coded and scattered across different parts of the lib.go file. This shows the level of quality very distinctly. Let's count the usages.

The first usage is on line 683 in function func loadWindowsHostArchives(ctxt *Link) { :

if p := ctxt.findLibPath("libmingwex.a"); p != "none" { ... }

The second usage is in the same function on line 729 and it is commented in a TODO block.

The third usage is in the function func (ctxt *Link) hostlink() { which starts on line 1342 and ends on line 1902.

Here I must stop and make another comment. Well, usage of gigantic functions ~1000 lines long is also a sign of a bad quality. If you want to make a good product – you should read how code is written in C++ language for example. It is just a piece of advice. C++ is concidered to be the most difficult programming language in the world by many programmers and their standards are more than just words ...

In this gigantic function which is unreadable in practice, mingwex is used on line 1789:

argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")

Apart from these three places, the mingwex is not used in the source code of Golang 1.20.3.

Upvotes: 0

Views: 2316

Answers (1)

Daniel
Daniel

Reputation: 31579

  1. Using cgo ldflags you can add link flags to link with the library, e.g.

    // #cgo LDFLAGS: -lpng
    import "C"
    
  2. Using the CC environment variable, see this answer.

  3. It is just in the standard output of go build.

Upvotes: 1

Related Questions