How can I check in a makefile if I am running in a posix shell (msys/cygwin) or the windows cmd shell?
The following works for me:
ifeq ($(shell echo %OS%),%OS%)
$(info Running in a POSIX shell)
else
$(info Running in a Windows cmd shell)
endif
You could replace %OS% with any standard environment variable defined in a DOS environment.
Related
So I wanted to create a make run command so that I can test locally. It loads some env vars before running it.
I have a win.env file
set ENV1=val1
set ENV2=val2
and a lin.env file
export ENV1=val1
export ENV2=val2
in the Makefile I have:
run:
ifeq ($(OS),Windows_NT)
. ./win.env && go run .
else
. ./lin.env && go run .
endif
On linux it works, but on windows it says:
'.' is not recognized as an internal or external command,
operable probram or batch file.
make: *** [run] Error 1
How can I load the env vars before running my program?
The . command is a feature of the POSIX shell. You are not using a POSIX shell on Windows, you're using Windows cmd.exe.
First, you can't name the file win.env. Windows cares a lot about file extensions so you'll have to name this file win.bat or something like that.
Second, in Windows cmd.exe you just run the script; it doesn't start a new command program like POSIX systems do.
run:
ifeq ($(OS),Windows_NT)
win.bat; go run .
else
. ./lin.env && go run .
endif
I have some makefiles that I had written when macOS still used bash. Now, that macOS has switched to zsh, they no longer work. I'm wondering how to get the environment variables to work again. Here's a simple example:
Makefile:
all:
echo $(GOPATH)
Bash Output:
$ make
echo /Users/me/go
/Users/me/go
Zsh Output:
% make
echo
From a Windows Subsystem for Linux (v1) Alpine bash terminal, I would like to set an environment variable that get's passed into a windows executable. Is there any way to do this?
example of what I was hoping would print "Hello, World!":
windows-10:~# export X=World
windows-10:~# cmd.exe /c 'echo Hello, %X%!'
Hello, %X%!
See answer from Philipe below.
Here is a copy of the pertinent info from https://learn.microsoft.com/en-us/windows/wsl/interop
Share environment variables between Windows and WSL
Available in Windows Insider builds 17063 and later.
Prior to 17063, only Windows environment variable that WSL could access was PATH (so you could launch Win32 executables from under WSL).
Starting in 17063, WSL and Windows share WSLENV, a special environment variable created to bridge Windows and Linux distros running on WSL.
Properties of WSLENV:
It is shared; it exists in both Windows and WSL environments.
It is a list of environment variables to share between Windows and WSL.
It can format environment variables to work well in Windows and WSL.
There are four flags available in WSLENV to influence how that environment variable is translated.
WSLENV flags:
/p - translates the path between WSL/Linux style paths and Win32 paths.
/l - indicates the environment variable is a list of paths.
/u - indicates that this environment variable should only be included when running WSL from Win32.
/w - indicates that this environment variable should only be included when running Win32 from WSL.
Flags can be combined as needed.
Can you try this ?
~$ export X=World
~$ export WSLENV=X/w
~$ cmd.exe /c 'echo Hello, %X%!'
Hello, World!
I had learned Makefile before, but there is a problem in Makefile when I typed the command "make" today.
Here is the piece of code:
[ -d _build ] || mkdir _build
And the error:
'[' is not recognized as an internal or external command, operable program or batch file.
and there is my Make version:
GNU Make 3.82.90
Built for i686-pc-mingw32
Can anybody tell me how to fix it?
Your makefile was written for Linux/Unix and you are running it under Windows.
In a makefile, the commands that compose the recipes of the targets are
written in the language of the OS shell. Under Windows the shell is cmd.
Under Linux by default it is bash. Under other Unix variants it is sh or
some other shell.
[ -d _build ] || mkdir _build
is a valid command for bash and some other Linux/Unix shells. Not for
cmd. The same will be true of almost all the other recipe commands in the
makefile. You have just hit the first such problem.
Your makefile is of no use under native Windows. On Windows you have a chance
of running it in a Linux virtual machine, or under the Windows 10 Subsystem for Linux,
or under a Unix-like environment for Windows such as Cygwin or MSYS2. You may
well need to install tools that the makefile recipes require in that Linux/Unix-like
system.
If the makefile is simple you can consider translating the unrecognized shell
commands into cmd commands, if you are able.
The problem arises when makefile needs be run on different OS and various setting should be properly set up (escaping, path separator, etc) depending on OS.
The first approach was to use Windows COMSPEC:
ifneq ($(COMSPEC)$(ComSpec),)
## in windows
else
## in linux
endif
This is false positive for Cygwin, because it sees Windows' environment variables and detects Cygwin as Windows.
Then we tried Linux PWD:
ifeq ($(PWD),)
## in windows
else
## in linux, cygwin
endif
However, as a result of integration of off-site tool we have PWD set in windows (one of the perl's modules). So, the detection fails again.
I wonder, what is the best approach to differentiate between Cygwin, Linux, Windows using environment variables?
Cygwin and (tested on Ubuntu) Linux provide an $OSTYPE environment variable, set to cygwin for Cygwin and linux-gnu for (Ubuntu) Linux.
Windows does not have this variable, and so it appears to be the only one you'll need. I suppose it's possible that your Linux doesn't provide it, in which case you can use $OSTYPE to distinguish between Windows and Cygwin and then fall back to uname for Cygwin vs. Linux.
Distinguishing between Windows/not Windows using SHELL is not working for me as proposed by pkh. It's appeared that SHELL variable is defined in makefile running by gmake (mine is ver. 3.81) and it equals to "sh.exe". So, the current working solution for me is extend pkh's idea with distinguishing by .exe Windows executable file extension:
ifneq ($(findstring .exe,$(SHELL)),)
$(warning In Windows)
else
$(warning In Linux/Cygwin)
endif
Assuming you do have gcc available on all your machines (ie you are compiling something using your makefiles), you could use
gcc -dumpmachine
to find out the OS for which gcc builds.
You could use the output to set some variables like WINDOWS, LINUX or store it directly in order to use the information.
On Cygwin the OSTYPE environment variable needs to be exported for make to see it.