Tag Archives: bash

Detecting location of Visual Studio 2017 and 2019

A few years ago, I wanted to use Bazel to build an old project of mine using Visual Studio 2017 Community.

Thing is, I don't install most of MSVS on my system partition, as it's on a relatively tiny SSD. So, where do I (portably) find it? And how do I set BAZEL_VS (per their documentation) to the correct path?

As I'm much more comfortable writing Bash scripts than writing old DOS-style Batch scripts, and as I'm going to have msys64 (or at least msys32) on my machines, clearly the answer is to write the resulting launcher in Bash. There are downsides to this approach, but it's doable.

Do you even need this for Bazel?

No. I just tried running bazel-2.0.0-windows-x86_64.exe with my project. It found MSVS2019 out of the box both in cmd.exe and in the MSYS64 shell.

Unfortunately, I have a genrule that depends on bash, which didn't work in cmd.exe even if I specified BAZEL_SH (missing binary for basename). And when I didn't pass BAZEL_SH while running under MSYS64, it had trouble finding SDL/SDL.h presumably because the aforementioned genrule didn't work.

Autodetection of MSVS2019 works, just set PATH Windows envvar to include msys binaries, and set BAZEL_SH Windows envvar to the output of cygpath -w /usr/bin/bash or cygpath -w /bin/bash.

You may want this for non-Bazel uses.

Finding Microsoft Visual Studio 2017

Assuming Bazel 2.0.0 is installed in C:\bazel under the default filename from the release on Github, this does the trick:

#!/bin/bash
# Based on https://superuser.com/a/539680 + searching around registry.
# Finds MSVS2017.
# Slashes when invoking 'reg query' are replaced with dashes because MSYS2.
VSPATH="$(cygpath -u "$(reg query 'HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7' -v 15.0 | tail -n+3 | head -n1  | awk '{for (i=3;i<=NF;i++) {printf "%s ",$i;};}' | sed 's/ *$//')")"

export BAZEL_SH="$(cygpath -w /usr/bin/bash)"
export BAZEL_VS="$VSPATH"

/c/bazel/bazel-2.0.0-windows-x86_64.exe $@

Finding Microsoft Visual Studio 2019

Unfortunately this is broken as of MSVS2019. See the explanation why that registry key is not used anymore.

The new situation is better: there's a tool that does get installed in a well-known path: %ProgramFiles(x86)%/Microsoft Visual Studio/Installer/vswhere.exe.

The problem is merely that Bash doesn't like parentheses in environment variable names, so ${ProgramFiles(x86)} won't be acceptable. However, it was visible in env output! Other people have spotted the same thing, but as their writings talk about PROGRAMFILES(X86) in all caps, I've concluded that maybe it's better to add the I flag to their sed-based solution.

#!/bin/bash
# Let's use VSWhere:
PROGRAMFILES_X86=$(env | sed -n s,'^PROGRAMFILES(X86)=',,pI) # because parens are not valid envvar names: http://mingw-users.1079350.n2.nabble.com/msysGit-bash-and-PROGRA$
VSWHERE=${PROGRAMFILES_X86}/Microsoft\ Visual\ Studio/Installer/vswhere.exe
VSWHERE="$(cygpath -u "${VSWHERE}")"

# Finding VC: https://github.com/microsoft/vswhere/wiki/Find-VC
VSPATH=$("${VSWHERE}" -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath)

export BAZEL_SH="$(cygpath -w /usr/bin/bash)"
export BAZEL_VS="$VSPATH"

/c/bazel/bazel-2.0.0-windows-x86_64.exe $@

VSCode

The problem with using Bazel integration into VSCode is that it wants a path to Bazel. But Bazel wants to have BAZEL_VS set.

Maybe I could work around this by writing a tool in a compilable language, then have it pass on all CLI arguments to actual bazel.exe, while also setting BAZEL_VS. Or maybe Bazel supports some settings in .bazelrc. I didn't care to check. Instead, I've used msys2_shell.cmd as the 'shell' for the integrated VSCode terminal. I'm used to manually running Bazel and I don't care enough about interactive debugging. For now, I just don't care enough to properly integrate Bazel into VSCode on Windows (though it would be neat).

Why even bother with Windows?

I need to trivially compare networking traffic between my project and a third-party program. The third-party program is written for Windows; it would likely work on other platforms under Wine, but I don't care enough to explore whether I can make a third-party binary patcher for that program work under Wine.

My program still works on Linux, built whether with Bazel or using Makefiles; but the deprecated SDL 1.2 was recently broken on macOS, my program won't work on macOS.

Getting this to work is also a nice exercise.

OS X's Terminal: Getting Home, End, PgUp, PgDn to work

Apple's Terminal on a Macbook requires a weird combination of fn+shift+left/right, fn+shift+up/down to get Home, End, PgUp and PgDn to work. And that still causes issues in a couple of places.

Despite maintaining my philosophy of "use defaults wherever possible", I've decided to ditch iTerm and iTerm2 for a simple reason: after quitting from Apple's Terminal, upon restart in Lion I get a screenful of information from my previous session. Quite handy if I had to restart a machine for some reason, but I don't want to lose the context!

Here are two fixes found Francois Planque's post.

First part involves fixing the escape sequences sent by the Terminal. Open Preferences (for example, by hitting Cmd+,), and navigate to Settings tab, then for the profile you want to adjust, navigate to Keyboard tab.

Over there, define the following escape sequences upon pressing home, end, page up and page down:

home: \033[1~
end: \033[4~
page up: \033[5~
page down: \033[6~

If you mess up something during input, use your mouse to hit the button "Delete one character". To get \033 in the dialog box, just press the Escape key instead of typing backslash, zero, three, three.

After applying this, voila! vim and mc now type these keys correctly.

But, you've just messed up bash.

Second fix involves editing ~/.inputrc (or /etc/inputrc). Neither of these rc files existed on my machine. From Garret LeSage's blog post (and as suggested in a comment on Francois's blog), I simply copy pasted the following:

"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[3~": delete-char
"\e[2~": quoted-insert
"\e[5C": forward-word
"\e[5D": backward-word
"\e\e[C": forward-word
"\e\e[D": backward-word
set completion-ignore-case On

It's nice to see an OS X-related tech post that's still as useful in 2012 as it was in 2005. And it's even nicer to see that it was originally intended for other UNIX and UNIX-style systems.

By the way: this post's ID is 2 * 333. Make of it whatever you want. 🙂

Checking out webkit without test cases

So you want to check out webkit to do some hacking. If you already tried this, you know that the test cases folder is enormous.

Not enormous solely by its size (which may be somewhat tolerable), but by amount of files in there. That's absolutely preposterous. I think that the ratio when I last canceled the checkout was something like 15mb of content versus 75mb of disk space usage. I think I used FAT back then. That means 60mb went just to store information about files. (These sizes of course do not ignore the duplicates in the .svn folders.)

It's completely irresponsible that someone put those in the project root, where nearly all the subfolders are essential except those test cases.

So if we just want to try out stuff and play around without running test cases ourselves, we don't want to check out this enormous folder and get stuck on this for half an hour, an hour, two or even more. Here comes svn's –depth parameter. UPDATE: Note! You will want to double-check that when you copy paste the command line from this site, there is actually two dashes before "depth". I've noticed that during copy-paste, they were replaced by a single line.

$ svn co http://svn.webkit.org/repository/webkit/trunk webkit --depth immediates
$ cd webkit
$ for i in `ls -d */ | sed 's/\///g' | grep -v Tests`; do cd "$i" ; svn update --set-depth infinity; cd .. ; done

  1. So, we checkout only immediate children-files for webkit and put them in webkit subdirectory. 
  2. Then we list only directories, (ls -d */) and remove all the appended slashes (sed 's/\///g'). We have one directory per line now. Finally we get only lines that do NOT include word Tests (grep -v Tests).
  3. Finally, we enter each directory, and tell svn to update, but now with infinite depth.
That's it! You should now have a Webkit working copy.
Tested on Mac OS X 10.6 Snow Leopard, with Webkit revision 52487. YMMV, but I think this should work on any Unix including GNU/Linux. You can probably pull this off on Windows using Cygwin or even msys.

Updated on Aug 22 2012, primarily to update formatting.