mirror of
https://github.com/mirror/make.git
synced 2025-01-27 04:40:33 +08:00
Create a new function $(file ...)
This commit is contained in:
parent
d6e1c6e6c5
commit
fca11f6039
@ -1,8 +1,13 @@
|
||||
2012-01-29 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* function.c (func_file): Create a new function, $(file ...)
|
||||
* doc/make.texi (File Function): Document the $(file ..) function.
|
||||
* NEWS: Announce it.
|
||||
|
||||
* gmk-default.scm (to-string-maybe): Use a more portable way to
|
||||
test for unprintable characters.
|
||||
* configure.in [GUILE]: Guile 1.6 doesn't have pkg-config
|
||||
* build_w32.bat: Ditto.
|
||||
|
||||
2012-01-28 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
|
14
NEWS
14
NEWS
@ -22,6 +22,12 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
|
||||
multiple consecutive backslash/newlines do not condense into one space.
|
||||
* In recipes, a recipe prefix following a backslash-newlines is removed.
|
||||
|
||||
* New command line option: --trace enables tracing of targets. When enabled
|
||||
the recipe to be invoked is printed even if it would otherwise be suppressed
|
||||
by .SILENT or a "@" prefix character. Also before each recipe is run the
|
||||
makefile name and linenumber where it was defined are shown as well as the
|
||||
prerequisites that caused the target to be considered out of date.
|
||||
|
||||
* New feature: The "job server" capability is now supported on Windows.
|
||||
Implementation contributed by Troy Runkel <Troy.Runkel@mathworks.com>
|
||||
|
||||
@ -32,16 +38,12 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
|
||||
interpreted as shell assignment. Change your assignment to add whitespace
|
||||
between the "!" and "=": "variable! = value"
|
||||
|
||||
* New Feature: GNU Guile integration
|
||||
* New feature: GNU Guile integration
|
||||
This version of GNU make can be compiled with GNU Guile integration.
|
||||
GNU Guile serves as an embedded extension language for make.
|
||||
See the "Guile Function" section in the GNU Make manual for details.
|
||||
|
||||
* New command line option: --trace enables tracing of targets. When enabled
|
||||
the recipe to be invoked is printed even if it would otherwise be suppressed
|
||||
by .SILENT or a "@" prefix character. Also before each recipe is run the
|
||||
makefile name and linenumber where it was defined are shown as well as the
|
||||
prerequisites that caused the target to be considered out of date.
|
||||
* New function: $(file ...) writes to a file.
|
||||
|
||||
* On failure, the makefile name and linenumber of the recipe that failed are
|
||||
shown.
|
||||
|
@ -47,12 +47,6 @@ if not ERRORLEVEL 1 set /P GUILECFLAGS= < guile.tmp
|
||||
pkg-config --libs --static --short-errors %PKGMSC% "guile-1.8" > guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILELIBS= < guile.tmp
|
||||
if not "%GUILECFLAGS%" == "" GoTo GuileDone
|
||||
echo "Checking for Guile 1.6"
|
||||
pkg-config --cflags --short-errors "guile-1.6" > guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILECFLAGS= < guile.tmp
|
||||
pkg-config --libs --static --short-errors %PKGMSC% "guile-2.0" > guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILELIBS= < guile.tmp
|
||||
if not "%GUILECFLAGS%" == "" GoTo GuileDone
|
||||
echo "No Guile found, building without Guile"
|
||||
GoTo NoGuile
|
||||
:NoPkgCfg
|
||||
|
@ -180,8 +180,7 @@ AC_ARG_WITH([guile], [AS_HELP_STRING([--with-guile],
|
||||
AS_IF([test "x$with_guile" != xno],
|
||||
[ PKG_CHECK_MODULES([GUILE], [guile-2.0], [have_guile=yes],
|
||||
[PKG_CHECK_MODULES([GUILE], [guile-1.8], [have_guile=yes],
|
||||
[PKG_CHECK_MODULES([GUILE], [guile-1.6], [have_guile=yes],
|
||||
[have_guile=no])])])
|
||||
[have_guile=no])])
|
||||
])
|
||||
|
||||
AS_IF([test "$have_guile" = yes],
|
||||
|
@ -265,6 +265,7 @@ Functions for Transforming Text
|
||||
* File Name Functions:: Functions for manipulating file names.
|
||||
* Conditional Functions:: Functions that implement conditions.
|
||||
* Foreach Function:: Repeat some text with controlled variation.
|
||||
* File Function:: Write text to a file.
|
||||
* Call Function:: Expand a user-defined function.
|
||||
* Value Function:: Return the un-expanded value of a variable.
|
||||
* Eval Function:: Evaluate the arguments as makefile syntax.
|
||||
@ -6563,6 +6564,7 @@ be substituted.
|
||||
* File Name Functions:: Functions for manipulating file names.
|
||||
* Conditional Functions:: Functions that implement conditions.
|
||||
* Foreach Function:: Repeat some text with controlled variation.
|
||||
* File Function:: Write text to a file.
|
||||
* Call Function:: Expand a user-defined function.
|
||||
* Value Function:: Return the un-expanded value of a variable.
|
||||
* Eval Function:: Evaluate the arguments as makefile syntax.
|
||||
@ -7214,7 +7216,7 @@ the result of the expansion is the expansion of the last argument.
|
||||
|
||||
@end table
|
||||
|
||||
@node Foreach Function, Call Function, Conditional Functions, Functions
|
||||
@node Foreach Function, File Function, Conditional Functions, Functions
|
||||
@section The @code{foreach} Function
|
||||
@findex foreach
|
||||
@cindex words, iterating over
|
||||
@ -7302,7 +7304,69 @@ might be useful if the value of @code{find_files} references the variable
|
||||
whose name is @samp{Esta-escrito-en-espanol!} (es un nombre bastante largo,
|
||||
no?), but it is more likely to be a mistake.
|
||||
|
||||
@node Call Function, Value Function, Foreach Function, Functions
|
||||
@node File Function, Call Function, Foreach Function, Functions
|
||||
@section The @code{file} Function
|
||||
@findex file
|
||||
@cindex writing to a file
|
||||
@cindex file, writing to
|
||||
|
||||
The @code{file} function allows the makefile to write to a file. Two
|
||||
modes of writing are supported: overwrite, where the text is written
|
||||
to the beginning of the file and any existing content is lost, and
|
||||
append, where the text is written to the end of the file, preserving
|
||||
the existing content. In all cases the file is created if it does not
|
||||
exist.
|
||||
|
||||
The syntax of the @code{file} function is:
|
||||
|
||||
@example
|
||||
$(file @var{op} @var{filename},@var{text})
|
||||
@end example
|
||||
|
||||
The operator @var{op} can be either @code{>} which indicates overwrite
|
||||
mode, or @code{>>} which indicates append mode. The @var{filename}
|
||||
indicates the file to be written to. There may optionally be
|
||||
whitespace between the operator and the file name.
|
||||
|
||||
When the @code{file} function is expanded all its arguments are
|
||||
expanded first, then the file indicated by @var{filename} will be
|
||||
opened in the mode described by @var{op}. Finally @var{text} will be
|
||||
written to the file. If @var{text} does not already end in a newline,
|
||||
a final newline will be written. The result of evaluating the
|
||||
@code{file} function is always the empty string.
|
||||
|
||||
It is a fatal error if the file cannot be opened for writing, or if
|
||||
the write operation fails.
|
||||
|
||||
For example, the @code{file} function can be useful if your build
|
||||
system has a limited command line size and your recipe runs a command
|
||||
that can accept arguments from a file as well. Many commands use the
|
||||
convention that an argument prefixed with an @code{@@} specifies a
|
||||
file containing more arguments. Then you might write your recipe in
|
||||
this way:
|
||||
|
||||
@example
|
||||
@group
|
||||
program: $(OBJECTS)
|
||||
$(file >$@@.in,$^)
|
||||
$(CMD) $(CMDFLAGS) @@$@@.in
|
||||
@@rm $@@.in
|
||||
@end group
|
||||
@end example
|
||||
|
||||
If the command required each argument to be on a separate line of the
|
||||
input file, you might write your recipe like this:
|
||||
|
||||
@example
|
||||
@group
|
||||
program: $(OBJECTS)
|
||||
$(file >$@@.in,) $(foreach O,$^,$(file >>$@@.in,$O))
|
||||
$(CMD) $(CMDFLAGS) @@$@@.in
|
||||
@@rm $@@.in
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@node Call Function, Value Function, File Function, Functions
|
||||
@section The @code{call} Function
|
||||
@findex call
|
||||
@cindex functions, user defined
|
||||
|
40
function.c
40
function.c
@ -2104,6 +2104,45 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED)
|
||||
return o;
|
||||
}
|
||||
|
||||
static char *
|
||||
func_file (char *o, char **argv, const char *funcname UNUSED)
|
||||
{
|
||||
char *fn = argv[0];
|
||||
|
||||
if (fn[0] == '>')
|
||||
{
|
||||
FILE *fp;
|
||||
const char *mode = "w";
|
||||
|
||||
/* We are writing a file. */
|
||||
++fn;
|
||||
if (fn[0] == '>')
|
||||
{
|
||||
mode = "a";
|
||||
++fn;
|
||||
}
|
||||
fn = next_token (fn);
|
||||
|
||||
fp = fopen (fn, mode);
|
||||
if (fp == NULL)
|
||||
fatal (reading_file, _("open: %s: %s"), fn, strerror (errno));
|
||||
else
|
||||
{
|
||||
int l = strlen (argv[1]);
|
||||
int nl = (l == 0 || argv[1][l-1] != '\n');
|
||||
|
||||
if (fputs (argv[1], fp) == EOF || (nl && fputc('\n', fp) == EOF))
|
||||
fatal (reading_file, _("write: %s: %s"), fn, strerror (errno));
|
||||
|
||||
fclose (fp);
|
||||
}
|
||||
}
|
||||
else
|
||||
fatal (reading_file, _("Invalid file operation: %s"), fn);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
static char *
|
||||
func_abspath (char *o, char **argv, const char *funcname UNUSED)
|
||||
{
|
||||
@ -2191,6 +2230,7 @@ static struct function_table_entry function_table_init[] =
|
||||
{ STRING_SIZE_TUPLE("and"), 1, 0, 0, func_and},
|
||||
{ STRING_SIZE_TUPLE("value"), 0, 1, 1, func_value},
|
||||
{ STRING_SIZE_TUPLE("eval"), 0, 1, 1, func_eval},
|
||||
{ STRING_SIZE_TUPLE("file"), 1, 2, 1, func_file},
|
||||
#ifdef EXPERIMENTAL
|
||||
{ STRING_SIZE_TUPLE("eq"), 2, 2, 1, func_eq},
|
||||
{ STRING_SIZE_TUPLE("not"), 0, 1, 1, func_not},
|
||||
|
@ -1,3 +1,7 @@
|
||||
2012-01-29 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/functions/file: Test the new $(file ...) function.
|
||||
|
||||
2012-01-12 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/functions/guile: New regression tests for Guile support.
|
||||
|
94
tests/scripts/functions/file
Normal file
94
tests/scripts/functions/file
Normal file
@ -0,0 +1,94 @@
|
||||
# -*-perl-*-
|
||||
|
||||
$description = 'Test the $(file ...) function.';
|
||||
|
||||
# Test > and >>
|
||||
run_make_test(q!
|
||||
define A
|
||||
a
|
||||
b
|
||||
endef
|
||||
B = c d
|
||||
$(file >file.out,$(A))
|
||||
$(foreach L,$(B),$(file >> file.out,$L))
|
||||
x:;@echo hi; cat file.out
|
||||
!,
|
||||
'', "hi\na\nb\nc\nd");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Test >> to a non-existent file
|
||||
run_make_test(q!
|
||||
define A
|
||||
a
|
||||
b
|
||||
endef
|
||||
$(file >> file.out,$(A))
|
||||
x:;@cat file.out
|
||||
!,
|
||||
'', "a\nb");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Test > to a read-only file
|
||||
touch('file.out');
|
||||
chmod(0444, 'file.out');
|
||||
|
||||
# Find the error that will be printed
|
||||
my $e;
|
||||
open(my $F, '>', 'file.out') and die "Opened read-only file!\n";
|
||||
$e = "$!";
|
||||
|
||||
run_make_test(q!
|
||||
define A
|
||||
a
|
||||
b
|
||||
endef
|
||||
$(file > file.out,$(A))
|
||||
x:;@cat file.out
|
||||
!,
|
||||
'', "#MAKEFILE#:6: *** open: file.out: $e. Stop.",
|
||||
512);
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Use variables for operator and filename
|
||||
run_make_test(q!
|
||||
define A
|
||||
a
|
||||
b
|
||||
endef
|
||||
OP = >
|
||||
FN = file.out
|
||||
$(file $(OP) $(FN),$(A))
|
||||
x:;@cat file.out
|
||||
!,
|
||||
'', "a\nb");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Don't add newlines if one already exists
|
||||
run_make_test(q!
|
||||
define A
|
||||
a
|
||||
b
|
||||
|
||||
endef
|
||||
$(file >file.out,$(A))
|
||||
x:;@cat file.out
|
||||
!,
|
||||
'', "a\nb");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Empty text
|
||||
run_make_test(q!
|
||||
$(file >file.out,)
|
||||
$(file >>file.out,)
|
||||
x:;@cat file.out
|
||||
!,
|
||||
'', "\n\n");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
1;
|
@ -89,6 +89,7 @@ sub toplevel
|
||||
|
||||
foreach (# UNIX-specific things
|
||||
'TZ', 'TMPDIR', 'HOME', 'USER', 'LOGNAME', 'PATH',
|
||||
'LD_LIBRARY_PATH',
|
||||
# Purify things
|
||||
'PURIFYOPTIONS',
|
||||
# Windows NT-specific stuff
|
||||
|
Loading…
Reference in New Issue
Block a user