skeeto / w64devkit

Portable C and C++ Development Kit for x64 (and x86) Windows
The Unlicense
2.7k stars 185 forks source link

Running w64devkit.exe from an existing cmd.exe prompt #18

Closed moodmosaic closed 2 years ago

moodmosaic commented 2 years ago

(This might be an odd question.)

Can I run w64devkit.exe from an existing cmd.exe prompt? Or it's meant to be run standalone by simply executing w64devkit.exe?

skeeto commented 2 years ago

You can do that, though it won't work quite as well. Before w64devkit.exe there was activate.bat. It put the w64devkit bin/ in PATH and launched a BusyBox shell, but because it was a batch script it left a cmd.exe process in control of the console. Unfortunately cmd.exe interferes with other processes attached to its console window, particularly sh, and eventually causes problems. This cmd.exe behavior cannot be changed or disabled. I talked a bit about it here:

Well-behaved alias commands on Windows https://nullprogram.com/blog/2021/02/08/

When you launch w64devkit.exe outside of a console, it gets a new console window (being a console subsystem program), but doesn't share it with a cmd.exe process. However, if you launch it from cmd.exe, then that cmd.exe will remain active in the console and interfere. It's still usable, just sometimes annoying.

You haven't said why you want to do this, but perhaps it's similar one of my reasons: The cmd.exe console has a special environment (vcvars.bat), and I'd like w64devkit to inherit this environment so that I could access the Visual Studio toolchain (cl.exe, link.exe, etc.) from w64devkit. To avoid cmd.exe, I use its "start" built-in to launch a new cmd.exe-free console while preserving the environment.

start "C:\path\to\w64devkit\w64devkit.exe"

By the way, "start" is also useful from BusyBox sh. Since it's a built-in, not a program, you must access it by way of a temporary cmd.exe. For example, here's how I open documentation from the command line:

$ cmd /c start win32.chm $ cmd /c start cppreference/en/index.html

Technically you don't need w64devkit.exe at all. It's just a convenient entry point. Currently it does four things:

  1. Prepend w64devkit's bin/ to PATH
  2. Set W64DEVKIT to the version number
  3. Set W64DEVKIT_HOME to the root w64devkit/ directory
  4. Run "sh -l" and wait for it to exit

You could stop at (1) and just use cmd.exe as your shell. Or you could accomplish (1) and (4) using whatever other mechanism you want (shortcut, etc.) if you don't care about the W64DEVKIT variables. (They're not used or needed by w64devkit itself, but are there for consumption in your own scripts.)

moodmosaic commented 2 years ago

Thank you for the detailed explanation!

My reason is same as yours, (vcvars.bat, which I'd like w64devkit to inherit).

@skeeto, I guess the opposite could work, then?

  1. Run w64devkit.exe
  2. Run vcvars.bat, then, from the same console

For visual reference, an example that might help other readers:

image

image

(Private bytes on the very right may be ignored.)

skeeto commented 2 years ago

When you invoke a batch script from cmd.exe, it's like sourcing a script from a unix shell: the script is run by your current cmd.exe instance, allowing it to set environment variables, change the working directory, etc. However, if you invoke a batch script from the BusyBox shell, it will start a cmd.exe just for that script, and so none of the changes to the environment would apply to the BusyBox shell. So unfortunately you can't flip it around. With vcvars.bat you have no option but to route through cmd.exe first since it's a cmd.exe script.

Using my suggestion from before about "start", you could launch w64devkit from a batch script like so:

call C:\path\to\vcvars64.bat start C:\path\to\w64devkit.exe

moodmosaic commented 2 years ago

Very useful, thank you, Christopher. :+1:

moodmosaic commented 2 years ago

One more question (so I don't create a whole new GH issue for it).

If I install Git, will that interfere with the files in the bin folder of w64devkit? I notice, for example, that cat exists in both w64devkit and Git installation.

skeeto commented 1 year ago

You should avoid having Git's "usr/bin" in PATH. Git knows how to find these programs when it needs them, and having them in PATH is mostly going to confuse other programs, especially since these are MSYS2 and not native Win32 binaries. However, since w64devkit.exe prepends its bin/ at the front of PATH, it shouldn't get confused about Git binaries already in PATH.

Here's what I've found works best:

Install the portable "thumbdrive edition" Git. The standard installer is too hands-on, asking dumb questions already resolved by my .gitconfig, and which also shouldn't be system-wide configuration anyway. (Debugging Git problems is harder when arbitrary local system configuration is an extra variable.) In contrast, the portable "installer" works exactly like w64devkit: unzips Git to your selection location and doesn't install anything outside of this directory. Exactly what I want from all Windows software.

Put only Git's cmd/ in PATH. I do this in my w64devkit .profile since I install Git to a predictable $HOME/git. To upgrade Git, I delete this directory and then unzip the new Git into the same place. This gives you git.exe and gitk.exe without extraneous utilities, and these behave well with w64devkit.

https://github.com/skeeto/dotfiles/blob/master/w64devkit.profile

(Extra notes about my .profile: I unzip the AdoptOpenJDK/Adoptium .zip to $HOME/jdk, I pluck Python out of the WinPython "dot" distribution as $HOME/python, and I bootstrap Go from source at $HOME/go. Documentation also gets unzipped into predictable locations. Like everything else so far, these are "portable" and self-contained. I've streamlined all this such that, without admin access, I can convert any Windows system into a productive, offline-friendly environment for eight programming languages inside of a few minutes.)

moodmosaic commented 1 year ago

@moodmosaic If I install Git

My fault, I used the wrong word here ("install"). By that I meant the portable "thumbdrive edition" Git (just like you wrote) 👍

@skeeto Put only Git's cmd/ in PATH

Yes, that's exactly what I am doing. 👍

@skeeto I've streamlined all this such that, without admin access, I can convert any Windows system

Yes! That's (more or less) exactly what I am doing. I have a directory (I call it "snapshot") and everything inside is (pretty much) portable (like git, text editors, code editors, python, etc).

I set the (portable) Git's HOME variable to point into that folder, too. So when I do cd ~ it'll always take me there. That folder is all I need. Apart from that, any Windows machine will work.

(Even with Docker, which I use at work, I don't use the Windows built-in virtualization for it, I just use the CLI and the actual Docker runs remotely, outside Windows.)