Commit ea0fcd1b by O'Reilly Media, Inc.

Initial commit

parents
9780596006105
\ No newline at end of file
## Example files for the title:
# Managing Projects with GNU Make 3rd Edition, by Robert Mecklenburg
[![Managing Projects with GNU Make 3rd Edition, by Robert Mecklenburg](http://akamaicovers.oreilly.com/images/9780596006105/cat.gif)](https://www.safaribooksonline.com/library/view/title/0596006101//)
The following applies to example files from material published by O’Reilly Media, Inc. Content from other publishers may include different rules of usage. Please refer to any additional usage rights explained in the actual example files or refer to the publisher’s website.
O'Reilly books are here to help you get your job done. In general, you may use the code in O'Reilly books in your programs and documentation. You do not need to contact us for permission unless you're reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from our books does not require permission. Answering a question by citing our books and quoting example code does not require permission. On the other hand, selling or distributing a CD-ROM of examples from O'Reilly books does require permission. Incorporating a significant amount of example code from our books into your product's documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN.
If you think your use of code examples falls outside fair use or the permission given here, feel free to contact us at <permissions@oreilly.com>.
Please note that the examples are not production code and have not been carefully testing. They are provided "as-is" and come with no warranty of any kind.
File added
# combine - concatentate one sequence of numbers with another
combine = $(foreach i, $1, $(addprefix $i, $2))
# stripzero - Remove one leading zero from each word
stripzero = $(patsubst 0%,%,$1)
# generate - Produce all permutations of three elements from the word list
generate = $(call stripzero, \
$(call stripzero, \
$(call combine, $1, \
$(call combine, $1, $1))))
# number_line - Create a number line from 0 to 999
number_line := $(call generate,0 1 2 3 4 5 6 7 8 9)
length := $(word $(words $(number_line)), $(number_line))
# plus - Use the number line to add two integers
plus = $(word $2, \
$(wordlist $1, $(length), \
$(wordlist 3, $(length), $(number_line))))
# gt - Use the number line to determine if $1 is greater than $2
gt = $(filter $1, \
$(wordlist 3, $(length), \
$(wordlist $2, $(length), $(number_line))))
all:
@echo $(call plus,4,7)
@echo $(if $(call gt,4,7),is,is not)
@echo $(if $(call gt,7,4),is,is not)
@echo $(if $(call gt,7,7),is,is not)
# backwards - a reverse number line
backwards := $(call generate, 9 8 7 6 5 4 3 2 1 0)
# reverse - reverse a list of words
reverse = $(strip \
$(foreach f, \
$(wordlist 1, $(length), $(backwards)), \
$(word $f, $1)))
# minus - compute $1 minus $2
minus = $(word $2, \
$(call reverse, \
$(wordlist 1, $1, $(number_line))))
minus:
# $(call minus, 7, 4)
include defstruct.mk
$(call defstruct, foo, defslot(size, 0))
bar := $(call new, foo)
$(call set-value, bar, siz, 10)
include defstruct.mk
$(call new, no-such-structure)
# $(next-id) - return a unique number
next_id_counter :=
define next-id
$(words $(next_id_counter))$(eval next_id_counter += 1)
endef
# all_structs - a list of the defined structure names
all_structs :=
value_sep := XxSepxX
# $(call defstruct, struct_name, $(call defslot, slot_name, value), ...)
define defstruct
$(eval all_structs += $1) \
$(eval $1_def_slotnames :=) \
$(foreach v, $2 $3 $4 $5 $6 $7 $8 $9 $(10) $(11), \
$(if $($v_name), \
$(eval $1_def_slotnames += $($v_name)) \
$(eval $1_def_$($v_name)_default := $($v_value))))
endef
# $(call defslot,slot_name,slot_value)
define defslot
$(eval tmp_id := $(next_id))
$(eval $1_$(tmp_id)_name := $1)
$(eval $1_$(tmp_id)_value := $2)
$1_$(tmp_id)
endef
# all_instances - a list of all the instances of any structure
all_instances :=
# $(call new, struct_name)
define new
$(strip \
$(if $(filter $1,$(all_structs)),, \
$(error new on unknown struct '$(strip $1)')) \
$(eval instance := $1@$(next-id)) \
$(eval all_instances += $(instance)) \
$(foreach v, $($(strip $1)_def_slotnames), \
$(eval $(instance)_$v := $($(strip $1)_def_$v_default))) \
$(instance))
endef
# $(call delete, variable)
define delete
$(strip \
$(if $(filter $($(strip $1)),$(all_instances)),, \
$(error Invalid instance '$($(strip $1))')) \
$(eval all_instances := $(filter-out $($(strip $1)),$(all_instances))) \
$(foreach v, $($(strip $1)_def_slotnames), \
$(eval $(instance)_$v := )))
endef
# $(call struct-name, instance_id)
define struct-name
$(firstword $(subst @, ,$($(strip $1))))
endef
# $(call check-params, instance_id, slot_name)
define check-params
$(if $(filter $($(strip $1)),$(all_instances)),, \
$(error Invalid instance '$(strip $1)')) \
$(if $(filter $2,$($(call struct-name,$1)_def_slotnames)),, \
$(error Instance '$($(strip $1))' does not have slot '$(strip $2)'))
endef
# $(call get-value, instance_id, slot_name)
define get-value
$(strip \
$(call check-params,$1,$2) \
$($($(strip $1))_$(strip $2)))
endef
# $(call set-value, instance_id, slot_name, value)
define set-value
$(call check-params,$1,$2) \
$(eval $($(strip $1))_$(strip $2) := $3)
endef
# $(call dump-struct, struct_name)
define dump-struct
{ $(strip $1)_def_slotnames "$($(strip $1)_def_slotnames)" \
$(foreach s, \
$($(strip $1)_def_slotnames),$(strip \
$(strip $1)_def_$s_default "$($(strip $1)_def_$s_default)")) }
endef
# $(call print-struct, struct_name)
define print-struct
{ $(foreach s, \
$($(strip $1)_def_slotnames),$(strip \
{ "$s" "$($(strip $1)_def_$s_default)" })) }
endef
# $(call dump-instance, instance_id)
define dump-instance
{ $(eval tmp_name := $(call struct-name,$1)) \
$(foreach s, \
$($(tmp_name)_def_slotnames),$(strip \
{ $($(strip $1))_$s "$($($(strip $1))_$s)" })) }
endef
# $(call print-instance, instance_id)
define print-instance
{ $(foreach s, \
$($(call struct-name,$1)_def_slotnames),"$(strip \
$(call get-value,$1,$s))") }
endef
include defstruct.mk
$(call defstruct, file-info, \
$(call defslot, path,), \
$(call defslot, type,unix), \
$(call defslot, host,oscar))
before := $(call new, file-info)
$(call set-value, before, path,/etc/password)
$(call set-value, before, host,wasatch)
after := $(call new,file-info)
$(call set-value, after, path,/etc/shadow)
$(call set-value, after, host,wasatch)
demo:
# before = $(before)
# before.path = $(call get-value, before, path)
# before.type = $(call get-value, before, type)
# before.host = $(call get-value, before, host)
# print before = $(call print-instance, before)
# dump before = $(call dump-instance, before)
#
# all_instances = $(all_instances)
# all_structs = $(all_structs)
# print file-info = $(call print-struct, file-info)
# dump file-info = $(call dump-struct, file-info)
x:
@echo $A
A = B
echo there
count_words: count_words.o lexer.o -lfl
gcc count_words.o lexer.o -lfl -ocount_words
count_words.o: count_words.c
gcc -c count_words.c
lexer.o: lexer.c
gcc -c lexer.c
lexer.c: lexer.l
flex -t lexer.l > lexer.c
#include <stdio.h>
extern int fee_count, fie_count, foe_count, fum_count;
extern int yylex( void );
int main( int argc, char ** argv )
{
yylex();
printf( "%d %d %d %d\n", fee_count, fie_count, foe_count, fum_count );
exit( 0 );
}
int fee_count = 0;
int fie_count = 0;
int foe_count = 0;
int fum_count = 0;
%%
fee fee_count++;
fie fie_count++;
foe foe_count++;
fum fum_count++;
#! /bin/bash
echo '$ count_words < lexer.l'
count_words < lexer.l
count_words: count_words.o lexer.o -lfl
gcc count_words.o lexer.o -lfl -o count_words
count_words.o: count_words.c
gcc -c count_words.c
lexer.o: lexer.c
gcc -c lexer.c
lexer.c: lexer.l
flex -t lexer.l > lexer.c
#include <stdio.h>
extern int fee_count, fie_count, foe_count, fum_count;
extern int yylex( void );
int main( int argc, char ** argv )
{
while ( yylex() )
;
printf( "%d %d %d %d\n", fee_count, fie_count, foe_count, fum_count );
exit( 0 );
}
int fee_count = 0;
int fie_count = 0;
int foe_count = 0;
int fum_count = 0;
%%
fee fee_count++;
fie fie_count++;
foe foe_count++;
fum fum_count++;
.
\n
#! /bin/bash
make >& /dev/null
# Do this copy to avoid touching the other side of the symlink.
cp lexer.l x
rm lexer.l
mv x lexer.l
touch lexer.l
echo '$ make'
make
#! /bin/bash
echo '$ count_words < lexer.l'
count_words < lexer.l
hello: hello.c
gcc hello.c -o hello
#include <stdio.h>
main( int argc, char *argv[] )
{
printf( "Hello, world\n" );
}
count_words: count_words.o counter.o lexer.o -lfl
gcc $^ -o $@
count_words.o: count_words.c
gcc -c $<
counter.o: counter.c
gcc -c $<
lexer.o: lexer.c
gcc -c $<
lexer.c: lexer.l
flex -t $< > $@
I was attempting to use the -l link flag feature in a prerequisite and
discovered a surpising feature. make will not match a -lxx
prerequisite with a libxx.a target:
vpath %.a .
count_words: count_words.o -lcounter
libcounter.a: libcounter.a(lexer.o)
When run yields:
make
gcc -c -o count_words.o count_words.c
make: *** No rule to make target `-lcounter', needed by `count_words'. Stop.
$ make --version
GNU Make 3.80
Copyright (C) 2002 Free Software Foundation, Inc.
Is this expected behavior?
Thanks,
Robert
VPATH = src include
CPPFLAGS = -I include
count_words: counter.o lexer.o -lfl
count_words.o: counter.h
counter.o: counter.h lexer.h
lexer.o: lexer.h
#ifdef COUNTER_H_
#define COUNTER_H_
extern void
counter( int counts[4] );
#endif
#ifndef LEXER_H_
#define LEXER_H_
extern int fee_count, fie_count, foe_count, fum_count;
extern int yylex( void );
#endif
#! /bin/bash
echo '$ count_words < lexer.l'
count_words < lexer.l
#include <stdio.h>
#include <counter.h>
int main( int argc, char ** argv )
{
int counts[4];
counter( counts );
printf( "%d %d %d %d\n", counts[0], counts[1], counts[2], counts[3] );
exit( 0 );
}
#include <lexer.h>
#include <counter.h>
void counter( int counts[4] )
{
while ( yylex() )
;
counts[0] = fee_count;
counts[1] = fie_count;
counts[2] = foe_count;
counts[3] = fum_count;
}
%{
#include <lexer.h>
%}
int fee_count = 0;
int fie_count = 0;
int foe_count = 0;
int fum_count = 0;
%%
fee fee_count++;
fie fie_count++;
foe foe_count++;
fum fum_count++;
.
\n
VPATH = src include
CPPFLAGS = -I include
count_words: libcounter.a /lib/libfl.a
libcounter.a: libcounter.a(lexer.o) libcounter.a(counter.o)
libcounter.a(lexer.o): lexer.o
$(AR) $(ARFLAGS) $@ $<
libcounter.a(counter.o): counter.o
$(AR) $(ARFLAGS) $@ $<
count_words.o: counter.h
counter.o: counter.h lexer.h
lexer.o: lexer.h
#ifdef COUNTER_H_
#define COUNTER_H_
extern void
counter( int counts[4] );
#endif
#ifndef LEXER_H_
#define LEXER_H_
extern int fee_count, fie_count, foe_count, fum_count;
extern int yylex( void );
#endif
#! /bin/bash
echo '$ count_words < lexer.l'
count_words < lexer.l
#include <stdio.h>
#include <counter.h>
int main( int argc, char ** argv )
{
int counts[4];
counter( counts );
printf( "%d %d %d %d\n", counts[0], counts[1], counts[2], counts[3] );
exit( 0 );
}
#include <lexer.h>
#include <counter.h>
void counter( int counts[4] )
{
while ( yylex() )
;
counts[0] = fee_count;
counts[1] = fie_count;
counts[2] = foe_count;
counts[3] = fum_count;
}
%{
#include <lexer.h>
%}
int fee_count = 0;
int fie_count = 0;
int foe_count = 0;
int fum_count = 0;
%%
fee fee_count++;
fie fie_count++;
foe foe_count++;
fum fum_count++;
.
\n
VPATH = src include
CPPFLAGS = -I include
count_words: libcounter.a -lfl
libcounter.a: libcounter.a(lexer.o) libcounter.a(counter.o)
count_words.o: counter.h
counter.o: counter.h lexer.h
lexer.o: lexer.h
VPATH = src include
CPPFLAGS = -I include
count_words: count_words.o counter.o lexer.o -lfl
gcc $^ -o $@
count_words.o: count_words.c counter.h
gcc $(CPPFLAGS) -c $< -o $@
counter.o: counter.c counter.h lexer.h
gcc $(CPPFLAGS) -c $< -o $@
lexer.o: lexer.c lexer.h
gcc $(CPPFLAGS) -c $< -o $@
lexer.c: lexer.l
flex -t $< > $@
#ifdef COUNTER_H_
#define COUNTER_H_
extern void
counter( int counts[4] );
#endif
#ifndef LEXER_H_
#define LEXER_H_
extern int fee_count, fie_count, foe_count, fum_count;
extern int yylex( void );
#endif
#! /bin/bash
echo '$ src/count_words < src/lexer.l'
src/count_words < src/lexer.l
#include <stdio.h>
#include <counter.h>
int main( int argc, char ** argv )
{
int counts[4];
counter( counts );
printf( "%d %d %d %d\n", counts[0], counts[1], counts[2], counts[3] );
exit( 0 );
}
#include <lexer.h>
#include <counter.h>
void counter( int counts[4] )
{
while ( yylex() )
;
counts[0] = fee_count;
counts[1] = fie_count;
counts[2] = foe_count;
counts[3] = fum_count;
}
%{
#include <lexer.h>
%}
int fee_count = 0;
int fie_count = 0;
int foe_count = 0;
int fum_count = 0;
%%
fee fee_count++;
fie fie_count++;
foe foe_count++;
fum fum_count++;
.
\n
count_words: count_words.o counter.o lexer.o -lfl
gcc $^ -o $@
count_words.o: count_words.c include/counter.h
gcc -c $<
counter.o: