Building Juju 2.5.0 on Windows


#1

I’m trying to work out how we build Windows binaries. Is it just that we cross compile?

Reading through the build bot I see:
https://jenkins.juju.canonical.com/job/BuildJuju-windows-amd64/1349/consoleText

Which does:

  • export GOPATH=/var/lib/jenkins/workspace/BuildJuju-windows-amd64/_build
  • export GOARCH=amd64
  • export GOOS=windows
  • SERIES=win2012
  • go version
    go version go1.11.5 linux/amd64
  • go install github.com/juju/juju/cmd/juju github.com/juju/juju/cmd/jujud
  • juju_exe=/var/lib/jenkins/workspace/BuildJuju-windows-amd64/_build/bin/windows_amd64/juju.exe
  • iss_dir=/var/lib/jenkins/workspace/BuildJuju-windows-amd64/_build/src/github.com/juju/juju/scripts/win-installer

That seems pretty clear that we are cross compiling.

The big issue is that it seems our new dependency on github.com/coreos/dlopen and github.com/coreos/go-systemd are causing real problems for me to just go install github.com/juju/juju/....

The first problem was:

$ go install -v github.com/juju/juju/cmd/juju github.com/juju/juju/cmd/jujud
github.com/juju/juju/vendor/github.com/coreos/pkg/dlopen
# github.com/juju/juju/vendor/github.com/coreos/pkg/dlopen
vendor\github.com\coreos\pkg\dlopen\dlopen.go:21:11: fatal error: dlfcn.h: No such file or directory
 // #include <dlfcn.h>
           ^~~~~~~~~
compilation terminated.

Searching around on the web seems there are other coreos complaints about missing this file, but also turns up:
https://github.com/dlfcn-win32/dlfcn-win32

Which has Make targets for mingw and visual studio 12 targets. (Though the Visual Studio Community edition seems to be 2017?)

Anyway, downloading that, and then copying dlfcn.h and libdlfcn.a to the mingw64 lib and include dirs gets past the first issue, then gives:

$ time go install -v github.com/juju/juju/cmd/juju/...
github.com/juju/juju/vendor/github.com/coreos/pkg/dlopen
# github.com/juju/juju/vendor/github.com/coreos/pkg/dlopen
C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../lib/libdl.a(dlfcn.o):dlfcn.c:(.text+0x374): undefined reference to `EnumProcessModules'
collect2.exe: error: ld returned 1 exit status

However, that seems to be just that you need to add “-lpsapi” for dlfcn-win32. Now, that requires editing a “vendor” directory, which I’m not fond of, but it makes progress.

But after doing all that, I then get:

$ time go install -v github.com/juju/juju/cmd/juju/...
github.com/juju/juju/vendor/github.com/coreos/go-systemd/util
# github.com/juju/juju/vendor/github.com/coreos/go-systemd/util
util\util_cgo.go:122:11: could not determine kind of name for C.my_sd_pid_get_owner_uid
util\util_cgo.go:121:10: could not determine kind of name for C.uid_t
cgo:
gcc errors for preamble:
util\util_cgo.go:24:46: error: unknown type name 'uid_t'; did you mean 'pid_t'?
 // my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid)
                                              ^~~~~
                                              pid_t

I haven’t found a definitive reason why we’re missing ‘uid_t’. AFAICT it is supposed to be defined in <sys/types.h> which is clearly being imported.

I feel like maybe the answer is that for jujud on windows we shouldn’t be including coreos. Because if we are, is it actually getting the right definitions that Windows needs for all of those header files, or is it compiling against the Linux definitions.

Thoughts?


#2

That sucks, we do have a windows box to play with on aws, I wonder if we could build on there instead?


#3

I had a multitude of issues when I tried to run the Windows binaries related to external deps. If I have to work with Juju in Windows I always do so via WSL. Which works fine and dandy :slight_smile:


#4

So it seems that in 2.5.0 we updated our dependency on the coreos package, (with ~60 new commits going but all in 2016).

The problematic commit seems to be:

commit 17b531ae5d2ab59869f63e42a84ea5d772cfb995
Author: Iago López Galeiras <iago@kinvolk.io>
Date:   Mon Feb 1 13:31:49 2016 +0100

    sdjournal: dlopen libsystemd instead of linking against it

    This allows not having to link users of the library to libsystemd,
    detect at runtime if it exists or not and react accordingly.

Of course, the claim there is that now it doesn’t actually depend on libsystemd. (with the particular caveat that now we do depend on dlopen/libdl.)

It feels like the best route forward would be to change the code in ‘service/*’ to not import anything related to systemd. service/agentconf.go has a valid comment at the top that everything in the file is systemd specific, discovery.go would be able to notice that we wouldn’t be able to call systemd.IsRunning() anyway, since there wouldn’t be a systemd bus on Windows. ‘service/service.go’ needs a bit more rework, as it is full of case statements, trying to be the abstraction for service implementations. But we could change it to more of a Registry based system, rather than hard-coded cases.