-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmkweb
executable file
·1042 lines (926 loc) · 30.6 KB
/
mkweb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/make -f
# Create a static website using source and template files
# Copyright (C) 2009-2012 Bruno BEAUFILS <[email protected]>
#
# Look for DOC or HELP in this file for more informations.
#
# This software comes with ABSOLUTELY NO WARRANTY.
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation in its version 2.
# See the README or COPYING file for details.
##############################################################################
VERSION := 3-dev
VERSION_TIMESTAMP := 20120607
# Here are "interesting" variables corresponding to some basic settings. They
# must be recursively expanded if they use less "interesting" variables
# defined further in their value.
# Settings may be stored in this file (may be fixed on command line)
ifeq ($(origin SETTINGS), undefined)
SETTINGS = .$(MAKEFILE)rc
endif
# Absolute path of source files (where this makefile is executed)
SOURCE := $(CURDIR)
# Processed files wil be copied in this directory
ifeq ($(origin DESTINATION), undefined)
DESTINATION = $(PREFIX)-site
endif
# HTML files created will be based on this template file (absolute path)
ifeq ($(origin TEMPLATE), undefined)
TEMPLATE := $(SOURCE)/template.html
endif
# Basename of makefile used to prepare source files
ifeq ($(origin PREPARE), undefined)
PREPARE := .prepare
endif
# Template content between these marks will be replaced by file content
ifeq ($(origin START_CONTENT), undefined)
START_CONTENT := <!-- @START_CONTENT@ -->
STOP_CONTENT := <!-- @END_CONTENT@ -->
endif
# DATE_FORMAT should respect strftime(3) format
ifeq ($(origin DATE_FORMAT), undefined)
DATE_FORMAT := '%Y/%m/%d %H:%M:%S'
endif
# Clean up generated HTML file if USE_TIDY is set to 1
ifeq ($(origin USE_TIDY), undefined)
USE_TIDY := 1
endif
# Tidy config file
ifeq ($(origin TIDY_CONFIG), undefined)
TIDY_CONFIG := $(SOURCE)/.tidyrc
endif
# Basename of files containing filename specification to ignore
ifeq ($(origin IGNORE), undefined)
IGNORE := .ignore
endif
# Basename of files containing filename specification to keep as is
ifeq ($(origin KEEP), undefined)
KEEP := .keep
endif
# Show exact executed commands only if VERBOSE is set to 1
ifeq ($(origin VERBOSE), undefined)
VERBOSE := 0
endif
# Do not print anything on execution if SILENT is set to 1
ifeq ($(origin SILENT), undefined)
SILENT := 0
endif
# Try to hard link files instead of copying it if HARD_LINK is set to 1
ifeq ($(origin HARD_LINK), undefined)
HARD_LINK := 0
endif
# Default action to execute (maybe modified if DEFAULT_JOB is set)
all: create
define QUICKDOC
##############################################################################
# 1. Create a template html file such as :
#
# +-- template.html -----------------------------+
# | <html> |
# | <head></head> |
# | <body> |
# | <h1>My website</h1> |
# | <!-- @START_CONTENT@ --> |
# | <p>Content will come here</p> |
# | <p>Use this file to set up your CSS.</p> |
# | <!-- @END_CONTENT@ --> |
# | </body> |
# | </html> |
# +----------------------------------------------+
#
# 2. Create source files containing content such as :
#
# +-- welcome.html -------------------------------------------+
# | <p>Welcome guys</p> |
# | <p> |
# | In this website you will not find anything interesting |
# | about <a href="about/me.html">me</a> |
# | </p> |
# +-----------------------------------------------------------+
#
# +-- about/me.html -----------------------------------------------------+
# | <p>You have been warned !</p> |
# | <p>Nothing here, go back <a href="@ROOT@/welcome.html">home</a></p> |
# +----------------------------------------------------------------------+
#
# 3. Call the command and specify the destination website directory path :
#
# mkweb DESTINATION=/path/to/your/website/destination
#
# 4. That's it your website is created at the right place, with all page
# having the same layout taken from your template file, content being
# inserted at the right place.
#
# For more details call `./mkweb doc`
#
##############################################################################
endef
export QUICKDOC
define DOC
##############################################################################
# In this documentation :
#
# * uppercased words refer to variables defined in mkweb command file ;
#
# * root of source files is where the command is executed.
#
# mkweb is a command build as a *simple* makefile which can be processed by
# GNU make (which should thus be installed in order to run it).
#
# The goal of this command is to use files with `.html` extension (source
# files) in order to create new files, with same basename and same relative
# path, under the directory DESTINATION. Existing hierarchy of files is
# preserved and reproduced.
#
# Source files are transformed after being selected. They also may be prepared
# before being transformed.
#
# Files transformation process
# ----------------------------
#
# Created file are based on a template in which every text between
# START_CONTENT and STOP_CONTENT is replaced by the content of the processed
# `.html` file.
#
# The used template is a file with same basename as TEMPLATE. This file is
# looked up from the directory containing the processed `.html` file up to the
# root of source files (which is the directory where the command is executed,
# also stored in SOURCE). This lookup process is done upward and use the first
# matching template file found, or TEMPLATE if none are found in the path.
#
# Creation of new `.html` files from sources one is done by a perl script
# build and stored in PERL_PROG.
#
# This processing replaces some strings found in the source file:
#
# * @DIR@ by the dirname of source file (from the root of source files)
#
# * @FILE@ by the basename of source file
#
# * @ROOT@ by a relative path to the root of source files
#
# * @DATE@ by the current date using format DATE_FORMAT
#
# * @MTIME@ by the last modification date of source file
#
# Other strings replacement may be done :
#
# * via HOOK_MACROS. In that case HOOK_MACROS must be an even numbered list of
# strings. First string is replaced by second, third by fourth, etc.
#
# * via string replacement definitions in source file. In that case
# definitions must be at the very beginning of the file. A definition is a
# single line with a string (the one to be replaced), a colon, one or more
# spaces, another string (the replacement). Definitions ends when an empty
# line is found. Definitions are removed from the source file before
# transformation process.
#
# Generated `.html` files are cleaned up by tidy unless USE_TIDY is set to
# 0. tidy uses TIDY_CONFIG config file, which is set by default to
# SOURCE/.tidyrc.
#
# Content may be filtered before processing, via HOOK_BEFORE, or after (but
# before tidy), via HOOK_AFTER.
#
# Files selection process
# -----------------------
#
# Files without `.html` suffix are copied without modification in their
# destination directory.
#
# Every source directory may contain an IGNORE file or a KEEP file.
#
# Some files are completely ignored by the whole process (nothing is done on
# them). It is the case for TIDY_CONFIG, TEMPLATE, SETTINGS and files:
#
# * which basename is IGNORE, KEEP, PREPARE or same basename as TEMPLATE,
#
# * which name use a space, a single quote, a double quote or a backslash,
#
# * which name is an emacs backup name (ends with a tilda character),
#
# * which basename is mentioned in the IGNORE file located in their directory,
#
# * which basename match a pattern mentioned in an IGNORE file located in one
# of the directories above their own directory,
#
# * which relative path (or directory path) from another directory is
# mentioned in the IGNORE file located in this (root) directory,
#
# * which relative path (or directory path) from another directory match a
# pattern mentioned in an IGNORE file located in one of the directories
# above this (root) directory.
#
# Some files with `.html` suffix may be copied as is (without being touched by
# the whole modification process). It is the case for files:
#
# * which basename is mentioned in the KEEP file located in their directory,
#
# * which basename match a pattern mentioned in a KEEP file located in one of
# the directories above their own directory,
#
# * which relative path (or directory path) from another directory is
# mentioned in the KEEP file located in this (root) directory,
#
# * which relative path (or directory path) from another directory match a
# pattern mentioned in an KEEP file located in one of the directories above
# this (root) directory.
#
# Patterns for file to ignore or to keep may use 2 differents joker: `*` match
# any string of characters (including the empty one) and `?` match any single
# character.
#
# Files selection is done by a perl script build and stored in PERL_FIND.
#
# File preparation process
# ------------------------
#
# In order to prepare source files special makefiles may be used. Before
# transformation start and using a deep-first algorithm, **every** PREPARE
# files found in a directory under the root of source files are passed to the
# make command. This call to `make` is done after having moved to the
# directory holding the PREPARE file. This phase is not subject to file
# selection process.
#
# If `.html` file are created by this preparation phase they are considered as
# source files in the transformation phase.
#
# Customisation
# -------------
#
# Customisation of almost everything in the command may be done by modifying
# variables. This can be done :
#
# * through command line using `VARIABLE=value` form parameters
#
# * through the SETTINGS file which may simply respect makefile syntax. The
# simplest case is to fix variables through `VARIABLE = value` form line.
#
# Copy operations may be replace by hard link ones. This is the case if
# HARD_LINK is set to 1 and if it the underlying operating system allows it
# (destination is on the same filesystem as source). That may save some space
# for big websites. In case hard link is used, one should however remember
# that every `.html` destination files depends on TEMPLATE. For `.html` files
# which need to be kept as is, that means, for instance, that if TEMPLATE is
# more recent than any such `.html` kept file, each time the command is called
# every such file will be processed : destination *is* source when hard
# linked.
#
##############################################################################
endef
export DOC
define HELP
##############################################################################
# usage: $(MAKEFILE) [VAR=VALUE ...] [ACTION]
#
# where ACTION includes
#
# help show this help message
# quick display a very short howto about $(MAKEFILE)
# doc display documentation
# version display version number
#
# prepare prepare source files
# create prepare source files and then create web site pages
#
# check check if needed commands and files are available
#
# list-vars list available variables with current values
# list-files list source files to be processed
# list-build list destination files to be created
# list-ignored list ignored files in source directory
# list-prepare list directory in which preparation takes place
#
# clean remove unnecessary files (backup files, etc.)
# real-clean remove generated files and unnecessary files
#
# If no ACTION specified the `create` one is issued unless DEFAULT_ACTION
# variable is set.
##############################################################################
endef
export HELP
# Name and basename of the current makefile
COMMAND := $(firstword $(MAKEFILE_LIST))
MAKEFILE := $(notdir $(firstword $(MAKEFILE_LIST)))
# Temporary directory
TMP := /tmp
# Useful prefix for temporary file
PREFIX := $(TMP)/$(MAKEFILE)
# Temporary perl modification program
ifeq ($(origin PERL_PROG), undefined)
PERL_PROG := $(PREFIX)-transform
endif
# Temporary perl find program
ifeq ($(origin PERL_FIND), undefined)
PERL_FIND := $(PREFIX)-find
endif
# Temporary perl date program
ifeq ($(origin PERL_DATE), undefined)
PERL_DATE := $(PREFIX)-date
endif
# Temporary flag to ensure needed commands have been checked
ifeq ($(origin CHECKED), undefined)
CHECKED := $(PREFIX)-checked
endif
# If user-settings file exists read it now!
ifeq ($(wildcard $(SETTINGS)),$(SETTINGS))
include $(SETTINGS)
endif
# Modify default target if DEFAULT_ACTION is set
ifneq ($(DEFAULT_ACTION),)
default: $(DEFAULT_ACTION)
.DEFAULT_GOAL := default
endif
# What shell to use
SHELL := /bin/bash
# By default do not show executed shell commands
ifeq ($(VERBOSE),0)
Q := @
else
Q :=
endif
# By default show executed actions
ifeq ($(SILENT),0)
ECHO := echo
OUT :=
else
ECHO := :
OUT := 1>/dev/null 2>&1
endif
# Tools must exist: we use this makefile twice at first use
ifeq ($(shell test -x $(PERL_FIND) || echo 1), 1)
FIRST_USE := 1
# If prepare is a target run it in a separate pass before others
else ifeq ($(findstring prepare,$(MAKECMDGOALS)),prepare)
PREPARE_PASS := 1
NEXT_MAKECMDGOALS := $(subst prepare,,$(MAKECMDGOALS))
endif
# Try to improve performance and deal symbolic links as file
MAKEFLAGS += -rR --no-print-directory -L
.PHONY: \
all default \
help doc quick \
create prepare \
check \
list-vars list-files list-ignored list-gen \
clean real-clean \
debug
##############################################################################
# Perl script to include source into template with some macro substitutions
ifdef FIRST_USE
define PERL_PROG_FILE
#!/usr/bin/perl
#-----------------------------------------------------------------------------
# Get template filename from command line
my $$template = shift(@ARGV);
# Get macros from command line
my %macros;
while ($$#ARGV != -1)
{
my $$k = shift(@ARGV);
my $$v = shift(@ARGV);
$$macros{$$k} = $$v;
}
# Substitute macros on given line
sub substitute
{
my ($$l) = @_;
foreach (keys(%macros))
{
$$l =~ s/$$_/$$macros{$$_}/g;
}
print($$l);
}
# Macros may be defined at start of source
my $$first = 1;
my $$first_line;
while (<STDIN>)
{
my ($$k, $$v) = split(/:\s+/, $$_);
if ($$first)
{
$$first = 0;
# If no macros on first line : no macros at all
if(!defined($$v))
{
$$first_line = $$_;
last;
}
}
# Empty line ends macros definition
last if ($$k eq "\n");
chomp($$v);
$$macros{$$k} = $$v;
}
# Open file
open(T, $$template) || die "cannot open $$template";
my $$inside = 0;
# Run through template file content
while (<T>)
{
# Entering content part
if ($$_ =~ q{$(START_CONTENT)})
{
$$inside = 1;
# Output content part
if (defined($$first_line))
{
&substitute("$$first_line");
undef($$first_line);
}
while (<STDIN>)
{
&substitute("$$_");
}
}
# Exiting content part
elsif ($$inside && $$_ =~ q{$(STOP_CONTENT)})
{
$$inside = 0;
}
# Output template part
elsif ($$inside == 0)
{
&substitute("$$_");
}
}
close(T);
#-----------------------------------------------------------------------------
endef
export PERL_PROG_FILE
endif
# Perl script to find files (replace some find command usage specific to GNU)
ifdef FIRST_USE
define PERL_FIND_FILE
#!/usr/bin/perl
#-----------------------------------------------------------------------------
use Getopt::Long;
my @files = ();
my @regexp = ();
my $$invert = 0;
my $$dir = 0;
my $$delete = 0;
my @basename = ();
my $$sep = "\n";
# Get root of finding process and then others parameters from command line
my $$root = shift || die("no root directory specified");
GetOptions(
"e=s" => \@regexp, # regexp path need to match
"basename=s" => \@basename, # basename file need to match
"dir" => \$$dir, # print only dir part of matching path
"delete" => \$$delete, # delete files instead of just print them
"v" => \$$invert) # invert the meaning of matching
|| die();
# Get all path from root directory
find($$root);
# Filter path by regexp...
if (scalar(@regexp) > 0)
{
@files = grep($$invert != &match_re($$_), @files);
}
# ... by basename
if (defined($$basename[0]))
{
# $$sep = " ";
@files = grep(defined($$_), map(match_name($$_), @files));
}
# Sort (longest first) matching paths and remove duplicates
my $$prev = undef;
@files = grep($$_ ne $$prev && (($$prev) = $$_), sort(compare @files));
# Delete and print or just print matching files
if ($$delete)
{
# $$sep = "\n";
map({unlink($$_); print($$_.$$sep); } @files);
}
else
{
print(map({$$_ .= $$sep} @files));
}
# Fill @files with path to every ordinary or symbolic link files under $$root
sub find
{
my $$root = shift;
opendir(DIR, $$root) || die("can't opendir $$root");
my @entries = grep { !/^\.$$/ && !/^\.\.$$/ } readdir(DIR);
closedir(DIR);
foreach (@entries)
{
if (-d "$$root/$$_" && ! -l "$$root/$$_")
{
# push(@files, "$$root/$$_/");
find("$$root/$$_");
}
else
{
push(@files, "$$root/$$_");
}
}
}
# True if entry match ones of recorded regexps
sub match_re
{
my $$entry = shift;
foreach (@regexp)
{
if ($$entry =~ m{$$_}) { return 1; }
}
return 0;
}
# Output dirname of entry if entry's basename match recorded ones
sub match_name
{
my $$entry = shift;
my @parts = split(/\//, $$entry);
foreach (@basename)
{
if ($$_ eq "$$parts[$$#parts]")
{
if ($$dir)
{
pop(@parts);
if (@parts >= 1) { return join("/", @parts); }
return ".";
}
return $$entry;
}
}
return undef;
}
# Compare paths: longest first (with more slashes) then classic lexicographic
sub compare
{
my $$c = ($$b =~ tr{/}{}) - ($$a =~ tr{/}{});
return $$c ? $$c : $$a cmp $$b;
}
#-----------------------------------------------------------------------------
endef
export PERL_FIND_FILE
endif
# Perl script to get formatted timestamp for today (-) or for specified file
ifdef FIRST_USE
define PERL_DATE_FILE
#!/usr/bin/perl
#-----------------------------------------------------------------------------
use POSIX qw(strftime);
my $$file = shift(@ARGV);
my $$format = join(" ", @ARGV);
my $$epoch;
if ($$file eq "-") { $$epoch = time() }
elsif (-e $$file) { ($$a,$$a,$$a,$$a,$$a,$$a,$$a,$$a,$$epoch,$$a,$$a,$$a) = stat($$file); }
print(strftime($$format,localtime($$epoch)));
#-----------------------------------------------------------------------------
endef
export PERL_DATE_FILE
endif
##############################################################################
# How to recall the makefile if two passes are needed (first use for instance)
CMD_MAKE := $(MAKE) -f $(COMMAND) $(MAKEFLAGS)
# Useful variables for commands (need to be recursively expanded)
ifndef FIRST_USE
file = $(notdir $@)
dir = $(subst $(DESTINATION)/,,$(dir $@))
root = $(shell echo $(subst $(SOURCE),@,$(dir $<)) | sed -e 's![^@/]\+!..!g' -e 'y/@/./' -e 's!/$$!!' -e 's!^\./!!')
date = $(shell perl $(PERL_DATE) - $(DATE_FORMAT))
mtime = $(shell perl $(PERL_DATE) $< $(DATE_FORMAT))
exist = $(subst $(1)/,,$(wildcard $(1)/$(2)))
name2bre = $(subst .,\.,$(subst [,\[,$(subst ],\],$(subst ^,\^,$(subst $$,\$$,$(subst *,\*,$(subst \,\\,$(1))))))))
glob2bre = $(subst *,.*,$(subst ?,.,$(subst [,\[,$(subst ],\],$(subst ^,\^,$(subst $$,\$$,$(subst .,\.,$(subst \,\\,$(1)))))))))
endif
# Command used to find files
CMD_FIND := perl $(PERL_FIND)
# Ouput all source files (if opt=-v) or all ignored source files
ifndef FIRST_USE
CMD_FILES := \
$(CMD_FIND) $(SOURCE) \
-e '^$(SOURCE)/$(MAKEFILE)$$' \
-e '$(call name2bre,$(TIDY_CONFIG))' \
-e '$(call name2bre,$(TEMPLATE))' \
-e '$(call name2bre,$(SETTINGS))' \
-e '$(call name2bre,/$(IGNORE))$$' \
-e '$(call name2bre,/$(KEEP))$$' \
-e '$(call name2bre,/$(notdir $(TEMPLATE)))$$' \
-e '$(call name2bre,/$(PREPARE))$$' \
-e '[ "'\''\\]' \
-e '~$$' \
$(foreach dir, \
$(shell $(CMD_FIND) $(SOURCE) -basename $(IGNORE) -dir), \
$(addprefix -e '$(dir)/,$(addsuffix $$',$(call name2bre,$(shell sed -e 's!/$$!!g' $(dir)/$(IGNORE))))) \
$(addprefix -e '$(dir)/,$(addsuffix $$',$(call glob2bre,$(shell sed -e 's!/$$!!g' $(dir)/$(IGNORE))))) \
$(addprefix -e '$(dir)/,$(addsuffix /',$(call name2bre,$(shell sed -e 's!/$$!!g' $(dir)/$(IGNORE))))) \
$(addprefix -e '$(dir)/,$(addsuffix /',$(call glob2bre,$(shell sed -e 's!/$$!!g' $(dir)/$(IGNORE))))) \
) \
$$opt
endif
# Let pass only source files which should be kept as is
ifndef FIRST_USE
tmp_keep := \
$(foreach dir, \
$(shell $(CMD_FIND) $(SOURCE) -basename $(KEEP) -dir), \
$(addprefix -e ^$(dir)/,$(addsuffix $$,$(call name2bre,$(shell sed 's!/$$!!g' $(dir)/$(KEEP))))) \
$(addprefix -e ^$(dir)/,$(addsuffix $$,$(call glob2bre,$(shell sed 's!/$$!!g' $(dir)/$(KEEP))))) \
$(addprefix -e ^$(dir)/,$(addsuffix /,$(call name2bre,$(shell sed 's!/$$!!g' $(dir)/$(KEEP))))) \
$(addprefix -e ^$(dir)/,$(addsuffix /,$(call glob2bre,$(shell sed 's!/$$!!g' $(dir)/$(KEEP))))))
CMD_KEEP := $(if $(value tmp_keep),grep -q $(tmp_keep),false)
endif
# Output the right template file path to use
ifndef FIRST_USE
tmp_ini = $(1) :=
tmp_acc = $(if $($(1)),$(1):=$($(1))/$(2),$(1):=$(2))
CMD_TEMPLATE = \
$(lastword $(TEMPLATE) \
$(foreach template,\
$(notdir $(TEMPLATE)) \
$(foreach word, \
$(subst /, ,$(dir)), \
$(eval $(call tmp_acc,path,$(word))) \
$(path)/$(notdir $(TEMPLATE))) \
$(eval $(call tmp_ini,path)), \
$(call exist,$(SOURCE),$(template))))
endif
# Tidy HTML from standard input to standard output
ifeq ($(USE_TIDY),1)
CMD_TIDY := tidy -q $(if $(TIDY_CONFIG),-config $(TIDY_CONFIG))
endif
# Send dependency content to standard output (and filter it if asked)
ifndef FIRST_USE
CMD_BEFORE = \
< $< \
$(if $(value HOOK_BEFORE),$(HOOK_BEFORE) |)
endif
# Send template with content replaced by standard input to standard output
ifndef FIRST_USE
CMD_HTML = \
perl $(PERL_PROG) $(CMD_TEMPLATE) \
@DIR@ "$(dir)" \
@FILE@ "$(file)" \
@ROOT@ "$(root)" \
@DATE@ "$(date)" \
@MTIME@ "$(mtime)" \
$(if $(value HOOK_MACROS),$(HOOK_MACROS))
endif
# Filter standard input if asked, tidy and then save it to destination file
ifndef FIRST_USE
CMD_AFTER = \
$(if $(value HOOK_AFTER),| $(HOOK_AFTER)) \
$(if $(value CMD_TIDY),| $(CMD_TIDY) -f $(TMP)/$(subst /,_,$(dir)$(file).tidylog)) \
>$@ || true
endif
# Copy a file preserving symbolic link (or hard link it, if asked) in existing
# destination directory
ifeq ($(HARD_LINK),0)
CMD_COPY = \
test -L '$<' && flags=-PR ; \
mkdir -p $(dir $@) && \
cp $$flags -f '$<' '$@'
else
CMD_COPY = \
test -L '$<' && flags=-PR ; \
mkdir -p $(dir $@) && \
ln -f '$<' '$@' 2>/dev/null 1>&2 || cp $$flags -f '$<' '$@'
endif
# Output all dir containing makefile used to prepare source files
ifndef FIRST_USE
CMD_PREPARE := $(CMD_FIND) $(SOURCE) -basename $(PREPARE) -dir
endif
##############################################################################
# Check if a command is available (must be used through call)
DO_CHECK_CMD = \
$(ECHO) -n " CHECK " ; \
which $(1) $(OUT)
# Check if a GNU command is available (must be used through call)
DO_CHECK_GNUCMD = \
$(ECHO) -n " CHECK " ; \
$(1) --version 2>/dev/null | grep -q GNU && echo `which $(1)` $(OUT)
# Check if a file exist (must be used through call)
DO_CHECK_FILE = \
$(ECHO) " CHECK $(1)" ; \
$(if $(wildcard $(1)),true,false)
# Prepare a source directory
DO_PREPARE := \
$(ECHO) " PREPARE $$dir" ; \
$(MAKE) -C $$dir -f $(PREPARE) --no-print-directory
# Process source (HTML) file
ifndef FIRST_USE
DO_HTML = \
if echo $< | $(CMD_KEEP) ; then \
$(ECHO) "KEEP_COPY $(dir)$(file)" ; \
$(CMD_COPY) $(OUT); \
else \
$(ECHO) -e " DO_HTML (on $(CMD_TEMPLATE)) $(dir)$(file)" ; \
mkdir -p $(dir $@) && \
$(CMD_BEFORE) $(CMD_HTML) $(CMD_AFTER) ; \
fi
endif
# Copy file
DO_COPY = \
$(ECHO) " COPY $(dir)$(file)" ; \
$(CMD_COPY) $(OUT)
# List of auxiliary programs need for the creation process
ALL_PROGS := $(PERL_PROG) $(PERL_FIND) $(PERL_DATE)
PROGS = $(if $(value HOOK_PROGS),$(HOOK_PROGS),$(ALL_PROGS))
# List of all source files to process
ifndef FIRST_USE
ALL_FILES := $(subst $(SOURCE)/,$(DESTINATION)/,$(shell opt=-v ; $(CMD_FILES)))
FILES = $(if $(value HOOK_FILES),$(HOOK_FILES),$(ALL_FILES))
endif
# List of all dirs containing makefile used to prepare source files
ifndef FIRST_USE
PREPARE_DIRS := $(shell $(CMD_PREPARE))
endif
# Debug stuff
DEBUG_DEPS :=
##############################################################################
# Targets
# Show help message
help:
@echo "$$HELP" | sed -e 's/^# //' -e 's/^#*//'
# Show very short howto
quick:
@echo "$$QUICKDOC" | tr -d '#'
# Show complete documentation
doc:
@echo "$$DOC" | tr -d '#'
# Show version number
version:
@printf "$(VERSION)\t$(VERSION_TIMESTAMP)\n"
# Prepare source files
ifdef FIRST_USE
prepare: check
$(Q)$(CMD_MAKE) $@
else ifdef PREPARE_PASS
prepare:
$(Q)for dir in $(PREPARE_DIRS) ; do $(DO_PREPARE) ; done
ifneq ($(NEXT_MAKECMDGOALS),)
$(Q)$(CMD_MAKE) $(NEXT_MAKECMDGOALS)
endif
else
prepare:
endif
# Create web site
ifdef FIRST_USE
create: check
$(Q)$(CMD_MAKE) $@
else ifndef PREPARE_PASS
create: $(FILES)
endif
# Check if all needed tools are available
check: $(CHECKED) $(PROGS)
$(CHECKED):
$(Q)$(call DO_CHECK_CMD,which)
$(Q)$(call DO_CHECK_CMD,perl)
$(Q)$(call DO_CHECK_CMD,sed)
$(Q)$(call DO_CHECK_CMD,tr)
ifeq ($(USE_TIDY),1)
$(Q)$(call DO_CHECK_CMD,tidy)
$(Q)$(call DO_CHECK_FILE,$(TIDY_CONFIG))
endif
$(Q)$(call DO_CHECK_CMD,true)
$(Q)$(call DO_CHECK_CMD,false)
$(Q)$(call DO_CHECK_FILE,$(TEMPLATE))
$(Q)touch $(CHECKED)
# Generate perl modification program
$(PERL_PROG): $(COMMAND)
$(Q)echo "$$PERL_PROG_FILE" >$@
$(Q)chmod +x $@
# Generate perl find program
$(PERL_FIND): $(COMMAND)
$(Q)echo "$$PERL_FIND_FILE" >$@
$(Q)chmod +x $@
# Generate perl date program
$(PERL_DATE): $(COMMAND)
$(Q)echo "$$PERL_DATE_FILE" >$@
$(Q)chmod +x $@
# Show used variables
ifdef FIRST_USE
list-vars: check
$(Q)$(CMD_MAKE) $@
else
list-vars:
@echo " SETTINGS = $(SETTINGS)"
@echo " SOURCE = $(SOURCE)"
@echo " DESTINATION = $(DESTINATION)"
@echo " TEMPLATE = $(TEMPLATE)"
@echo " START_CONTENT = $(START_CONTENT)"
@echo " STOP_CONTENT = $(STOP_CONTENT)"
@echo " DATE_FORMAT = $(DATE_FORMAT)"
@echo " TIDY_CONFIG = $(TIDY_CONFIG)"
@echo " IGNORE = $(IGNORE)"
@echo " KEEP = $(KEEP)"
@echo " PREPARE = $(PREPARE)"
@echo " USE_TIDY = $(USE_TIDY)"
@echo " VERBOSE = $(VERBOSE)"
@echo " SILENT = $(SILENT)"
@echo " VERSION = $(VERSION)"
@echo " VERSION_TIMESTAMP = $(VERSION_TIMESTAMP)"
endif
# Show all source files
ifdef FIRST_USE
list-files: $(PROGS)
$(Q)$(CMD_MAKE) $@
else
list-files:
$(Q)opt=-v ; $(CMD_FILES)
endif
# Show all ignored files
ifdef FIRST_USE
list-ignored: $(PROGS)
$(Q)$(CMD_MAKE) $@
else
list-ignored:
$(Q)$(CMD_FILES)
endif
# Show all generated files
ifdef FIRST_USE
list-build: $(PROGS)
$(Q)$(CMD_MAKE) $@
else
list-build:
$(Q)echo "$(FILES)"
endif
# Show all dirs in which source are prepared
ifdef FIRST_USE
list-prepare: $(PROGS)
$(Q)$(CMD_MAKE) $@
else
list-prepare:
$(Q)$(CMD_PREPARE)
endif
# Create a destination HTML file from a source one
# FIXME: mauvaises dependances si on a un nouveau TEMPLATE le fichier n'est pas recree
ifdef FIRST_USE
$(DESTINATION)/%.html: $(PROGS)
$(Q)$(CMD_MAKE) $@
else
$(DESTINATION)/%.html: $(SOURCE)/%.html $(CMD_TEMPLATE)
$(Q)$(DO_HTML)
endif
# Copy source non-HTML file as is in destination
$(DESTINATION)/%:: $(SOURCE)/%
$(Q)$(DO_COPY)
# Clean all unwanted files in the source directory
ifdef FIRST_USE
clean: $(PROGS)
$(Q)$(CMD_MAKE) $@
else
clean:
$(Q)$(CMD_FIND) $(SOURCE) -e '.*~$$' -delete
endif
# Remove all files which can be created
ifdef FIRST_USE
real-clean: $(PROGS)
$(Q)$(CMD_MAKE) $@
else
real-clean:
$(Q)rm -rf $(FILES) $(PROGS) $(CHECKED)
$(Q)for i in files ignored build prepare ; do rm -f $(PREFIX)-$$i ; done
endif
# Debug stuff
ifdef FIRST_USE
debug: $(PROGS)
$(Q)$(CMD_MAKE) $@
else
debug: list-vars
@echo ''