3

Background

I'm attempting to write a semi-portable Makefile that will be used on Windows without MinGW or Cygwin. As a result I pretty much have to stick to standard commands provided by Windows. I'm aware of UnxUtils, but I'd like to avoid using them as much as possible. Additionally, I'd like to avoid having to write any special batch scripts if I can help it. The solution will be used on many different computers by people that aren't particularly familiar with Linux, Windows, or command-line build systems, so environment paths can't be relied on and additional installations aren't possible. The solution will replace an existing system that's severely lacking in some of the more advanced make system features which are approaching necessity so I'm trying to minimize impact of changes by avoiding any new software installs.

Problem

The problem I'm encountering has to do with how make interprets shell commands used as part of a rule. I simply want to echo a blank-line in a way that can also be redirected to a file as part of a few different rules. In Windows, the only way to echo a blank line is to add a . immediately after the echo command, without any spaces: echo.. When provided as a line in a rule it causes issues though.

some_rule :
   @echo.
   @echo Text going to file > someFile.txt
   @echo. >> someFile.txt
   @echo Other text going to a file >> someFile.txt
   

In the example provided, the first line @echo. and the third line, @echo. >> someFile.txt, cause an error:

process_begin: CreateProcess(NULL, echo., ...) failed.

I've seen some explanations that say there shouldn't be a space on the third line and it should instead be @echo.>> someFile.txt, but that makes no difference when I tested it.

Explanation

I'm pretty sure the issue comes from the fact that make implements a manual look up of the implicit shell command and is detecting echo. as the command rather than echo. The resulting error is that it didn't find echo..exe or the equivalent as either a command or executable in the environment path, triggering the error indicated above.

Question

How do I implement a command as part of a makefile rule to output a blank line such that it would work in the case above? My actual makefile looks more like the following, and I'm hoping to replace either the ECHO variable so it operates more like the Linux version of echo, or the NEWLINE variable so it can actually output a blank line in a way that allows it to either be printed to the terminal or redirected to a file.

NEWLINE=echo.
ECHO=echo
SILENT=@

some_rule :
   $(SILENT)$(NEWLINE)
   $(SILENT)$(ECHO) Text going to file > someFile.txt
   $(SILENT)$(NEWLINE) >> someFile.txt
   $(SILENT)$(ECHO) Other text going to a file >> someFile.txt
Community
  • 1
  • 1
mtalexan
  • 677
  • 1
  • 7
  • 17
  • I worked on it for a bit and discovered that if I create an `echo..bat` file in my current directory, that only contains the line `echo.`, I don't get the error out of the makefile. That suggests my analysis of why the makefile was choking is correct. Unfortunately this solution actually causes an infinite loop where the `echo..bat` file calls itself recursively forever so it's not a workable solution. – mtalexan Dec 20 '13 at 22:20

3 Answers3

7

I write both portable Makefiles and portable scripts. You can achieve what you desire without making another script. You can just use something which is syntactically correct in either context.

echo;

This will echo a blank line in both Batch files on Windows in NMake and in Bash or sh on unix or Gnu make. Surely that is all you need?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
1

If you can arrange for a text file containing a single blank line to exist in the working directory, then more blank.txt will display the blank line in a reasonably OS-independent way.

Also, I just found this which might help. I think you could create your echo..bat batch file, but give it these contents:

@echo off
echo[

Single script to run in both Windows batch and Linux Bash?

Or forget the fragile echo..bat idea and make a universal shell script/batch file called blank.bat:

:; echo ""
:<<"::CMDLITERAL"
@echo.
::CMDLITERAL

I created this file in windows, then copied to Linux and OSX. With the right permissions, it will output a blank line in all three!

Community
  • 1
  • 1
Digital Trauma
  • 15,475
  • 3
  • 51
  • 83
  • I feel kind of obtuse for not thinking of the echo..bat script not using one of the alternate methods to do the same thing and preventing infinite recursive calls to itself, but that ended up being the best solution. I really like the Windows batch and Linux Bash info though. I'm not so concerned about generating custom OS specific scripts that get set as commands, I'll just work it into the makefile configuration architecture that a OS specific target gets called from the OS independent makefile to setup and clean up any system generated scripts. – mtalexan Dec 23 '13 at 15:12
  • It appears that `echo/` also works to write a single newline. – David R Tribble Mar 06 '14 at 22:28
  • @DavidRTribble `echo/` on linux will be `bash: echo/: No such file or directory`. – Bo R Apr 25 '19 at 16:47
0

I faced a very similar error as well. The problem I found was in the PATH env variable. I had an empty entry in my PATH variable.

PATH=<path1>;;<path2>

Just removing the second semi colon, removed the error. I think the root cause is in the "CreateProcess" and "SearchPath" APIs. I think it cannot process an empty entry when searching for the executable. Not 100% sure though.