Setting NMake Makefile directory - windows

GNU Make has the option to change to a directory where the make file is before running make:
make -C <Makefile dir here>
Is it possible to do the same thing with NMake? I can't seem to find the flag for it.

I don't think there is a flag for that. But this is essentially just changing directory before executing make and getting back afterwards, so you should be just fine with:
pushd <dir> && nmake & popd
Note the first && causes nmake to run only when pushd succeeded, while & allows to execute popd regardless of nmake exit code.

Related

GNU make directory listing using $(shell dir ) command

I am trying to list all the subdirectories inside a certain folder. My operating system is Windows 10, I am using a GNU Make file and the version is : GNU Make 4.0 Built for x86_64-pc-cygwin, and this is the command I used :
ROOT_DIRECTORY := X:\
DIRS := $(shell dir $(ROOT_DIRECTORY) /s /b /ad)
$(info subdirs : $(DIRS))
when I execute the command dir /s /b /ad using the CMD it works just fine however when I try to execute it using the $(shell ) function the output is :
./tools/bin/sh: dir: command not found
subdirs :
make does not use cmd.exe to run shell commands, at least not by default. It uses a POSIX shell, which you can see is the component that issues your diagnostic message (.tools/bin/sh). The shell command for listing directory contents is ls, but it will not, by itself, give you what you want, because it has no equivalent to dir /ad.
That you are attempting to do this at all is suspicious. If make is an appropriate tool for your job at all then you should probably be approaching the problem in a different way. If you must use make, however, then one option would be to ensure that Cygwin's find program is installed, and use that:
DIRS := $(shell find * -type d)
(Be sure not to get Windows's find command, which does a different job. You may need to provide a path to the correct find.)
Another option might be to run cmd.exe explicitly.

Makefile error make (e=2): The system cannot find the file specified

I am using a makefile in windows to push some files on a Unix server (here a text file "blob.txt" in the same folder of my makefile).
My makefile script is:
setup:
pscp blob.txt username#hostname:/folder/
I start a command prompt, go in the folder where blob.txt and the makefile are present and type:
make setup
Which results in:
pscp blob.txt username#hostname:/folder/
process_begin: CreateProcess(NULL, pscp blob.txt username#hostname:/folder/, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [setup] Error 2
In a #fail ... whereas if I enter directly the command in the command prompt:
pscp blob.txt username#hostname:/folder/
It works ... I really wonder why.
The error
process_begin: CreateProcess(NULL, pscp blob.txt username#hostname:/folder/, ...) failed.
make (e=2): The system cannot find the file specified.
is almost certainly complaining that Windows cannot find pscp.
This is almost certainly because the value of %PATH% (or whatever) is different when make spawns a shell/console then when you have it open manually.
Compare the values to confirm that. Then either use the full path to pscp in the makefile recipe or ensure that the value of PATH is set correctly for make's usage.
I didn't want to remove GIT's bin folder from the PATH variable (I am using a Windows machine), as I use it quite often. So I looked for a workaround, and here it is:
Add the <git-installation-directory>/usr/bin directory to your PATH variable too. This basically adds the rest of the linux-like commands that come with the "GIT bash" to your environment. After applying this, my makefiles ran normally again. :)
If you are curious about what shell is being invoked by make, just add $(info $(SHELL)) at the beginning of your makefile. The path/name of the shell being invoked is printed to the console as soon as you run make.
I know this is an old question that has been answered, but thought I'd and my experiences for anyone still running into this. I was getting the same cryptic error Colonel Beauvel (though with the windows MOVE command, not pscp):
process_begin: CreateProcess(NULL, move /y foo\bar.c .\baz.c, ...) failed.
make (e=2): The system cannot find the file specified.
Our CI was running the same Makefile and working perfectly. Turns out CI was using mingw32-make and I was using GNU make. Uninstalling GNU make (which got installed as part of an unrelated bulk package) and aliasing mingw32-make to 'make' works perfectly.
#user3869623's solution works for me. I'd like to share some details of mine to complete the picture.
My makefile contains below target:
clean:
#echo '$(OS)'
ifeq ($(OS),Windows_NT)
del /s *.o *.d *.elf *.map *.log
endif
When I run make clean, I see this error:
Since it says something went wrong with echo, so I change my makefile target to below:
clean:
ifeq ($(OS),Windows_NT)
del /s *.o *.d *.elf *.map *.log
endif
This time, make clean gives me this error:
I am surprised to see bash here since I am working in Windows command line.
Then I checked my %PATH%, I see this entry:
C:\DevTools\Git\bin
There's a bash.exe and sh.exe in that path. So I removed this entry, and it works fine now.
BUT I STILL DON'T KNOW WHY BASH GET INTO THIS???
ADD 1
As to why the C:\DevTools\Git\bin shows up in my %PATH%, because I am using Sublime and it always asks me for the Git binaries:
In my case, I had git\bin in my %PATH% which contains bash.exe and sh.exe.
Removing %GIT_HOME%\bin from the PATH worked for me.
To build on user3869623's response.
In my case i had git\bin in my %PATH% which contains bash.exe and sh.exe.. Removing %GIT_HOME%\bin from the PATH worked for me
While this recommendation may allow make to run, it will likely cause issues for git, especially if the makefile is installing software from a git repository.
A better solution is to simply change %GIT_HOME%\bin to %GIT_HOME%\cmd
For those who tried removing the git bin folder from PATH and it didn't work for them, search your PATH variables for any paths containing bash.exe.
In my case I found a variable linking to cygwin bin folder C:\cygwin64\bin, removed it and it worked.
I had the same issue, and this thread really helped me solve it. In my case, it was a conflict between make and the sh.exe that was visible through my path, due to both git and mingw64. To fix my issue, without breaking Git, I added these lines to the top of my batch file that calls make:
set path=%path:git\bin=;%
set path=%path:mingw64\bin=;%
set path=%path:usr\bin=;%
This hides the extra sh.exe instances from make for that instance only.
I ran into this problem recently and this question was one of the top hits for my searches.
None of the other answers here helped me. The fix, for me, was to put the binary name in quotes:
setup:
"pscp" blob.txt username#hostname:/folder/
-"pscp" blob.txt username#hostname:/folder/ # Failure is OK, `-` in front
I'm on windows.
By explicitly setting my compiler to gcc (instead of cl?) it solved my problem.
CC = gcc
I hope some people more knowledgeable than me could explain why changing the compiler would impact the makefile parsing.

mingw32-make + mklink... just not getting along?

Not sure if anyone else has gotten this to work, but I'm having no end of trouble even with the following simple line in my Makefile running mingw32-make:
mklink Mk Makefile
The following created the link, but mingw32-make puked and threw error 255 thereafter:
$(shell cmd /c 'mklink Mk Makefile')
Nothing else is problematic, and I have a relatively complex makefile. Only mklink is doing this. (Apparently msys has it's own problems with ln so going down that path appears pointless.)
The following works for me, (on Win7 Home Premium, in VirtualBox),
provided I invoke it in a shell running with administrator privilege:
$ cat makefile.tst
all:
cmd /c "mklink mk makefile.tst"
#echo "Success!"
$ make -f makefile.tst
cmd /c "mklink mk makefile.tst"
symbolic link created for mk <<===>> makefile.tst
Success!
$ rm mk
$ mingw32-make -f makefile.tst
cmd /c "mklink mk makefile.tst"
symbolic link created for mk <<===>> makefile.tst
Success!
My shell, in this case is MSYS sh.exe, invoked via msys.bat from cmd.exe with UAC escalation to administrator privilege. This is so that I can show that the mklink command works both in MSYS' own make.exe, and in mingw32-make.exe; (of course, the mingw32-make.exe example also works directly from the elevated cmd.exe shell itself).
I suspect that attempting to use mklink directly within the makefile, without the cmd /c preamble, may not work because mklink is a cmd.exe built-in, which GNU make may not know to run this way ... it reports a CreateProcess failure, because the specified file cannot be found, when I try it.
Your use of make's $(shell ...) construct would not work, because that causes make to invoke the command in the wrong phase of operation ... when parsing the makefile itself, and constructing its dependency graph, rather than as a command to run when the containing rule is invoked, where it will now attempt to execute the output from the $(shell ...) command as a command in its own right; this is clearly not what you want!
Just to clarify the position with regard to MSYS' own ln command: it does work as well as can be expected, within the limitations of the versions of Windows on which it was originally implemented. In particular:
$ ln fileA fileB
creates a file-to-file hard link, on file systems such as NTFS, which support such links, and falls back to creating a copy on file systems such as FAT, which don't. Also:
$ ln dirA dirB
fails, as it should; hard linked directories are a recipe for disaster, and are not allowed, (just as they are forbidden on unix platforms). However:
$ ln -s fileA refB
will not create a symbolic link, (because no version of Windows supported them at the time when MSYS was developed, and no one has stepped forward to implement the capability, since they have become available ... although, their implementation still seems flaky, on Vista and Win7 anyway); rather, this command falls back to creating a hard link if possible, or a file copy otherwise. Similarly:
$ ln -s dirA refB
will not create a symbolic directory link, and in this case, there is no fall back; it simply and unconditionally fails! (It might be argued that a deep copy of the directory could be a suitable fall back action, but it isn't implemented so; instead, the lndir command is provided, to facilitate this).

"make clean" issue in MSYS/Cygwin

I finally managed to compile a program in Windows, which took a while and would have not been possible without some help from here. It all works now, except: "make clean" yields
/bin/sh: del: command not found
Makefile:44: recipe for target `clean' failed
make: *** [clean] Error 127
In the makefile, the clean command looks like
clean:
del /S *.o *~ *.out [...], eliminating all resulting .o and executables resulting from make.
mingw64 is in the path, and I tried with cygwin/bin in the path and without, both with the same result. "Make" was done with mingw32-make in msys. I also tried "mingw-32-make clean" in msys, still no luck; I am also not sure if "make clean" is supported in Cygwin at all. I run the whole thing on Windows 7, 64 bit.
How can I fix this problem?
It seems like you are mixing your platforms. del is a cmd.exe builtin, which is why it cannot be found by Bash. The analog to del is rm.
Try running make under cmd.exe
or
editing the Makefile, replacing del /S with rm -f
It is also possible to create a file called makefile.defs in you project folder and overwrite the makefile variable RM which is automatically set to "del" by eclipse. The file is included by "makefile" in the [Name of Config] folder
my File just contains:
RM := rm -rf
This works fine for me.

Calling Windows commands (e.g. del) from a GNU makefile

It does not appear to be possible to call Windows system commands (e.g. del, move, etc) using GNU Make. I'm trying to create a makefile that doesn't rely on the user having extra tools (e.g. rm.exe from Cygwin) installed.
When the following rule is run, an error is reported del: command not found:
clean:
del *.o
This is presumably because there is no such execuatable as "del". I've also tried running it as an option to cmd but with this only seems to open a new prompt:
clean:
cmd /C del *.o
I'm using Windows XP (5.1.2600) with GNU Make 3.79.1 that is bundled as part of MSys.
It seems the /C switch needs to be escaped because a / is interpreted as a path in GNU Make. The following works as expected:
clean:
cmd //C del *.o
Because DOS-based systems have two different commands for removing files and directories, I find that having two different defines works the best:
ifeq ($(OS),Windows_NT)
RM = cmd //C del //Q //F
RRM = cmd //C rmdir //Q //S
else
RM = rm -f
RRM = rm -f -r
endif
clean:
$(RM) $(TARGET).elf $(TARGET).map
$(RRM) $(BUILD_DIR)
Happened to me too. At the top of your makefile add:
SHELL=cmd
Since you are compiling on windows, select 'cmd' as the default shell. This
is important because GNU make will search the path for a linux/unix like shell and if it finds one it will use it instead. This is the case when cygwin is installed. The side effect of this behavior is that commands like 'del' and 'echo' are not found. If we tell GNU make to use 'cmd' as its shell, then 'del' and such will be available.
del is a builtin command of cmd.exe (as well as previously command.com). Your command cmd /C del *.o should work, if it starts a new command prompt I suspect that cmd maybe might be a wrapper. Have you tried to call cmd with its full path (e.g. c:/WINDOWS/system32/cmd.exe)?
Tom Longridge's answer was close to the truth for me, but the escaping needed to be done using a backslash before the forward slash on the Windows Vista Business machine I was needing this for:
RM=cmd \/C del
Another solution is to create a del.bat file containing:
#echo off
del %*
then the makefile can simply contain
clean:
del *.o
this cleans up the makefile, but may clutter your build directory slightly.
I just completed this. I am not sure if things have changed in DOS/Windows but this was how it had to be formatted with current versions.
OBJ=o
BIN=bin
clean:
cmd /C del $(OBJ)\\*.o
cmd /C del $(BIN)\\*.exe

Resources