In a (Free)BSD make file the contents is handled in various ways. Technically speaking: all the text characters are scanned and subsequently parsed. What adds to the complexity is that
sometimes "stuff" gets output to the shell. The shell in turn interprets that "stuff" that
make(1) handed over and, after processing, the shell hands it back to
make(1). Sometimes
make(1) pre-processes it before handing it over to the shell.
Both syntax and semantics matter. Maybe you have been trying to get the value of the
/bin/sh shell variable uname (also in bash):
make(1) uses a (sub)shell of
/bin/sh to execute shell commands. (note: it does not rely on the shell from which the
make
command is issued.) However, there is the shell command
uname
that makes things more readily accessible:
The easiest and most straightforward solution, as mentioned in earlier messages, is the use of the command
uname
in your make file using the syntax "!=":
If you really want to use the
shell variable* uname into your make file then you can let the shell handle the expansion of the shell variable:
Code:
OSNAME3 != echo $$(uname)
You can even use your initial setup to make this happen:
Code:
OSNAME = $$(uname)
OSNAME4 != echo $(OSNAME)
Putting all the possible constructs together as an example, you get the following
Makefile:
Makefile:
OSNAME = $$(uname)
OSNAME2 != uname
OSNAME3 != echo $$(uname)
OSNAME4 != echo $(OSNAME)
#include $(OSNAME).Mk
#include $(OSNAME2).Mk
#include $(OSNAME3).Mk
#include $(OSNAME4).Mk
target:
echo "OSNAME - $(OSNAME)"
echo "OSNAME2 - $(OSNAME2)"
echo "OSNAME3 - $(OSNAME3)"
echo "OSNAME4 - $(OSNAME4)"
As written with the comments in place, make will not complain. However,
after removing the #-characters, make is not happy. The following sequence shows how that can be remied (commands are issued from a tcsh):
Code:
% make
make: "<path-to-make_file>/Makefile" line 5: Could not find $(uname).Mk
make: "<path-to-make_file>/Makefile" line 6: Could not find FreeBSD.Mk
make: "<path-to-make_file>/Makefile" line 7: Could not find FreeBSD.Mk
make: "<path-to-make_file>/Makefile" line 8: Could not find FreeBSD.Mk
make: Fatal errors encountered -- cannot continue
make: stopped in <path-to-make_file>
% touch \$\(uname\).Mk FreeBSD.Mk
% ls *.Mk
$(uname).Mk FreeBSD.Mk
% make
echo "OSNAME - $(uname)"
OSNAME - FreeBSD
echo "OSNAME2 - FreeBSD"
OSNAME2 - FreeBSD
echo "OSNAME3 - FreeBSD"
OSNAME3 - FreeBSD
echo "OSNAME4 - FreeBSD"
OSNAME4 - FreeBSD
You can see how the different options have been made to work. When using
include $(OSNAME).Mk
, you get
include $$(uname).Mk
; that is technically legal syntax but, it needs a rather special file and, most probably, that is not what is intended. This point is where semantics are important: at this particular location in a make file this is just NOT the '
sometimes "stuff" gets output to the shell'. Here
make(1) only interprets the
include $$(uname).Mk
as follows. Usually a construction in a make file as
$(uname)
or
${uname}
would be interpreted as a reference to a
make file variable. However, because the $-character is preceded by another $-character, the second $-character does not have a special meaning and is instead interpreted just as a literal $-character. The first extra $-character functions as an escape character. The total string is:
include $$(uname).Mk
**. The big difference here is that in this particular position in a make file there is nothing output to the shell: the shell doesn't get to "see it".
make(1) will now try to include the file
$(uname).Mk; note the single $-character.
The following may also be helpful:
I'm not familiar with the intricacies of GNU make however, for (Free)BSD
make(1) meta mode is pretty important. Additionally, if you're searching/experimenting for an all-encompassing build system, I too suggest that you look at other options. Besides the option mentioned by
ralphbsz you might have a look at
cmake. Note however that more often than not such alternatives, like cmake, are basically
build generator systems that generate (make) code "sort of under the hood" and are easily tailored for a specific target make system. Such a
build generator system as cmake is intended to abstract from the underlying make system for which it generates code and making your cmake files system independent. This means that by adding another layer of abstraction, you—mostly—won't have to deal with the intricacies of the various underlying make systems.
___
* by using the value of a shell variable you increase the dependance on particular properties of a certain shell. I'd consider using an external command a somewhat safer option.
** you should be able to find that in the output of
make -d A
but there is quite a lot of text in that debug output.