Navigate back to the homepage

Build jiri for Windows

LER0ever
August 25th, 2018 · 2 min read

jiri

“Jiri integrates repositories intelligently” is the official description as well as a recursive acronym for jiri.

It is a multi-repo management tool used internally at Google for their Fuchsia OS development. The project manifest format is pretty much like repo, which is commonly used for Android development and was later adopted by other communities like CoreOS.

I came across Fuchsia even before its kernel was renamed to Zircon, and at that time, the Fuchsia OS itself is pretty much unusable. But I found jiri particularly useful for my own projects. Since then, I started using jiri for my own large projects that requires splitting repositories and gather them together to build (like my own libraries, my build tools, etc.)

Motivation

The workflow using jiri has been fine until recently. I send my graphics card back to the manufacturor for repairing, and therefore I have to shutdown my desktop until I received the repaired GPU. In my desktop machine previously, I have various OSes all configured ready for development:

  • Manjaro Linux latest
  • Hackintosh 10.12.6 high sierra
  • Windows 10 (insider)
  • Solus (for entertainment)

And jiri works pretty well on my Linux development environment as well as that illegal Hackintosh ;)

But now I’m stuck with a laptop running only Windows 10 Home …

I’ve already setup all the required dev tools (I assume you did if you want to build jiri on Windows as well), but in jiri’s documentation it is said to only compile under Linux and macOS, so I patched it to make it at least build on Windows (since most of it is written in platform independent Go code).

The Patch

1diff --git a/cmd/jiri/cmd.go b/cmd/jiri/cmd.go
2index d6761be..82e801b 100644
3--- a/cmd/jiri/cmd.go
4+++ b/cmd/jiri/cmd.go
5@@ -8,30 +8,13 @@
6 package main
7
8 import (
9- "fmt"
10 "runtime"
11- "syscall"
12-
13 "fuchsia.googlesource.com/jiri/cmdline"
14 )
15
16 func init() {
17 runtime.GOMAXPROCS(runtime.NumCPU())
18- if runtime.GOOS == "darwin" {
19- var rLimit syscall.Rlimit
20- err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)
21- if err != nil {
22- fmt.Println("Unable to obtain rlimit: ", err)
23- }
24- if rLimit.Cur < rLimit.Max {
25- rLimit.Max = 999999
26- rLimit.Cur = 999999
27- err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
28- if err != nil {
29- fmt.Println("Unable to increase rlimit: ", err)
30- }
31- }
32- }
33+ // darwin rlimit manipulation moved to conditional compilation
34 cmdRoot = newCmdRoot()
35 }
36
37diff --git a/textutil/util.go b/textutil/util.go
38index 7f03047..63a8cdf 100644
39--- a/textutil/util.go
40+++ b/textutil/util.go
41@@ -5,40 +5,28 @@
42 package textutil
43
44 import (
45- "syscall"
46- "unsafe"
47+ "golang.org/x/crypto/ssh/terminal"
48+ "os"
49 )
50
51 // TerminalSize returns the dimensions of the terminal, if it's available from
52 // the OS, otherwise returns an error.
53 func TerminalSize() (row, col int, _ error) {
54- // Try getting the terminal size from stdout, stderr and stdin respectively.
55- // We try each of these in turn because the mechanism we're using fails if any
56- // of the fds is redirected on the command line. E.g. "tool | less" redirects
57- // the stdout of tool to the stdin of less, and will mean tool cannot retrieve
58- // the terminal size from stdout.
59- //
60- // TODO(toddw): This probably only works on some linux / unix variants; add
61- // build tags and support different platforms.
62- if row, col, err := terminalSize(syscall.Stdout); err == nil {
63+ // Try getting the terminal size from stdout, stderr and stdin respectively
64+ // using terminal.GetSize function, which should work on most platforms.
65+
66+ fdOut := int(os.Stdout.Fd())
67+ fdIn := int(os.Stdin.Fd())
68+ fdErr := int(os.Stderr.Fd())
69+
70+ if row, col, err := terminal.GetSize(fdOut); err == nil {
71 return row, col, err
72 }
73- if row, col, err := terminalSize(syscall.Stderr); err == nil {
74+
75+ if row, col, err := terminal.GetSize(fdErr); err == nil {
76 return row, col, err
77 }
78- return terminalSize(syscall.Stdin)
79-}
80
81-func terminalSize(fd int) (int, int, error) {
82- var ws winsize
83- if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&ws))); err != 0 {
84- return 0, 0, err
85- }
86- return int(ws.row), int(ws.col), nil
87+ return terminal.GetSize(fdIn)
88 }
89
90-// winsize must correspond to the struct defined in "sys/ioctl.h". Do not
91-// export this struct; it's a platform-specific implementation detail.
92-type winsize struct {
93- row, col, xpixel, ypixel uint16
94-}

Basically, I replaced the “get terminal size” function with the golang.org/x/crypto/ssh/terminal’s GetSize() functions and moved darwin-specific initializing code to a separate file that is only processed when GOOS is darwin.

Building git2go

This is the painful part, since git2go did not provide any documentation on how to build on Windows, and most people do that in msys/cygwin, which I don’t feel comfortable with. The compilation process I tried uses gcc, go nothing else on Windows.

Package Manager: Scoop

Scoop is a tool I discovered recently, before that I’d always used Chocolatey. The advantage of Scoop over Chocolatey is that it updates packages much more frequently and almost all of its packages are up to date.

Installing packages is not hard as well:

1scoop install -g go gcc cmake pkg-config

This would get most of the dependencies required for building jiri installed.

Build libgit2

1git clone https://github.com/libgit2/libgit2.git
2cd libgit2
3# git checkout whatever
4mkdir build; cd build
5cmake .. -DCMAKE_C_COMPILER={path to your}/gcc.exe -DCMAKE_CXX_COMPILER={path to your}/g++.exe -DCMAKE_INSTALL_PREFIX={whatever}
6mingw32-make -j16
7mingw32-make install

Set the pkg-config path

1set PKG_CONFIG_PATH={whatever prefix}/lib/pkgconfig;

Building jiri

Apply the patch and Build

1patch -Np1 {path to your}/jiri-win.patch
2go build fuchsia.googlesource.com/jiri/cmd/jiri

Now you have jiri.exe inside the project root

Copy the libgit2.dll

jiri.exe requires libgit2.dll available if you built it dynamically, therefore you need to copy that dll either to the same directory as jiri.exe or somewhere Windows could find it…

There we Go

jiri windows

More articles from L.E.R Space | Blog

Download and stitch together OSTEP book

What is OSTEP I'm currently taking the Undergrad OS course at UW-Madison this semester (CS537: Operating System). Our professor is REMZI H…

April 16th, 2018 · 1 min read

高性能排序算法

马上明天就是紧张刺激的GCJ 201…

April 5th, 2018 · 1 min read
© 2014–2020 L.E.R Space | Blog
Link to $https://twitter.com/LER0everLink to $https://github.com/LER0everLink to $https://instagram.com/rongyi.ioLink to $https://www.linkedin.com/in/LER0ever