11

I have GO 1.7 installed on my Windows 10. I created test program and it works perfectly in Windows. Next step is to try to run it on my docker virtual machine with Ubuntu.

I found here some info about the way to do it

set GOARCH=amd64
set GOOS=linux
go tool dist install -v pkg/runtime
go install -v -a std

I run line 1 and 2 in cmd and there is no problem. At line 3 I have an error

go tool dist: open C:\Go\src\pkg\runtime: The system cannot find the path specified.

I check manually this folder and there is a runtime only for windows

enter image description here

The question is where and how can I download it for linux? Or maybe thats I'm doing is completely wrong way...

UPDATE 09/02/2017

I ran like it was suggested

set GOARCH=amd64
set GOOS=linux
go build -o "myapp"

After I copied this file to shared folder, copied form there to another not shared folder (to avoid an issue described here) and executed

root@7dd1655ae5db:/__notshared# ./myapp
bash: ./myapp: cannot execute binary file: Exec format error

After I downloaded file package checked my file

root@7dd1655ae5db:/__notshared# file myapp
myapp: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows

It seems that during build not linux executable was created.

Community
  • 1
  • 1
Vitalii
  • 10,091
  • 18
  • 83
  • 151
  • I think you don't need the third command, just installing the std (ie `go install std`) is enough. – ain Feb 08 '17 at 16:10

3 Answers3

9

That other question is a bit old (from 2013).

Cross-platform support evolved a lot, all you need to do is change the environment variables (GOARCH and GOOS) and run go build.

Navigate to the folder of the main package, then:

set GOARCH=amd64
set GOOS=linux
go build

You may change the name of the result binary like this:

go build -o "myapp"

Note that in Linux to compile the app for Windows amd64, a single command is enough (in the folder of the main package):

GOOS=windows GOARCH=amd64 go build

This is also confirmed in blog post: Dave Cheney: Cross compilation with Go 1.5:

To cross compile a Go program using Go 1.5 the process is as follows:

  1. set GOOS and GOARCH to be the values for the target operating system and architecture.

  2. run go build -v YOURPACKAGE

Notes

You don't have to, and you shouldn't run go install, as that will compile and install the packages in your GOPATH, which is often not wanted. Doing cross compilation is not for developing / testing your app and packages. It is to produce a single binary which you will run on another system / computer.

go build will not install anything, it will just produce the executable binary. For details, see What does go build build?

Also confirmed in blog post: Dave Cheney: Cross compilation with Go 1.5:

When cross compiling, you should use go build, not go install. This is the one of the few cases where go build is preferable to go install.

The reason for this is go install always caches compiled packages, .a files, into the pkg/ directory that matches the root of the source code.

Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827
  • I believe that when cross-compiling you still have to have the standard lib for the target platform installed. I use ie `sudo env GOOS=windows GOARCH=amd64 /usr/local/go/bin/go install std` to enable cross-compiling for win64 on my Ubuntu. – ain Feb 08 '17 at 16:08
  • 4
    @ain No, it doesn't. In Linux, all you need to do is run `GOOS=windows GOARCH=amd64 go build` in the folder of the main package (just verified it). – icza Feb 08 '17 at 16:10
  • Could it be that you have already the std installed? I sure had to use the command in my first comment in order to be able to cross compile after I last time upgraded go (to 1.7). Of couse, once you have it installed you can just build from then on... – ain Feb 08 '17 at 16:12
  • 4
    @ain No, just the "bare" binary Go distribution, from the official [Downloads](https://golang.org/dl/) page. The go tool will recompile everything needed from the standard lib (from source) to the target os/arch, that's why it takes longer. – icza Feb 08 '17 at 17:22
  • 2
    @ain To add, you can always run `go tool dist list` to list the OS/ARCH combinations that your install of Go supports. – Igor Dubinskiy Feb 08 '17 at 22:13
7

I found a problem and a solution of it.

In my Windows 10 these commands

set GOARCH=amd64
set GOOS=linux

in cmd and also in powershell console did really nothing! Only the way it works is that I need to open Control Panel -> System -> System Advanced Settings -> Environment Variables and add them there manually.

enter image description here

If you use Visual Studio Code for development, do not forget to restart it.

UPDATE 24/02/2017

Instead all above you can set variable in windows powershell like this

$env:GOOS = "linux"

and read it to console

$env:GOOS

Vitalii
  • 10,091
  • 18
  • 83
  • 151
  • 2
    _"The `SET` command did realy nothing!"_ The `SET` command does not set the environment variable system-wide, only in the current command shell. So to other shells and apps it has no effect, this is no secret. – icza Feb 10 '17 at 17:18
  • 1
    But this even did not for current command shell. I set it, make build, copy my file to my linux container, run "file" comand and see that file is build for windows. Only when I do it to whole system the way I described, it works. I do not know why but it's like this for my windows 10 – Vitalii Feb 10 '17 at 21:30
  • Just for vscode, you can do: File->Preference->Settings: search for go.toolsEnvVars => add inside: `"GOARCH": "amd64", "GOOS": "linux"` There is no need to restart – B.Z. May 07 '21 at 16:28
1

What worked for me, on Windows 10 with Go 1.14, is the following:

go env -w GOARCH=amd64
go env -w GOOS=linux
go build -o test-linux test.go

That's it.

I tried this in both Windows command prompt and Windows PowerShell. There's no difference in results.

If you open the binary file in a text editor, you should see that it begins with ELF (Linux), and not MZ (Windows).

I ran it on a Linux machine (RHEL 7.3) with the given architecture, and it worked properly. It gave correct output.

After copying the file to the Linux machine, I had to make it executable:

$ chmod +x test-linux

Then I was able to run it:

$ ./test-linux

You can also run the following command on Linux, to get more detail about the file:

$ file test-linux
test-linux: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

Of course, if your architecture is amd64 already, then you don't have to set it again. You can just set the GOOS.

You can also revert GOOS to windows after you're done with cross-compiling. When I closed the Windows command prompt and PowerShell, and ran go env to see the list of Go environment variables, and GOOS kept the linux value. I didn't try with restarting Windows. So, if you now want to compile for Windows again:

go env -w GOOS=windows

You need to use the correct casing, as shown here. For example, Windows or Linux won't work.

ivanbgd
  • 171
  • 1
  • 5