How build lib for 386 arch with cgo on windows? - windows

I have a golang library that builds and works well on Linux, MacOs and Windows. The problem comes when I'm trying to build it for 386 on the amd64 Windows VM. I've installed latest golang SDK and mingw, which makes amd64 build work fine, but not the 386:
PS > gcc -v
gcc.exe (MinGW-W64 x86_64-posix-seh, built by Brecht Sanders) 11.2.0
PS > go version
go version go1.18.3 windows/amd64
PS > $Env:GOOS = "windows"; $Env:GOARCH = "386"; $Env:CGO_ENABLED ="1"; go build -v -buildmode=c-shared -ldflags="-s -w" -gcflags="-l" -o xyz_amd64.dll xyz_win_dll.go
...
runtime/cgo
c:/programdata/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible c:/pro
gramdata/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/lib/libmingwthrd.a when searching for -lmingwt
hrd
...
<a lot of skipping incompatible messages here>
collect2.exe: error: ld returned 1 exit status
How to fix it? AFAIK it should be possible to build for both arch on the same box.

Cgo build fail, I solve it by this way: firstly, ensure build C code successfully.
generally, cgo cross compilation require C cross compilation and Go cross compilation . maybe you can add set // #cgo CFLAGS:C_CrossBuild_Parameters.
As you can see, it's not easy. It's why Cross compilation goes out the window

I've found the diff in the project description and switched to https://www.mingw-w64.org/. It contains libs for both arch 386 and x64. Now across compilation works fine to me.

Related

Standalone build of DPDK on Windows fails for examples application

Building the example application skeleton or l2fwd or l3fwd via DPDK meson with option -Dexamples=, creates the binary executable without any warnings or error. But executing the same example as standalone build leads to DPDK build error
C:\dpdk\dpdk-21.02\examples\skeleton>gcc basicfwd.c -include rte_config.h -march=native -IC:/include -Wl,--as-needed -LC:/lib -lrte_cfgfile -lrte_hash -lrte_cmdline -lrte_pci -lrte_ethdev -lrte_meter -lrte_net -lrte_mbuf -lrte_mempool -lrte_rcu -lrte_ring -lrte_eal -lrte_telemetry -lrte_kvargs
In file included from C:/include/rte_eal.h:21,
from basicfwd.c:7:
C:/include/rte_bus.h:22:10: fatal error: sys/queue.h: No such file or directory
#include <sys/queue.h>
^~~~~~~~~~~~~
compilation terminated.
Expectation:
C:\dpdk\dpdk-21.02\examples\skeleton>dir
Directory of C:\dpdk\dpdk-21.02\examples\skeleton
<DIR> .
<DIR> ..
163,348 a.exe
5,458 basicfwd.c
1,511 Makefile
322 meson.build
Steps to reproduce the error
Platform: x86_64, Intel E5 2680 Xeon
OS: windows server 2019
DPDK version: 21.02
Meson version: 0.57.1
Ninja version: 1.10.2
Pkg-config version: 0.26
Steps followed: http://doc.dpdk.org/guides/windows_gsg/index.html
compiler flags: execute pkg-config --cflags --libs libdpdk
There is a difference in the CFLAGS and LDFLAGS when one uses meson meson -Dexamples=l2fwd build and meson build. In the former scenario, the dependency is pulled from DPDK root folder directly and direct link to lib/librte_eal/windows/include. But when DPDK pkg has installed the files under lib/librte_eal/windows/include are not copied over which causes build failure.
Checking meson.build in lib/librte_eal/windows/ reveals the only install is for 'rte_os.h', 'rte_virt2phys.h', and 'rte_windows.h'. Folder 'netinet' and 'sys' are skipped. Based on the update from DPDK maintainer, since DPDK on windows is experimental only validation done is with meson -Dexamples=l2fwd build. Hence as temporary work around is to use -I[DPDK folder]\lib\librte_eal\windows\include\
Note:
Thanks to #stackinside for the comment
working on DPDK patch to plug the missing files.

How to cross-compile with .gpr project file and gprbuild?

I'm trying to cross-compile from Linux (Fedora 29) an Ada program with Windows as target. I have no knowledge about compilation and the Gnat project manager doc couldn't help the noob I am.
I would prefer to use switches inside the project file and keep the command the simplest possible. What should I do?
I tried gprbuild -P logfilter.gpr --target=Windows which leads to
Error: no compiler found for language 'c', target = Windows, default runtime
Error: no compiler found for language 'ada', target = Windows, default runtime
logfilter.gpr:3:09: warning: no compiler specified for language "Ada", ignoring all its sources
logfilter.gpr:7:19: "log_filter_main.adb" is not a source of project "logfilter"
gprbuild: problems with main sources
Here is my gprconfig:
prconfig has found the following compilers on your PATH.
Only those matching the target and the selected compilers are displayed.
1. GNAT for Ada in /usr/bin/ version 8.3 (default runtime)
2. GCC-ASM for Asm in /usr/bin/ version 8.3.1
3. GCC-ASM for Asm2 in /usr/bin/ version 8.3.1
4. GCC-ASM for Asm_Cpp in /usr/bin/ version 8.3.1
5. LLVM for C in /usr/bin/ version 7.0.1
6. GCC for C in /usr/bin/ version 8.3.1
7. G++ for C++ in /usr/bin/ version 8.3.1
and my gprconfig --show-targets:
List of targets supported by a compiler:
x86_64-redhat-linux
x86_64-unknown-linux-gnu
here is my file.gpr:
with "../../lib/gnat/gtkada";
project LogFilter is
for Source_Dirs use ("src");
for Object_Dir use "obj";
for Exec_Dir use "exec";
for Main use ("log_filter_main.adb");
package Builder is
for Executable ("main.adb") use "Logs_Filter";
end Builder;
package Compiler is
for Switches ("ada") use ("-gnat2012");
end Compiler;
end Logfilter;
Once I did this with Fedora 24. But this required to build a cross compiler. I still have a docker image
and patches for fedora packages
I filled a request on fedora to include ada in windows in cross compiler, but they closed it. I'm unable to find the bug number, however.
Tell me if you are interested in fresh version of this or instructions how to use.
Update: I've rebuilt cross for FC29. You can try it this way:
dnf copr enable reznik/ada
dnf install mingw64-gcc-gnat
dnf install gprbuild
sed -i -e 's/-pc-mingw/-w64-mingw/g' /usr/share/gprconfig/*
cat > hello.adb << EOF
with Ada.Text_IO;
procedure Hello is
begin
Ada.Text_IO.Put_Line ("Hello");
end Hello;
EOF
cat > hello.gpr << EOF
project Hello is
for Main use ("hello.adb");
end Hello;
EOF
gprbuild --target=x86_64-w64-mingw32 -P hello.gpr
file hello.exe
hello.exe: PE32+ executable (console) x86-64, for MS Windows
PS: link to copr
As others have pointed out, the issue you're encountering is because you're not using a cross compiler.
Just to clarify something about gprbuild that might make this clearer: gprbuild is just a front-end for the versions of gcc and gnat on your system. Essentially it's just an Ada-specific analogue of make. It processes the project configuration file and works out what parts of the project to be built. From the gprconfig output it looks like you're using the FSF GNAT obtained from the Fedora repos. gprconfig --show-targets is only showing you the targets of the native Linux compilers that it's found in your $PATH.
To solve your problem you'll need to find an Ada compiler targeting Windows. AdaCore provide a pretty decent native Windows compiler if that's an option for you.

How to cross compile solaris 32-bit

We are currently building our Go executables for several platforms including Solaris 64-bit. We have requests for a 32-bit Solaris executable version as well and I am unable to get this to work (the person who setup the Solaris 64-bit cross compiler is gone and unreachable).
I tried just setting -m32 flag on go build using our existing solaris cross compilation, but that didn't work, so I am attempting to build a Solaris 32-bit specific cross compiler.
I googled and found some vague examples, so I am following this process:
Copy headers and libraries from a 32-bit Solaris machine to my Linux build machine.
D/L and build binutils and gcc pointing SYSROOT to the downloaded 32-bit Solaris headers and libraries where:
$TARGET=sparc-sun-solaris2.10
$SYSROOT=/path/to/solaris32/includes
$PREFIX=/path/to/gcc-output
binutils-2.31/configure -target=$TARGET --prefix=$PREFIX -with-sysroot=$SYSROOT -v
gcc-8.2.0/configure --target=$TARGET --with-gnu-as --with-gnu-ld --prefix=$PREFIX -with-sysroot=$SYSROOT --disable-libgcj --enable-languages=c,c++,go -v
Create a symlink to gogcc and put GCC on the path
Compile a trivial test go program like this:
go build --compiler gccgo --gccgoflags "-m32 -O3 -static-libgo -Wl,-dy -lnsl -lsocket -lrt -lsendfile" -o ${GOTOOLS}/${BINARIES}/${PROJECT_NAME}/test/solaris_sparc32 test/main.go
This fails as follows:
go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags
command-line-arguments
gccgo: error: may not use both -m32 and -m64
Clearly I don't know what I'm doing. Can anyone point me in the right direction?
Solaris 32-bit does not appear to be supported, according to the list of supported OS/arch targets:
The valid combinations of $GOOS and $GOARCH are:
$GOOS $GOARCH
...
solaris amd64
...
That is, Solaris 64-bit is explicitly listed as a supported platform but Solaris 32-bit is not listed.
As such, there is good reason to believe that go programs will not run reliably on Solaris 32-bit systems and you probably should not agree to support that platform (if you do happen to get that cross compilation working) mainly because the go team itself does not support it!

Cross-compiling Rust from Windows to ARM Linux

I'm using Windows 10. I would like to cross-compile a Rust program to run on armv7-unknown-linux-gnueabihf. (armv7-unknown-linux-muscl would also be acceptable but it doesn't seem to be available.)
Here are my steps:
Install rustup
rustup toolchain install stable-x86_64-pc-windows-gnu
rustup toolchain default stable-x86_64-pc-windows-gnu
rustup target add armv7-unknown-linux-gnueabihf
Edit my ./cargo/config file to contain:
[build]
target = "armv7-unknown-linux-gnueabihf"
cargo build
This compiles everything fine, but when it comes to linking it gives this error:
error: could not exec the linker `cc`: The system cannot find the file specified. (os error 2)
As far as I have been able to determine, this is because Rust doesn't have its own linker and uses GCC instead. Apparently I need to provide this myself and add this to the ./cargo/config file:
[target.armv7-unknown-linux-gnueabihf]
linker = "c:/path/to/my/gcc/cross/compiler"
Is that right? If so where on Earth can I download such a cross-compiler for Windows and why doesn't rustup install it? Having to compile a cross-compiling version of GCC yourself is the biggest pain of cross-compiling C/C++ programs. Does Rustup really not make this any easier?
Thanks to #Notlikethat's comment:
a) Yes you need to provide your own GCC cross-compiler.
b) You can get one here (select a mingw32 build).
Just unzip linaro's GCC then point cargo to it:
[target.armv7-unknown-linux-gnueabihf]
linker = "C:/Users/me/gcc-linaro-5.3.1-2016.05-i686-mingw32_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc.exe"
It seems to work even though it is arm- and not armv7-. I guess linking doesn't depend on the ISA. Actually I haven't run it yet, but it builds without errors!
Edit:
You can now use armv7-unknown-linux-musleabihf instead and get an actually portable binary (i.e. it doesn't depend on the GNU C library which often causes compatibility issues).
For MacOS better use: musleabihf, for Windows you can use gnueabihf as bellow:
Mac
$ brew install arm-linux-gnueabihf-binutils
$ rustup target add armv7-unknown-linux-musleabihf
In .cargo/config
[build]
target = "armv7-unknown-linux-musleabihf"
[target.armv7-unknown-linux-c]
linker = "arm-linux-gnueabihf-ld"
With simple src/main.rs
fn main() {
println!("Hello, Raspberry!");
}
Then things are fine:
Hasans-Air:rpi hasan$ cargo build
Compiling rpi v0.1.0 (/Users/hasan/PycharmProjects/rpi)
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
Hasans-Air:rpi hasan$ scp target/armv7-unknown-linux-musleabihf/debug/rpi pi#192.168.1.43:
pi#192.168.1.43's password:
rpi 100% 2702KB 2.6MB/s 00:01
Hasans-Air:rpi hasan$ ssh pi#192.168.1.43 'chmod +x ~/rpi && ~/rpi'
pi#192.168.1.43's password:
Hello, Raspberry!
Win 10
Get the linker from here, and run:
rustup target add armv7-unknown-linux-gnueabihf
Creating file .cargo/config with content:
[build]
target = "armv7-unknown-linux-gnueabihf"
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
And with simple src/main.rs:
fn main() {
println!("Hello, Raspberry! from Win 10");
}
I was able to get things done

Go/Golang Cross-Compile from Mac to Windows: fatal error: 'windows.h' file not found

Summary: when I try cross-compiling a .go source file that includes a C file somewhere in the file chain, targeting Windows AMD64 from a Mac host, I get:
/usr/local/go/src/runtime/cgo/gcc_windows_amd64.c:8:10: fatal error: 'windows.h' file not found
Purely Go code seems to cross compile without error; is there a way to get the proper header files for cross compilation when C files are involved?
More details: I installed LiteIDE on my Mac for working on some .go projects, and LiteIDE makes it relatively simple to target other platforms as build targets. I tested it on a small test project I had, purely Go, and it seemed to run without error.
Later I tried it on a current, larger project and had to adjust several env settings in the IDE to get it to work (complaints about C files without CGO enabled, and GOPATH not set properly even though it's set in .bash_profile and verified in echo $VARIABLE just fine.) The result is
/usr/local/go/src/runtime/cgo/gcc_windows_amd64.c:8:10: fatal error: 'windows.h' file not found
Trying to target Linux (os linux, arch amd64) gives
# runtime/cgo
ld: unknown option: --build-id=none
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've double checked I have XCode installed; gcc is installed:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr with-gxx-include- dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
...and Go is the latest version:
go version go1.6.2 darwin/amd64
I also checked that this isn't just from LiteIDE (since LiteIDE seems to override env settings and ignore what's in the terminal?); an example attempt at the console gives:
MyUsername$ env GOOS=windows GOARCH=amd64 CGO_ENABLED=1 go build -v
golang.org/x/net/html/atom
runtime/cgo
golang.org/x/crypto/ssh/terminal
golang.org/x/net/html
github.com/howeyc/gopass
# runtime/cgo
/usr/local/go/src/runtime/cgo/gcc_windows_amd64.c:8:10: fatal error: 'windows.h' file not found
github.com/andybalholm/cascadia
github.com/PuerkitoBio/goquery
I suspect this is because the application uses networking libraries in Go and I think the native libraries are still calling some C files to fill in gaps. Is there a way to get the proper libraries for building on Linux/Windows or does this need to be done on the target platforms in order to work?
Building native applications on the host platform seems to work without issue.
To enable cross-compiling for CGO you need to have a local toolchain that can compile C code for that target.
I'm not very familiar with Mac OS X, but on Arch Linux all I had to do was install mingw-w64-toolchain and compile my go code with:
env GOOS="windows" GOARCH="386" CGO_ENABLED="1" CC="i686-w64-mingw32-gcc" go build
// or to target win 64
env GOOS="windows" GOARCH="amd64" CGO_ENABLED="1" CC="x86_64-w64-mingw32-gcc" go build
On OSX, you can install mingw with homebrew: brew install mingw-w64
About the other error message though, ld: unknown option: --build-id=none seems like a bug, you might want to report that on the Go issue tracker.

Resources