One of the advantages of working with Unix and Linux is that every tool can cooperate with the other utilities on the system. This behavior results in an astonishing power, limited only by user's inventive.
In this context, G-Cows' real power doesn't come from its features, but from the way it integrates in your Unix-like environment. In this section we'll see how to use G-Cows and the Make utility installed on every Unix and Linux system in order to build and maintain web sites.
Cows allows to create a standard HTML file from a source consisting of HTML code and Cows-scripts. When working on a web site you'll probably write a number of source files and run Cows on each of them.
Every time you modify a source file, you need to run Cows on it in order to update the relative page. You also need to run Cows on every file including the modified one. Also, whenever a Cows source file refers to external files (e.g. by the mean of fsize() and fdate()) you need to run Cows on the source every time one or more of such files are modified.
Directory examples-1.5/update/ contains the following files:
File hello1.cws:
<h1>Hello 1</h1> <cows> verbatim ("foo1.html"); verbatim ("foo.html"); </cows>
File hello2.cws:
<h1>Hello 2</h1> <cows> verbatim ("foo2.html"); verbatim ("foo.html"); </cows>
File foo1.html:
<p> This is file foo1.html </p>
File foo2.html:
<p> This is file foo2.html </p>
File foo.html:
<p> This is file foo.html </p>
The verbatim () statement simply insert a verbatim copy of an external file within Cows output. In order to create the HTML files type:
$ cows hello1.cws hello1.html $ cows hello2.cws hello2.html
Now, suppose you modify foo1.html: you need to run Cows on hello1.cws in order to update the relative html file:
$ cows hello1.cws hello1.html
You don't need to run Cows on hello2.cws since this source file doesn't rely on foo1.html in any way.
Things are different if you modify foo.html since both hello1.cws and hello2.cws include a verbatim copy of it. In order to update your site you need to run Cows on both files:
$ cows hello1.cws hello1.html $ cows hello2.cws hello2.html
It's easy to see that if your site consists in more than a couple of files, there are many chances of an error. An easy solution is to write a simple shell script running Cows on each source file. This is not a clean way to solve the problem since your script will do a lot of useless work.
Moreover, Cows allow to automatically insert the date of last modify in you pages; if you run Cows when source file doesn't change, you'll get wrong dates.
That's where Make comes in help.
Make is a powerful tool available on all Unix and Linux systems; on Linux type make -version to make sure it's correctly installed in your system; you should get a message like this:
$ make --version GNU Make version 3.79.1, by Richard Stallman and Roland McGrath. Built for i686-pc-linux-gnu Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Don't worry if the message is different or if you have another version of Make; if it's not installed on your computer please refer to the documentation coming with your distribution in order to install it.
To introduce you to Make I'll simply quote some part from the documentation with GNU/make.
The purpose of the make utility is to determine automatically which pieces of a large program need to be recompiled, and issue the commands to recompile them. [ ... ] Make is not limited to programs. You can use it to describe any task where some files must be updated automatically from others whenever the others change. To prepare to use make, you must write a file called the makefile that describes the relationships among files in your program and provides commands for updating each file. [ ... ] Once a suitable makefile exists, each time you change some source files, this simple shell command: make suffices to perform all necessary recompilations.
Now, you probably understand how Make can help us; directory examples-1.5/update_make/ contains the same files in examples-1.5/update/ plus the following Makefile (explanations are inserted as comments so read it carefully).
File Makefile:
# First, we tell Make that the default target is the creation of files # hello1.html and hello2.html. In other words, if we simply type # `make' these files will be created. all: hello1.html hello2.html # Now, we tell Make that hello1.html depends on hello1.cws, foo1.html # and foo.html; so Make knows WHEN it need to be updated. On a separate # line we tell Make the command needed to create hello1.html; so Make # knows HOW to update it # IMPORTANT: you __MUST__ place a TAB character before the command hello1.html: hello1.cws foo1.html foo.html cows hello1.cws hello1.html # The same as before, for hello2.html hello2.html: hello2.cws foo2.html foo.html cows hello2.cws hello2.html # Now, we tell Make that if user types `make clean', he must delete # files hello1.html hello2.html. clean: rm -f hello1.html hello2.html # Lately, we tell Make that `all' and `clean' are rule names, not # files; so, if a file named `all' or `clean' exists in the directory, # Make won't try to update it. .PHONY: all clean
Now, type ls; you'll see that files hello1.html and hello2.html don't exist yet. Then run Make.
$ ls Makefile foo.html foo1.html foo2.html hello1.cws hello2.cws $ make cows hello1.cws hello1.html cows hello2.cws hello2.html
As you can see, Make executed Cows twice in order to create hello1.html and hello2.html. Type ls to make sure the files are there:
$ ls Makefile foo1.html hello1.cws hello2.cws foo.html foo2.html hello1.html hello2.html
Now, type Make again; both files are up to date so nothing should happen:
$ make make: Nothing to be done for `all'.
OK, now modify foo1.html (you can simply use the touch command) an run Make once more time:
$ touch foo1.html $ make cows hello1.cws hello1.html
OK ! Make correctly updated hello1.html. Now, modify foo.html: Make should update both files.
$ touch foo.html $ make cows hello1.cws hello1.html cows hello2.cws hello2.html
Finally, use Make to delete the target files, make sure they are gone and use Make to create them again:
$ ls Makefile foo1.html hello1.cws hello2.cws foo.html foo2.html hello1.html hello2.html $ make clean rm -f hello1.html hello2.html $ ls Makefile foo.html foo1.html foo2.html hello1.cws hello2.cws $ make cows hello1.cws hello1.html cows hello2.cws hello2.html $ ls Makefile foo1.html hello1.cws hello2.cws foo.html foo2.html hello1.html hello2.html
The Make utility, available on every Unix and Linux system, allows to handle dependencies among our web pages, Cows source files and external files, giving us a powerful way to update our sites.
Now, we are left with the problem of creating makefiles; this can be a very long operation, even or a small site. Moreover, if you forget about a dependency or you write a wrong rule, you'll be in big troubles: your update procedure will be broken and some pages won't be correctly updated. Of course, this is not a Make limitation; we are simply dealing with a large number of files with multiple dependencies so we need a lot of rules in order to describe the update procedure.
That's where Cows-mkgen comes in help; Cows-mkgen is a small utility that examines a directory tree looking for Cows sources, parses them and automatically generates a suitable makefile.
The standard way of building a site with G-Cows consists in the following steps:
write source files;
run Cows-mkgen in order to create a makefile;
run Make in order to create the html files.
Now, when you modify one or more files, you simply need to run Make to update those (and only) HTML files that depends on the modified ones.
Important: of course, if changes result in different updating rules, the makefile must be regenerated; in other words, you need to run Cows-mkgen:
every time you add a new .cws file to your site;
every time you add or change a dependency in a .cws file by adding or changing a verbatim (), include (), fsize (), fdate (), exec (), evalexec () statement;
every time you add or change a special directive for Cows-mkgen (see Section 6.6).
This section describes makefiles created by Cows-mkgen. You don't need to read this if you're simply trying G-Cows to see if you might need it or not. However, if you decide to use it, it's better to understand how thing are done.
To see an example of a Makefile generated by Cows-mkgen, you can simple move to directory update/ from the examples archive and type cows-mkgen. This is the generated Makefile:
File Makefile:
# Generated automatically from Makefile.cm by cows-mkgen 1.5 # Copyright (C) 2002, 2003, 2004, 2005 Andrea Sozzi # This makefile is free software; you have unlimited # permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # This makefile is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY, to the extent permitted # by law; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. prefix = ./ __cows_OPTS = main_OPTS = TARGETS = $(prefix)hello1.html\ $(prefix)hello2.html\ all: $(TARGETS) $(prefix)hello1.html: hello1.cws \ foo.html \ foo1.html cows $(__cows_OPTS) $(main_OPTS) hello1.cws $(prefix)hello1.html $(prefix)hello2.html: hello2.cws \ foo.html \ foo2.html cows $(__cows_OPTS) $(main_OPTS) hello2.cws $(prefix)hello2.html clean: rm -f $(TARGETS) dist-noupdate: cd ../ && \ tar chozf update/update.tar.gz \ -X update/Makefile.sources update && \ cd update dist: all dist-noupdate sitedist: dist-noupdate .PHONY: all clean dist dist-noupdate sitedist
As you can see, this makefile is more complex than the hand-written one. Basically, target files and options for cows are defined as variables. Cows-mkgen can handle very complex situations: as an example your site can use different layouts and translation in more languages. Moreover, you may want some special options to be passed to Cows when creating your sites. These situations lead to very complex makefiles so it's essential to use variables.
Let's quickly examine the Makefile. First, four variables are defined: prefix
, __cows_OPTS
, main_OPTS
and TARGETS
. They store
respectively:
site's prefix;
the options that will be passed to the Cows interpreter
the options that will be passed to the Cows interpreter only for the main site;
the list of target files (i.e. the file to be generated).
Then we find the default target all, defined in terms of
variable TARGETS
, and rules for generation of every file;
note that the command used to create files has the form:
cows $(__cows_OPTS) $(main_OPTS) hello1.cws $(prefix)hello1.html
$(__cows_OPTS), $(main_OPTS) and $(prefix) will be replaced by the value of variables __cows_OPTS
, main_OPTS
and prefix
(in this simple case these variables are empty strings and
the current directory).
Finally, the standard target clean, which cleans the directory tree erasing all the generated files, and other targets we'll analyze later in the manual: dist, dist-noupdate and sitedist. They are used to create a tar archive of the site, without including the sources. In practice, they allow to extract files you'll move to the web server hosting your site.
Another file is generated by Cows-mkgen: this is called Makefile.sources. Let's see it:
File Makefile.sources:
Makefile Makefile~ Makefile.cm Makefile.cm~ Makefile.sources Makefile.sources~ Makefile.add Makefile.add~ update.tar.gz hello1.cws hello1.cws~ hello2.cws hello2.cws~
This is an automatically generated list of the source files of your project, plus a number of standard files that can be generated by the makefile. This list is used to exclude these files from the above mentioned archives of output file. In practice, these archives are created by packaging all files in your project directory tree, leaving out these sources.
The generated Makefile provides a number of targets; the most used are all and clean, which allow to create the whole site and to delete it. In order to perform the corresponding actions you simply need to type make followed by the name of the target. As an example, make all will create the whole site while make clean will delete it.
These are the available targets:
Create all output files. This is the default target; this means that running simply make is equivalent to running make all
Delete all output files. Clean your project's directory tree.
First, run make all to update output files (if needed). Then create a gzipped tar archive with all the files stored in your project's directory tree except those listed in Makefile.sources. Archive will be named after the root directory of your project (e.g. if your site is created within directory your_site/, archive will be called your_site.tar.gz).
Create the archive as the previous target, without updating the site first.
An obsolete, alternate name for dist-noupdate. You shouldn't use it, use make dist-noupdate instead. This form is only kept for backward compatibility with older versions of G-Cows.
This manual can be downloaded from http://www.g-cows.org/.