Mail Archives: djgpp/1996/10/27/12:32:58
On Fri, 25 Oct 1996, Marc Singer wrote:
> I fetched an updated version of make3.75. It does not want to run my
> makefiles that work fine with v3.73. The problems appear to be
> related to the use of redirection. I have constructs such as these
>
> define loop_projects
> echo for i in $(SUBPROJ) >> sh.in
> echo do >> sh.in
> echo setenv ii $$i >> sh.in
> echo if [ -d $$ii ] >> sh.in
> echo then >> sh.in
> echo echo --- $$ii >> sh.in
> echo (cd $$ii; $(MAKE) -s $@@ ) >> sh.in
> echo fi >> sh.in
> echo done >> sh.in
> endef
>
> They don't work in the latest version. The sh scipt is not created.
I need to see the context in which these are used, because the above
fragment works for me (almost, see below) in a quick example that I've
hacked. For now, some comments which may or may not help you understand
what's wrong.
First, you don't need the above hackery anymore. If you have a Unixy
shell installed anywhere on your PATH, just put the commands into a rule,
say "SHELL=/bin/sh" on your Makefile, and Make will invoke `sh'. Note
that it will invoke `sh' even if it is NOT in /bin; just being anywhere
along the PATH is enough. (Is this great or what?) More details about the
shell-related features in the new port of Make may be found in the
README.dos file from the Make distribution (since it isn't included with
the binary distribution, I reproduce it below).
Second, if you want to use special characters in commands, you need to
quote them. One of the special characters is `;', since the new Make
knows about multiple commands on a single line. So in the example I
tried, everything worked except the line which says thus:
echo (cd $$ii; $(MAKE) -s $@@ ) >> sh.in
since Make now breaks it into "echo (cd $$ii" and "$(MAKE) -s ...". (As
a general rule, you should always quote strings passed to `echo', to
avoid such calamities.)
Third, the new port will certainly break some Makefiles which use kludges
such as above to work around limitations of the previous ports. (Just
for the record: it also broke some of my Makefiles.) However, I can't
feel too sympathetic to these cases, since the new port is so much
better (not only IMHO), and there is no simple way to have the both new
functionality and compatibility to previous kludges. If you hit one of
these spots, you will have to rework your Makefiles, but I think it's an
effort which will pay itself because you get much more compatible and
portable Makefiles.
------------------- README.dos for Make 3.75 ------------------------
Port of GNU Make to 32-bit protected mode on MSDOS and MS-Windows.
Builds with DJGPP v2.01 port of GNU C/C++ compiler and utilities.
New (since 3.74) DOS-specific features:
1. Supports long filenames when run from DOS box on Windows 95.
2. Supports both stock DOS COMMAND.COM and Unix-style shells
(details in ``Notes'' below).
3. Supports DOS drive letters in dependencies and pattern rules.
4. Better support for DOS-style backslashes in pathnames (but see
``Notes'' below).
5. The $(shell) built-in can run arbitrary complex commands,
including pipes and redirection, even when COMMAND.COM is your
shell.
6. Can be built without floating-point code (see below).
7. Supports signals in child programs and restores the original
directory if the child was interrupted.
8. Can be built without (a previous version of) Make.
To build:
1. Unzip the archive, preserving the directory structure (-d switch
if you use PKUNZIP). If you build Make on Windows 95, use an
unzip program that supports long filenames in zip files.
2. Invoke the `configure.bat' batch file:
configure
If it doesn't find a working Make, it will suggest to use the
`dosbuild.bat' batch file to build Make. Either do as it
suggests or install another Make program (a pre-compiled binary
should be available from the usual DJGPP sites).
3. If you have Make, the configure script will need a Unix-style
Sed program. If you don't have that installed, you can find it
on one of the DJGPP mirror sites.
4. If you will need to run Make on machines without an FPU, you
might consider building a version of Make which doesn't issue
floating-point instructions (the features which need FP
computations don't help much on MSDOS anyway). To this end,
invoke the configure batch file like so:
configure no-float
5. Invoke Make.
6. If you have a Unix-style shell installed, you can use the
`install' target. You will also need GNU Fileutils and GNU
Sh-utils for this (they should be available from the DJGPP
sites).
7. The `clean' targets require Unix-style `rm' program.
Notes:
-----
1. The shell issue.
This is probably the most significant improvement in this port.
The original behavior of GNU Make is to invoke commands
directly, as long as they don't include characters special to
the shell or internal shell commands, because that is faster.
When shell features like redirection or filename wildcards are
involved, Make calls the shell.
This port supports both DOS shells (the stock COMMAND.COM and
its 4DOS/NDOS replacements), and Unix-style shells (tested with
the venerable Stewartson's `ms_sh' 2.3 and the recent DJGPP port
of `bash' by Daisuke Aoyama <jack AT st DOT rim DOT or DOT jp>).
When the $SHELL variable points to a Unix-style shell, Make
works just like you'd expect on Unix, calling the shell for any
command that involves characters special to the shell or
internal shell commands. The only difference is that, since
there is no standard way to pass command lines longer than the
infamous DOS 126-character limit, this port of Make writes the
command line to a temporary disk file and then invokes the shell
on that file.
If $SHELL points to a DOS-style shell, however, Make will not
call it automatically, as it does with Unix shells. Stock
COMMAND.COM is too dumb and would unnecessarily limit the
functionality of Make. For example, you would not be able to
use long command lines in commands that use redirection or
pipes. Therefore, when presented with a DOS shell, this port of
Make will emulate most of the shell functionality, like
redirection and pipes, and shall only call the shell when a
batch file or a command internal to the shell is invoked. (Even
when a command is an internal shell command, Make will first
search the $PATH for it, so that if a Makefile calls `mkdir',
you can install, say, a port of GNU `mkdir' and have it called
in that case.)
The key to all this is the extended functionality of `spawn' and
`system' functions from the DJGPP library; this port just calls
`system' where it would invoke the shell on Unix. The most
important aspect of these functions is that they use a special
mechanism to pass long (up to 16KB) command lines to DJGPP
programs. In addition, `system' emulates some internal
commands, like `cd' (so that you can now use forward slashes
with it, and can also change the drive if the directory is on
another drive). Another aspect worth mentioning is that you can
call Unix shell scripts directly, provided that the shell whose
name is mentioned on the first line of the script is installed
anywhere along the $PATH. It is impossible to tell here
everything about these functions; refer to the DJGPP library
reference for more details.
The $(shell) built-in is implemented in this port by calling
`popen'. Since `popen' calls `system', the above considerations
are valid for $(shell) as well. In particular, you can put
arbitrary complex commands, including pipes and redirection,
inside $(shell), which is in many cases a valid substitute for
the Unix-style command substitution (`command`) feature.
2. "SHELL=/bin/sh" -- or is it?
Many Unix Makefiles include a line which sets the SHELL, for
those versions of Make which don't have this as the default.
Since many DOS systems don't have `sh' installed (in fact, most
of them don't even have a `/bin' directory), this port takes
such directives with a grain of salt. It will only honor such a
directive if the basename of the shell name (like `sh' in the
above example) can indeed be found in the directory that is
mentioned in the SHELL= line (`/bin' in the above example), or
in the current working directory, or anywhere on the $PATH (in
that order). If the basename doesn't include a filename
extension, Make will look for any known extension that indicates
an executable file (.exe, .com, .bat, .btm, .sh, and even .sed
and .pl). If any such file is found, then $SHELL will be
defined to the exact pathname of that file, and that shell will
hence be used for the rest of the processing. But if the named
shell is *not* found, the line which sets it will be effectively
ignored, leaving the value of $SHELL as it was before. Since a
lot of decisions that this port makes depend on the gender of
the shell, I feel it doesn't make any sense to tailor Make's
behavior to a shell which is nowhere to be found.
Note that the above special handling of "SHELL=" only happens
for Makefiles; if you set $SHELL in the environment or on the
Make command line, you are expected to give the complete
pathname of the shell, including the filename extension.
The default value of $SHELL is computed as on Unix (see the Make
manual for details), except that if $SHELL is not defined in the
environment, $COMSPEC is used. Also, if an environment variable
named $MAKESHELL is defined, it takes precedence over both
$COMSPEC and $SHELL. Note that, unlike Unix, $SHELL in the
environment *is* used to set the shell (since on MSDOS, it's
unlikely that the interactive shell will not be suitable for
Makefile processing).
The bottom line is that you can now write Makefiles where some
of the targets require a real (i.e. Unix-like) shell, which will
nevertheless work when such shell is not available (provided, of
course, that the commands which should always work, don't
require such a shell). More important, you can convert Unix
Makefiles to MSDOS and leave the line which sets the shell
intact, so that people who do have Unixy shell could use it for
targets which aren't converted to DOS (like `install' and
`uninstall', for example).
3. Default directories.
GNU Make knows about standard directories where it searches for
library and include files mentioned in the Makefile. Since
MSDOS machines don't have standard places for these, this port
will search ${DJDIR}/lib and ${DJDIR}/include respectively.
$DJDIR is defined automatically by the DJGPP startup code as the
root of the DJGPP installation tree (unless you've tampered with
the DJGPP.ENV file). This should provide reasonable default
values, unless you moved parts of DJGPP to other directories.
4. Letter-case in filenames.
If you run Make on Windows 95, you should be aware of the
letter-case issue. Make is internally case-sensitive, but all
file operations are case-insensitive on Windows 95, so
e.g. files `FAQ', `faq' and `Faq' all refer to the same file, as
far as Windows is concerned. The underlying DJGPP C library
functions honor the letter-case of the filenames they get from
the OS, except that by default, they down-case 8+3 DOS filenames
which are stored in upper case in the directory and would break
many Makefiles otherwise. (The details of which filenames are
converted to lower case are explained in the DJGPP libc docs,
under the `_preserve_fncase' and `_lfn_gen_short_fname'
functions, but as a thumb rule, any filename that is stored in
upper case in the directory, is a legal DOS 8+3 filename and
doesn't include characters illegal on MSDOS FAT filesystems,
will be automatically down-cased.) User reports that I have
indicate that this default behavior is generally what you'd
expect; however, since this is the first DJGPP port of Make that
supports long filenames, your input is most welcome.
In any case, if you hit a situation where you must force Make to
get the 8+3 DOS filenames in upper case, set FNCASE=y in the
environment or in the Makefile.
5. DOS-style pathnames.
There are a lot of places throughout the program sources which
make implicit assumptions about the pathname syntax. In
particular, the directories are assumed to be separated by `/',
and any pathname which doesn't begin with a `/' is assumed to be
relative to the current directory. This port attempts to
support DOS-style pathnames which might include the drive letter
and use backslashes instead of forward slashes. However, this
support is not complete; I feel that pursuing this support too
far might break some more important features, particularly if
you use a Unix-style shell (where a backslash is a quote
character). I only consider support of backslashes desirable
because some Makefiles invoke non-DJGPP programs which don't
understand forward slashes. A notable example of such programs
is the standard programs which come with MSDOS. Otherwise, you
are advised to stay away from backslashes whenever possible. In
particular, filename globbing won't work on pathnames with
backslashes, because the GNU `glob' library doesn't support them
(backslash is special in filename wildcards, and I didn't want
to break that).
One feature which *does* work with backslashes is the filename-
related built-in functions such as $(dir), $(notdir), etc.
Drive letters in pathnames are also fully supported.
Bug reports:
-----------
Bugs that are clearly related to the MSDOS/DJGPP port should be
reported first on the comp.os.msdos.djgpp news group (if you cannot
post to Usenet groups, write to the DJGPP mailing list,
<djgpp AT delorie DOT com>, which is an email gateway into the above news
group). For other bugs, please follow the the procedure explained
in the "Bugs" chapter of the Info docs. If you don't have an Info
reader, look up that chapter in the `make.i1' file with any text
browser/editor.
Enjoy,
Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
- Raw text -