diff options
author | Luca Falavigna <dktrkranz@debian.org> | 2010-01-02 20:56:27 +0100 |
---|---|---|
committer | Luca Falavigna <dktrkranz@debian.org> | 2010-01-02 20:56:27 +0100 |
commit | 72c578fd4b0b4a5a43e18594339ac4ff26c376dc (patch) | |
tree | cadaf3abe37a1066ceae933bc8fe7b75c85f56d2 /doc | |
parent | 548ed1064f327bccc6e538806740d41ea2d928a1 (diff) |
Imported Upstream version 1.2.0.d20091224upstream/1.2.0.d20091224
Diffstat (limited to 'doc')
182 files changed, 66403 insertions, 0 deletions
diff --git a/doc/MANIFEST b/doc/MANIFEST new file mode 100644 index 0000000..008afab --- /dev/null +++ b/doc/MANIFEST @@ -0,0 +1 @@ +scons.mod diff --git a/doc/SConscript b/doc/SConscript new file mode 100644 index 0000000..fd18ef4 --- /dev/null +++ b/doc/SConscript @@ -0,0 +1,530 @@ +# +# SConscript file for building SCons documentation. +# + +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +import os.path +import re +import string + +Import('build_dir', 'env', 'whereis') + +env = env.Clone() + +build = os.path.join(build_dir, 'doc') + +# +# +# +dist_doc_tar_gz = '$DISTDIR/scons-doc-${VERSION}.tar.gz' + +# +# We'll only try to build text files (for some documents) +# if lynx is available to do the dump. +# +fig2dev = whereis('fig2dev') +epydoc = whereis('epydoc') +groff = whereis('groff') +lynx = whereis('lynx') +man2html = whereis('man2html') +jade_original = whereis('jade') +jade = whereis('openjade') or jade_original +jadetex = whereis('jadetex') +pdfjadetex = whereis('pdfjadetex') +jw = whereis('jw') +tidy = whereis('tidy') + +tar_deps = [] +tar_list = [] + +entity_re = re.compile(r'<!entity\s+(?:%\s+)?(?:\S+)\s+SYSTEM\s+"([^"]*)">', re.I) +format_re = re.compile(r'<(?:graphic|imagedata)\s+fileref="([^"]*)"(?:\s+format="([^"]*)")?') + +# +# Find internal dependencies in .xml files: +# +# <!entity bground SYSTEM "bground.xml"> +# <graphic fileref="file.jpg"> +# <imagedata fileref="file.jpg"> +# +# This only finds one per line, and assumes that anything +# defined as a SYSTEM entity is, in fact, a file included +# somewhere in the document. +# +def scanxml(node, env, target): + includes = [] + + contents = node.get_text_contents() + + includes.extend(entity_re.findall(contents)) + + matches = format_re.findall(contents) + for m in matches: + file, format = m + if format and file[-len(format):] != format: + file = file + '.' + format + if not os.path.isabs(file): + a = [] + f = file + while f: + f, tail = os.path.split(f) + if tail == 'doc': + break + a = [tail] + a + file = apply(os.path.join, a, {}) + includes.append(file) + + return includes + +s = Scanner(name = 'xml', function = scanxml, skeys = ['.xml', '.mod']) + +orig_env = env +env = orig_env.Clone(SCANNERS = [s], + SCONS_PROC_PY = File('#bin/scons-proc.py').rfile(), + SCONSOUTPUT_PY = File('#bin/sconsoutput.py').rfile()) + +# Fetch the list of files in the build engine that contain +# SCons documentation XML for processing. +def chop(s): return s[:-1] + +# If we ever read doc from __scons_doc__ strings in *.py files again, +# here's how it's done: +#manifest_in = File('#src/engine/MANIFEST.in').rstr() +#manifest_xml_in = File('#src/engine/MANIFEST-xml.in').rstr() +#scons_doc_files = map(chop, open(manifest_in).readlines() +\ +# open(manifest_xml_in).readlines()) +#scons_doc_files = map(lambda x: '#src/engine/'+x, scons_doc_files) +#manifest_in = File('#src/engine/MANIFEST.in').rstr() + +manifest_xml_in = File('#src/engine/MANIFEST-xml.in').rstr() +scons_doc_files = map(chop, open(manifest_xml_in).readlines()) +scons_doc_files = map(lambda x: File('#src/engine/'+x).rstr(), scons_doc_files) + +if not jw: + print "jw not found, skipping building User Guide." +else: + # + # Always create a version.xml file containing the version information + # for this run. Ignore it for dependency purposes so we don't + # rebuild all the docs every time just because the date changes. + # + date, ver, rev = env.Dictionary('DATE', 'VERSION', 'REVISION') + version_xml = File(os.path.join(build, "version.xml")) + #version_xml = File("version.xml") + verfile = str(version_xml) + try: + os.unlink(verfile) + except OSError: + pass # okay if the file didn't exist + dir, f = os.path.split(verfile) + try: + os.makedirs(dir) + except OSError: + pass # okay if the directory already exists + open(verfile, "w").write("""<!-- +THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. +--> +<!ENTITY builddate "%s"> +<!ENTITY buildversion "%s"> +<!ENTITY buildrevision "%s"> +""" % (date, ver, rev)) + + builders_gen = os.path.join(build, 'user', 'builders.gen') + builders_mod = os.path.join(build, 'user', 'builders.mod') + tools_gen = os.path.join(build, 'user', 'tools.gen') + tools_mod = os.path.join(build, 'user', 'tools.mod') + variables_gen = os.path.join(build, 'user', 'variables.gen') + variables_mod = os.path.join(build, 'user', 'variables.mod') + + # We put $( - $) around $SOURCES in the command line below because + # the path names will change when a given input file is found in + # a repository one run and locally the next, and we don't want + # to rebuild documentation just because it's found in one location + # vs. the other. The *.gen and *.mod targets will still be dependent + # on the list of the files themselves. + doc_output_files = [builders_gen, builders_mod, + tools_gen, tools_mod, + variables_gen, variables_mod] + b = env.Command(doc_output_files, + scons_doc_files, + "$PYTHON $SCONS_PROC_PY --xml -b ${TARGETS[0]},${TARGETS[1]} -t ${TARGETS[2]},${TARGETS[3]} -v ${TARGETS[4]},${TARGETS[5]} $( $SOURCES $)") + env.Depends(b, "$SCONS_PROC_PY") + + env.Local(b) + + # + # Each document will live in its own subdirectory. List them here + # as hash keys, with a hash of the info to control its build. + # + docs = { + 'design' : { + 'htmlindex' : 'book1.html', + 'ps' : 1, + 'pdf' : 1, + 'text' : 0, + }, + # This doesn't build on all systems, and the document is old + # enough that there's reallyno need to build it every time any + # more, so just comment it out for now. + #'python10' : { + # 'htmlindex' : 't1.html', + # 'html' : 1, + # 'ps' : 1, + # 'pdf' : 0, + # 'text' : 0, + # 'graphics' : [ + # 'arch.fig', + # 'builder.fig', + # 'job-task.fig', + # 'node.fig', + # 'scanner.fig', + # 'sig.fig' + # ], + #}, + 'reference' : { + 'htmlindex' : 'book1.html', + 'html' : 1, + 'ps' : 1, + 'pdf' : 1, + 'text' : 0, + }, + # For whenever (if ever?) we start putting developer guide + # information in a printable document instead of the wiki. + #'developer' : { + # 'htmlindex' : 'book1.html', + # 'html' : 1, + # 'ps' : 1, + # 'pdf' : 1, + # 'text' : 0, + #}, + 'user' : { + 'htmlindex' : 'book1.html', + 'html' : 1, + 'ps' : 1, + 'pdf' : 1, + 'text' : 1, + 'graphics' : [ + 'SCons-win32-install-1.jpg', + 'SCons-win32-install-2.jpg', + 'SCons-win32-install-3.jpg', + 'SCons-win32-install-4.jpg', + ], + 'sconsoutput' : 1, + }, + } + + # + # We have to tell SCons to scan the top-level XML files which + # get included by the document XML files in the subdirectories. + # + manifest = File('MANIFEST').rstr() + src_files = map(lambda x: x[:-1], open(manifest).readlines()) + for s in src_files: + base, ext = os.path.splitext(s) + if ext in ['.fig', '.jpg']: + orig_env.Install(build, s) + else: + orig_env.SCons_revision(os.path.join(build, s), s) + Local(os.path.join(build, s)) + + # + # For each document, build the document itself in HTML, Postscript, + # and PDF formats. + # + for doc in docs.keys(): + manifest = File(os.path.join(doc, 'MANIFEST')).rstr() + src_files = map(lambda x: x[:-1], + open(manifest).readlines()) + build_doc = docs[doc].get('sconsoutput') and int(ARGUMENTS.get('BUILDDOC', 0)) + for s in src_files: + doc_s = os.path.join(doc, s) + build_s = os.path.join(build, doc, s) + base, ext = os.path.splitext(doc_s) + if ext in ['.fig', '.jpg']: + orig_env.InstallAs(build_s, doc_s) + else: + if build_doc and ext == '.xml': + env.Command(doc_s, + base + '.in', + "$PYTHON $SCONSOUTPUT_PY $SOURCE > $TARGET") + orig_env.SCons_revision(build_s, doc_s) + Local(build_s) + + main = os.path.join(build, doc, 'main.xml') + out = 'main.out' + + # Hard-coding the scons-src path is a bit of a hack. This can + # be reworked when a better solution presents itself. + scons_src_main = os.path.join(build_dir, 'scons-src', 'doc', main) + env.Ignore(scons_src_main, version_xml) + + htmldir = os.path.join(build, 'HTML', 'scons-%s' % doc) + htmlindex = os.path.join(htmldir, docs[doc]['htmlindex']) + html = os.path.join(build, 'HTML', 'scons-%s.html' % doc) + ps = os.path.join(build, 'PS', 'scons-%s.ps' % doc) + pdf = os.path.join(build, 'PDF', 'scons-%s.pdf' % doc) + text = os.path.join(build, 'TEXT', 'scons-%s.txt' % doc) + + if docs[doc].get('html') and jade: + def copy_index_html(target, source, env): + # Older versions of DocBook|jw|jade|whatever would + # create a book1.html file, while newer versions create + # an index.html file (logically enough). The scons.org + # web site links expect book1.html, so we're going to + # leave the target as is, and run this post-processing + # action function to check that the target really did + # get created, and if it didn't, copy it from index.html. + t = str(target[0]) + if not os.path.exists(t): + i = os.path.join(os.path.split(t)[0], 'index.html') + open(t, 'w').write(open(i, 'r').read()) + return None + + cmds = [ + Delete("${TARGET.dir}/*.html"), + "jw -b html -o ${TARGET.dir} $SOURCES", + ] + if tidy: + cmds.append("tidy -m -q $TARGET || true") + cmds.append(Action(copy_index_html)) + env.Command(htmlindex, File(main), cmds) + Local(htmlindex) + + cmds = [ + Delete("${TARGET.dir}/main.html"), + "jw -u -b html -o ${TARGET.dir} $SOURCES", + Move("$TARGET", "${TARGET.dir}/main.html"), + ] + if tidy: + cmds.append("tidy -m -q $TARGET || true") + env.Command(html, File(main), cmds) + Local(html) + + env.Ignore([html, htmlindex], version_xml) + + tar_deps.extend([html, htmlindex]) + tar_list.extend([html, htmldir]) + + for g in docs[doc].get('graphics', []): + base, ext = os.path.splitext(g) + if ext == '.fig': + jpg = base + '.jpg' + htmldir_jpg = os.path.join(htmldir, jpg) + if fig2dev: + fig = os.path.join(build, doc, g) + env.Command(htmldir_jpg, fig, + "%s -L jpeg -q 100 $SOURCES $TARGET" % fig2dev) + else: + env.InstallAs(htmldir_jpg, jpg) + env.Depends(html, htmldir_jpg) + Local(htmldir_jpg) + else: + src = os.path.join(build, doc, g) + Local(env.Install(htmldir, src)) + + if docs[doc].get('ps') and jadetex and jade_original: + env.Command(ps, main, [ + Delete("${TARGET.dir}/%s" % out), + "jw -b ps -o ${TARGET.dir} -p %s $SOURCES" % jade_original, + "mv ${TARGET.dir}/main.ps $TARGET", + Delete("${TARGET.dir}/%s" % out), + ]) + Local(ps) + + env.Ignore(ps, version_xml) + + tar_deps.append(ps) + tar_list.append(ps) + + for g in docs[doc].get('graphics', []): + base, ext = os.path.splitext(g) + if ext == '.fig': + eps = base + '.eps' + build_eps = os.path.join(build, 'PS', eps) + if fig2dev: + fig = os.path.join(build, doc, g) + env.Command(build_eps, fig, "%s -L eps $SOURCES $TARGET" % fig2dev) + else: + env.InstallAs(build_eps, eps) + env.Depends(ps, build_eps) + Local(build_eps) + else: + src = os.path.join(build, doc, g) + Local(env.Install(htmldir, src)) + + if docs[doc].get('pdf') and pdfjadetex and jade_original: + env.Command(pdf, main, [ + Delete("${TARGET.dir}/%s" % out), + "jw -b pdf -o ${TARGET.dir} -p %s $SOURCES" % jade_original, + "mv ${TARGET.dir}/main.pdf $TARGET", + Delete("${TARGET.dir}/out"), + ]) + Local(pdf) + + env.Ignore(pdf, version_xml) + + tar_deps.append(pdf) + tar_list.append(pdf) + + if docs[doc].get('text') and jade and lynx: + env.Command(text, html, "lynx -dump ${SOURCE.abspath} > $TARGET") + Local(text) + + env.Ignore(text, version_xml) + + tar_deps.append(text) + tar_list.append(text) + +# +# Man page(s), in good ol' troff format. +# +man_page_list = ['scons.1', 'sconsign.1', 'scons-time.1'] + +for m in man_page_list: + x = orig_env.SCons_revision(os.path.join(build, 'man', m), + os.path.join('man', m)) + +man_i_files = ['builders.man', 'tools.man', 'variables.man'] + +man_intermediate_files = map(lambda x: os.path.join(build, 'man', x), + man_i_files) + +cmd = "$PYTHON $SCONS_PROC_PY --man -b ${TARGETS[0]} -t ${TARGETS[1]} -v ${TARGETS[2]} $( $SOURCES $)" +man_intermediate_files = env.Command(man_intermediate_files, + scons_doc_files, + cmd) +env.Depends(man_intermediate_files, "$SCONS_PROC_PY") +Local(man_intermediate_files) + +for man_1 in man_page_list: + man, _1 = os.path.splitext(man_1) + + man_1 = os.path.join(build, 'man', man_1) + + if groff: + ps = os.path.join(build, 'PS', '%s-man.ps' % man) + text = os.path.join(build, 'TEXT', '%s-man.txt' % man) + + b = env.Command(ps, man_1, "( cd ${SOURCES.dir} && groff -man -Tps ${SOURCES.file} ) > $TARGET") + Local(ps) + env.Depends(b, man_intermediate_files) + + b = env.Command(text, man_1, "( cd ${SOURCES.dir} && groff -man -Tascii ${SOURCES.file} ) > $TARGET") + Local(text) + env.Depends(b, man_intermediate_files) + + tar_deps.extend([ps, text]) + tar_list.extend([ps, text]) + + if man2html: + html = os.path.join(build, 'HTML' , '%s-man.html' % man) + + def strip_to_first_html_tag(target, source, env): + t = str(target[0]) + contents = open(t).read() + contents = contents[string.find(contents, '<HTML>'):] + open(t, 'w').write(contents) + return 0 + + cmds = [ + "( cd %s/man && cp %s .. )" % (build, string.join(man_i_files)), + "( cd ${SOURCE.dir} && man2html ${SOURCE.file} ) > $TARGET", + Action(strip_to_first_html_tag), + ] + if tidy: + cmds.append("tidy -m -q $TARGET || true") + b = env.Command(html, man_1, cmds) + Local(html) + env.Depends(b, man_intermediate_files) + + tar_deps.append(html) + tar_list.append(html) + +if not epydoc: + print "epydoc not found, skipping building API documentation." +else: + # XXX Should be in common with reading the same thing in + # the SConstruct file. + e = os.path.join('#src', 'engine') + manifest_in = File(os.path.join(e, 'MANIFEST.in')).rstr() + sources = map(lambda x: x[:-1], open(manifest_in).readlines()) + sources = filter(lambda x: string.find(x, 'Optik') == -1, sources) + sources = filter(lambda x: string.find(x, 'Platform') == -1, sources) + sources = filter(lambda x: string.find(x, 'Tool') == -1, sources) + # XXX + sources = filter(lambda x: string.find(x, 'Options') == -1, sources) + + e = os.path.join(build, '..', 'scons', 'engine') + sources = map(lambda x, e=e: os.path.join(e, x), sources) + + epydoc_commands = [ + Delete('$OUTDIR'), + '$EPYDOC $EPYDOCFLAGS --debug --output $OUTDIR --docformat=restructuredText --name SCons --url http://www.scons.org/ $SOURCES', + Touch('$TARGET'), + ] + + htmldir = os.path.join(build, 'HTML', 'scons-api') + env.Command('${OUTDIR}/index.html', sources, epydoc_commands, + EPYDOC=epydoc, EPYDOCFLAGS='--html', OUTDIR=htmldir) + tar_deps.append(htmldir) + tar_list.append(htmldir) + + # PDF and PostScript and TeX are built from the + # same invocation. + api_dir = os.path.join(build, 'scons-api') + api_pdf = os.path.join(api_dir, 'api.pdf') + api_ps = os.path.join(api_dir, 'api.ps') + api_tex = os.path.join(api_dir, 'api.tex') + api_targets = [api_pdf, api_ps, api_tex] + env.Command(api_targets, sources, epydoc_commands, + EPYDOC=epydoc, EPYDOCFLAGS='--pdf', OUTDIR=api_dir) + Local(api_targets) + + pdf_install = os.path.join(build, 'PDF', 'scons-api.pdf') + env.InstallAs(pdf_install, api_pdf) + tar_deps.append(pdf_install) + tar_list.append(pdf_install) + Local(pdf_install) + + ps_install = os.path.join(build, 'PS', 'scons-api.ps') + env.InstallAs(ps_install, api_ps) + tar_deps.append(ps_install) + tar_list.append(ps_install) + Local(ps_install) + +# +# Now actually create the tar file of the documentation, +# for easy distribution to the web site. +# +if tar_deps: + tar_list = string.join(map(lambda x, b=build+'/': string.replace(x, b, ''), + tar_list)) + t = env.Command(dist_doc_tar_gz, tar_deps, + "tar cf${TAR_HFLAG} - -C %s %s | gzip > $TARGET" % (build, tar_list)) + AddPostAction(dist_doc_tar_gz, Chmod(dist_doc_tar_gz, 0644)) + Local(t) + Alias('doc', t) +else: + Alias('doc', os.path.join(build_dir, 'doc')) diff --git a/doc/design/MANIFEST b/doc/design/MANIFEST new file mode 100644 index 0000000..33ab8f0 --- /dev/null +++ b/doc/design/MANIFEST @@ -0,0 +1,14 @@ +acks.xml +bground.xml +copyright.xml +engine.fig +engine.jpg +engine.xml +goals.xml +install.xml +intro.xml +issues.xml +main.xml +native.xml +overview.xml +scons.mod diff --git a/doc/design/acks.xml b/doc/design/acks.xml new file mode 100644 index 0000000..b1a8a58 --- /dev/null +++ b/doc/design/acks.xml @@ -0,0 +1,179 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + I'm grateful to the following people + for their influence, knowing or not, + on the design of &SCons;: + + </para> + + <variablelist> + <varlistentry> + <term>Bob Sidebotham</term> + <listitem> + <para> + + First, as the original author of &Cons;, Bob did the real heavy + lifting of creating the underlying model for dependency management + and software construction, as well as implementing it in Perl. + During the first years of &Cons;' existence, Bob did a skillful + job of integrating input and code from the first users, and + consequently is a source of practical wisdom and insight into the + problems of real-world software construction. His continuing + advice has been invaluable. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>The &SCons; Development Team</term> + <listitem> + <para> + + A big round of thanks go to those brave souls who have + gotten in on the ground floor: + David Abrahams, + Charles Crain, + Steven Leblanc. + Anthony Roach, + and + Steven Shaw. + Their contributions, + through their general knowledge of software build issues in general + Python in particular, + have made &SCons; what it is today. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>The &Cons; Community</term> + <listitem> + <para> + + The real-world build problems that the users of &Cons; + share on the <command>cons-discuss</command> mailing list + have informed much of the thinking that + has gone into the &SCons; design. + In particular, + Rajesh Vaidheeswarran, + the current maintainer of &Cons;, + has been a very steady influence. + I've also picked up valuable insight from + mailing-list participants + Johan Holmberg, + Damien Neil, + Gary Oberbrunner, + Wayne Scott, + and Greg Spencer. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Peter Miller</term> + <listitem> + + <para> + + Peter has indirectly + influenced two aspects of the &SCons; design: + + </para> + + <para> + + Miller's influential paper + <citetitle>Recursive Make Considered Harmful</citetitle> + was what led me, indirectly, to my involvement with &Cons; + in the first place. + Experimenting with the single-Makefile approach he describes in + <citetitle>RMCH</citetitle> led me to conclude that while it worked + as advertised, it was not an extensible scheme. This solidified + my frustration with Make and led me to try &Cons;, which at its + core shares the single-process, universal-DAG model of the "RMCH" + single-Makefile technique. + + </para> + + <para> + + The testing framework that Miller created for his + Aegis change management system + changed the way I approach software development + by providing a framework for rigorous, repeatable + testing during development. + It was my success at using Aegis for personal projects + that led me to begin my involvement with &Cons; + by creating the <command>cons-test</command> regression suite. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Stuart Stanley</term> + <listitem> + <para> + + An experienced Python programmer, + Stuart provided valuable advice and insight + into some of the more useful Python idioms at my disposal + during the original <literal>ScCons</literal>; design + for the Software Carpentry contest. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Gary Holt</term> + <listitem> + <para> + + I don't know which came first, + the first-round Software Carpentry contest entry + or the tool itself, + but Gary's design for &Makepp; + showed me that it is possible to marry + the strengths of &Cons;-like dependency management + with backwards compatibility for &Makefile;s. + Striving to support both + &Makefile; compatibility and + a native Python interface + cleaned up the &SCons; design immeasurably + by factoring out the common elements + into the Build Engine. + + </para> + </listitem> + </varlistentry> + </variablelist> + diff --git a/doc/design/bground.xml b/doc/design/bground.xml new file mode 100644 index 0000000..c404e86 --- /dev/null +++ b/doc/design/bground.xml @@ -0,0 +1,86 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Most of the ideas in &SCons; originate with &Cons;, a Perl-based + software construction utility that has been in use by a small but + growing community since its development by Bob Sidebotham at FORE + Systems in 1996. The &Cons; copyright was transferred in 2000 from + Marconi (who purchased FORE Systems) to the Free Software Foundation. + I've been a principal implementer and maintainer of &Cons; for several + years. + + </para> + + <para> + + &Cons; was originally designed to handle complicated software build + problems (multiple directories, variant builds) while keeping the + input files simple and maintainable. The general philosophy is that + the build tool should ``do the right thing'' with minimal input + from an unsophisticated user, while still providing a rich set of + underlying functionality for more complicated software construction + tasks needed by experts. + + </para> + + <para> + + In 2000, the Software Carpentry sought entries in a contest for a + new, Python-based build tool that would provide an improvement + over Make for physical scientists and other non-programmers + struggling to use their computers more effectively. Prior to that, + the idea of combining the superior build architecture of &Cons; + with the easier syntax of Python had come up several times on + the <literal>cons-discuss</literal> mailing list. The Software + Carpentry contest provided the right motivation to spend some + actual time working on a design document. + + </para> + + <para> + + After two rounds of competition, the submitted design, named + <application>ScCons</application>, won the competition. Software + Carpentry, however, did not immediately fund implementation of the + build tool, instead contracting for additional, more detailed draft(s) + of the design document. This proved to be not as strong motivation as + actual coding, and after several months of inactivity, I essentially + resigned from the Software Carpentry effort in early 2001 to start + working on the tool independently. + + </para> + + <para> + + After half a year of prototyping some of the important infrastructure, + I accumulated enough code to take the project public at SourceForge, + renaming it &SCons; to distinguish it slightly from the version of the + design that won the Software Carpentry contest while still honoring + its roots there and in the original &Cons; utility. And also because + it would be a teensy bit easier to type. + + </para> diff --git a/doc/design/copyright.xml b/doc/design/copyright.xml new file mode 100644 index 0000000..d73906e --- /dev/null +++ b/doc/design/copyright.xml @@ -0,0 +1,39 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<blockquote> + <para> + + Copyright (c) 2001 Steven Knight + + Portions of this document, by the same author, were previously + published Copyright 2000 by CodeSourcery LLC, under the Software Carpentry + Open Publication License, the terms of which are available at + <ulink url="http://www.software-carpentry.com/openpub-license.html"> + http://www.software-carpentry.com/openpub-license.html + </ulink>. + + </para> +</blockquote> diff --git a/doc/design/engine.fig b/doc/design/engine.fig new file mode 100644 index 0000000..90f3d4f --- /dev/null +++ b/doc/design/engine.fig @@ -0,0 +1,179 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 2100 8700 3600 9300 +2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5 + 2100 8700 3600 8700 3600 9300 2100 9300 2100 8700 +4 0 0 100 0 18 14 0.0000 4 165 900 2400 9075 Node.FS\001 +-6 +6 7050 6900 9000 7500 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 7050 6900 9000 6900 9000 7500 7050 7500 7050 6900 +4 0 0 100 0 18 14 0.0000 4 165 1530 7200 7275 Intercessor.FS\001 +-6 +6 9450 6900 11400 7500 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 9450 6900 11400 6900 11400 7500 9450 7500 9450 6900 +4 0 0 100 0 18 14 0.0000 4 165 1560 9600 7275 Intercessor.DB\001 +-6 +6 1200 4200 2400 4800 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 1200 4200 2400 4200 2400 4800 1200 4800 1200 4200 +4 0 0 100 0 18 14 0.0000 4 165 870 1350 4575 Scanner\001 +-6 +6 2400 3300 3600 3900 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 2400 3300 3600 3300 3600 3900 2400 3900 2400 3300 +4 0 0 100 0 18 14 0.0000 4 165 750 2625 3675 Builder\001 +-6 +6 8700 1650 10500 2250 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 8700 1650 10500 1650 10500 2250 8700 2250 8700 1650 +4 0 0 100 0 18 14 0.0000 4 165 1185 9000 2025 Intercessor\001 +-6 +6 1500 1650 3300 2250 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 1500 1650 3300 1650 3300 2250 1500 2250 1500 1650 +4 0 0 100 0 18 14 0.0000 4 165 1320 1725 2025 Environment\001 +-6 +6 7800 8700 9300 9300 +2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5 + 7800 8700 9300 8700 9300 9300 7800 9300 7800 8700 +4 0 0 100 0 18 14 0.0000 4 165 930 8100 9075 Node.DB\001 +-6 +6 1500 10200 2400 10800 +2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5 + 1500 10200 2400 10200 2400 10800 1500 10800 1500 10200 +4 0 0 100 0 18 14 0.0000 4 165 315 1800 10575 Dir\001 +-6 +6 3300 10200 4200 10800 +2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5 + 3300 10200 4200 10200 4200 10800 3300 10800 3300 10200 +4 0 0 100 0 18 14 0.0000 4 165 375 3600 10575 File\001 +-6 +6 6000 10200 7200 10800 +2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5 + 6000 10200 7200 10200 7200 10800 6000 10800 6000 10200 +4 0 0 100 0 18 14 0.0000 4 165 555 6300 10575 Table\001 +-6 +6 7800 10200 9300 10800 +2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5 + 7800 10200 9300 10200 9300 10800 7800 10800 7800 10200 +4 0 0 100 0 18 14 0.0000 4 165 765 8100 10575 Record\001 +-6 +6 9900 10200 11100 10800 +2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5 + 9900 10200 11100 10200 11100 10800 9900 10800 9900 10200 +4 0 0 100 0 18 14 0.0000 4 165 510 10200 10575 Field\001 +-6 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 6900 5250 6825 5175 6900 5100 6975 5175 6900 5250 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 6300 5250 6225 5175 6300 5100 6375 5175 6300 5250 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 5700 5250 5625 5175 5700 5100 5775 5175 5700 5250 +2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 4800 2700 7200 2700 7200 5100 4800 5100 4800 2700 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4 + 5100 5100 5025 5250 5175 5250 5100 5100 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 5 + 0 0 1.00 60.00 120.00 + 6300 5250 6300 5700 8400 5700 8400 4200 7200 4200 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 5 + 0 0 1.00 60.00 120.00 + 5700 5250 5700 6000 9000 6000 9000 3600 7200 3600 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2 + 5100 5250 5100 8100 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 4725 3675 4650 3600 4725 3525 4800 3600 4725 3675 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 4725 4575 4650 4500 4725 4425 4800 4500 4725 4575 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 4650 3600 3600 3600 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 4650 4500 2400 4500 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1800 2400 1800 4200 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3000 2400 3000 3300 +2 1 1 1 0 7 100 0 -1 4.000 0 0 7 0 0 2 + 5850 1950 5850 2700 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 3000 2400 2925 2325 3000 2250 3075 2325 3000 2400 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5 + 1800 2400 1725 2325 1800 2250 1875 2325 1800 2400 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2 + 3300 1950 8700 1950 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2 + 9600 2400 9600 6600 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4 + 7950 6900 7950 6600 10350 6600 10350 6900 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4 + 9600 2250 9525 2400 9675 2400 9600 2250 +2 1 0 1 0 7 100 0 -1 4.000 0 0 7 0 0 2 + 4800 3000 7200 3000 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2 + 4800 3300 7200 3300 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4 + 2850 9300 2775 9450 2925 9450 2850 9300 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 4 + 2100 10200 2100 9900 3750 9900 3750 10200 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5 + 6600 10200 6600 9900 10500 9900 10500 10200 10500 10125 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2 + 2850 9450 2850 9900 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2 + 8475 9450 8475 10200 +2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4 + 8475 9300 8400 9450 8550 9450 8475 9300 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 1 + 2775 6825 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 1800 10200 1800 9000 2100 9000 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 9900 10500 9300 10500 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 7800 10500 7200 10500 +2 1 0 1 0 7 100 0 -1 4.000 0 0 7 0 0 4 + 2850 8700 2850 8100 8550 8100 8550 8700 +2 1 1 1 0 7 100 0 -1 4.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 10350 7500 10350 9000 9300 9000 +2 1 1 1 0 7 100 0 -1 4.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 7050 7200 2400 7200 2400 8700 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 5 + 0 0 1.00 60.00 120.00 + 6900 5250 6900 5400 7800 5400 7800 4800 7200 4800 +4 0 0 100 0 18 14 0.0000 4 165 555 4950 2925 Node\001 +4 0 0 100 0 16 10 0.0000 4 150 825 7350 3525 dependency\001 +4 0 0 100 0 16 10 0.0000 4 45 60 7425 3825 *\001 +4 0 0 100 0 16 10 0.0000 4 120 555 7350 4125 srcnode\001 +4 0 0 100 0 16 10 0.0000 4 120 90 7425 4425 1\001 +4 0 0 100 0 16 10 0.0000 4 150 570 7350 4725 repnode\001 +4 0 0 100 0 16 10 0.0000 4 120 90 7425 5025 1\001 +4 0 0 100 0 16 10 0.0000 4 120 270 2550 4725 0..1\001 +4 0 0 100 0 16 10 0.0000 4 120 270 3750 3825 0..1\001 +4 0 0 100 0 0 12 0.0000 4 75 90 1875 4050 *\001 +4 0 0 100 0 0 12 0.0000 4 75 90 3075 3150 *\001 +4 0 0 100 0 16 14 0.0000 4 210 600 5100 3750 build()\001 +4 0 0 100 0 16 14 0.0000 4 210 630 5100 4260 scan()\001 +4 0 0 100 0 0 12 0.0000 4 135 90 9750 10725 1\001 +4 0 0 100 0 16 10 0.0000 4 120 90 1650 10125 1\001 +4 0 0 100 0 16 10 0.0000 4 45 60 1875 9225 *\001 +4 0 0 100 0 16 10 0.0000 4 120 90 7650 10725 1\001 +4 0 0 100 0 16 10 0.0000 4 45 60 7275 10725 *\001 +4 0 0 100 0 16 10 0.0000 4 45 60 9375 10725 *\001 diff --git a/doc/design/engine.jpg b/doc/design/engine.jpg Binary files differnew file mode 100644 index 0000000..2e82232 --- /dev/null +++ b/doc/design/engine.jpg diff --git a/doc/design/engine.xml b/doc/design/engine.xml new file mode 100644 index 0000000..1a1e335 --- /dev/null +++ b/doc/design/engine.xml @@ -0,0 +1,1964 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<section id="sect-principles"> + <title>General Principles</title> + + <section> + <title>Keyword arguments</title> + + <para> + + All methods and functions in this API will support the use of keyword + arguments in calls, for the sake of explicitness and readability. + For brevity in the hands of experts, most methods and functions + will also support positional arguments for their most-commonly-used + arguments. As an explicit example, the following two lines will each + arrange for an executable program named <filename>foo</filename> (or + <filename>foo.exe</filename> on a Win32 system) to be compiled from + the <filename>foo.c</filename> source file: + + </para> + + <programlisting> + env.Program(target = 'foo', source = 'foo.c') + + env.Program('foo', 'foo.c') + </programlisting> + + </section> + + <section> + <title>Internal object representation</title> + + <para> + + All methods and functions use internal (Python) objects that + represent the external objects (files, for example) for which they + perform dependency analysis. + + </para> + + <para> + + All methods and functions in this API that accept an external object + as an argument will accept <emphasis>either</emphasis> a string + description or an object reference. For example, the two following + two-line examples are equivalent: + + </para> + + <programlisting> + env.Object(target = 'foo.o', source = 'foo.c') + env.Program(target = 'foo', 'foo.o') # builds foo from foo.o + + foo_obj = env.Object(target = 'foo.o', source = 'foo.c') + env.Program(target = 'foo', foo_obj) # builds foo from foo.o + </programlisting> + + </section> + +</section> + + + +<section id="sect-envs"> + <title>&ConsEnvs</title> + + <para> + + A &consenv; is the basic means by which a software system interacts + with the &SCons; Python API to control a build process. + + </para> + + <para> + + A &consenv; is an object with associated methods for generating target + files of various types (&Builder; objects), other associated object + methods for automatically determining dependencies from the contents + of various types of source files (&Scanner; objects), and a dictionary + of values used by these methods. + + </para> + + <para> + + Passing no arguments to the &Environment; instantiation creates a + &consenv; with default values for the current platform: + + </para> + + <programlisting> + env = Environment() + </programlisting> + + <section> + <title>&Consvars;</title> + + <para> + + A &consenv; has an associated dictionary of &consvars; that control how + the build is performed. By default, the &Environment; method creates + a &consenv; with values that make most software build "out of the box" + on the host system. These default values will be generated at the + time &SCons; is installed using functionality similar to that provided + by GNU &Autoconf;. + <footnote> + <para> + It would be nice if we could avoid re-inventing the wheel here by + using some other Python-based tool &Autoconf replacement--like what + was supposed to come out of the Software Carpentry configuration + tool contest. It will probably be most efficient to roll our own + logic initially and convert if something better does come along. + </para> + </footnote> + At a minimum, there will be pre-configured sets of default values + that will provide reasonable defaults for UNIX and Windows NT. + + </para> + + <para> + + The default &consenv; values may be overridden when a new &consenv; is + created by specifying keyword arguments: + + </para> + + <programlisting> + env = Environment(CC = 'gcc', + CCFLAGS = '-g', + CPPPATH = ['.', 'src', '/usr/include'], + LIBPATH = ['/usr/lib', '.']) + </programlisting> + + </section> + + <section> + <title>Fetching &consvars;</title> + + <para> + + A copy of the dictionary of &consvars; can be returned using + the &Dictionary; method: + + </para> + + <programlisting> + env = Environment() + dict = env.Dictionary() + </programlisting> + + <para> + + If any arguments are supplied, then just the corresponding value(s) + are returned: + + </para> + + <programlisting> + ccflags = env.Dictionary('CCFLAGS') + cc, ld = env.Dictionary('CC', 'LD') + </programlisting> + + </section> + + <section> + <title>Copying a &consenv;</title> + + <para> + + A method exists to return a copy of an existing environment, with + any overridden values specified as keyword arguments to the method: + + </para> + + <programlisting> + env = Environment() + debug = env.Copy(CCFLAGS = '-g') + </programlisting> + + </section> + + <section> + <title>Multiple &consenvs;</title> + + <para> + + Different external objects often require different build + characteristics. Multiple &consenvs; may be defined, each with + different values: + + </para> + + <programlisting> + env = Environment(CCFLAGS = '') + debug = Environment(CCFLAGS = '-g') + env.Make(target = 'hello', source = 'hello.c') + debug.Make(target = 'hello-debug', source = 'hello.c') + </programlisting> + + <para> + + Dictionaries of values from multiple &consenvs; may be passed to the + &Environment; instantiation or the &Copy; method, in which case the + last-specified dictionary value wins: + + </para> + + <programlisting> + env1 = Environment(CCFLAGS = '-O', LDFLAGS = '-d') + env2 = Environment(CCFLAGS = '-g') + new = Environment(env1.Dictionary(), env2.Dictionary()) + </programlisting> + + <para> + + The <varname>new</varname> environment in the above example retains + <literal>LDFLAGS = '-d'</literal> from the <varname>env1</varname> + environment, and <literal>CCFLAGS = '-g'</literal> from the + <varname>env2</varname> environment. + + </para> + + <!-- + + hardware details + current directory + OS environment variables + compilers and options, + aliases for commands, + versions of tools + + environment overrides a la Cons + + compilation options + + cross compilation via selection of tool+options + + paths for header files (specify alternate path) + + accomodate smart compilers that can tell you + "I know how to turn .c or .ccp into .o", + "I know how to turn .f into .o" + + --> + + </section> + + <section> + <title>Variable substitution</title> + + <para> + + Within a construction command, any variable from the &consenv; may + be interpolated by prefixing the name of the construction with + <symbol>$</symbol>: + + </para> + + <programlisting> + MyBuilder = Builder(command = "$XX $XXFLAGS -c $_INPUTS -o $target") + + env.Command(targets = 'bar.out', sources = 'bar.in', + command = "sed '1d' < $source > $target") + </programlisting> + + <para> + + Variable substitution is recursive: the command line is expanded + until no more substitutions can be made. + + </para> + + <para> + + Variable names following the <symbol>$</symbol> may be enclosed in + braces. This can be used to concatenate an interpolated value with an + alphanumeric character: + + </para> + + <programlisting> + VerboseBuilder = Builder(command = "$XX -${XXFLAGS}v > $target") + </programlisting> + + <para> + + The variable within braces may contain a pair of parentheses + after a Python function name to be evaluated (for example, + <literal>${map()}</literal>). &SCons; will interpolate the return + value from the function (presumably a string): + + </para> + + <programlisting> + env = Environment(FUNC = myfunc) + env.Command(target = 'foo.out', source = 'foo.in', + command = "${FUNC($<)}") + </programlisting> + + <para> + + If a referenced variable is not defined in the &consenv;, + the null string is interpolated. + + </para> + + <para> + + The following special variables can also be used: + + </para> + + <variablelist> + + <varlistentry> + <term><literal>$targets</literal></term> + <listitem> + <para> + + All target file names. If multiple targets are specified in an + array, <literal>$targets</literal> expands to the entire list of + targets, separated by a single space. + + </para> + + <para> + + Individual targets from a list may be extracted by enclosing + the <literal>targets</literal> keyword in braces and using the + appropriate Python array index or slice: + + </para> + + <programlisting> + ${targets[0]} # expands to the first target + + ${targets[1:]} # expands to all but the first target + + ${targets[1:-1]} # expands to all but the first and last targets + </programlisting> + + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>$target</literal></term> + <listitem> + <para> + + A synonym for <literal>${targets[0]}</literal>, the first target + specified. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>$sources</literal></term> + <listitem> + <para> + + All input file names. Any input file names that + are used anywhere else on the current command + line (via <literal>${sources[0]}</literal>, + <literal>${sources{[1]}</literal>, etc.) are removed from the + expanded list. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + Any of the above special variables may be enclosed in braces and + followed immediately by one of the following attributes to select just + a portion of the expanded path name: + + </para> + + <variablelist> + + <varlistentry> + <term><literal>.base</literal></term> + <listitem> + <para> + + Basename: the directory plus the file name, minus any file suffix. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>.dir</literal></term> + <listitem> + <para> + + The directory in which the file lives. This is a relative path, + where appropriate. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>.file</literal></term> + <listitem> + <para> + + The file name, minus any directory portion. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>.suffix</literal></term> + <listitem> + <para> + + The file name suffix (that is, the right-most dot in the file name, + and all characters to the right of that). + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>.filebase</literal></term> + <listitem> + <para> + + The file name (no directory portion), minus any file suffix. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>.abspath</literal></term> + <listitem> + <para> + + The absolute path to the file. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + </section> + +</section> + + + +<section id="sect-builders"> + <title>&Builder; Objects</title> + + <para> + + By default, &SCons; supplies (and uses) a number of pre-defined + &Builder; objects: + + </para> + + <informaltable> + <tgroup cols="2"> + <tbody> + + <row> + <entry>&Object;</entry> + <entry>compile or assemble an object file</entry> + </row> + + <row> + <entry>&Library;</entry> + <entry>archive files into a library</entry> + </row> + + <row> + <entry>&SharedLibrary;</entry> + <entry>archive files into a shared library</entry> + </row> + + <row> + <entry>&Program;</entry> + <entry>link objects and/or libraries into an executable</entry> + </row> + + <row> + <entry>&MakeBuilder;</entry> + <entry>build according to file suffixes; see below</entry> + </row> + + </tbody> + </tgroup> + </informaltable> + +<!-- +&Library; and &SharedLibrary; have nearly identical +semantics, just different +tools and &consenvs (paths, etc.) that they use. +In other words, you can construct a shared library +using just the &Library; &Builder; object +with a different environment. +I think that's a better way to do it. +Feedback? +--> + + <para> + + A &consenv; can be explicitly initialized with associated &Builder; + objects that will be bound to the &consenv; object: + + </para> + + <programlisting> + env = Environment(BUILDERS = ['Object', 'Program']) + </programlisting> + + <para> + + &Builder; objects bound to a &consenv; can be called directly as + methods. When invoked, a &Builder; object returns a (list of) objects + that it will build: + + </para> + + <programlisting> + obj = env.Object(target ='hello.o', source = 'hello.c') + lib = env.Library(target ='libfoo.a', + source = ['aaa.c', 'bbb.c']) + slib = env.SharedLibrary(target ='libbar.so', + source = ['xxx.c', 'yyy.c']) + prog = env.Program(target ='hello', + source = ['hello.o', 'libfoo.a', 'libbar.so']) + </programlisting> + + <section> + <title>Specifying multiple inputs</title> + + <para> + + Multiple input files that go into creating a target file may be passed + in as a single string, with the individual file names separated by + white space: + + </para> + + <programlisting> + env.Library(target = 'foo.a', source = 'aaa.c bbb.c ccc.c') + env.Object(target = 'yyy.o', source = 'yyy.c') + env.Program(target = 'bar', source = 'xxx.c yyy.o foo.a') + </programlisting> + + <para> + + Alternatively, multiple input files that go into creating a target + file may be passed in as an array. This allows input files to be + specified using their object representation: + + </para> + + <programlisting> + env.Library(target = 'foo.a', source = ['aaa.c', 'bbb.c', 'ccc.c']) + yyy_obj = env.Object(target = 'yyy.o', source = 'yyy.c') + env.Program(target = 'bar', source = ['xxx.c', yyy_obj, 'foo.a']) + </programlisting> + + <para> + + Individual string elements within an array of input files are + <emphasis>not</emphasis> further split into white-space separated + file names. This allows file names that contain white space to + be specified by putting the value into an array: + + <programlisting> + env.Program(target = 'foo', source = ['an input file.c']) + </programlisting> + + </para> + + </section> + + <section> + <title>Specifying multiple targets</title> + + <para> + + Conversely, the generated target may be a string listing multiple + files separated by white space: + + </para> + + <programlisting> + env.Object(target = 'grammar.o y.tab.h', source = 'grammar.y') + </programlisting> + + <para> + + An array of multiple target files can be used to mix string and object + representations, or to accomodate file names that contain white space: + + </para> + + <programlisting> + env.Program(target = ['my program'], source = 'input.c') + </programlisting> + + </section> + + <section> + <title>File prefixes and suffixes</title> + + <para> + + For portability, if the target file name does not already have an + appropriate file prefix or suffix, the &Builder; objects will + append one appropriate for the file type on the current system: + + </para> + + <programlisting> + # builds 'hello.o' on UNIX, 'hello.obj' on Windows NT: + obj = env.Object(target ='hello', source = 'hello.c') + + # builds 'libfoo.a' on UNIX, 'foo.lib' on Windows NT: + lib = env.Library(target ='foo', source = ['aaa.c', 'bbb.c']) + + # builds 'libbar.so' on UNIX, 'bar.dll' on Windows NT: + slib = env.SharedLibrary(target ='bar', source = ['xxx.c', 'yyy.c']) + + # builds 'hello' on UNIX, 'hello.exe' on Windows NT: + prog = env.Program(target ='hello', + source = ['hello.o', 'libfoo.a', 'libbar.so']) + </programlisting> + + </section> + + <section> + <title>&Builder; object exceptions</title> + + <para> + + &Builder; objects raise the following exceptions on error: + + <!-- + LIST THESE ONCE WE FIGURE OUT WHAT THEY ARE FROM CODING THEM. + --> + + </para> + </section> + + <section> + <title>User-defined &Builder; objects</title> + + <para> + + Users can define additional &Builder; objects for specific external + object types unknown to &SCons;. A &Builder; object may build its + target by executing an external command: + + </para> + + <programlisting> + WebPage = Builder(command = 'htmlgen $HTMLGENFLAGS $sources > $target', + suffix = '.html', + src_suffix = '.in') + </programlisting> + + <para> + + Alternatively, a &Builder; object may also build its target by + executing a Python function: + + </para> + + <programlisting> + def update(dest): + # [code to update the object] + return 1 + + OtherBuilder1 = Builder(function = update, + src_suffix = ['.in', '.input']) + </programlisting> + + <para> + + An optional argument to pass to the function may be specified: + + </para> + + <programlisting> + def update_arg(dest, arg): + # [code to update the object] + return 1 + + OtherBuilder2 = Builder(function = update_arg, + function_arg = 'xyzzy', + src_suffix = ['.in', '.input']) + </programlisting> + + <para> + + Both an external command and an internal function may be specified, + in which case the function will be called to build the object first, + followed by the command line. + + </para> + + <!-- + NEED AN EXAMPLE HERE. + --> + + <para> + + User-defined &Builder; objects can be used like the default &Builder; + objects to initialize &consenvs;. + + </para> + + <programlisting> + WebPage = Builder(command = 'htmlgen $HTMLGENFLAGS $sources > $target', + suffix = '.html', + src_suffix = '.in') + env = Environment(BUILDERS = ['WebPage']) + env.WebPage(target = 'foo.html', source = 'foo.in') + # Builds 'bar.html' on UNIX, 'bar.htm' on Windows NT: + env.WebPage(target = 'bar', source = 'bar.in') + </programlisting> + + <para> + + The command-line specification can interpolate variables from the + &consenv;; see "Variable substitution," above. + + </para> + + <para> + + A &Builder; object may optionally be initialized with a list of: + + </para> + + <itemizedlist> + <listitem> + <para> + + the prefix of the target file (e.g., 'lib' for libraries) + + </para> + </listitem> + + <listitem> + <para> + + the suffix of the target file (e.g., '.a' for libraries) + + </para> + </listitem> + + <listitem> + <para> + + the expected suffixes of the input files + (e.g., '.o' for object files) + + </para> + </listitem> + </itemizedlist> + + <para> + + These arguments are used in automatic + dependency analysis and to generate output file names that don't + have suffixes supplied explicitly. + + </para> + </section> + + <section> + <title>Copying &Builder; Objects</title> + + <para> + + A &Copy; method exists to return a copy of an existing &Builder; + object, with any overridden values specified as keyword arguments to + the method: + + </para> + + <programlisting> + build = Builder(function = my_build) + build_out = build.Copy(suffix = '.out') + </programlisting> + + <para> + + Typically, &Builder; objects will be supplied by a tool-master or + administrator through a shared &consenv;. + + </para> + </section> + + <section> + <title>Special-purpose build rules</title> + + <para> + + A pre-defined &Command; builder exists to associate a target file with + a specific command or list of commands for building the file: + + </para> + + <programlisting> + env.Command(target = 'foo.out', source = + command = 'foo.in', "foo.process $sources > $target") + + commands = [ "bar.process -o .tmpfile $sources", + "mv .tmpfile $target" ] + env.Command(target = 'bar.out', source = 'bar.in', command = commands) + </programlisting> + + <para> + This is useful when it's too cumbersome to create a &Builder; + object just to build a single file in a special way. + + </para> + </section> + + <section> + <title>The &MakeBuilder; &Builder;</title> + + <para> + + A pre-defined &Builder; object named &MakeBuilder; exists to make + simple builds as easy as possible for users, at the expense of + sacrificing some build portability. + + </para> + + <para> + + The following minimal example builds the 'hello' program from the + 'hello.c' source file: + + </para> + + <programlisting> + Environment().Make('hello', 'hello.c') + </programlisting> + + <para> + + Users of the &MakeBuilder; &Builder; object are not required to + understand intermediate steps involved in generating a file--for + example, the distinction between compiling source code into an object + file, and then linking object files into an executable. The details + of intermediate steps are handled by the invoked method. Users that + need to, however, can specify intermediate steps explicitly: + + </para> + + <programlisting> + env = Environment() + env.Make(target = 'hello.o', source = 'hello.c') + env.Make(target = 'hello', source = 'hello.o') + </programlisting> + + <para> + + The &MakeBuilder; method understands the file suffixes specified and + "does the right thing" to generate the target object and program + files, respectively. It does this by examining the specified output + suffixes for the &Builder; objects bound to the environment. + + </para> + + <para> + + Because file name suffixes in the target and source file names + must be specified, the &MakeBuilder; method can't be used + portably across operating systems. In other words, for the + example above, the &MakeBuilder; builder will not generate + <filename>hello.exe</filename> on Windows NT. + + </para> + + </section> + + <section> + <title>&Builder; maps</title> + +<!-- +Do we even need this anymore? +Now that the individual builders +have specified <literal>suffix</literal> +and <literal>src_suffix</literal> values, +all of the information we need to support +the &MakeBuilder; builder is right there in the environment. +I think this is a holdover from before I +added the <literal>suffix</literal> arguments. +If you want &MakeBuilder; to do something different, +you set it up with another environment... +--> + + <para> + + The <function>env.Make</function> method "does the right thing" to + build different file types because it uses a dictionary from the + &consenv; that maps file suffixes to the appropriate &Builder; object. + This &BUILDERMAP; can be initialized at instantiation: + + </para> + + <programlisting> + env = Environment(BUILDERMAP = { + '.o' : Object, + '.a' : Library, + '.html' : WebPage, + '' : Program, + }) + </programlisting> + + <para> + + With the &BUILDERMAP; properly initialized, the + <function>env.Make</function> method can be used to build additional + file types: + + </para> + + <programlisting> + env.Make(target = 'index.html', source = 'index.input') + </programlisting> + + <para> + + &Builder; objects referenced in the &BUILDERMAP; do not need to be + listed separately in the &BUILDERS; variable. The &consenv; will + bind the union of the &Builder; objects listed in both variables. + + </para> + + <!-- + + YYY support scanners which detect files which haven't been generated yet + + --> + + </section> + +</section> + + + +<section id="sect-deps"> + <title>Dependencies</title> + + <section> + <title>Automatic dependencies</title> + + <para> + + By default, &SCons; assumes that a target file has <literal>automatic + dependencies</literal> on the: + + </para> + + <blockquote> + <simplelist> + + <member>tool used to build the target file</member> + + <member>contents of the input files</member> + + <member>command line used to build the target file</member> + + </simplelist> + </blockquote> + + <para> + + If any of these changes, the target file will be rebuilt. + + </para> + </section> + + <section> + <title>Implicit dependencies</title> + + <para> + + Additionally, &SCons; can scan the contents of files for + <literal>implicit dependencies</literal> on other files. For + example, &SCons; will scan the contents of a <filename>.c</filename> + file and determine that any object created from it is + dependent on any <filename>.h</filename> files specified via + <literal>#include</literal>. &SCons;, therefore, "does the right + thing" without needing to have these dependencies listed explicitly: + + </para> + + <programlisting> + % cat Construct + env = Environment() + env.Program('hello', 'hello.c') + % cat hello.c + #include "hello_string.h" + main() + { + printf("%s\n", STRING); + } + % cat > hello_string.h + #define STRING "Hello, world!\n" + % scons . + gcc -c hello.c -o hello.o + gcc -o hello hello.c + % ./hello + Hello, world! + % cat > hello_string.h + #define STRING "Hello, world, hello!\n" + % scons . + gcc -c hello.c -o hello.o + gcc -o hello hello.c + % ./hello + Hello, world, hello! + % + </programlisting> + + </section> + + <section> + <title>Ignoring dependencies</title> + + <para> + + Undesirable <literal>automatic dependencies</literal> or + <literal>implicit dependencies</literal> may be ignored: + + </para> + + <programlisting> + env.Program(target = 'bar', source = 'bar.c') + env.Ignore('bar', '/usr/bin/gcc', 'version.h') + </programlisting> + + <para> + + In the above example, the <filename>bar</filename> program will not + be rebuilt if the <filename>/usr/bin/gcc</filename> compiler or the + <filename>version.h</filename> file change. + + </para> + </section> + + <section> + <title>Explicit dependencies</title> + + <para> + + Dependencies that are unknown to &SCons; may be specified explicitly + in an &SCons; configuration file: + + </para> + + <programlisting> + env.Dependency(target = 'output1', dependency = 'input_1 input_2') + env.Dependency(target = 'output2', dependency = ['input_1', 'input_2']) + env.Dependency(target = 'output3', dependency = ['white space input']) + + env.Dependency(target = 'output_a output_b', dependency = 'input_3') + env.Dependency(target = ['output_c', 'output_d'], dependency = 'input_4') + env.Dependency(target = ['white space output'], dependency = 'input_5') + </programlisting> + + <para> + + Just like the <literal>target</literal> keyword argument, the + <literal>dependency</literal> keyword argument may be specified as a + string of white-space separated file names, or as an array. + + </para> + + <para> + + A dependency on an &SCons; configuration file itself may be specified + explicitly to force a rebuild whenever the configuration file changes: + + </para> + + <programlisting> + env.Dependency(target = 'archive.tar.gz', dependency = 'SConstruct') + </programlisting> + + </section> + +</section> + + + +<section id="sect-scanners"> + <title>&Scanner; Objects</title> + + <para> + + Analagous to the previously-described &Builder; objects, &SCons; + supplies (and uses) &Scanner; objects to search the contents of + a file for implicit dependency files: + + </para> + + <informaltable> + <tgroup cols="2"> + <tbody> + + <row> + <entry>CScan</entry> + <entry>scan .{c,C,cc,cxx,cpp} files for #include dependencies</entry> + </row> + + </tbody> + </tgroup> + </informaltable> + + <para> + + A &consenv; can be explicitly initialized with + associated &Scanner; objects: + + </para> + + <programlisting> + env = Environment(SCANNERS = ['CScan', 'M4Scan']) + </programlisting> + + <para> + + &Scanner; objects bound to a &consenv; can be + associated directly with specified files: + + </para> + + <programlisting> + env.CScan('foo.c', 'bar.c') + env.M4Scan('input.m4') + </programlisting> + + <section> + <title>User-defined &Scanner; objects</title> + + <para> + + A user may define a &Scanner; object to scan a type of file for + implicit dependencies: + + </para> + + <programlisting> + def scanner1(file_contents): + # search for dependencies + return dependency_list + + FirstScan = Scanner(function = scanner1) + </programlisting> + + <para> + + The scanner function must return a list of dependencies that its finds + based on analyzing the file contents it is passed as an argument. + + </para> + + <para> + + The scanner function, when invoked, will be passed the calling + environment. The scanner function can use &consenvs; from the passed + environment to affect how it performs its dependency scan--the + canonical example being to use some sort of search-path construction + variable to look for dependency files in other directories: + + </para> + + <programlisting> + def scanner2(file_contents, env): + path = env.{'SCANNERPATH'} # XXX + # search for dependencies using 'path' + return dependency_list + + SecondScan = Scanner(function = scanner2) + </programlisting> + + <para> + + The user may specify an additional argument when the &Scanner; object + is created. When the scanner is invoked, the additional argument + will be passed to the scanner funciton, which can be used in any way + the scanner function sees fit: + + </para> + + <programlisting> + def scanner3(file_contents, env, arg): + # skip 'arg' lines, then search for dependencies + return dependency_list + + Skip_3_Lines_Scan = Scanner(function = scanner2, argument = 3) + Skip_6_Lines_Scan = Scanner(function = scanner2, argument = 6) + </programlisting> + + </section> + + <section> + <title>Copying &Scanner; Objects</title> + + <para> + + A method exists to return a copy of an existing &Scanner; object, + with any overridden values specified as keyword arguments to the + method: + + </para> + + <programlisting> + scan = Scanner(function = my_scan) + scan_path = scan.Copy(path = '%SCANNERPATH') + </programlisting> + + <para> + + Typically, &Scanner; objects will be supplied by a tool-master or + administrator through a shared &consenv;. + + </para> + </section> + + <section> + <title>&Scanner; maps</title> + +<!-- +If the &BUILDERMAP; proves unnecessary, +we could/should get rid of this one, too, +by adding a parallel <literal>src_suffix</literal> +argument to the &Scanner; factory... +Comments? +--> + + <para> + + Each &consenv; has a &SCANNERMAP;, a dictionary that associates + different file suffixes with a scanner object that can be used to + generate a list of dependencies from the contents of that file. This + &SCANNERMAP; can be initialized at instantiation: + + </para> + + <programlisting> + env = Environment(SCANNERMAP = { + '.c' : CScan, + '.cc' : CScan, + '.m4' : M4Scan, + }) + </programlisting> + + <para> + + &Scanner; objects referenced in the &SCANNERMAP; do not need to + be listed separately in the &SCANNERS; variable. The &consenv; + will bind the union of the &Scanner; objects listed + in both variables. + + </para> + + </section> + +</section> + + + +<section id="sect-targets"> + <title>Targets</title> + + <para> + + The methods in the build engine API described so far merely + establish associations that describe file dependencies, how a + file should be scanned, etc. Since the real point is to actually + <emphasis>build</emphasis> files, &SCons; also has methods that + actually direct the build engine to build, or otherwise manipulate, + target files. + + </para> + + <section> + <title>Building targets</title> + <para> + + One or more targets may be built as follows: + + </para> + + <programlisting> + env.Build(target = ['foo', 'bar']) + </programlisting> + + <para> + + Note that specifying a directory (or other collective object) will + cause all subsidiary/dependent objects to be built as well: + + </para> + + <programlisting> + env.Build(target = '.') + + env.Build(target = 'builddir') + </programlisting> + + <para> + + By default, &SCons; explicitly removes a target file before + invoking the underlying function or command(s) to build it. + + </para> + </section> + + <section> + <title>Removing targets</title> + + <para> + + A "cleanup" operation of removing generated (target) files is + performed as follows: + + </para> + + <programlisting> + env.Clean(target = ['foo', 'bar']) + </programlisting> + + <para> + + Like the &Build; method, the &Clean; method may be passed a + directory or other collective object, in which case the subsidiary + target objects under the directory will be removed: + + </para> + + <programlisting> + env.Clean(target = '.') + + env.Clean(target = 'builddir') + </programlisting> + + <para> + + (The directories themselves are not removed.) + + </para> + </section> + + <section> + <title>Suppressing cleanup removal of build-targets</title> + + <para> + + By default, &SCons; explicitly removes all build-targets + when invoked to perform "cleanup". Files that should not be + removed during "cleanup" can be specified via the + &NoClean; method: + + </para> + + <programlisting> + env.Library(target = 'libfoo.a', source = ['aaa.c', 'bbb.c', 'ccc.c']) + env.NoClean('libfoo.a') + </programlisting> + + <para> + + The NoClean operation has precedence over the Clean operation. + A target that is specified as both Clean and NoClean, will not + be removed during a clean. + + In the following example, target 'foo' will not be removed + during "cleanup": + + <programlisting> + env.Clean(target = 'foo') + env.NoClean('foo') + </programlisting> + + + </para> + + </section> + + <section> + <title>Suppressing build-target removal</title> + + <para> + + As mentioned, by default, &SCons; explicitly removes a target + file before invoking the underlying function or command(s) to build + it. Files that should not be removed before rebuilding can be + specified via the &Precious; method: + + </para> + + <programlisting> + env.Library(target = 'libfoo.a', source = ['aaa.c', 'bbb.c', 'ccc.c']) + env.Precious('libfoo.a') + </programlisting> + + </section> + + <section> + <title>Default targets</title> + + <para> + + The user may specify default targets that will be built if there are no + targets supplied on the command line: + + </para> + + <programlisting> + env.Default('install', 'src') + </programlisting> + + <para> + + Multiple calls to the &Default; method (typically one per &SConscript; + file) append their arguments to the list of default targets. + + </para> + </section> + + <section> + <title>File installation</title> + + <para> + + Files may be installed in a destination directory: + + </para> + + <programlisting> + env.Install('/usr/bin', 'program1', 'program2') + </programlisting> + + <para> + + Files may be renamed on installation: + + </para> + + <programlisting> + env.InstallAs('/usr/bin/xyzzy', 'xyzzy.in') + </programlisting> + + <para> + + Multiple files may be renamed on installation by specifying + equal-length lists of target and source files: + + </para> + + <programlisting> + env.InstallAs(['/usr/bin/foo', '/usr/bin/bar'], + ['foo.in', 'bar.in']) + </programlisting> + + </section> + + <section> + <title>Target aliases</title> + + <para> + + In order to provide convenient "shortcut" target names that expand to + a specified list of targets, aliases may be established: + + </para> + + <programlisting> + env.Alias(alias = 'install', + targets = ['/sbin', '/usr/lib', '/usr/share/man']) + </programlisting> + + <para> + + In this example, specifying a target of <literal>install</literal> + will cause all the files in the associated directories to be built + (that is, installed). + + </para> + + <para> + + An &Alias; may include one or more other &Aliases; in its list: + + </para> + + <programlisting> + env.Alias(alias = 'libraries', targets = ['lib']) + env.Alias(alias = 'programs', targets = ['libraries', 'src']) + </programlisting> + + </section> + +</section> + + + +<section id="sect-custom"> + <title>Customizing output</title> + +<!-- +Take this whole section with a grain of salt. +I whipped it up without a great deal of thought +to try to add a "competitive advantage" +for the second round of the Software Carpentry contest. +In particular, hard-coding the +analysis points and the keywords that specify them +feels inflexible, +but I can't think of another way it would be +done effectively. +I dunno, maybe this is fine as it is... +--> + + <para> + + The &SCons; API supports the ability to customize, redirect, or + suppress its printed output through user-defined functions. + &SCons; has several pre-defined points in its build process at + which it calls a function to (potentially) print output. User-defined + functions can be specified for these call-back points when &Build; + or &Clean;is invoked: + + </para> + + <programlisting> + env.Build(target = '.', + on_analysis = dump_dependency, + pre_update = my_print_command, + post_update = my_error_handler) + on_error = my_error_handler) + </programlisting> + + <para> + + The specific call-back points are: + + </para> + + <variablelist> + + <varlistentry> + <term><literal>on_analysis</literal></term> + <listitem> + <para> + + Called for every object, immediately after the object has been + analyzed to see if it's out-of-date. Typically used to print a + trace of considered objects for debugging of unexpected dependencies. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>pre_update</literal></term> + <listitem> + <para> + + Called for every object that has been determined to be out-of-date + before its update function or command is executed. Typically used + to print the command being called to update a target. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>post_update</literal></term> + <listitem> + <para> + + Called for every object after its update function or command has + been executed. Typically used to report that a top-level specified + target is up-to-date or was not remade. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>on_error</literal></term> + <listitem> + <para> + + Called for every error returned by an update function or command. + Typically used to report errors with some string that will be + identifiable to build-analysis tools. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + Functions for each of these call-back points all take the same + arguments: + + </para> + + <programlisting> + my_dump_dependency(target, level, status, update, dependencies) + </programlisting> + + <para> + + where the arguments are: + + </para> + + <variablelist> + + <varlistentry> + <term><literal>target</literal></term> + <listitem> + <para> + + The target object being considered. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>level</literal></term> + <listitem> + <para> + + Specifies how many levels the dependency analysis has + recursed in order to consider the <literal>target</literal>. + A value of <literal>0</literal> specifies a top-level + <literal>target</literal> (that is, one passed to the + &Build; or &Clean; method). Objects which a top-level + <literal>target</literal> is directly dependent upon have a + <literal>level</literal> of <1>, their direct dependencies have a + <literal>level</literal> of <2>, etc. Typically used to indent + output to reflect the recursive levels. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>status</literal></term> + <listitem> + <para> + + A string specifying the current status of the target + (<literal>"unknown"</literal>, <literal>"built"</literal>, + <literal>"error"</literal>, <literal>"analyzed"</literal>, etc.). A + complete list will be enumerated and described during implementation. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>update</literal></term> + <listitem> + <para> + + The command line or function name that will be (or has been) executed + to update the <literal>target</literal>. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>dependencies</literal></term> + <listitem> + <para> + + A list of direct dependencies of the target. + + </para> + </listitem> + </varlistentry> + + </variablelist> + +</section> + + + +<section id="separate"> + <title>Separate source and build trees</title> + +<!-- +I've never liked Cons' use of the name <literal>Link</literal> +for this functionality, +mainly because the term is overloaded +with linking object files into an executable. +Yet I've never come up with anything better. +Any suggestions? +--> + +<!-- +Also, I made this an &Environment; method because +it logically belongs in the API reference +(the build engine needs to know about it), +and I thought it was clean to have +everything in the build-engine API +be called through an &Environment; object. +But <literal>&Link</literal> isn't really +associated with a specific environment +(the &Cons; classic implementation just +leaves it as a bare function call), +so maybe we should just follow that example +and not call it through an environment... +--> + + <para> + + &SCons; allows target files to be built completely separately from + the source files by "linking" a build directory to an underlying + source directory: + + </para> + + <programlisting> + env.Link('build', 'src') + + SConscript('build/SConscript') + </programlisting> + + <para> + + &SCons; will copy (or hard link) necessary files (including the + &SConscript; file) into the build directory hierarchy. This allows the + source directory to remain uncluttered by derived files. + + </para> + +</section> + + + +<section id="sect-variant"> + <title>Variant builds</title> + + <para> + + The &Link; method may be used in conjunction with multiple + &consenvs; to support variant builds. The following + &SConstruct; and &SConscript; files would build separate debug and + production versions of the same program side-by-side: + + </para> + + <programlisting> + % cat SConstruct + env = Environment() + env.Link('build/debug', 'src') + env.Link('build/production', 'src') + flags = '-g' + SConscript('build/debug/SConscript', Export(env)) + flags = '-O' + SConscript('build/production/SConscript', Export(env)) + % cat src/SConscript + env = Environment(CCFLAGS = flags) + env.Program('hello', 'hello.c') + </programlisting> + + <para> + + The following example would build the appropriate program for the current + compilation platform, without having to clean any directories of object + or executable files for other architectures: + + </para> + + <programlisting> + % cat SConstruct + build_platform = os.path.join('build', sys.platform) + Link(build_platform, 'src') + SConscript(os.path.join(build_platform, 'SConscript')) + % cat src/SConscript + env = Environment + env.Program('hello', 'hello.c') + </programlisting> + +</section> + + + +<section id="sect-repositories"> + <title>Code repositories</title> + +<!-- +Like &Link;, &Repository; and &Local; are part of the +API reference, but not really tied to any specific environment. +Is it better to be consistent about calling +everything in the API through an environment, +or to leave these independent so as +not to complicate their calling interface? +--> + + <para> + + &SCons; may use files from one or more shared code repositories in order + to build local copies of changed target files. A repository would + typically be a central directory tree, maintained by an integrator, + with known good libraries and executables. + + </para> + + <programlisting> + Repository('/home/source/1.1', '/home/source/1.0') + </programlisting> + + <para> + + Specified repositories will be searched in-order for any file + (configuration file, input file, target file) that does not exist + in the local directory tree. When building a local target file, + &SCons; will rewrite path names in the build command to use the + necessary repository files. This includes modifying lists of + <option>-I</option> or <option>-L</option> flags to specify an + appropriate set of include paths for dependency analysis. + + </para> + <para> + + &SCons; will modify the Python <varname>sys.path</varname> variable to + reflect the addition of repositories to the search path, so that any + imported modules or packages necessary for the build can be found in a + repository, as well. + + </para> + <para> + + If an up-to-date target file is found in a code repository, the file + will not be rebuilt or copied locally. Files that must exist locally + (for example, to run tests) may be specified: + + </para> + + <programlisting> + Local('program', 'libfoo.a') + </programlisting> + + <para> + + in which case &SCons; will copy or link an up-to-date copy of the + file from the appropriate repository. + + </para> + +</section> + + + +<section id="sect-caching"> + <title>Derived-file caching</title> + +<!-- +There should be extensions to this part of the API for +auxiliary functions like cleaning the cache. +--> + + <para> + + &SCons; can maintain a cache directory of target files which may be + shared among multiple builds. This reduces build times by allowing + developers working on a project together to share common target + files: + + </para> + + <programlisting> + Cache('/var/tmp/build.cache/i386') + </programlisting> + + <para> + + When a target file is generated, a copy is added to the cache. + When generating a target file, if &SCons; determines that a file + that has been built with the exact same dependencies already exists + in the specified cache, &SCons; will copy the cached file rather + than re-building the target. + + </para> + <para> + + Command-line options exist to modify the &SCons; caching behavior + for a specific build, including disabling caching, building + dependencies in random order, and displaying commands as if cached + files were built. + + </para> + +</section> + + + +<section id="sect-jobs"> + <title>Job management</title> + +<!-- +This has been completely superseded by +the more sophisticated &Task; manager +that Anthony Roach has contributed. +I need to write that up... +--> + + <para> + + A simple API exists to inform the Build Engine how many jobs may + be run simultaneously: + + </para> + + <programlisting> + Jobs(limit = 4) + </programlisting> + +</section> diff --git a/doc/design/goals.xml b/doc/design/goals.xml new file mode 100644 index 0000000..2a7b69b --- /dev/null +++ b/doc/design/goals.xml @@ -0,0 +1,216 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + As a next-generation build tool, + &SCons should fundamentally + improve on its predecessors. + Rather than simply being driven by trying to + <emphasis>not</emphasis> be like previous tools, + &SCons; aims to satisfy the following goals: + + </para> + + <variablelist> + + <varlistentry> + <term><literal>Practicality</literal></term> + <listitem> + <para> + + The &SCons; design emphasizes + an implementable feature set + that lets users get practical, useful work done. + &SCons; is helped in this regard by its roots in &Cons;, + which has had its feature set honed by + several years of input + from a dedicated band of users. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Portability</literal></term> + <listitem> + <para> + + &SCons; is intended as a portable build tool, + able to handle software construction tasks + on a variety of operating systems. + It should be possible (although not mandatory) + to use &SCons; so that the same configuration file + builds the same software correctly on, + for example, both Linux and Windows NT. + Consequently, &SCons; should hide from users + operating-system-dependent details + such as filename extensions + (for example, <filename>.o</filename> + vs. <filename>.obj</filename>). + + <!-- + XXX: enable writing portable builds without forcing it + --> + + <!-- + XXX: still write non-portably for quick-and-dirty + --> + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Usability</literal></term> + <listitem> + <para> + + Novice users should be able to grasp quickly + the rudiments of using &SCons; to build their software. + This extends to installing &SCons;, too. + Installation should be painless, + and the installed &SCons; + should work "out of the box" + to build most software. + + </para> + + <para> + + This goal should be kept in mind during implementation, + when there is always a tendency to try to optimize too early. + Speed is nice, but not as important as clarity + and ease of use. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Utility</literal></term> + <listitem> + <para> + + &SCons; should also provide a rich enough set of features + to accommodate building more complicated software projects. + However, the features required for + building complicated software projects + should not get in the way of novice users. + (See the previous goal.) + In other words, complexity should be available + when it's needed + but not required to get work done. + Practically, this implies that &SCons; + shouldn't be dumbed down to the point it + excludes complicated software builds. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Sharability</literal></term> + <listitem> + <para> + + As a key element in balancing the conflicting + needs of <literal>Usability</literal> and <literal>Utility</literal>, + &SCons; should provide mechanisms to + allow &SCons; users to share build rules, + dependency scanners, and other objects and recipes + for constructing software. + A good sharing mechanism should support + the model wherein most developers on a project + use rules and templates + that are created + and maintained by a local integrator or build-master, + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Extensibility</literal></term> + <listitem> + <para> + + &SCons; should provide mechanisms for + easily extending its capabilities, + including building new types of files, + adding new types of dependency scanning, + being able to accomodate dependencies + between objects other than files, + etc. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Flexibility</literal></term> + <listitem> + <para> + + In addition to providing a useful command-line interface, + &SCons; should provide the right architectural + framework for embedding its dependency management + in other interfaces. + &SCons; would help strengthen other GUIs or IDEs + and the additional requirements of the + other interfaces would help broaden and solidify + the core &SCons; dependency management. + + </para> + </listitem> + </varlistentry> + + </variablelist> + +<section id="sect-fix-make"> + <title>Fixing &Make;'s problems</title> + + <para> + +<!-- +To be written. +--> + + </para> + +</section> + +<section id="sect-fix-cons"> + <title>Fixing &Cons;'s problems</title> + + <para> + +<!-- +To be written. +--> + + </para> + +</section> diff --git a/doc/design/install.xml b/doc/design/install.xml new file mode 100644 index 0000000..e670e83 --- /dev/null +++ b/doc/design/install.xml @@ -0,0 +1,28 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- +THIS CHAPTER NEEDS TO BE DISCUSSED AND WRITTEN. +--> diff --git a/doc/design/intro.xml b/doc/design/intro.xml new file mode 100644 index 0000000..561baa4 --- /dev/null +++ b/doc/design/intro.xml @@ -0,0 +1,111 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + The &SCons; tool provides an easy-to-use, feature-rich interface + for constructing software. Architecturally, &SCons; separates + its dependency analysis and external object management into an + interface-independent Build Engine that could be embedded in any + software system that can run Python. + + </para> + + <para> + + At the command line, &SCons; presents an easily-grasped tool + where configuration files are Python scripts, reducing the need + to learn new build-tool syntax. Inexperienced users can use + intelligent methods that ``do the right thing'' to build software + with a minimum of fuss. Sophisticated users can use a rich set + of underlying features for finer control of the build process, + including mechanisms for easily extending the build process to new + file types. + + </para> + + <para> + + Dependencies are tracked using digital signatures, + which provide more robust dependency analysis than file time + stamps. Implicit dependencies are determined automatically by + scanning the contents of source files, avoiding the need for + laborious and fragile maintenance of static lists of dependencies in + configuration files. + + </para> + + <para> + + The &SCons; tool supports use of files from one or more central code + repositories, a mechanism for caching derived files, and parallel + builds. The tool also includes a framework for sharing build + environments, which allows system administrators or integrators to + define appropriate build parameters for use by other users. + + </para> + +<section id="sect-document"> + <title>About This Document</title> + + <para> + + This document is an ongoing work-in-progress to write down the ideas + and tradeoffs that have gone, and will go into, the &SCons; design. + As such, this is intended primarily for use by developers and others + working on &SCons;, although it is also intended to serve as a + detailed overview of &SCons; for other interested parties. It will + be continually updated and evolve, and will likely overlap with other + documentation produced by the project. Sections of this document + that deal with syntax, for example, may move or be copied into a user + guide or reference manual. + + </para> + + <para> + + So please don't assume that everything mentioned here has been + decided and carved in stone. If you have ideas for improvements, or + questions about things that don't seem to make any sense, please help + improve the design by speaking up about them. + + </para> + +<!-- +Sections marked like this +(prefixed with <literal>RATIONALE:</literal> in the HTML, +surrounded by <literal>BEGIN RATIONALE:</literal> +and <literal>END RATIONALE:</literal> +in the printed documentatio) +are DocBook REMARKs, +comments about the document +rather than actual document. +I've used these to mark sections that need work, +but also to cite some open design issues. +If you have input on any of these marked issues, +I'm especially eager to hear it. +--> + +</section> diff --git a/doc/design/issues.xml b/doc/design/issues.xml new file mode 100644 index 0000000..1f9a78c --- /dev/null +++ b/doc/design/issues.xml @@ -0,0 +1,195 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + <para> + + No build tools is perfect. + Here are some &SCons; issues that + do not yet have solutions. + + </para> + + <section> + <title>Interaction with SC-config</title> + + <para> + + The SC-config tool will be used in the &SCons; installation + process to generate an appropriate default construction environment + so that building most software works "out of the box" on the + installed platform. The SC-config tool will find reasonable default + compilers (C, C++, Fortran), linkers/loaders, library archive tools, + etc. for specification in the default &SCons; construction + environment. + + </para> + + </section> + + <section> + <title>Interaction with test infrastructures</title> + + <para> + + &SCons; can be configured to use SC-test (or some other test tool) + to provide controlled, automated testing of software. The &Link; + method could link a <filename>test</filename> subdirectory to a build + subdirectory: + + </para> + + <programlisting> + Link('test', 'build') + SConscript('test/SConscript')</programlisting> + + <para> + + Any test cases checked in with the source code will be linked + into the <filename>test</filename> subdirectory and executed. If + &SConscript; files and test cases are written with this in mind, then + invoking: + + </para> + + <programlisting> + % sccons test</programlisting> + + <para> + + Would run all the automated test cases that depend on any changed + software. + + </para> + + + <!-- + + YYY integrate with SC-test to provide sanity check on new tools + "discovery testing" of new tools + results recorded in a central database + central database can be somewhere else on web + + --> + + </section> + + <section> + <title>Java dependencies</title> + + <para> + + Java dependencies are difficult for an external dependency-based + construction tool to accomodate. Determining Java class dependencies + is more complicated than the simple pattern-matching of C or C++ + <literal>#include</literal> files. From the point of view of an + external build tool, the Java compiler behaves "unpredictably" + because it may create or update multiple output class files and + directories as a result of its internal class dependencies. + + </para> + + <para> + + An obvious &SCons; implementation would be to have the &Scanner; + object parse output from <command>Java -depend -verbose</command> to + calculate dependencies, but this has the distinct disadvantage of + requiring two separate compiler invocations, thereby slowing down + builds. + + </para> + + </section> + + <section> + <title>Limitations of digital signature calculation</title> + + <para> + + In practice, calculating digital signatures of a file's contents is a + more robust mechanism than time stamps for determining what needs + building. However: + + </para> + + <orderedlist numeration="arabic"> + + <listitem> + <para> + + Developers used to the time stamp model of &Make; can initially + find digital signatures counter-intuitive. The assumption that: + + <programlisting> + % touch file.c</programlisting> + + will cause a rebuild of <filename>file</filename> is strong... + + </para> + </listitem> + + <listitem> + <para> + + Abstracting dependency calculation into a single digital signature + loses a little information: It is no longer possible to tell + (without laborious additional calculation) which input file dependency + caused a rebuild of a given target file. A feature that could + report, "I'm rebuilding file X because it's out-of-date with respect + to file Y," would be good, but an digital-signature implementation of + such a feature is non-obvious. + + </para> + </listitem> + + </orderedlist> + + </section> + + <section> + <title>Remote execution</title> + + <para> + + The ability to use multiple build systems through remote execution + of tools would be good. This should be implementable through the + &Job; class. Construction environments would need modification + to specify build systems. + + </para> + + </section> + + <section> + <title>Conditional builds</title> + + <para> + + The ability to check run-time conditions as suggested on the + sc-discuss mailing list ("build X only if: the machine is idle / + the file system has Y megabytes free space") would also be good, + but is not part of the current design. + + </para> + + </section> diff --git a/doc/design/main.xml b/doc/design/main.xml new file mode 100644 index 0000000..e991b36 --- /dev/null +++ b/doc/design/main.xml @@ -0,0 +1,158 @@ +<?xml version="1.0"?> + +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ + + <!-- + We haven't updated the design document in ages. + Rather than fool people into thinking that it's + actually up-to-date and reflects the current design, + hard-code the version from back when we last updated it. + <!ENTITY % version SYSTEM "../version.xml"> + %version; + --> + <!ENTITY builddate "2001/12/13 20:55:46"> + <!ENTITY buildversion "0.91"> + <!ENTITY buildrevision "0.01.D177"> + + <!-- + Also freeze the scons.mod DTD extensions + to what they were way back when. + <!ENTITY % scons SYSTEM "../scons.mod"> + --> + <!ENTITY % scons SYSTEM "scons.mod"> + %scons; + + <!ENTITY acks SYSTEM "acks.xml"> + <!ENTITY bground SYSTEM "bground.xml"> + <!ENTITY copyright SYSTEM "copyright.xml"> + <!ENTITY engine SYSTEM "engine.xml"> + <!ENTITY goals SYSTEM "goals.xml"> + <!ENTITY install SYSTEM "install.xml"> + <!ENTITY intro SYSTEM "intro.xml"> + <!ENTITY issues SYSTEM "issues.xml"> + <!ENTITY native SYSTEM "native.xml"> + <!ENTITY overview SYSTEM "overview.xml"> + +]> + +<book> + <bookinfo> + <title>SCons Design version &buildversion;</title> + + <author> + <firstname>Steven</firstname> + <surname>Knight</surname> + </author> + + <edition>Revision &buildrevision; (&builddate;)</edition> + + <pubdate>2001</pubdate> + + <copyright> + <year>2001</year> + <holder>Steven Knight</holder> + </copyright> + + <legalnotice> + ©right; + </legalnotice> + + <releaseinfo>version &buildversion;</releaseinfo> + + </bookinfo> + + <chapter id="chap-intro"> + <title>Introduction</title> + &intro; + </chapter> + + <chapter id="chap-goals"> + <title>Goals</title> + &goals; + </chapter> + + <chapter id="chap-overview"> + <title>Overview</title> + &overview; + </chapter> + + <chapter id="chap-engine"> + <title>Build Engine API</title> + &engine; + </chapter> + + <chapter id="chap-native"> + <title>Native Python Interface</title> + &native; + </chapter> + + <!-- + + <chapter id="chap-install"> + <title>Installation</title> + &install; + </chapter> + + --> + + <chapter id="chap-issues"> + <title>Other Issues</title> + &issues; + </chapter> + + <chapter id="chap-background"> + <title>Background</title> + &bground; + </chapter> + + <chapter id="chap-summary"> + <title>Summary</title> + <para> + + &SCons; offers a robust and feature-rich design for an SC-build + tool. With a Build Engine based on the proven design of + the &Cons; utility, it offers increased simplification of the + user interface for unsophisticated users with the addition + of the "do-the-right-thing" <function>env.Make</function> + method, increased flexibility for sophisticated users with the + addition of &Builder; and &Scanner; objects, a mechanism to + allow tool-masters (and users) to share working construction + environments, and embeddability to provide reliable dependency + management in a variety of environments and interfaces. + + </para> + </chapter> + + <chapter id="chap-acks"> + <title>Acknowledgements</title> + &acks; + </chapter> + +</book> diff --git a/doc/design/native.xml b/doc/design/native.xml new file mode 100644 index 0000000..8cdd867 --- /dev/null +++ b/doc/design/native.xml @@ -0,0 +1,364 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<para> + + The "Native Python" interface is the interface + that the actual &SCons; utility will present to users. + Because it exposes the Python Build Engine API, + &SCons; users will have direct access to the complete + functionality of the Build Engine. + In contrast, a different user interface such as a GUI + may choose to only use, and present to the end-user, + a subset of the Build Engine functionality. + +</para> + +<section id="sect-config"> + <title>Configuration files</title> + + <para> + + &SCons; configuration files are simply Python scripts that invoke + methods to specify target files to be built, rules for building the + target files, and dependencies. Common build rules are available by + default and need not be explicitly specified in the configuration + files. + + </para> + + <para> + + By default, the &SCons; utility searches for a file named + &SConstruct;, &Sconstruct; or &sconstruct (in that order) in the + current directory, and reads its configuration from the first file + found. A <option>-f</option> command-line option exists to read a + different file name. + + </para> + +</section> + + + +<section id="sect-syntax"> + <title>Python syntax</title> + + <para> + + Because &SCons; configuration files are Python scripts, normal Python + syntax can be used to generate or manipulate lists of targets or + dependencies: + + </para> + + <programlisting> + sources = ['aaa.c', 'bbb.c', 'ccc.c'] + env.Make('bar', sources) + </programlisting> + + <para> + + Python flow-control can be used to iterate through invocations of + build rules: + + </para> + + <programlisting> + objects = ['aaa.o', 'bbb.o', 'ccc.o'] + for obj in objects: + src = replace(obj, '.o', '.c') + env.Make(obj, src) + </programlisting> + + <para> + + or to handle more complicated conditional invocations: + + </para> + + <programlisting> + # only build 'foo' on Linux systems + if sys.platform == 'linux1': + env.Make('foo', 'foo.c') + </programlisting> + + <para> + + Because &SCons; configuration files are Python scripts, syntax errors + will be caught by the Python parser. Target-building does not begin + until after all configuration files are read, so a syntax error will + not cause a build to fail half-way. + + </para> + +</section> + + + +<section id="sect-subsidiary"> + <title>Subsidiary configuration Files</title> + + <para> + + A configuration file can instruct &SCons; to read up subsidiary + configuration files. Subsidiary files are specified explicitly in a + configuration file via the &SConscript; method. As usual, multiple + file names may be specified with white space separation, or in an + array: + + </para> + + <programlisting> + SConscript('other_file') + SConscript('file1 file2') + SConscript(['file3', 'file4']) + SConscript(['file name with white space']) + </programlisting> + + <para> + + An explicit <literal>sconscript</literal> keyword may be used: + + </para> + + <programlisting> + SConscript(sconscript = 'other_file') + </programlisting> + + <para> + + Including subsidiary configuration files is recursive: a configuration + file included via &SConscript; may in turn &SConscript; other + configuration files. + + </para> + +</section> + + + +<section id="sect-scoping"> + <title>Variable scoping in subsidiary files</title> + + <para> + + When a subsidiary configuration file is read, it is given its own + namespace; it does not have automatic access to variables from the parent + configuration file. + + </para> + + <para> + + Any variables (not just &SCons; objects) that are to be shared between configuration files must be + explicitly passed in the &SConscript; call + using the &Export method: + + </para> + + <programlisting> + env = Environment() + debug = Environment(CCFLAGS = '-g') + installdir = '/usr/bin' + SConscript('src/SConscript', Export(env=env, debug=debug, installdir=installdir)) + </programlisting> + +<!-- +The <literal>env=env</literal> stuff bugs me +because it imposes extra work on the normal +case where you <emphasis>don't</emphasis> rename +the variables. +Can we simplify the &Export; method +so that a string +without a keyword assignment +is split into variables that are passed +through transparently? +Equivalent to the above example: +<literal>SConscript('src/SConscript', Export('env debug installdir'))</literal> +--> + + <para> + + Which may be specified explicitly using a keyword argument: + + </para> + + <programlisting> + env = Environment() + debug = Environment(CCFLAGS = '-g') + installdir = '/usr/bin' + SConscript(sconscript = 'src/SConscript', + export = Export(env=env, debug=debug, installdir=installdir)) + </programlisting> + + <para> + + Explicit variable-passing provides control over exactly what is available + to a subsidiary file, and avoids unintended side effects of changes in + one configuration file affecting other far-removed configuration files + (a very hard-to-debug class of build problem). + + </para> + +</section> + + + +<section id="sect-hierarchy"> + <title>Hierarchical builds</title> + + <para> + + The &SConscript; method is so named because, by convention, subsidiary + configuration files in subdirectories are named &SConscript;: + + </para> + + <programlisting> + SConscript('src/SConscript') + SConscript('lib/build_me') + </programlisting> + + <para> + + When a subsidiary configuration file is read from a subdirectory, all + of that configuration file's targets and build rules are interpreted + relative to that directory (as if &SCons; had changed its working + directory to that subdirectory). This allows for easy support of + hierarchical builds of directory trees for large projects. + + </para> + +</section> + + + +<section id="sect-sharing"> + <title>Sharing &consenvs;</title> + + <para> + + &SCons; will allow users to share &consenvs, as well as other &SCons; + objects and Python variables, by importing them from a central, shared + repository using normal Python syntax: + + </para> + + <programlisting> + from LocalEnvironments import optimized, debug + + optimized.Make('foo', 'foo.c') + debug.Make('foo-d', 'foo.c') + </programlisting> + + <para> + + The expectation is that some local tool-master, integrator or + administrator will be responsible for assembling environments (creating + the &Builder; objects that specify the tools, options, etc.) and make + these available for sharing by all users. + + </para> + + <para> + + The modules containing shared &consenvs; + (<literal>LocalEnvironments</literal> in the above example) can be + checked in and controlled with the rest of the source files. This + allows a project to track the combinations of tools and command-line + options that work on different platforms, at different times, and with + different tool versions, by using already-familiar revision control + tools. + + </para> + +</section> + + + +<section id="sect-help"> + <title>Help</title> + + <para> + + The &SCons; utility provides a &Help; function to allow the writer + of a &SConstruct; file to provide help text that is specific to + the local build tree: + + </para> + + <programlisting> + Help(""" + Type: + scons . build and test everything + scons test build the software + scons src run the tests + scons web build the web pages + """) + </programlisting> + + <para> + + This help text is displayed in response to the <option>-h</option> + command-line option. Calling the &Help; function more than once is an + error. + + </para> + +</section> + + + +<section id="sect-debug"> + <title>Debug</title> + + <para> + + &SCons; supports several command-line options for printing extra + information with which to debug build problems. + + </para> + +<!-- +These need to be specified and explained +beyond what the man page will have. +--> + + <!-- BEGIN HTML --> + + <para> + + See the -d, -p, -pa, and -pw options + in the <!--<A HREF="#sccons_Man_page">man page</A>-->, below. + All of these options make use of call-back functions to + <!--<A HREF="reference.html#Customizing_output">control the output</A>--> + printed by the Build Engine. + + </para> + + <!-- END HTML --> + +</section> diff --git a/doc/design/overview.xml b/doc/design/overview.xml new file mode 100644 index 0000000..38e4258 --- /dev/null +++ b/doc/design/overview.xml @@ -0,0 +1,498 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<section id="sect-architecture"> + <title>Architecture</title> + + <para> + + The heart of &SCons; is its <emphasis>Build Engine</emphasis>. + The &SCons; Build Engine is a Python module + that manages dependencies between + external objects + such as files or database records. + The Build Engine is designed to + be interface-neutral + and easily embeddable in any + software system that needs dependency + analysis between updatable objects. + + </para> + + <para> + + The key parts of the Build Engine architecture + are captured in the following quasi-UML diagram: + + </para> + +<!-- +Including this figure makes our PDF build blow up. +The figure, however, +is left over from the Software Carpentry contest +and is therefore old, out-of-date, and needs to be redone anyway. +This is where it will go, anyway... +--> + + <!-- + YARG! THIS MAKES THE PDF BUILD BLOW UP. HELP! + <figure> + <title>&SCons; Architecture</title> + <graphic fileref="engine.jpg"> + </figure> + --> + + <para> + + The point of &SCons; is to manage + dependencies between arbitrary external objects. + Consequently, the Build Engine does not restrict or specify + the nature of the external objects it manages, + but instead relies on subclass of the &Node; + class to interact with the external system or systems + (file systems, database management systems) + that maintain the objects being examined or updated. + + </para> + + <para> + + The Build Engine presents to the software system in + which it is embedded + a Python API for specifying source (input) and target (output) objects, + rules for building/updating objects, + rules for scanning objects for dependencies, etc. + Above its Python API, + the Build Engine is completely + interface-independent, + and can be encapsulated by any other software + that supports embedded Python. + + </para> + + <para> + + Software that chooses to use the Build Engine + for dependency management + interacts with it + through <emphasis>Construction Environments</emphasis>. + A Construction Environment consists + of a dictionary of environment variables, + and one or more associated + &Scanner; objects + and &Builder; objects. + The Python API is used to + form these associations. + + </para> + + <para> + + A &Scanner; object specifies + how to examine a type of source object + (C source file, database record) + for dependency information. + A &Scanner; object may use + variables from the associated + Construction Environment + to modify how it scans an object: + specifying a search path for included files, + which field in a database record to consult, + etc. + + </para> + + <para> + + A &Builder; object specifies + how to update a type of target object: + executable program, object file, database field, etc. + Like a &Scanner; object, + a &Builder; object may use + variables from the associated + Construction Environment + to modify how it builds an object: + specifying flags to a compiler, + using a different update function, + etc. + + </para> + + <para> + + &Scanner; and &Builder; objects will return one or more + &Node; objects that represent external objects. + &Node; objects are the means by which the + Build Engine tracks dependencies: + A &Node; may represent a source (input) object that + should already exist, + or a target (output) object which may be built, + or both. + The &Node; class is sub-classed to + represent external objects of specific type: + files, directories, database fields or records, etc. + Because dependency information, however, + is tracked by the top-level &Node; methods and attributes, + dependencies can exist + between nodes representing different external object types. + For example, + building a file could be made + dependent on the value of a given + field in a database record, + or a database table could depend + on the contents of an external file. + + </para> + + <para> + + The Build Engine uses a &Job; class (not displayed) + to manage the actual work of updating external target objects: + spawning commands to build files, + submitting the necessary commands to update a database record, + etc. + The &Job; class has sub-classes + to handle differences between spawning + jobs in parallel and serially. + + </para> + + <para> + + The Build Engine also uses a + &Signature; class (not displayed) + to maintain information about whether + an external object is up-to-date. + Target objects with out-of-date signatures + are updated using the appropriate + &Builder; object. + + </para> + + <!-- BEGIN HTML --> + + <!-- + Details on the composition, methods, + and attributes of these classes + are available in the A HREF="internals.html" Internals /A page. + --> + + <!-- END HTML --> + +</section> + + + +<section id="sect-engine"> + <title>Build Engine</title> + + <para> + + More detailed discussion of some of the + Build Engine's characteristics: + + </para> + + <section> + <title>Python API</title> + + <para> + + The Build Engine can be embedded in any other software + that supports embedding Python: + in a GUI, + in a wrapper script that + interprets classic <filename>Makefile</filename> syntax, + or in any other software that + can translate its dependency representation + into the appropriate calls to the Build Engine API. + <!--<xref linkend="chap-native">--> describes in detail + the specification for a "Native Python" interface + that will drive the &SCons; implementation effort. + + </para> + + </section> + + <section> + <title>Single-image execution</title> + + <para> + + When building/updating the objects, + the Build Engine operates as a single executable + with a complete Directed Acyclic Graph (DAG) + of the dependencies in the entire build tree. + This is in stark contrast to the + commonplace recursive use of Make + to handle hierarchical directory-tree builds. + + </para> + + </section> + + <section> + <title>Dependency analysis</title> + + <para> + + Dependency analysis is carried out via digital signatures + (a.k.a. "fingerprints"). + Contents of object are examined and reduced + to a number that can be stored and compared to + see if the object has changed. + Additionally, &SCons; uses the same + signature technique on the command-lines that + are executed to update an object. + If the command-line has changed since the last time, + then the object must be rebuilt. + + </para> + + </section> + + <section> + <title>Customized output</title> + + <para> + + The output of Build Engine is customizable + through user-defined functions. + This could be used to print additional desired + information about what &SCons; is doing, + or tailor output to a specific build analyzer, + GUI, or IDE. + + </para> + + </section> + + <section> + <title>Build failures</title> + + <para> + + &SCons; detects build failures via the exit status from the tools + used to build the target files. By default, a failed exit status + (non-zero on UNIX systems) terminates the build with an appropriate + error message. An appropriate class from the Python library will + interpret build-tool failures via an OS-independent API. + + </para> + + <para> + + If multiple tasks are executing in a parallel build, and one tool + returns failure, &SCons; will not initiate any further build tasks, + but allow the other build tasks to complete before terminating. + + </para> + + <para> + + A <option>-k</option> command-line option may be used to ignore + errors and continue building other targets. In no case will a target + that depends on a failed build be rebuilt. + + </para> + + </section> + +</section> + + + +<section id="sect-interfaces"> + <title>Interfaces</title> + + <para> + + As previously described, + the &SCons; Build Engine + is interface-independent above its Python API, + and can be embedded in any software system + that can translate its dependency requirements + into the necessary Python calls. + + </para> + + <para> + + The "main" &SCons; interface + for implementation purposes, + uses Python scripts as configuration files. + Because this exposes the Build Engine's Python API to the user, + it is current called the "Native Python" interface. + + </para> + + <para> + + This section will also discuss + how &SCons; will function in the context + of two other interfaces: + the &Makefile; interface of the classic &Make; utility, + and a hypothetical graphical user interface (GUI). + + </para> + + <section> + <title>Native Python interface</title> + + <para> + + The Native Python interface is intended to be the primary interface + by which users will know &SCons;--that is, + it is the interface they will use + if they actually type &SCons; at a command-line prompt. + + </para> + + <para> + + In the Native Python interface, &SCons; configuration files are simply + Python scripts that directly invoke methods from the Build Engine's + Python API to specify target files to be built, rules for building + the target files, and dependencies. Additional methods, specific to + this interface, are added to handle functionality that is specific to + the Native Python interface: reading a subsidiary configuration file; + copying target files to an installation directory; etc. + + </para> + + <para> + + Because configuration files are Python scripts, Python flow control + can be used to provide very flexible manipulation of objects and + dependencies. For example, a function could be used to invoke a common + set of methods on a file, and called iteratively over an array of + files. + + </para> + + <para> + + As an additional advantage, syntax errors in &SCons; Native Python + configuration files will be caught by the Python parser. Target-building + does not begin until after all configuration files are read, so a syntax + error will not cause a build to fail half-way. + + </para> + + </section> + + <section> + <title>Makefile interface</title> + + <para> + + An alternate &SCons; interface would provide backwards + compatibility with the classic &Make utility. + This would be done by embedding the &SCons; Build Engine + in a Python script that can translate existing + &Makefile;s into the underlying calls to the + Build Engine's Python API + for building and tracking dependencies. + Here are approaches to solving some of the issues + that arise from marrying these two pieces: + + </para> + + <itemizedlist> + + <listitem> + <para> + &Makefile; suffix rules can be translated + into an appropriate &Builder; object + with suffix maps from the Construction Environment. + </para> + </listitem> + + <listitem> + <para> + Long lists of static dependences + appended to a &Makefile; by + various <command>"make depend"</command> schemes + can be preserved + but supplemented by + the more accurate dependency information + provided by &Scanner; objects. + </para> + </listitem> + + <listitem> + <para> + Recursive invocations of &Make; + can be avoided by reading up + the subsidiary &Makefile; instead. + </para> + </listitem> + + </itemizedlist> + + <para> + + Lest this seem like too outlandish an undertaking, + there is a working example of this approach: + Gary Holt's &Makepp; utility + is a Perl script that provides + admirably complete parsing of complicated &Makefile;s + around an internal build engine inspired, + in part, by the classic <application>Cons</application> utility. + + </para> + + </section> + + <section> + <title>Graphical interfaces</title> + + <para> + + The &SCons; Build Engine + is designed from the ground up to be embedded + into multiple interfaces. + Consequently, embedding the dependency capabilities + of &SCons; into graphical interface + would be a matter of mapping the + GUI's dependency representation + (either implicit or explicit) + into corresponding calls to the Python API + of the &SCons; Build Engine. + + </para> + + <para> + + Note, however, that this proposal leaves the problem of + designed a good graphical interface + for representing software build dependencies + to people with actual GUI design experience... + + </para> + + </section> + +</section> diff --git a/doc/design/scons.mod b/doc/design/scons.mod new file mode 100644 index 0000000..d805210 --- /dev/null +++ b/doc/design/scons.mod @@ -0,0 +1,429 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + An SCons-specific DTD module, for use with SCons DocBook + documentation, that contains names, phrases, acronyms, etc. used + throughout the SCons documentation. + +--> + + + +<!-- + + Other applications that we reference. + +--> + +<!ENTITY Aegis "<application>Aegis</application>"> +<!ENTITY Ant "<application>Ant</application>"> +<!ENTITY Autoconf "<application>Autoconf</application>"> +<!ENTITY Automake "<application>Automake</application>"> +<!ENTITY cc "<application>cc</application>"> +<!ENTITY Cons "<application>Cons</application>"> +<!ENTITY cp "<application>cp</application>"> +<!ENTITY csh "<application>csh</application>"> +<!ENTITY gcc "<application>gcc</application>"> +<!ENTITY Jam "<application>Jam</application>"> +<!ENTITY jar "<application>jar</application>"> +<!ENTITY javac "<application>javac</application>"> +<!ENTITY javah "<application>javah</application>"> +<!ENTITY Make "<application>Make</application>"> +<!ENTITY Makepp "<application>Make++</application>"> +<!ENTITY Python "<application>Python</application>"> +<!ENTITY ranlib "<application>ranlib</application>"> +<!ENTITY rmic "<application>rmic</application>"> +<!ENTITY SCons "<application>SCons</application>"> +<!ENTITY scons "<application>scons</application>"> +<!ENTITY ScCons "<application>ScCons</application>"> +<!ENTITY tar "<application>tar</application>"> +<!ENTITY touch "<application>touch</application>"> +<!ENTITY zip "<application>zip</application>"> + + +<!-- + + Classes. + +--> + +<!ENTITY Action "<classname>Action</classname>"> +<!ENTITY ActionBase "<classname>ActionBase</classname>"> +<!ENTITY CommandAction "<classname>CommandAction</classname>"> +<!ENTITY FunctionAction "<classname>FunctionAction</classname>"> +<!ENTITY ListAction "<classname>ListAction</classname>"> +<!ENTITY Builder "<classname>Builder</classname>"> +<!ENTITY BuilderBase "<classname>BuilderBase</classname>"> +<!ENTITY CompositeBuilder "<classname>CompositeBuilder</classname>"> +<!ENTITY MultiStepBuilder "<classname>MultiStepBuilder</classname>"> +<!ENTITY Job "<classname>Job</classname>"> +<!ENTITY Jobs "<classname>Jobs</classname>"> +<!ENTITY Serial "<classname>Serial</classname>"> +<!ENTITY Parallel "<classname>Parallel</classname>"> +<!ENTITY Node "<classname>Node</classname>"> +<!ENTITY Node_FS "<classname>Node.FS</classname>"> +<!ENTITY Scanner "<classname>Scanner</classname>"> +<!ENTITY Sig "<classname>Sig</classname>"> +<!ENTITY Signature "<classname>Signature</classname>"> +<!ENTITY Taskmaster "<classname>Taskmaster</classname>"> +<!ENTITY TimeStamp "<classname>TimeStamp</classname>"> +<!ENTITY Walker "<classname>Walker</classname>"> +<!ENTITY Wrapper "<classname>Wrapper</classname>"> + + + +<!-- + + Options, command-line. + +--> + +<!ENTITY debug-explain "<literal>--debug=explain</literal>"> +<!ENTITY implicit-cache "<literal>--implicit-cache</literal>"> +<!ENTITY implicit-deps-changed "<literal>--implicit-deps-changed</literal>"> +<!ENTITY implicit-deps-unchanged "<literal>--implicit-deps-unchanged</literal>"> +<!ENTITY Q "<literal>-Q</literal>"> + +<!-- + + Options, SConscript-settable. + +--> + +<!ENTITY implicit_cache "<literal>implicit_cache</literal>"> +<!ENTITY implicit_deps_changed "<literal>implicit_deps_changed</literal>"> +<!ENTITY implicit_deps_unchanged "<literal>implicit_deps_unchanged</literal>"> + + + +<!-- + + File and directory names. + +--> + +<!ENTITY build "<filename>build</filename>"> +<!ENTITY Makefile "<filename>Makefile</filename>"> +<!ENTITY Makefiles "<filename>Makefiles</filename>"> +<!ENTITY SConscript "<filename>SConscript</filename>"> +<!ENTITY SConstruct "<filename>SConstruct</filename>"> +<!ENTITY Sconstruct "<filename>Sconstruct</filename>"> +<!ENTITY sconstruct "<filename>sconstruct</filename>"> +<!ENTITY sconsign "<filename>.sconsign</filename>"> +<!ENTITY src "<filename>src</filename>"> + + + +<!-- + + Methods and functions. This includes functions from both + the Build Engine and the Native Python Interface. + +--> + +<!ENTITY Add "<function>Add</function>"> +<!ENTITY AddOptions "<function>AddOptions</function>"> +<!ENTITY Alias "<function>Alias</function>"> +<!ENTITY Aliases "<function>Aliases</function>"> +<!ENTITY Append "<function>Append</function>"> +<!ENTITY BoolOption "<function>BoolOption</function>"> +<!ENTITY Build "<function>Build</function>"> +<!ENTITY CacheDir "<function>CacheDir</function>"> +<!ENTITY Clean "<function>Clean</function>"> +<!ENTITY Clone "<function>Clone</function>"> +<!ENTITY Command "<function>Command</function>"> +<!ENTITY Configure "<function>Configure</function>"> +<!ENTITY Copy "<function>Copy</function>"> +<!ENTITY Default "<function>Default</function>"> +<!ENTITY DefaultRules "<function>DefaultRules</function>"> +<!ENTITY Depends "<function>Depends</function>"> +<!ENTITY Dir "<function>Dir</function>"> +<!ENTITY Entry "<function>Entry</function>"> +<!ENTITY EnumOption "<function>EnumOption</function>"> +<!ENTITY Environment "<function>Environment</function>"> +<!ENTITY Export "<function>Export</function>"> +<!ENTITY File "<function>File</function>"> +<!ENTITY Finish "<function>Finish</function>"> +<!ENTITY GenerateHelpText "<function>GenerateHelpText</function>"> +<!ENTITY Help "<function>Help</function>"> +<!ENTITY Ignore "<function>Ignore</function>"> +<!ENTITY Import "<function>Import</function>"> +<!ENTITY Install "<function>Install</function>"> +<!ENTITY InstallAs "<function>InstallAs</function>"> +<!ENTITY Link "<function>Link</function>"> +<!ENTITY ListOption "<function>ListOption</function>"> +<!ENTITY Local "<function>Local</function>"> +<!ENTITY Module "<function>Module</function>"> +<!ENTITY NoClean "<function>NoClean</function>"> +<!ENTITY Objects "<function>Objects</function>"> +<!ENTITY Options "<function>Options</function>"> +<!ENTITY PackageOption "<function>PackageOption</function>"> +<!ENTITY PathOption "<function>PathOption</function>"> +<!ENTITY Precious "<function>Precious</function>"> +<!ENTITY Prepend "<function>Prepend</function>"> +<!ENTITY Replace "<function>Replace</function>"> +<!ENTITY Repository "<function>Repository</function>"> +<!ENTITY Return "<function>Return</function>"> +<!ENTITY RuleSet "<function>RuleSet</function>"> +<!ENTITY Salt "<function>Salt</function>"> +<!ENTITY SetBuildSignatureType "<function>SetBuildSignatureType</function>"> +<!ENTITY SetContentSignatureType "<function>SetContentSignatureType</function>"> +<!ENTITY SourceSignature "<function>SourceSignature</function>"> +<!ENTITY SourceSignatures "<function>SourceSignatures</function>"> +<!ENTITY Split "<function>Split</function>"> +<!ENTITY TargetSignatures "<function>TargetSignatures</function>"> +<!ENTITY Task "<function>Task</function>"> + +<!-- Environment methods --> +<!ENTITY subst "<function>subst</function>"> + +<!-- Configure context functions --> +<!ENTITY Message "<function>Message</function>"> +<!ENTITY Result "<function>Result</function>"> +<!ENTITY CheckCHeader "<function>CheckCHeader</function>"> +<!ENTITY CheckCXXHeader "<function>CheckCXXHeader</function>"> +<!ENTITY CheckFunc "<function>CheckFunc</function>"> +<!ENTITY CheckHeader "<function>CheckHeader</function>"> +<!ENTITY CheckLib "<function>CheckLib</function>"> +<!ENTITY CheckLibWithHeader "<function>CheckLibWithHeader</function>"> +<!ENTITY CheckType "<function>CheckType</function>"> +<!ENTITY TryAction "<function>TryAction</function>"> +<!ENTITY TryBuild "<function>TryBuild</function>"> +<!ENTITY TryCompile "<function>TryCompile</function>"> +<!ENTITY TryLink "<function>TryLink</function>"> +<!ENTITY TryRun "<function>TryRun</function>"> + +<!-- Python functions --> +<!ENTITY str "<function>str</function>"> +<!ENTITY zipfile "<function>zipfile</function>"> + +<!-- Obsolete, but referenced in old documents. --> +<!ENTITY Cache "<function>Cache</function>"> + + + +<!-- + + Global variables. + +--> + +<!ENTITY ARGUMENTS "<varname>ARGUMENTS</varname>"> +<!ENTITY BUILD_TARGETS "<varname>BUILD_TARGETS</varname>"> +<!ENTITY COMMAND_LINE_TARGETS "<varname>COMMAND_LINE_TARGETS</varname>"> +<!ENTITY DEFAULT_TARGETS "<varname>DEFAULT_TARGETS</varname>"> + + + +<!-- + + Construction variables. + +--> + +<!ENTITY BUILDERMAP "<varname>BUILDERMAP</varname>"> +<!ENTITY BUILDERS "<varname>BUILDERS</varname>"> +<!ENTITY CC "<varname>CC</varname>"> +<!ENTITY CCFLAGS "<varname>CCFLAGS</varname>"> +<!ENTITY CCCOM "<varname>CCCOM</varname>"> +<!ENTITY COLOR "<varname>COLOR</varname>"> +<!ENTITY COLORS "<varname>COLORS</varname>"> +<!ENTITY CONFIG "<varname>CONFIG</varname>"> +<!ENTITY CPPDEFINES "<varname>CPPDEFINES</varname>"> +<!ENTITY ENV "<varname>ENV</varname>"> +<!ENTITY JAVACLASSDIR "<varname>JAVACLASSDIR</varname>"> +<!ENTITY LIBDIRPREFIX "<varname>LIBDIRPREFIX</varname>"> +<!ENTITY LIBDIRSUFFIX "<varname>LIBDIRSUFFIX</varname>"> +<!ENTITY LIBLINKPREFIX "<varname>LIBLINKPREFIX</varname>"> +<!ENTITY LIBLINKSUFFIX "<varname>LIBLINKSUFFIX</varname>"> +<!ENTITY LIBPATH "<varname>LIBPATH</varname>"> +<!ENTITY LIBS "<varname>LIBS</varname>"> +<!ENTITY LINK "<varname>LINK</varname>"> +<!ENTITY LINKCOM "<varname>LINKCOM</varname>"> +<!ENTITY LINKFLAGS "<varname>LINKFLAGS</varname>"> +<!ENTITY RELEASE "<varname>RELEASE</varname>"> +<!ENTITY RELEASE_BUILD "<varname>RELEASE_BUILD</varname>"> +<!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>"> +<!ENTITY SCANNERS "<varname>SCANNERS</varname>"> +<!ENTITY TARFLAGS "<varname>TARFLAGS</varname>"> +<!ENTITY TARSUFFIX "<varname>TARSUFFIX</varname>"> + + + +<!-- + + Environment variables. + +--> + +<!ENTITY PATH "<varname>PATH</varname>"> +<!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>"> +<!ENTITY SCONSFLAGS "<varname>SCONSFLAGS</varname>"> + + + +<!-- + + Function and method arguments. + +--> + +<!ENTITY allowed_values "<varname>allowed_values</varname>"> +<!ENTITY build_dir "<varname>build_dir</varname>"> +<!ENTITY map "<varname>map</varname>"> +<!ENTITY ignorecase "<varname>ignorecase</varname>"> +<!ENTITY options "<varname>options</varname>"> +<!ENTITY exports "<varname>exports</varname>"> +<!ENTITY source "<varname>source</varname>"> +<!ENTITY target "<varname>target</varname>"> + + + +<!-- + + Values of function and method arguments. + +--> + +<!ENTITY all "<literal>all</literal>"> +<!ENTITY none "<literal>none</literal>"> + + + +<!-- + + Builder and Scanner objects. + +--> + +<!ENTITY BuildDir "<function>BuildDir</function>"> +<!ENTITY CFile "<function>CFile</function>"> +<!ENTITY CXXFile "<function>CXXFile</function>"> +<!ENTITY DVI "<function>DVI</function>"> +<!ENTITY Jar "<function>Jar</function>"> +<!ENTITY Java "<function>Java</function>"> +<!ENTITY JavaH "<function>JavaH</function>"> +<!ENTITY Library "<function>Library</function>"> +<!ENTITY Object "<function>Object</function>"> +<!ENTITY PCH "<function>PCH</function>"> +<!ENTITY PDF "<function>PDF</function>"> +<!ENTITY PostScript "<function>PostScript</function>"> +<!ENTITY Program "<function>Program</function>"> +<!ENTITY RES "<function>RES</function>"> +<!ENTITY RMIC "<function>RMIC</function>"> +<!ENTITY SharedLibrary "<function>SharedLibrary</function>"> +<!ENTITY SharedObject "<function>SharedObject</function>"> +<!ENTITY StaticLibrary "<function>StaticLibrary</function>"> +<!ENTITY StaticObject "<function>StaticObject</function>"> +<!ENTITY Tar "<function>Tar</function>"> +<!ENTITY Zip "<function>Zip</function>"> + +<!-- Obsolete, but referenced in old documents. --> +<!ENTITY MakeBuilder "<function>Make</function>"> + + + +<!-- + + Terms. Define both singular and plural forms in various + case-sensitive combinations for use in titles, in-line, etc. + +--> + +<!ENTITY buildfunc "<literal>builder function</literal>"> +<!ENTITY builder_method "<literal>builder method</literal>"> + +<!ENTITY Configure_Contexts "<literal>Configure Contexts</literal>"> +<!ENTITY configure_context "<literal>configure context</literal>"> + +<!ENTITY ConsEnv "<literal>Construction Environment</literal>"> +<!ENTITY ConsEnvs "<literal>Construction Environments</literal>"> +<!ENTITY Consenv "<literal>Construction environment</literal>"> +<!ENTITY Consenvs "<literal>Construction environments</literal>"> +<!ENTITY consenv "<literal>construction environment</literal>"> +<!ENTITY consenvs "<literal>construction environments</literal>"> + +<!ENTITY ConsVar "<literal>Construction Variable</literal>"> +<!ENTITY ConsVars "<literal>Construction Variables</literal>"> +<!ENTITY Consvar "<literal>Construction variable</literal>"> +<!ENTITY Consvars "<literal>Construction variables</literal>"> +<!ENTITY consvar "<literal>construction variable</literal>"> +<!ENTITY consvars "<literal>construction variables</literal>"> + +<!ENTITY CPPPATH "<literal>CPPPATH</literal>"> + +<!ENTITY Dictionary "<literal>Dictionary</literal>"> + +<!ENTITY Emitter "<literal>Emitter</literal>"> +<!ENTITY emitter "<literal>emitter</literal>"> +<!ENTITY Generator "<literal>Generator</literal>"> +<!ENTITY generator "<literal>generator</literal>"> + +<!ENTITY Nodes "<literal>Nodes</literal>"> + +<!ENTITY signature "<literal>signature</literal>"> +<!ENTITY buildsignature "<literal>build signature</literal>"> + +<!ENTITY true "<literal>true</literal>"> +<!ENTITY false "<literal>false</literal>"> + +<!ENTITY typedef "<literal>typedef</literal>"> + +<!-- + + File and program names used in examples. + +--> + +<!ENTITY bar "<application>bar</application>"> +<!ENTITY common1_c "<filename>common1.c</filename>"> +<!ENTITY common2_c "<filename>common2.c</filename>"> +<!ENTITY custom_py "<filename>custom.py</filename>"> +<!ENTITY goodbye "<application>goodbye</application>"> +<!ENTITY goodbye_o "<filename>goodbye.o</filename>"> +<!ENTITY goodbye_obj "<filename>goodbye.obj</filename>"> +<!ENTITY file_dll "<filename>file.dll</filename>"> +<!ENTITY file_in "<filename>file.in</filename>"> +<!ENTITY file_lib "<filename>file.lib</filename>"> +<!ENTITY file_o "<filename>file.o</filename>"> +<!ENTITY file_obj "<filename>file.obj</filename>"> +<!ENTITY file_out "<filename>file.out</filename>"> +<!ENTITY foo "<application>foo</application>"> +<!ENTITY foo_o "<filename>foo.o</filename>"> +<!ENTITY foo_obj "<filename>foo.obj</filename>"> +<!ENTITY hello "<application>hello</application>"> +<!ENTITY hello_c "<filename>hello.c</filename>"> +<!ENTITY hello_exe "<filename>hello.exe</filename>"> +<!ENTITY hello_h "<filename>hello.h</filename>"> +<!ENTITY hello_o "<filename>hello.o</filename>"> +<!ENTITY hello_obj "<filename>hello.obj</filename>"> +<!ENTITY libfile_a "<filename>libfile_a</filename>"> +<!ENTITY libfile_so "<filename>libfile_so</filename>"> +<!ENTITY new_hello "<application>new_hello</application>"> +<!ENTITY new_hello_exe "<application>new_hello.exe</application>"> +<!ENTITY prog "<filename>prog</filename>"> +<!ENTITY prog1 "<filename>prog1</filename>"> +<!ENTITY prog2 "<filename>prog2</filename>"> +<!ENTITY prog_c "<filename>prog.c</filename>"> +<!ENTITY prog_exe "<filename>prog.exe</filename>"> +<!ENTITY stdio_h "<filename>stdio.h</filename>"> + +<!-- + + Punctuation. + +--> + +<!ENTITY plus "<literal>+</literal>"> +<!ENTITY hash "<literal>#</literal>"> + +<!-- + + Mailing lists + +--> + +<!ENTITY scons-announce "<literal>announce@scons.tigris.org</literal>"> +<!ENTITY scons-devel "<literal>dev@scons.tigris.org</literal>"> +<!ENTITY scons-users "<literal>users@scons.tigris.org</literal>"> diff --git a/doc/developer/MANIFEST b/doc/developer/MANIFEST new file mode 100644 index 0000000..eece338 --- /dev/null +++ b/doc/developer/MANIFEST @@ -0,0 +1,9 @@ +architecture.xml +branches.xml +copyright.xml +cycle.xml +main.xml +packaging.xml +preface.xml +sourcetree.xml +testing.xml diff --git a/doc/developer/architecture.xml b/doc/developer/architecture.xml new file mode 100644 index 0000000..3a6e18c --- /dev/null +++ b/doc/developer/architecture.xml @@ -0,0 +1,40 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Architecture</title> + + <para> + + XXX + </para> + + </section> diff --git a/doc/developer/branches.xml b/doc/developer/branches.xml new file mode 100644 index 0000000..e46b616 --- /dev/null +++ b/doc/developer/branches.xml @@ -0,0 +1,40 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>&SCons; Branches</title> + + <para> + + XXX + </para> + + </section> diff --git a/doc/developer/copyright.xml b/doc/developer/copyright.xml new file mode 100644 index 0000000..7a37cb9 --- /dev/null +++ b/doc/developer/copyright.xml @@ -0,0 +1,32 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<blockquote> + <para> + + SCons Developer's Guide Copyright (c) 2007 Steven Knight + + </para> +</blockquote> diff --git a/doc/developer/cycle.xml b/doc/developer/cycle.xml new file mode 100644 index 0000000..b56edd2 --- /dev/null +++ b/doc/developer/cycle.xml @@ -0,0 +1,40 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Development Cycle</title> + + <para> + + XXX + </para> + + </section> diff --git a/doc/developer/main.xml b/doc/developer/main.xml new file mode 100644 index 0000000..0ebed33 --- /dev/null +++ b/doc/developer/main.xml @@ -0,0 +1,110 @@ +<?xml version="1.0"?> + +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ + + <!ENTITY % version SYSTEM "../version.xml"> + %version; + + <!ENTITY % scons SYSTEM "../scons.mod"> + %scons; + + <!ENTITY architecture SYSTEM "architecture.xml"> + <!ENTITY branches SYSTEM "branches.xml"> + <!ENTITY copyright SYSTEM "copyright.xml"> + <!ENTITY cycle SYSTEM "cycle.xml"> + <!ENTITY packaging SYSTEM "packaging.xml"> + <!ENTITY preface SYSTEM "preface.xml"> + <!ENTITY sourcetree SYSTEM "sourcetree.xml"> + <!ENTITY testing SYSTEM "testing.xml"> + +]> + +<book> + <bookinfo> + <title>SCons Developer's Guide &buildversion;</title> + + <author> + <firstname>Steven</firstname> + <surname>Knight</surname> + </author> + + <edition>Revision &buildrevision; (&builddate;)</edition> + + <pubdate>2007</pubdate> + + <copyright> + <year>2007</year> + <holder>Steven Knight</holder> + </copyright> + + <legalnotice> + ©right; + </legalnotice> + + <releaseinfo>version &buildversion;</releaseinfo> + + </bookinfo> + + <preface id="chap-preface"> + <title>Preface</title> + &preface; + </preface> + + <chapter id="chap-development-cycle"> + <title>Development Cycle</title> + &cycle; + </chapter> + + <chapter id="chap-source-tree"> + <title>Source Tree</title> + &sourcetree; + </chapter> + + <chapter id="chap-testing"> + <title>Testing</title> + &testing; + </chapter> + + <chapter id="chap-branches"> + <title>Branches</title> + &branches; + </chapter> + + <chapter id="chap-packaging"> + <title>Packaging</title> + &packaging; + </chapter> + + <chapter id="chap-architecture"> + <title>Architecture</title> + &architecture; + </chapter> + +</book> diff --git a/doc/developer/packaging.xml b/doc/developer/packaging.xml new file mode 100644 index 0000000..92b6a31 --- /dev/null +++ b/doc/developer/packaging.xml @@ -0,0 +1,40 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Packaging</title> + + <para> + + XXX + </para> + + </section> diff --git a/doc/developer/preface.xml b/doc/developer/preface.xml new file mode 100644 index 0000000..ece9cdc --- /dev/null +++ b/doc/developer/preface.xml @@ -0,0 +1,175 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + This document assumes that you already know how &SCons; + and that you want to learn how to work on the code. + + </para> + + <section> + <title>&SCons; Principles</title> + + <para> + + There are a few overriding principles + we try to live up to in designing and implementing &SCons: + + </para> + + <variablelist> + + <varlistentry> + <term>Correctness</term> + + <listitem> + <para> + + First and foremost, + by default, &SCons; guarantees a correct build + even if it means sacrificing performance a little. + We strive to guarantee the build is correct + regardless of how the software being built is structured, + how it may have been written, + or how unusual the tools are that build it. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Performance</term> + + <listitem> + <para> + + Given that the build is correct, + we try to make &SCons; build software + as quickly as possible. + In particular, wherever we may have needed to slow + down the default &SCons; behavior to guarantee a correct build, + we also try to make it easy to speed up &SCons; + through optimization options that let you trade off + guaranteed correctness in all end cases for + a speedier build in the usual cases. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Convenience</term> + + <listitem> + <para> + + &SCons; tries to do as much for you out of the box as reasonable, + including detecting the right tools on your system + and using them correctly to build the software. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + In a nutshell, we try hard to make &SCons; just + "do the right thing" and build software correctly, + with a minimum of hassles. + + </para> + + </section> + + <section> + <title>Acknowledgements</title> + + <para> + + &SCons; would not exist without a lot of help + from a lot of people, + many of whom may not even be aware + that they helped or served as inspiration. + So in no particular order, + and at the risk of leaving out someone: + + </para> + + <para> + + First and foremost, + &SCons; owes a tremendous debt to Bob Sidebotham, + the original author of the classic Perl-based &Cons; tool + which Bob first released to the world back around 1996. + Bob's work on Cons classic provided the underlying architecture + and model of specifying a build configuration + using a real scripting language. + My real-world experience working on Cons + informed many of the design decisions in SCons, + including the improved parallel build support, + making Builder objects easily definable by users, + and separating the build engine from the wrapping interface. + + </para> + + <para> + + Greg Wilson was instrumental in getting + &SCons; started as a real project + when he initiated the Software Carpentry design + competition in February 2000. + Without that nudge, + marrying the advantages of the Cons classic + architecture with the readability of Python + might have just stayed no more than a nice idea. + + </para> + + <para> + + Thanks to Peter Miller + for his splendid change management system, &Aegis;, + which has provided the &SCons; project + with a robust development methodology from day one, + and which showed me how you could + integrate incremental regression tests into + a practical development cycle + (years before eXtreme Programming arrived on the scene). + + </para> + + <para> + + And last, thanks to Guido van Rossum + for his elegant scripting language, + which is the basis not only for the &SCons; implementation, + but for the interface itself. + + </para> + + </section> diff --git a/doc/developer/sourcetree.xml b/doc/developer/sourcetree.xml new file mode 100644 index 0000000..97bfee0 --- /dev/null +++ b/doc/developer/sourcetree.xml @@ -0,0 +1,40 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Source Tree</title> + + <para> + + XXX + </para> + + </section> diff --git a/doc/developer/testing.xml b/doc/developer/testing.xml new file mode 100644 index 0000000..a41c61b --- /dev/null +++ b/doc/developer/testing.xml @@ -0,0 +1,40 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Testing</title> + + <para> + + XXX + </para> + + </section> diff --git a/doc/man/MANIFEST b/doc/man/MANIFEST new file mode 100644 index 0000000..8e69d1c --- /dev/null +++ b/doc/man/MANIFEST @@ -0,0 +1,2 @@ +scons.1 +sconsign.1 diff --git a/doc/man/scons-time.1 b/doc/man/scons-time.1 new file mode 100644 index 0000000..8231c9d --- /dev/null +++ b/doc/man/scons-time.1 @@ -0,0 +1,1017 @@ +.\" Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining +.\" a copy of this software and associated documentation files (the +.\" "Software"), to deal in the Software without restriction, including +.\" without limitation the rights to use, copy, modify, merge, publish, +.\" distribute, sublicense, and/or sell copies of the Software, and to +.\" permit persons to whom the Software is furnished to do so, subject to +.\" the following conditions: +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +.\" KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +.\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +.\" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +.\" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +.\" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +.\" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" doc/man/scons-time.1 4577 2009/12/27 19:44:43 scons +.\" +.\" ES - Example Start - indents and turns off line fill +.de ES +.RS +.nf +.. +.\" EE - Example End - ends indent and turns line fill back on +.de EE +.RE +.fi +.. +'\"========================================================================== +.de SF +.B scons-time func +[\fB-h\fR] +[\fB--chdir=\fIDIR\fR] +[\fB-f \fIFILE\fR] +[\fB--fmt=\fIFORMAT\fR] +[\fB--func=\fINAME\fR] +[\fB-p \fISTRING\fR] +[\fB-t \fINUMBER\fR] +[\fB--title= TITLE\fR] +[\fIARGUMENTS\fR] +.. +'\"-------------------------------------------------------------------------- +.de SY +.B scons-time mem +[\fB-h\fR] +[\fB--chdir=\fIDIR\fR] +[\fB-f \fIFILE\fR] +[\fB--fmt=\fIFORMAT\fR] +[\fB-p \fISTRING\fR] +[\fB--stage=\fISTAGE\fR] +[\fB-t \fINUMBER\fR] +[\fB--title=\fITITLE\fR] +[\fIARGUMENTS\fR] +.. +'\"-------------------------------------------------------------------------- +.de SO +.B scons-time obj +[\fB-h\fR] +[\fB--chdir=\fIDIR\fR] +[\fB-f \fIFILE\fR] +[\fB--fmt=\fIFORMAT\fR] +[\fB-p \fISTRING\fR] +[\fB--stage=\fISTAGE\fR] +[\fB-t \fINUMBER\fR] +[\fB--title=\fITITLE\fR] +[\fIARGUMENTS\fR] +.. +'\"-------------------------------------------------------------------------- +.de SR +.B scons-time run +[\fB-hnqv\fR] +[\fB--aegis=\fIPROJECT\fR] +[\fB-f \fIFILE\fR] +[\fB--number=\fINUMBER\fR] +[\fB--outdir=\fIOUTDIR\fR] +[\fB-p \fISTRING\fR] +[\fB--python=\fIPYTHON\fR] +[\fB-s \fIDIR\fR] +[\fB--scons=\fISCONS\fR] +[\fB--svn=\fIURL\fR] +[\fIARGUMENTS\fR] +.. +'\"-------------------------------------------------------------------------- +.de ST +.B scons-time time +[\fB-h\fR] +[\fB--chdir=\fIDIR\fR] +[\fB-f \fIFILE\fR] +[\fB--fmt=\fIFORMAT\fR] +[\fB-p \fISTRING\fR] +[\fB-t \fINUMBER\fR] +[\fB--title=\fITITLE\fR] +[\fB--which=\fIWHICH\fR] +[\fIARGUMENTS\fR] +.. +.TH SCONS-TIME 1 "December 2009" +.SH NAME +scons-time \- generate and display SCons timing information +'\"========================================================================== +.SH SYNOPSIS +.B scons-time +.IR subcommand +[ +.IR options ... +] +[ +.IR arguments ... +] +'\"-------------------------------------------------------------------------- +.SS "Generating Timing Information" +.SR +'\"-------------------------------------------------------------------------- +.SS "Extracting Function Timings" +.SF +'\"-------------------------------------------------------------------------- +.SS "Extracting Memory Statistics" +.SY +'\"-------------------------------------------------------------------------- +.SS "Extracting Object Counts" +.SO +'\"-------------------------------------------------------------------------- +.SS "Extracting Execution Times" +.ST +'\"-------------------------------------------------------------------------- +.SS "Help Text" +.B scons-time help +.I SUBCOMMAND +[...] +'\"========================================================================== +.SH DESCRIPTION +The +.B scons-time +command runs an SCons configuration +through a standard set of profiled timings +and can extract and graph information from the +resulting profiles and log files of those timings. +The action to be performed by the +.B scons-time +script is specified +by a subcommand, the first argument on the command line. +See the +.B SUBCOMMANDS +section below for information about the operation +of specific subcommands. +.P +The basic way to use +.B scons-time +is to run the +.B scons-time run +subcommand +(possibly multiple times) +to generate profile and log file output, +and then use one of the other +subcommands to display the results +captured in the profiles and log files +for a particular kind of information: +function timings +(the +.B scons-time func +subcommand), +total memory used +(the +.B scons-time mem +subcommand), +object counts +(the +.B scons-time obj +subcommand) +and overall execution time +(the +.B scons-time time +subcommand). +Options exist to place and find the +profiles and log files in separate directories, +to generate the output in a format suitable +for graphing with the +.BR gnuplot (1) +program, +and so on. +.P +There are two basic ways the +.B scons-time run +subcommand +is intended to be used +to gather timing statistics +for a configuration. +One is to use the +.B --svn= +option to test a configuration against +a list of revisions from the SCons Subversion repository. +This will generate a profile and timing log file +for every revision listed with the +.B --number= +option, +and can be used to look at the +impact of commited changes to the +SCons code base on a particular +configuration over time. +.P +The other way is to profile incremental changes to a +local SCons code base during a development cycle--that is, +to look at the performance impact of changes +you're making in the local tree. +In this mode, +you run the +.B scons-time run +subcommand +.I without +the +.B --svn= +option, +in which case it simply looks in the profile/log file output directory +(the current directory by default) +and automatically figures out the +.I next +run number for the output profile and log file. +Used in this way, +the development cycle goes something like: +make a change to SCons; +run +.B scons-time run +to profile it against a specific configuration; +make another change to SCons; +run +.B scons-time run +again to profile it; +etc. +'\"========================================================================== +.SH OPTIONS +The +.B scons-time +command only supports a few global options: +.TP +-h, --help +Displays the global help text and exits, +identical to the +.B scons-time help +subcommand. +.TP +-V, --version +Displays the +.B scons-time +version and exits. +.P +Most functionality is controlled by options +to the individual subcommands. +See the next section for information +about individual subcommand options. +'\"========================================================================== +.SH SUBCOMMANDS +The +.B scons-time +command supports the following +individual subcommands. +'\"-------------------------------------------------------------------------- +.SS "The func Subcommand" +.SF +.P +The +.B scons-time func +subcommand displays timing information +for a specific Python function within SCons. +By default, it extracts information about the +.BR _main () +function, +which includes the Python profiler timing +for all of SCons. +.P +The +.B scons-time func +subcommand extracts function timing information +from all the specified file arguments, +which should be Python profiler output files. +(Normally, these would be +.B *.prof +files generated by the +.B scons-time run +subcommand, +but they can actually be generated +by any Python profiler invocation.) +All file name arguments will be +globbed for on-disk files. +.P +If no arguments are specified, +then function timing information +will be extracted from all +.B *.prof +files, +or the subset of them +with a prefix specified by the +.B -p +option. +.P +Options include: +.TP +-C DIRECTORY, --chdir=DIRECTORY +Changes to the specified +.I DIRECTORY +before looking for the specified files +(or files that match the specified patterns). +.TP +-f FILE, --file=FILE +Reads configuration information from the specified +.IR FILE . +.TP +-fmt=FORMAT, --format=FORMAT +Reports the output in the specified +.IR FORMAT . +The formats currently supported are +.B ascii +(the default) +and +.BR gnuplot . +.TP +--func=NAME +Extracts timings for the specified function +.IR NAME . +The default is to report cumulative timings for the +.BR _main () +function, +which contains the entire SCons run. +.TP +-h, --help +Displays help text for the +.B scons-time func +subcommand. +.TP +-p STRING, --prefix=STRING +Specifies the prefix string for profiles +from which to extract function timing information. +This will be used to search for profiles +if no arguments are specified on the command line. +.TP +-t NUMBER, --tail=NUMBER +Only extracts function timings from the last +.I NUMBER +files. +'\"-------------------------------------------------------------------------- +.SS "The help Subcommand" +.B scons-time help +.I SUBCOMMAND +[...] +The +.B help +subcommand prints help text for any +other subcommands listed as later arguments on the command line. +'\"-------------------------------------------------------------------------- +.SS "The mem Subcommand" +.SY +.P +The +.B scons-time mem +subcommand displays how much memory SCons uses. +.P +The +.B scons-time mem +subcommand extracts memory use information +from all the specified file arguments, +which should be files containing output from +running SCons with the +.B --debug=memory +option. +(Normally, these would be +.B *.log +files generated by the +.B scons-time run +subcommand.) +All file name arguments will be +globbed for on-disk files. +.P +If no arguments are specified, +then memory information +will be extracted from all +.B *.log +files, +or the subset of them +with a prefix specified by the +.B -p +option. +.P +.TP +-C DIR, --chdir=DIR +Changes to the specified +.I DIRECTORY +before looking for the specified files +(or files that match the specified patterns). +.TP +-f FILE, --file=FILE +Reads configuration information from the specified +.IR FILE . +.TP +-fmt=FORMAT, --format=FORMAT +Reports the output in the specified +.IR FORMAT . +The formats currently supported are +.B ascii +(the default) +and +.BR gnuplot . +.TP +-h, --help +Displays help text for the +.B scons-time mem +subcommand. +.TP +-p STRING, --prefix=STRING +Specifies the prefix string for log files +from which to extract memory usage information. +This will be used to search for log files +if no arguments are specified on the command line. +.TP +--stage=STAGE +Prints the memory used at the end of the specified +.IR STAGE : +.B pre-read +(before the SConscript files are read), +.B post-read , +(after the SConscript files are read), +.B pre-build +(before any targets are built) +or +.B post-build +(after any targets are built). +If no +.B --stage +option is specified, +the default behavior is +.BR post-build , +which reports the final amount of memory +used by SCons during each run. +.TP +-t NUMBER, --tail=NUMBER +Only reports memory statistics from the last +.I NUMBER +files. +'\"-------------------------------------------------------------------------- +.SS "The obj Subcommand" +.SO +.P +The +.B scons-time obj +subcommand displays how many objects of a specific named type +are created by SCons. +.P +The +.B scons-time obj +subcommand extracts object counts +from all the specified file arguments, +which should be files containing output from +running SCons with the +.B --debug=count +option. +(Normally, these would be +.B *.log +files generated by the +.B scons-time run +subcommand.) +All file name arguments will be +globbed for on-disk files. +.P +If no arguments are specified, +then object counts +will be extracted from all +.B *.log +files, +or the subset of them +with a prefix specified by the +.B -p +option. +.TP +-C DIR, --chdir=DIR +Changes to the specified +.I DIRECTORY +before looking for the specified files +(or files that match the specified patterns). +.TP +-f FILE, --file=FILE +Reads configuration information from the specified +.IR FILE . +.TP +-fmt=FORMAT, --format=FORMAT +Reports the output in the specified +.IR FORMAT . +The formats currently supported are +.B ascii +(the default) +and +.BR gnuplot . +.TP +-h, --help +Displays help text for the +.B scons-time obj +subcommand. +.TP +-p STRING, --prefix=STRING +Specifies the prefix string for log files +from which to extract object counts. +This will be used to search for log files +if no arguments are specified on the command line. +.TP +--stage=STAGE +Prints the object count at the end of the specified +.IR STAGE : +.B pre-read +(before the SConscript files are read), +.B post-read , +(after the SConscript files are read), +.B pre-build +(before any targets are built) +or +.B post-build +(after any targets are built). +If no +.B --stage +option is specified, +the default behavior is +.BR post-build , +which reports the final object count during each run. +.TP +-t NUMBER, --tail=NUMBER +Only reports object counts from the last +.I NUMBER +files. +'\"-------------------------------------------------------------------------- +.SS "The run Subcommand" +.SR +The +.B scons-time run +subcommand is the basic subcommand +for profiling a specific configuration +against a version of SCons. +.P +The configuration to be tested +is specified as a list of files +or directories that will be unpacked or copied +into a temporary directory +in which SCons will be invoked. +The +.B scons-time run +subcommand understands file suffixes like +.BR .tar , +.BR .tar.gz , +.BR .tgz +and +.BR .zip +and will unpack their contents into a temporary directory. +If more than one argument is specified, +each one will be unpacked or copied +into the temporary directory "on top of" +the previous archives or directories, +so the expectation is that multiple +specified archives share the same directory layout. +.P +Once the file or directory arguments are unpacked or +copied to the temporary directory, +the +.B scons-time run +subcommand runs the +requested version of SCons +against the configuration +three times: +.TP +Startup +SCons is run with the +.B --help +option so that just the SConscript files are read, +and then the default help text is printed. +This profiles just the perceived "overhead" of starting up SCons +and processing the SConscript files. +.TP +Full build +SCons is run to build everything specified in the configuration. +Specific targets to be passed in on the command l ine +may be specified by the +.B targets +keyword in a configuration file; see below for details. +.TP +Rebuild +SCons is run again on the same just-built directory. +If the dependencies in the SCons configuration are correct, +this should be an up-to-date, "do nothing" rebuild. +.P +Each invocation captures the output log file and a profile. +.P +The +.B scons-time run +subcommand supports the following options: +.TP +--aegis=PROJECT +Specifies the Aegis +.I PROJECT +from which the +version(s) of +.B scons +being timed will be extracted. +When +.B --aegis +is specified, the +.BI --number= NUMBER +option specifies delta numbers +that will be tested. +Output from each invocation run will be placed in file +names that match the Aegis delta numbers. +If the +.B --number= +option is not specified, +then the default behavior is to time the +tip of the specified +.IR PROJECT . +.TP +-f FILE, --file=FILE +Reads configuration information from the specified +.IR FILE . +This often provides a more convenient way to specify and +collect parameters associated with a specific timing configuration +than specifying them on the command line. +See the +.B CONFIGURATION FILE +section below +for information about the configuration file parameters. +.TP +-h, --help +Displays help text for the +.B scons-time run +subcommand. +.TP +-n, --no-exec +Do not execute commands, +just printing the command-line equivalents of what would be executed. +Note that the +.B scons-time +script actually executes its actions in Python, +where possible, +for portability. +The commands displayed are UNIX +.I equivalents +of what it's doing. +.TP +--number=NUMBER +Specifies the run number to be used in the names of +the log files and profile outputs generated by this run. +.IP +When used in conjuction with the +.BI --aegis= PROJECT +option, +.I NUMBER +specifies one or more comma-separated Aegis delta numbers +that will be retrieved automatically from the specified Aegis +.IR PROJECT . +.IP +When used in conjuction with the +.BI --svn= URL +option, +.I NUMBER +specifies one or more comma-separated Subversion revision numbers +that will be retrieved automatically from the Subversion +repository at the specified +.IR URL . +Ranges of delta or revision numbers +may be specified be separating two numbers +with a hyphen +.RB ( \- ). +.P +Example: +.ES +% scons-time run --svn=http://scons.tigris.org/svn/trunk --num=1247,1249-1252 . +.EE +.TP +-p STRING, --prefix=STRING +Specifies the prefix string to be used for all of the log files +and profiles generated by this run. +The default is derived from the first +specified argument: +if the first argument is a directory, +the default prefix is the name of the directory; +if the first argument is an archive +(tar or zip file), +the default prefix is the the base name of the archive, +that is, what remains after stripping the archive suffix +.RB ( .tgz ", " .tar.gz " or " .zip ). +.TP +--python=PYTHON +Specifies a path to the Python executable to be used +for the timing runs. +The default is to use the same Python executable that +is running the +.B scons-time +command itself. +.TP +-q, --quiet +Suppresses display of the command lines being executed. +.TP +-s DIR, --subdir=DIR +Specifies the name of directory or subdirectory +from which the commands should be executed. +The default is XXX +.TP +--scons=SCONS +Specifies a path to the SCons script to be used +for the timing runs. +The default is XXX +.TP +--svn=URL, --subversion=URL +Specifies the +.I URL +of the Subversion repository from which the +version(s) of +.B scons +being timed will be extracted. +When +.B --svn +is specified, the +.BI --number= NUMBER +option specifies revision numbers +that will be tested. +Output from each invocation run will be placed in file +names that match the Subversion revision numbers. +If the +.B --number= +option is not specified, +then the default behavior is to time the +.B HEAD +of the specified +.IR URL . +.TP +-v, --verbose +Displays the output from individual commands to the screen +(in addition to capturing the output in log files). +'\"-------------------------------------------------------------------------- +.SS "The time Subcommand" +.ST +.P +The +.B scons-time time +subcommand displays SCons execution times +as reported by the +.B scons --debug=time +option. +.P +The +.B scons-time time +subcommand extracts SCons timing +from all the specified file arguments, +which should be files containing output from +running SCons with the +.B --debug=time +option. +(Normally, these would be +.B *.log +files generated by the +.B scons-time run +subcommand.) +All file name arguments will be +globbed for on-disk files. +.P +If no arguments are specified, +then execution timings +will be extracted from all +.B *.log +files, +or the subset of them +with a prefix specified by the +.B -p +option. +.TP +-C DIR, --chdir=DIR +Changes to the specified +.I DIRECTORY +before looking for the specified files +(or files that match the specified patterns). +.TP +-f FILE, --file=FILE +Reads configuration information from the specified +.IR FILE . +.TP +-fmt=FORMAT, --format=FORMAT +Reports the output in the specified +.IR FORMAT . +The formats currently supported are +.B ascii +(the default) +and +.BR gnuplot . +.TP +-h, --help +Displays help text for the +.B scons-time time +subcommand. +.TP +-p STRING, --prefix=STRING +Specifies the prefix string for log files +from which to extract execution timings. +This will be used to search for log files +if no arguments are specified on the command line. +.TP +-t NUMBER, --tail=NUMBER +Only reports object counts from the last +.I NUMBER +files. +.TP +--which=WHICH +Prints the execution time for the specified +.IR WHICH +value: +.B total +(the total execution time), +.B SConscripts +(total execution time for the SConscript files themselves), +.B SCons +(exectuion time in SCons code itself) +or +.B commands +(execution time of the commands and other actions +used to build targets). +If no +.B --which +option is specified, +the default behavior is +.BR total , +which reports the total execution time for each run. +'\"========================================================================== +.SH CONFIGURATION FILE +Various +.B scons-time +subcommands can read information from a specified +configuration file when passed the +.B \-f +or +.B \--file +options. +The configuration file is actually executed as a Python script. +Setting Python variables in the configuration file +controls the behavior of the +.B scons-time +script more conveniently than having to specify +command-line options or arguments for every run, +and provides a handy way to "shrink-wrap" +the necessary information for producing (and reporting) +consistent timing runs for a given configuration. +.TP +.B aegis +The Aegis executable for extracting deltas. +The default is simply +.BR aegis . +.TP +.B aegis_project +The Aegis project from which deltas should be extracted. +The default is whatever is specified +with the +.B --aegis= +command-line option. +.TP +.B archive_list +A list of archives (files or directories) +that will be copied to the temporary directory +in which SCons will be invoked. +.BR .tar , +.BR .tar.gz , +.BR .tgz +and +.BR .zip +files will have their contents unpacked in +the temporary directory. +Directory trees and files will be copied as-is. +.TP +.B initial_commands +A list of commands that will be executed +before the actual timed +.B scons +runs. +This can be used for commands that are necessary +to prepare the source tree\-for example, +creating a configuration file +that should not be part of the timed run. +.TP +.B key_location +The location of the key on Gnuplot graphing information +generated with the +.BR --format=gnuplot +option. +The default is +.BR "bottom left" . +.TP +.B prefix +The file name prefix to be used when +running or extracting timing for this configuration. +.TP +.B python +The path name of the Python executable +to be used when running or extracting information +for this configuration. +The default is the same version of Python +used to run the SCons +.TP +.B scons +The path name of the SCons script to be used +when running or extracting information +for this configuration. +The default is simply +.BR scons . +.TP +.B scons_flags +The +.B scons +flags used when running SCons to collect timing information. +The default value is +.BR "--debug=count --debug=memory --debug=time --debug=memoizer" . +.TP +.B scons_lib_dir +.TP +.B scons_wrapper +.TP +.B startup_targets +.TP +.B subdir +The subdirectory of the project into which the +.B scons-time +script should change +before executing the SCons commands to time. +.TP +.B subversion_url +The Subversion URL from +.TP +.B svn +The subversion executable used to +check out revisions of SCons to be timed. +The default is simple +.BR svn . +.TP +.B svn_co_flag +.TP +.B tar +.TP +.B targets +A string containing the targets that should be added to +the command line of every timed +.B scons +run. +This can be used to restrict what's being timed to a +subset of the full build for the configuration. +.TP +.B targets0 +.TP +.B targets1 +.TP +.B targets2 +.TP +.B title +.TP +.B unzip +.TP +.B verbose +.TP +.B vertical_bars +'\"-------------------------------------------------------------------------- +.SS Example +Here is an example +.B scons-time +configuration file +for a hypothetical sample project: +.P +.ES +# The project doesn't use SCons natively (yet), so we're +# timing a separate set of SConscript files that we lay +# on top of the vanilla unpacked project tarball. +arguments = ['project-1.2.tgz', 'project-SConscripts.tar'] + +# The subdirectory name contains the project version number, +# so tell scons-time to chdir there before building. +subdir = 'project-1.2' + +# Set the prefix so output log files and profiles are named: +# project-000-[012].{log,prof} +# project-001-[012].{log,prof} +# etc. +prefix = 'project' + +# The SConscript files being tested don't do any SConf +# configuration, so run their normal ./configure script +# before we invoke SCons. +initial_commands = [ + './configure', +] + +# Only time building the bin/project executable. +targets = 'bin/project' + +# Time against SCons revisions of the branches/core branch +subversion_url = 'http://scons.tigris.org/svn/scons/branches/core' +.EE +'\"========================================================================== +.SH ENVIRONMENT +The +.B scons-time +script uses the following environment variables: +.TP +.B PRESERVE +If this value is set, +the +.B scons-time +script will +.I not +remove the temporary directory or directories +in which it builds the specified configuration +or downloads a specific version of SCons. +'\"========================================================================== +.SH "SEE ALSO" +.BR gnuplot (1), +.BR scons (1) + +.SH AUTHORS +Steven Knight <knight at baldmt dot com> diff --git a/doc/man/scons.1 b/doc/man/scons.1 new file mode 100644 index 0000000..f57169b --- /dev/null +++ b/doc/man/scons.1 @@ -0,0 +1,10149 @@ +.\" Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining +.\" a copy of this software and associated documentation files (the +.\" "Software"), to deal in the Software without restriction, including +.\" without limitation the rights to use, copy, modify, merge, publish, +.\" distribute, sublicense, and/or sell copies of the Software, and to +.\" permit persons to whom the Software is furnished to do so, subject to +.\" the following conditions: +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +.\" KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +.\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +.\" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +.\" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +.\" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +.\" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" doc/man/scons.1 4577 2009/12/27 19:44:43 scons +.\" +.TH SCONS 1 "December 2009" +.\" ES - Example Start - indents and turns off line fill +.rm ES +.de ES +.RS +.nf +.. +.\" EE - Example End - ends indent and turns line fill back on +.rm EE +.de EE +.fi +.RE +.. +.SH NAME +scons \- a software construction tool +.SH SYNOPSIS +.B scons +[ +.IR options ... +] +[ +.IR name = val ... +] +[ +.IR targets ... +] +.SH DESCRIPTION + +The +.B scons +utility builds software (or other files) by determining which +component pieces must be rebuilt and executing the necessary commands to +rebuild them. + +By default, +.B scons +searches for a file named +.IR SConstruct , +.IR Sconstruct , +or +.I sconstruct +(in that order) in the current directory and reads its +configuration from the first file found. +An alternate file name may be +specified via the +.B -f +option. + +The +.I SConstruct +file can specify subsidiary +configuration files using the +.B SConscript() +function. +By convention, +these subsidiary files are named +.IR SConscript , +although any name may be used. +(Because of this naming convention, +the term "SConscript files" +is sometimes used to refer +generically to all +.B scons +configuration files, +regardless of actual file name.) + +The configuration files +specify the target files to be built, and +(optionally) the rules to build those targets. Reasonable default +rules exist for building common software components (executable +programs, object files, libraries), so that for most software +projects, only the target and input files need be specified. + +Before reading the +.I SConstruct +file, +.B scons +looks for a directory named +.I site_scons +in the directory containing the +.I SConstruct +file; if it exists, +.I site_scons +is added to sys.path, +the file +.IR site_scons/site_init.py , +is evaluated if it exists, +and the directory +.I site_scons/site_tools +is added to the default toolpath if it exist. +See the +.I --no-site-dir +and +.I --site-dir +options for more details. + +.B scons +reads and executes the SConscript files as Python scripts, +so you may use normal Python scripting capabilities +(such as flow control, data manipulation, and imported Python libraries) +to handle complicated build situations. +.BR scons , +however, reads and executes all of the SConscript files +.I before +it begins building any targets. +To make this obvious, +.B scons +prints the following messages about what it is doing: + +.ES +$ scons foo.out +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons: Building targets ... +cp foo.in foo.out +scons: done building targets. +$ +.EE + +The status messages +(everything except the line that reads "cp foo.in foo.out") +may be suppressed using the +.B -Q +option. + +.B scons +does not automatically propagate +the external environment used to execute +.B scons +to the commands used to build target files. +This is so that builds will be guaranteed +repeatable regardless of the environment +variables set at the time +.B scons +is invoked. +This also means that if the compiler or other commands +that you want to use to build your target files +are not in standard system locations, +.B scons +will not find them unless +you explicitly set the PATH +to include those locations. +Whenever you create an +.B scons +construction environment, +you can propagate the value of PATH +from your external environment as follows: + +.ES +import os +env = Environment(ENV = {'PATH' : os.environ['PATH']}) +.EE + +Similarly, if the commands use external environment variables +like $PATH, $HOME, $JAVA_HOME, $LANG, $SHELL, $TERM, etc., +these variables can also be explicitly propagated: + +.ES +import os +env = Environment(ENV = {'PATH' : os.environ['PATH'], + 'HOME' : os.environ['HOME']}) +.EE + +Or you may explicitly propagate the invoking user's +complete external environment: + +.ES +import os +env = Environment(ENV = os.environ) +.EE + +This comes at the expense of making your build +dependent on the user's environment being set correctly, +but it may be more convenient for many configurations. + +.B scons +can scan known input files automatically for dependency +information (for example, #include statements +in C or C++ files) and will rebuild dependent files appropriately +whenever any "included" input file changes. +.B scons +supports the +ability to define new scanners for unknown input file types. + +.B scons +knows how to fetch files automatically from +SCCS or RCS subdirectories +using SCCS, RCS or BitKeeper. + +.B scons +is normally executed in a top-level directory containing a +.I SConstruct +file, optionally specifying +as command-line arguments +the target file or files to be built. + +By default, the command + +.ES +scons +.EE + +will build all target files in or below the current directory. +Explicit default targets +(to be built when no targets are specified on the command line) +may be defined the SConscript file(s) +using the +.B Default() +function, described below. + +Even when +.B Default() +targets are specified in the SConscript file(s), +all target files in or below the current directory +may be built by explicitly specifying +the current directory (.) +as a command-line target: + +.ES +scons . +.EE + +Building all target files, +including any files outside of the current directory, +may be specified by supplying a command-line target +of the root directory (on POSIX systems): + +.ES +scons / +.EE + +or the path name(s) of the volume(s) in which all the targets +should be built (on Windows systems): + +.ES +scons C:\\ D:\\ +.EE + +To build only specific targets, +supply them as command-line arguments: + +.ES +scons foo bar +.EE + +in which case only the specified targets will be built +(along with any derived files on which they depend). + +Specifying "cleanup" targets in SConscript files is not usually necessary. +The +.B -c +flag removes all files +necessary to build the specified target: + +.ES +scons -c . +.EE + +to remove all target files, or: + +.ES +scons -c build export +.EE + +to remove target files under build and export. +Additional files or directories to remove can be specified using the +.BR Clean() +function. +Conversely, targets that would normally be removed by the +.B -c +invocation +can be prevented from being removed by using the +.BR NoClean () +function. + +A subset of a hierarchical tree may be built by +remaining at the top-level directory (where the +.I SConstruct +file lives) and specifying the subdirectory as the target to be +built: + +.ES +scons src/subdir +.EE + +or by changing directory and invoking scons with the +.B -u +option, which traverses up the directory +hierarchy until it finds the +.I SConstruct +file, and then builds +targets relatively to the current subdirectory: + +.ES +cd src/subdir +scons -u . +.EE + +.B scons +supports building multiple targets in parallel via a +.B -j +option that takes, as its argument, the number +of simultaneous tasks that may be spawned: + +.ES +scons -j 4 +.EE + +builds four targets in parallel, for example. + +.B scons +can maintain a cache of target (derived) files that can +be shared between multiple builds. When caching is enabled in a +SConscript file, any target files built by +.B scons +will be copied +to the cache. If an up-to-date target file is found in the cache, it +will be retrieved from the cache instead of being rebuilt locally. +Caching behavior may be disabled and controlled in other ways by the +.BR --cache-force , +.BR --cache-disable , +and +.B --cache-show +command-line options. The +.B --random +option is useful to prevent multiple builds +from trying to update the cache simultaneously. + +Values of variables to be passed to the SConscript file(s) +may be specified on the command line: + +.ES +scons debug=1 . +.EE + +These variables are available in SConscript files +through the ARGUMENTS dictionary, +and can be used in the SConscript file(s) to modify +the build in any way: + +.ES +if ARGUMENTS.get('debug', 0): + env = Environment(CCFLAGS = '-g') +else: + env = Environment() +.EE + +The command-line variable arguments are also available +in the ARGLIST list, +indexed by their order on the command line. +This allows you to process them in order rather than by name, +if necessary. +ARGLIST[0] returns a tuple +containing (argname, argvalue). +A Python exception is thrown if you +try to access a list member that +does not exist. + +.B scons +requires Python version 1.5.2 or later. +There should be no other dependencies or requirements to run +.B scons. + +.\" The following paragraph reflects the default tool search orders +.\" currently in SCons/Tool/__init__.py. If any of those search orders +.\" change, this documentation should change, too. +By default, +.B scons +knows how to search for available programming tools +on various systems. +On Windows systems, +.B scons +searches in order for the +Microsoft Visual C++ tools, +the MinGW tool chain, +the Intel compiler tools, +and the PharLap ETS compiler. +On OS/2 systems, +.B scons +searches in order for the +OS/2 compiler, +the GCC tool chain, +and the Microsoft Visual C++ tools, +On SGI IRIX, IBM AIX, Hewlett Packard HP-UX, and Sun Solaris systems, +.B scons +searches for the native compiler tools +(MIPSpro, Visual Age, aCC, and Forte tools respectively) +and the GCC tool chain. +On all other platforms, +including POSIX (Linux and UNIX) platforms, +.B scons +searches in order +for the GCC tool chain, +the Microsoft Visual C++ tools, +and the Intel compiler tools. +You may, of course, override these default values +by appropriate configuration of +Environment construction variables. + +.SH OPTIONS +In general, +.B scons +supports the same command-line options as GNU +.BR make , +and many of those supported by +.BR cons . + +.TP +-b +Ignored for compatibility with non-GNU versions of +.BR make. + +.TP +-c, --clean, --remove +Clean up by removing all target files for which a construction +command is specified. +Also remove any files or directories associated to the construction command +using the +.BR Clean () +function. +Will not remove any targets specified by the +.BR NoClean () +function. + +.TP +.RI --cache-debug= file +Print debug information about the +.BR CacheDir () +derived-file caching +to the specified +.IR file . +If +.I file +is +.B \- +(a hyphen), +the debug information are printed to the standard output. +The printed messages describe what signature file names are +being looked for in, retrieved from, or written to the +.BR CacheDir () +directory tree. + +.TP +--cache-disable, --no-cache +Disable the derived-file caching specified by +.BR CacheDir (). +.B scons +will neither retrieve files from the cache +nor copy files to the cache. + +.TP +--cache-force, --cache-populate +When using +.BR CacheDir (), +populate a cache by copying any already-existing, up-to-date +derived files to the cache, +in addition to files built by this invocation. +This is useful to populate a new cache with +all the current derived files, +or to add to the cache any derived files +recently built with caching disabled via the +.B --cache-disable +option. + +.TP +--cache-show +When using +.BR CacheDir () +and retrieving a derived file from the cache, +show the command +that would have been executed to build the file, +instead of the usual report, +"Retrieved `file' from cache." +This will produce consistent output for build logs, +regardless of whether a target +file was rebuilt or retrieved from the cache. + +.TP +.RI --config= mode +This specifies how the +.B Configure +call should use or generate the +results of configuration tests. +The option should be specified from +among the following choices: + +.TP +--config=auto +scons will use its normal dependency mechanisms +to decide if a test must be rebuilt or not. +This saves time by not running the same configuration tests +every time you invoke scons, +but will overlook changes in system header files +or external commands (such as compilers) +if you don't specify those dependecies explicitly. +This is the default behavior. + +.TP +--config=force +If this option is specified, +all configuration tests will be re-run +regardless of whether the +cached results are out of date. +This can be used to explicitly +force the configuration tests to be updated +in response to an otherwise unconfigured change +in a system header file or compiler. + +.TP +--config=cache +If this option is specified, +no configuration tests will be rerun +and all results will be taken from cache. +Note that scons will still consider it an error +if --config=cache is specified +and a necessary test does not +yet have any results in the cache. + +.TP +.RI "-C" " directory" ", --directory=" directory +Change to the specified +.I directory +before searching for the +.IR SConstruct , +.IR Sconstruct , +or +.I sconstruct +file, or doing anything +else. Multiple +.B -C +options are interpreted +relative to the previous one, and the right-most +.B -C +option wins. (This option is nearly +equivalent to +.BR "-f directory/SConstruct" , +except that it will search for +.IR SConstruct , +.IR Sconstruct , +or +.I sconstruct +in the specified directory.) + +.\" .TP +.\" -d +.\" Display dependencies while building target files. Useful for +.\" figuring out why a specific file is being rebuilt, as well as +.\" general debugging of the build process. + +.TP +-D +Works exactly the same way as the +.B -u +option except for the way default targets are handled. +When this option is used and no targets are specified on the command line, +all default targets are built, whether or not they are below the current +directory. + +.TP +.RI --debug= type +Debug the build process. +.I type +specifies what type of debugging: + +.TP +--debug=count +Print how many objects are created +of the various classes used internally by SCons +before and after reading the SConscript files +and before and after building targets. +This is not supported when run under Python versions earlier than 2.1, +when SCons is executed with the Python +.B -O +(optimized) option, +or when the SCons modules +have been compiled with optimization +(that is, when executing from +.B *.pyo +files). + +.TP +--debug=dtree +A synonym for the newer +.B --tree=derived +option. +This will be deprecated in some future release +and ultimately removed. + +.TP +--debug=explain +Print an explanation of precisely why +.B scons +is deciding to (re-)build any targets. +(Note: this does not print anything +for targets that are +.I not +rebuilt.) + +.TP +--debug=findlibs +Instruct the scanner that searches for libraries +to print a message about each potential library +name it is searching for, +and about the actual libraries it finds. + +.TP +--debug=includes +Print the include tree after each top-level target is built. +This is generally used to find out what files are included by the sources +of a given derived file: + +.ES +$ scons --debug=includes foo.o +.EE + +.TP +--debug=memoizer +Prints a summary of hits and misses using the Memoizer, +an internal subsystem that counts +how often SCons uses cached values in memory +instead of recomputing them each time they're needed. +Only available when using Python 2.2 or later. + +.TP +--debug=memory +Prints how much memory SCons uses +before and after reading the SConscript files +and before and after building targets. + +.TP +--debug=nomemoizer +A deprecated option preserved for backwards compatibility. + +.TP +--debug=objects +Prints a list of the various objects +of the various classes used internally by SCons. +This only works when run under Python 2.1 or later. + +.TP +--debug=pdb +Re-run SCons under the control of the +.RI pdb +Python debugger. + +.TP +--debug=presub +Print the raw command line used to build each target +before the construction environment variables are substituted. +Also shows which targets are being built by this command. +Output looks something like this: +.ES +$ scons --debug=presub +Building myprog.o with action(s): + $SHCC $SHCFLAGS $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES +\&... +.EE + +.TP +--debug=stacktrace +Prints an internal Python stack trace +when encountering an otherwise unexplained error. + +.TP +--debug=stree +A synonym for the newer +.B --tree=all,status +option. +This will be deprecated in some future release +and ultimately removed. + +.TP +--debug=time +Prints various time profiling information: +the time spent executing each individual build command; +the total build time (time SCons ran from beginning to end); +the total time spent reading and executing SConscript files; +the total time spent SCons itself spend running +(that is, not counting reading and executing SConscript files); +and both the total time spent executing all build commands +and the elapsed wall-clock time spent executing those build commands. +(When +.B scons +is executed without the +.B -j +option, +the elapsed wall-clock time will typically +be slightly longer than the total time spent +executing all the build commands, +due to the SCons processing that takes place +in between executing each command. +When +.B scons +is executed +.I with +the +.B -j +option, +and your build configuration allows good parallelization, +the elapsed wall-clock time should +be significantly smaller than the +total time spent executing all the build commands, +since multiple build commands and +intervening SCons processing +should take place in parallel.) + +.TP +--debug=tree +A synonym for the newer +.B --tree=all +option. +This will be deprecated in some future release +and ultimately removed. + +.TP +.RI --diskcheck= types +Enable specific checks for +whether or not there is a file on disk +where the SCons configuration expects a directory +(or vice versa), +and whether or not RCS or SCCS sources exist +when searching for source and include files. +The +.I types +argument can be set to: +.BR all , +to enable all checks explicitly +(the default behavior); +.BR none , +to disable all such checks; +.BR match , +to check that files and directories on disk +match SCons' expected configuration; +.BR rcs , +to check for the existence of an RCS source +for any missing source or include files; +.BR sccs , +to check for the existence of an SCCS source +for any missing source or include files. +Multiple checks can be specified separated by commas; +for example, +.B --diskcheck=sccs,rcs +would still check for SCCS and RCS sources, +but disable the check for on-disk matches of files and directories. +Disabling some or all of these checks +can provide a performance boost for large configurations, +or when the configuration will check for files and/or directories +across networked or shared file systems, +at the slight increased risk of an incorrect build +or of not handling errors gracefully +(if include files really should be +found in SCCS or RCS, for example, +or if a file really does exist +where the SCons configuration expects a directory). + +.TP +.RI --duplicate= ORDER +There are three ways to duplicate files in a build tree: hard links, +soft (symbolic) links and copies. The default behaviour of SCons is to +prefer hard links to soft links to copies. You can specify different +behaviours with this option. +.IR ORDER +must be one of +.IR hard-soft-copy +(the default), +.IR soft-hard-copy , +.IR hard-copy , +.IR soft-copy +or +.IR copy . +SCons will attempt to duplicate files using +the mechanisms in the specified order. + +.\" .TP +.\" -e, --environment-overrides +.\" Variables from the execution environment override construction +.\" variables from the SConscript files. + +.TP +.RI -f " file" ", --file=" file ", --makefile=" file ", --sconstruct=" file +Use +.I file +as the initial SConscript file. +Multiple +.B -f +options may be specified, +in which case +.B scons +will read all of the specified files. + +.TP +-h, --help +Print a local help message for this build, if one is defined in +the SConscript file(s), plus a line that describes the +.B -H +option for command-line option help. If no local help message +is defined, prints the standard help message about command-line +options. Exits after displaying the appropriate message. + +.TP +-H, --help-options +Print the standard help message about command-line options and +exit. + +.TP +-i, --ignore-errors +Ignore all errors from commands executed to rebuild files. + +.TP +.RI -I " directory" ", --include-dir=" directory +Specifies a +.I directory +to search for +imported Python modules. If several +.B -I +options +are used, the directories are searched in the order specified. + +.TP +--implicit-cache +Cache implicit dependencies. +This causes +.B scons +to use the implicit (scanned) dependencies +from the last time it was run +instead of scanning the files for implicit dependencies. +This can significantly speed up SCons, +but with the following limitations: +.IP +.B scons +will not detect changes to implicit dependency search paths +(e.g. +.BR CPPPATH ", " LIBPATH ) +that would ordinarily +cause different versions of same-named files to be used. +.IP +.B scons +will miss changes in the implicit dependencies +in cases where a new implicit +dependency is added earlier in the implicit dependency search path +(e.g. +.BR CPPPATH ", " LIBPATH ) +than a current implicit dependency with the same name. + +.TP +--implicit-deps-changed +Forces SCons to ignore the cached implicit dependencies. This causes the +implicit dependencies to be rescanned and recached. This implies +.BR --implicit-cache . + +.TP +--implicit-deps-unchanged +Force SCons to ignore changes in the implicit dependencies. +This causes cached implicit dependencies to always be used. +This implies +.BR --implicit-cache . + +.TP +--interactive +Starts SCons in interactive mode. +The SConscript files are read once and a +.B "scons>>>" +prompt is printed. +Targets may now be rebuilt by typing commands at interactive prompt +without having to re-read the SConscript files +and re-initialize the dependency graph from scratch. + +SCons interactive mode supports the following commands: + +.RS 10 +.TP 6 +.BI build "[OPTIONS] [TARGETS] ..." +Builds the specified +.I TARGETS +(and their dependencies) +with the specified +SCons command-line +.IR OPTIONS . +.B b +and +.B scons +are synonyms. + +The following SCons command-line options affect the +.B build +command: + +.ES +--cache-debug=FILE +--cache-disable, --no-cache +--cache-force, --cache-populate +--cache-show +--debug=TYPE +-i, --ignore-errors +-j N, --jobs=N +-k, --keep-going +-n, --no-exec, --just-print, --dry-run, --recon +-Q +-s, --silent, --quiet +--taskmastertrace=FILE +--tree=OPTIONS +.EE + +.IP "" 6 +Any other SCons command-line options that are specified +do not cause errors +but have no effect on the +.B build +command +(mainly because they affect how the SConscript files are read, +which only happens once at the beginning of interactive mode). + +.TP 6 +.BI clean "[OPTIONS] [TARGETS] ..." +Cleans the specified +.I TARGETS +(and their dependencies) +with the specified options. +.B c +is a synonym. +This command is itself a synonym for +.B "build --clean" + +.TP 6 +.BI exit +Exits SCons interactive mode. +You can also exit by terminating input +(CTRL+D on UNIX or Linux systems, +CTRL+Z on Windows systems). + +.TP 6 +.BI help "[COMMAND]" +Provides a help message about +the commands available in SCons interactive mode. +If +.I COMMAND +is specified, +.B h +and +.B ? +are synonyms. + +.TP 6 +.BI shell "[COMMANDLINE]" +Executes the specified +.I COMMANDLINE +in a subshell. +If no +.I COMMANDLINE +is specified, +executes the interactive command interpreter +specified in the +.B SHELL +environment variable +(on UNIX and Linux systems) +or the +.B COMSPEC +environment variable +(on Windows systems). +.B sh +and +.B ! +are synonyms. + +.TP 6 +.B version +Prints SCons version information. +.RE + +.IP +An empty line repeats the last typed command. +Command-line editing can be used if the +.B readline +module is available. + +.ES +$ scons --interactive +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons>>> build -n prog +scons>>> exit +.EE + +.TP +.RI -j " N" ", --jobs=" N +Specifies the number of jobs (commands) to run simultaneously. +If there is more than one +.B -j +option, the last one is effective. +.\" ??? If the +.\" .B -j +.\" option +.\" is specified without an argument, +.\" .B scons +.\" will not limit the number of +.\" simultaneous jobs. + +.TP +-k, --keep-going +Continue as much as possible after an error. The target that +failed and those that depend on it will not be remade, but other +targets specified on the command line will still be processed. + +.\" .TP +.\" .RI -l " N" ", --load-average=" N ", --max-load=" N +.\" No new jobs (commands) will be started if +.\" there are other jobs running and the system load +.\" average is at least +.\" .I N +.\" (a floating-point number). + +.\" +.\" .TP +.\" --list-derived +.\" List derived files (targets, dependencies) that would be built, +.\" but do not build them. +.\" [XXX This can probably go away with the right +.\" combination of other options. Revisit this issue.] +.\" +.\" .TP +.\" --list-actions +.\" List derived files that would be built, with the actions +.\" (commands) that build them. Does not build the files. +.\" [XXX This can probably go away with the right +.\" combination of other options. Revisit this issue.] +.\" +.\" .TP +.\" --list-where +.\" List derived files that would be built, plus where the file is +.\" defined (file name and line number). Does not build the files. +.\" [XXX This can probably go away with the right +.\" combination of other options. Revisit this issue.] + +.TP +-m +Ignored for compatibility with non-GNU versions of +.BR make . + +.TP +.RI --max-drift= SECONDS +Set the maximum expected drift in the modification time of files to +.IR SECONDS . +This value determines how long a file must be unmodified +before its cached content signature +will be used instead of +calculating a new content signature (MD5 checksum) +of the file's contents. +The default value is 2 days, which means a file must have a +modification time of at least two days ago in order to have its +cached content signature used. +A negative value means to never cache the content +signature and to ignore the cached value if there already is one. A value +of 0 means to always use the cached signature, +no matter how old the file is. + +.TP +.RI --md5-chunksize= KILOBYTES +Set the block size used to compute MD5 signatures to +.IR KILOBYTES . +This value determines the size of the chunks which are read in at once when +computing MD5 signatures. Files below that size are fully stored in memory +before performing the signature computation while bigger files are read in +block-by-block. A huge block-size leads to high memory consumption while a very +small block-size slows down the build considerably. + +The default value is to use a chunk size of 64 kilobytes, which should +be appropriate for most uses. + +.TP +-n, --just-print, --dry-run, --recon +No execute. Print the commands that would be executed to build +any out-of-date target files, but do not execute the commands. + +.TP +.RI --no-site-dir +Prevents the automatic addition of the standard +.I site_scons +dir to +.IR sys.path . +Also prevents loading the +.I site_scons/site_init.py +module if it exists, and prevents adding +.I site_scons/site_tools +to the toolpath. + +.\" .TP +.\" .RI -o " file" ", --old-file=" file ", --assume-old=" file +.\" Do not rebuild +.\" .IR file , +.\" and do +.\" not rebuild anything due to changes in the contents of +.\" .IR file . +.\" .TP +.\" .RI --override " file" +.\" Read values to override specific build environment variables +.\" from the specified +.\" .IR file . +.\" .TP +.\" -p +.\" Print the data base (construction environments, +.\" Builder and Scanner objects) that are defined +.\" after reading the SConscript files. +.\" After printing, a normal build is performed +.\" as usual, as specified by other command-line options. +.\" This also prints version information +.\" printed by the +.\" .B -v +.\" option. +.\" +.\" To print the database without performing a build do: +.\" +.\" .ES +.\" scons -p -q +.\" .EE + +.TP +.RI --profile= file +Run SCons under the Python profiler +and save the results in the specified +.IR file . +The results may be analyzed using the Python +pstats module. + +.TP +-q, --question +Do not run any commands, or print anything. Just return an exit +status that is zero if the specified targets are already up to +date, non-zero otherwise. +.TP +-Q +Quiets SCons status messages about +reading SConscript files, +building targets +and entering directories. +Commands that are executed +to rebuild target files are still printed. + +.\" .TP +.\" -r, -R, --no-builtin-rules, --no-builtin-variables +.\" Clear the default construction variables. Construction +.\" environments that are created will be completely empty. + +.TP +--random +Build dependencies in a random order. This is useful when +building multiple trees simultaneously with caching enabled, +to prevent multiple builds from simultaneously trying to build +or retrieve the same target files. + +.TP +-s, --silent, --quiet +Silent. Do not print commands that are executed to rebuild +target files. +Also suppresses SCons status messages. + +.TP +-S, --no-keep-going, --stop +Ignored for compatibility with GNU +.BR make . + +.TP +.RI --site-dir= dir +Uses the named dir as the site dir rather than the default +.I site_scons +dir. This dir will get prepended to +.IR sys.path , +the module +.IR dir /site_init.py +will get loaded if it exists, and +.IR dir /site_tools +will get added to the default toolpath. + +.TP +.RI --stack-size= KILOBYTES +Set the size stack used to run threads to +.IR KILOBYTES . +This value determines the stack size of the threads used to run jobs. +These are the threads that execute the actions of the builders for the +nodes that are out-of-date. +Note that this option has no effect unless the +.B num_jobs +option, which corresponds to -j and --jobs, is larger than one. Using +a stack size that is too small may cause stack overflow errors. This +usually shows up as segmentation faults that cause scons to abort +before building anything. Using a stack size that is too large will +cause scons to use more memory than required and may slow down the entire +build process. + +The default value is to use a stack size of 256 kilobytes, which should +be appropriate for most uses. You should not need to increase this value +unless you encounter stack overflow errors. + +.TP +-t, --touch +Ignored for compatibility with GNU +.BR make . +(Touching a file to make it +appear up-to-date is unnecessary when using +.BR scons .) + +.TP +.RI --taskmastertrace= file +Prints trace information to the specified +.I file +about how the internal Taskmaster object +evaluates and controls the order in which Nodes are built. +A file name of +.B - +may be used to specify the standard output. + +.TP +.RI -tree= options +Prints a tree of the dependencies +after each top-level target is built. +This prints out some or all of the tree, +in various formats, +depending on the +.I options +specified: + +.TP +--tree=all +Print the entire dependency tree +after each top-level target is built. +This prints out the complete dependency tree, +including implicit dependencies and ignored dependencies. + +.TP +--tree=derived +Restricts the tree output to only derived (target) files, +not source files. + +.TP +--tree=status +Prints status information for each displayed node. + +.TP +--tree=prune +Prunes the tree to avoid repeating dependency information +for nodes that have already been displayed. +Any node that has already been displayed +will have its name printed in +.BR "[square brackets]" , +as an indication that the dependencies +for that node can be found by searching +for the relevant output higher up in the tree. + +.IP +Multiple options may be specified, +separated by commas: + +.ES +# Prints only derived files, with status information: +scons --tree=derived,status + +# Prints all dependencies of target, with status information +# and pruning dependencies of already-visited Nodes: +scons --tree=all,prune,status target +.EE + +.TP +-u, --up, --search-up +Walks up the directory structure until an +.I SConstruct , +.I Sconstruct +or +.I sconstruct +file is found, and uses that +as the top of the directory tree. +If no targets are specified on the command line, +only targets at or below the +current directory will be built. + +.TP +-U +Works exactly the same way as the +.B -u +option except for the way default targets are handled. +When this option is used and no targets are specified on the command line, +all default targets that are defined in the SConscript(s) in the current +directory are built, regardless of what directory the resultant targets end +up in. + +.TP +-v, --version +Print the +.B scons +version, copyright information, +list of authors, and any other relevant information. +Then exit. + +.TP +-w, --print-directory +Print a message containing the working directory before and +after other processing. + +.TP +--no-print-directory +Turn off -w, even if it was turned on implicitly. + +.TP +.RI --warn= type ", --warn=no-" type +Enable or disable warnings. +.I type +specifies the type of warnings to be enabled or disabled: + +.TP +--warn=all, --warn=no-all +Enables or disables all warnings. + +.TP +--warn=cache-write-error, --warn=no-cache-write-error +Enables or disables warnings about errors trying to +write a copy of a built file to a specified +.BR CacheDir (). +These warnings are disabled by default. + +.TP +--warn=corrupt-sconsign, --warn=no-corrupt-sconsign +Enables or disables warnings about unfamiliar signature data in +.B .sconsign +files. +These warnings are enabled by default. + +.TP +--warn=dependency, --warn=no-dependency +Enables or disables warnings about dependencies. +These warnings are disabled by default. + +.TP +--warn=deprecated, --warn=no-deprecated +Enables or disables all warnings about use of +currently deprecated features. +These warnings are enabled by default. +Note that the +.B --warn=no-deprecated +option does not disable warnings about absolutely all deprecated features. +Warnings for some deprecated features that have already been through +several releases with deprecation warnings +may be mandatory for a release or two +before they are officially no longer supported by SCons. +Warnings for some specific deprecated features +may be enabled or disabled individually; +see below. + +.RS +.TP +--warn=deprecated-copy, --warn=no-deprecated-copy +Enables or disables warnings about use of the deprecated +.B env.Copy() +method. + +.TP +--warn=deprecated-source-signatures, --warn=no-deprecated-source-signatures +Enables or disables warnings about use of the deprecated +.B SourceSignatures() +function or +.B env.SourceSignatures() +method. + +.TP +--warn=deprecated-target-signatures, --warn=no-deprecated-target-signatures +Enables or disables warnings about use of the deprecated +.B TargetSignatures() +function or +.B env.TargetSignatures() +method. +.RE + +.TP +--warn=duplicate-environment, --warn=no-duplicate-environment +Enables or disables warnings about attempts to specify a build +of a target with two different construction environments +that use the same action. +These warnings are enabled by default. + +.TP +--warn=fortran-cxx-mix, --warn=no-fortran-cxx-mix +Enables or disables the specific warning about linking +Fortran and C++ object files in a single executable, +which can yield unpredictable behavior with some compilers. + +.TP +--warn=future-deprecated, --warn=no-future-deprecated +Enables or disables warnings about features +that will be deprecated in the future. +These warnings are disabled by default. +Enabling this warning is especially +recommended for projects that redistribute +SCons configurations for other users to build, +so that the project can be warned as soon as possible +about to-be-deprecated features +that may require changes to the configuration. + +.TP +--warn=link, --warn=no-link +Enables or disables warnings about link steps. + +.TP +--warn=misleading-keywords, --warn=no-misleading-keywords +Enables or disables warnings about use of the misspelled keywords +.B targets +and +.B sources +when calling Builders. +(Note the last +.B s +characters, the correct spellings are +.B target +and +.B source.) +These warnings are enabled by default. + +.TP +--warn=missing-sconscript, --warn=no-missing-sconscript +Enables or disables warnings about missing SConscript files. +These warnings are enabled by default. + +.TP +--warn=no-md5-module, --warn=no-no-md5-module +Enables or disables warnings about the version of Python +not having an MD5 checksum module available. +These warnings are enabled by default. + +.TP +--warn=no-metaclass-support, --warn=no-no-metaclass-support +Enables or disables warnings about the version of Python +not supporting metaclasses when the +.B --debug=memoizer +option is used. +These warnings are enabled by default. + +.TP +--warn=no-object-count, --warn=no-no-object-count +Enables or disables warnings about the +.B --debug=object +feature not working when +.B scons +is run with the python +.B \-O +option or from optimized Python (.pyo) modules. + +.TP +--warn=no-parallel-support, --warn=no-no-parallel-support +Enables or disables warnings about the version of Python +not being able to support parallel builds when the +.B -j +option is used. +These warnings are enabled by default. + +.TP +--warn=python-version, --warn=no-python-version +Enables or disables the warning about running +SCons with a deprecated version of Python. +These warnings are enabled by default. + +.TP +--warn=reserved-variable, --warn=no-reserved-variable +Enables or disables warnings about attempts to set the +reserved construction variable names +.BR CHANGED_SOURCES , +.BR CHANGED_TARGETS , +.BR TARGET , +.BR TARGETS , +.BR SOURCE , +.BR SOURCES , +.BR UNCHANGED_SOURCES +or +.BR UNCHANGED_TARGETS . +These warnings are disabled by default. + +.TP +--warn=stack-size, --warn=no-stack-size +Enables or disables warnings about requests to set the stack size +that could not be honored. +These warnings are enabled by default. + +.\" .TP +.\" .RI --write-filenames= file +.\" Write all filenames considered into +.\" .IR file . +.\" +.\" .TP +.\" .RI -W " file" ", --what-if=" file ", --new-file=" file ", --assume-new=" file +.\" Pretend that the target +.\" .I file +.\" has been +.\" modified. When used with the +.\" .B -n +.\" option, this +.\" show you what would be rebuilt if you were to modify that file. +.\" Without +.\" .B -n +.\" ... what? XXX +.\" +.\" .TP +.\" --warn-undefined-variables +.\" Warn when an undefined variable is referenced. + +.TP +.RI -Y " repository" ", --repository=" repository ", --srcdir=" repository +Search the specified repository for any input and target +files not found in the local directory hierarchy. Multiple +.B -Y +options may be specified, in which case the +repositories are searched in the order specified. + +.SH CONFIGURATION FILE REFERENCE +.\" .SS Python Basics +.\" XXX Adding this in the future would be a help. +.SS Construction Environments +A construction environment is the basic means by which the SConscript +files communicate build information to +.BR scons . +A new construction environment is created using the +.B Environment +function: + +.ES +env = Environment() +.EE + +Variables, called +.I construction +.IR variables , +may be set in a construction environment +either by specifying them as keywords when the object is created +or by assigning them a value after the object is created: + +.ES +env = Environment(FOO = 'foo') +env['BAR'] = 'bar' +.EE + +As a convenience, +construction variables may also be set or modified by the +.I parse_flags +keyword argument, which applies the +.B ParseFlags +method (described below) to the argument value +after all other processing is completed. +This is useful either if the exact content of the flags is unknown +(for example, read from a control file) +or if the flags are distributed to a number of construction variables. + +.ES +env = Environment(parse_flags = '-Iinclude -DEBUG -lm') +.EE + +This example adds 'include' to +.BR CPPPATH , +\&'EBUG' to +.BR CPPDEFINES , +and 'm' to +.BR LIBS . + +By default, a new construction environment is +initialized with a set of builder methods +and construction variables that are appropriate +for the current platform. +An optional platform keyword argument may be +used to specify that an environment should +be initialized for a different platform: + +.ES +env = Environment(platform = 'cygwin') +env = Environment(platform = 'os2') +env = Environment(platform = 'posix') +env = Environment(platform = 'win32') +.EE + +Specifying a platform initializes the appropriate +construction variables in the environment +to use and generate file names with prefixes +and suffixes appropriate for the platform. + +Note that the +.B win32 +platform adds the +.B SystemDrive +and +.B SystemRoot +variables from the user's external environment +to the construction environment's +.B ENV +dictionary. +This is so that any executed commands +that use sockets to connect with other systems +(such as fetching source files from +external CVS repository specifications like +.BR :pserver:anonymous@cvs.sourceforge.net:/cvsroot/scons ) +will work on Windows systems. + +The platform argument may be function or callable object, +in which case the Environment() method +will call the specified argument to update +the new construction environment: + +.ES +def my_platform(env): + env['VAR'] = 'xyzzy' + +env = Environment(platform = my_platform) +.EE + +Additionally, a specific set of tools +with which to initialize the environment +may be specified as an optional keyword argument: + +.ES +env = Environment(tools = ['msvc', 'lex']) +.EE + +Non-built-in tools may be specified using the toolpath argument: + +.ES +env = Environment(tools = ['default', 'foo'], toolpath = ['tools']) +.EE + +This looks for a tool specification in tools/foo.py (as well as +using the ordinary default tools for the platform). foo.py should +have two functions: generate(env, **kw) and exists(env). +The +.B generate() +function +modifies the passed-in environment +to set up variables so that the tool +can be executed; +it may use any keyword arguments +that the user supplies (see below) +to vary its initialization. +The +.B exists() +function should return a true +value if the tool is available. +Tools in the toolpath are used before +any of the built-in ones. For example, adding gcc.py to the toolpath +would override the built-in gcc tool. +Also note that the toolpath is +stored in the environment for use +by later calls to +.BR Clone () +and +.BR Tool () +methods: + +.ES +base = Environment(toolpath=['custom_path']) +derived = base.Clone(tools=['custom_tool']) +derived.CustomBuilder() +.EE + +The elements of the tools list may also +be functions or callable objects, +in which case the Environment() method +will call the specified elements +to update the new construction environment: + +.ES +def my_tool(env): + env['XYZZY'] = 'xyzzy' + +env = Environment(tools = [my_tool]) +.EE + +The individual elements of the tools list +may also themselves be two-element lists of the form +.RI ( toolname ", " kw_dict ). +SCons searches for the +.I toolname +specification file as described above, and +passes +.IR kw_dict , +which must be a dictionary, as keyword arguments to the tool's +.B generate +function. +The +.B generate +function can use the arguments to modify the tool's behavior +by setting up the environment in different ways +or otherwise changing its initialization. + +.ES +# in tools/my_tool.py: +def generate(env, **kw): + # Sets MY_TOOL to the value of keyword argument 'arg1' or 1. + env['MY_TOOL'] = kw.get('arg1', '1') +def exists(env): + return 1 + +# in SConstruct: +env = Environment(tools = ['default', ('my_tool', {'arg1': 'abc'})], + toolpath=['tools']) +.EE + +The tool definition (i.e. my_tool()) can use the PLATFORM variable from +the environment it receives to customize the tool for different platforms. + +If no tool list is specified, then SCons will auto-detect the installed +tools using the PATH variable in the ENV construction variable and the +platform name when the Environment is constructed. Changing the PATH +variable after the Environment is constructed will not cause the tools to +be redetected. + +SCons supports the following tool specifications out of the box: + +.ES +386asm +aixc++ +aixcc +aixf77 +aixlink +ar +as +bcc32 +c++ +cc +cvf +dmd +dvipdf +dvips +f77 +f90 +f95 +fortran +g++ +g77 +gas +gcc +gfortran +gnulink +gs +hpc++ +hpcc +hplink +icc +icl +ifl +ifort +ilink +ilink32 +intelc +jar +javac +javah +latex +lex +link +linkloc +m4 +masm +midl +mingw +mslib +mslink +mssdk +msvc +msvs +mwcc +mwld +nasm +pdflatex +pdftex +qt +rmic +rpcgen +sgiar +sgic++ +sgicc +sgilink +sunar +sunc++ +suncc +sunf77 +sunf90 +sunf95 +sunlink +swig +tar +tex +textfile +tlib +yacc +zip +.EE + +Additionally, there is a "tool" named +.B default +which configures the +environment with a default set of tools for the current platform. + +On posix and cygwin platforms +the GNU tools (e.g. gcc) are preferred by SCons, +on Windows the Microsoft tools (e.g. msvc) +followed by MinGW are preferred by SCons, +and in OS/2 the IBM tools (e.g. icc) are preferred by SCons. + +.SS Builder Methods + +Build rules are specified by calling a construction +environment's builder methods. +The arguments to the builder methods are +.B target +(a list of targets to be built, +usually file names) +and +.B source +(a list of sources to be built, +usually file names). + +Because long lists of file names +can lead to a lot of quoting, +.B scons +supplies a +.B Split() +global function +and a same-named environment method +that split a single string +into a list, separated on +strings of white-space characters. +(These are similar to the +string.split() method +from the standard Python library, +but work even if the input isn't a string.) + +Like all Python arguments, +the target and source arguments to a builder method +can be specified either with or without +the "target" and "source" keywords. +When the keywords are omitted, +the target is first, +followed by the source. +The following are equivalent examples of calling the Program builder method: + +.ES +env.Program('bar', ['bar.c', 'foo.c']) +env.Program('bar', Split('bar.c foo.c')) +env.Program('bar', env.Split('bar.c foo.c')) +env.Program(source = ['bar.c', 'foo.c'], target = 'bar') +env.Program(target = 'bar', Split('bar.c foo.c')) +env.Program(target = 'bar', env.Split('bar.c foo.c')) +env.Program('bar', source = string.split('bar.c foo.c')) +.EE + +Target and source file names +that are not absolute path names +(that is, do not begin with +.B / +on POSIX systems +or +.B \\ +on Windows systems, +with or without +an optional drive letter) +are interpreted relative to the directory containing the +.B SConscript +file being read. +An initial +.B # +(hash mark) +on a path name means that the rest of the file name +is interpreted relative to +the directory containing +the top-level +.B SConstruct +file, +even if the +.B # +is followed by a directory separator character +(slash or backslash). + +Examples: + +.ES +# The comments describing the targets that will be built +# assume these calls are in a SConscript file in the +# a subdirectory named "subdir". + +# Builds the program "subdir/foo" from "subdir/foo.c": +env.Program('foo', 'foo.c') + +# Builds the program "/tmp/bar" from "subdir/bar.c": +env.Program('/tmp/bar', 'bar.c') + +# An initial '#' or '#/' are equivalent; the following +# calls build the programs "foo" and "bar" (in the +# top-level SConstruct directory) from "subdir/foo.c" and +# "subdir/bar.c", respectively: +env.Program('#foo', 'foo.c') +env.Program('#/bar', 'bar.c') + +# Builds the program "other/foo" (relative to the top-level +# SConstruct directory) from "subdir/foo.c": +env.Program('#other/foo', 'foo.c') +.EE + +When the target shares the same base name +as the source and only the suffix varies, +and if the builder method has a suffix defined for the target file type, +then the target argument may be omitted completely, +and +.B scons +will deduce the target file name from +the source file name. +The following examples all build the +executable program +.B bar +(on POSIX systems) +or +.B bar.exe +(on Windows systems) +from the bar.c source file: + +.ES +env.Program(target = 'bar', source = 'bar.c') +env.Program('bar', source = 'bar.c') +env.Program(source = 'bar.c') +env.Program('bar.c') +.EE + +As a convenience, a +.B srcdir +keyword argument may be specified +when calling a Builder. +When specified, +all source file strings that are not absolute paths +will be interpreted relative to the specified +.BR srcdir . +The following example will build the +.B build/prog +(or +.B build/prog.exe +on Windows) +program from the files +.B src/f1.c +and +.BR src/f2.c : + +.ES +env.Program('build/prog', ['f1.c', 'f2.c'], srcdir='src') +.EE + +It is possible to override or add construction variables when calling a +builder method by passing additional keyword arguments. +These overridden or added +variables will only be in effect when building the target, so they will not +affect other parts of the build. For example, if you want to add additional +libraries for just one program: + +.ES +env.Program('hello', 'hello.c', LIBS=['gl', 'glut']) +.EE + +or generate a shared library with a non-standard suffix: + +.ES +env.SharedLibrary('word', 'word.cpp', + SHLIBSUFFIX='.ocx', + LIBSUFFIXES=['.ocx']) +.EE + +(Note that both the $SHLIBSUFFIX and $LIBSUFFIXES variables must be set +if you want SCons to search automatically +for dependencies on the non-standard library names; +see the descriptions of these variables, below, for more information.) + +It is also possible to use the +.I parse_flags +keyword argument in an override: + +.ES +env = Program('hello', 'hello.c', parse_flags = '-Iinclude -DEBUG -lm') +.EE + +This example adds 'include' to +.BR CPPPATH , +\&'EBUG' to +.BR CPPDEFINES , +and 'm' to +.BR LIBS . + +Although the builder methods defined by +.B scons +are, in fact, +methods of a construction environment object, +they may also be called without an explicit environment: + +.ES +Program('hello', 'hello.c') +SharedLibrary('word', 'word.cpp') +.EE + +In this case, +the methods are called internally using a default construction +environment that consists of the tools and values that +.B scons +has determined are appropriate for the local system. + +Builder methods that can be called without an explicit +environment may be called from custom Python modules that you +import into an SConscript file by adding the following +to the Python module: + +.ES +from SCons.Script import * +.EE + +All builder methods return a list-like object +containing Nodes that +represent the target or targets that will be built. +A +.I Node +is an internal SCons object +which represents +build targets or sources. + +The returned Node-list object +can be passed to other builder methods as source(s) +or passed to any SCons function or method +where a filename would normally be accepted. +For example, if it were necessary +to add a specific +.B -D +flag when compiling one specific object file: + +.ES +bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR') +env.Program(source = ['foo.c', bar_obj_list, 'main.c']) +.EE + +Using a Node in this way +makes for a more portable build +by avoiding having to specify +a platform-specific object suffix +when calling the Program() builder method. + +Note that Builder calls will automatically "flatten" +the source and target file lists, +so it's all right to have the bar_obj list +return by the StaticObject() call +in the middle of the source file list. +If you need to manipulate a list of lists returned by Builders +directly using Python, +you can either build the list by hand: + +.ES +foo = Object('foo.c') +bar = Object('bar.c') +objects = ['begin.o'] + foo + ['middle.o'] + bar + ['end.o'] +for object in objects: + print str(object) +.EE + +Or you can use the +.BR Flatten () +function supplied by scons +to create a list containing just the Nodes, +which may be more convenient: + +.ES +foo = Object('foo.c') +bar = Object('bar.c') +objects = Flatten(['begin.o', foo, 'middle.o', bar, 'end.o']) +for object in objects: + print str(object) +.EE + +Note also that because Builder calls return +a list-like object, not an actual Python list, +you should +.I not +use the Python +.B += +operator to append Builder results to a Python list. +Because the list and the object are different types, +Python will not update the original list in place, +but will instead create a new Node-list object +containing the concatenation of the list +elements and the Builder results. +This will cause problems for any other Python variables +in your SCons configuration +that still hold on to a reference to the original list. +Instead, use the Python +.B .extend() +method to make sure the list is updated in-place. +Example: + +.ES +object_files = [] + +# Do NOT use += as follows: +# +# object_files += Object('bar.c') +# +# It will not update the object_files list in place. +# +# Instead, use the .extend() method: +object_files.extend(Object('bar.c')) + +.EE + +The path name for a Node's file may be used +by passing the Node to the Python-builtin +.B str() +function: + +.ES +bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR') +print "The path to bar_obj is:", str(bar_obj_list[0]) +.EE + +Note again that because the Builder call returns a list, +we have to access the first element in the list +.B (bar_obj_list[0]) +to get at the Node that actually represents +the object file. + +Builder calls support a +.B chdir +keyword argument that +specifies that the Builder's action(s) +should be executed +after changing directory. +If the +.B chdir +argument is +a string or a directory Node, +scons will change to the specified directory. +If the +.B chdir +is not a string or Node +and is non-zero, +then scons will change to the +target file's directory. + +.ES +# scons will change to the "sub" subdirectory +# before executing the "cp" command. +env.Command('sub/dir/foo.out', 'sub/dir/foo.in', + "cp dir/foo.in dir/foo.out", + chdir='sub') + +# Because chdir is not a string, scons will change to the +# target's directory ("sub/dir") before executing the +# "cp" command. +env.Command('sub/dir/foo.out', 'sub/dir/foo.in', + "cp foo.in foo.out", + chdir=1) +.EE + +Note that scons will +.I not +automatically modify +its expansion of +construction variables like +.B $TARGET +and +.B $SOURCE +when using the chdir +keyword argument--that is, +the expanded file names +will still be relative to +the top-level SConstruct directory, +and consequently incorrect +relative to the chdir directory. +If you use the chdir keyword argument, +you will typically need to supply a different +command line using +expansions like +.B ${TARGET.file} +and +.B ${SOURCE.file} +to use just the filename portion of the +targets and source. + +.B scons +provides the following builder methods: + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +'\" BEGIN GENERATED BUILDER DESCRIPTIONS +'\" +'\" The descriptions below of the various SCons Builders are generated +'\" from the .xml files that live next to the various Python modules in +'\" the build enginer library. If you're reading this [gnt]roff file +'\" with an eye towards patching this man page, you can still submit +'\" a diff against this text, but it will have to be translated to a +'\" diff against the underlying .xml file before the patch is actually +'\" accepted. If you do that yourself, it will make it easier to +'\" integrate the patch. +'\" +'\" BEGIN GENERATED BUILDER DESCRIPTIONS +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.so builders.man +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +'\" END GENERATED BUILDER DESCRIPTIONS +'\" +'\" The descriptions above of the various SCons Builders are generated +'\" from the .xml files that live next to the various Python modules in +'\" the build enginer library. If you're reading this [gnt]roff file +'\" with an eye towards patching this man page, you can still submit +'\" a diff against this text, but it will have to be translated to a +'\" diff against the underlying .xml file before the patch is actually +'\" accepted. If you do that yourself, it will make it easier to +'\" integrate the patch. +'\" +'\" END GENERATED BUILDER DESCRIPTIONS +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +.P +All +targets of builder methods automatically depend on their sources. +An explicit dependency can +be specified using the +.B Depends +method of a construction environment (see below). + +In addition, +.B scons +automatically scans +source files for various programming languages, +so the dependencies do not need to be specified explicitly. +By default, SCons can +C source files, +C++ source files, +Fortran source files with +.B .F +(POSIX systems only), +.B .fpp, +or +.B .FPP +file extensions, +and assembly language files with +.B .S +(POSIX systems only), +.B .spp, +or +.B .SPP +files extensions +for C preprocessor dependencies. +SCons also has default support +for scanning D source files, +You can also write your own Scanners +to add support for additional source file types. +These can be added to the default +Scanner object used by the +.BR Object (), +.BR StaticObject (), +and +.BR SharedObject () +Builders by adding them +to the +.B SourceFileScanner +object as follows: + +See the section "Scanner Objects," +below, for a more information about +defining your own Scanner objects. + +.SS Methods and Functions to Do Things +In addition to Builder methods, +.B scons +provides a number of other construction environment methods +and global functions to +manipulate the build configuration. + +Usually, a construction environment method +and global function with the same name both exist +so that you don't have to remember whether +to a specific bit of functionality +must be called with or without a construction environment. +In the following list, +if you call something as a global function +it looks like: +.ES +.RI Function( arguments ) +.EE +and if you call something through a construction +environment it looks like: +.ES +.RI env.Function( arguments ) +.EE +If you can call the functionality in both ways, +then both forms are listed. + +Global functions may be called from custom Python modules that you +import into an SConscript file by adding the following +to the Python module: + +.ES +from SCons.Script import * +.EE + +Except where otherwise noted, +the same-named +construction environment method +and global function +provide the exact same functionality. +The only difference is that, +where appropriate, +calling the functionality through a construction environment will +substitute construction variables into +any supplied strings. +For example: + +.ES +env = Environment(FOO = 'foo') +Default('$FOO') +env.Default('$FOO') +.EE + +In the above example, +the first call to the global +.B Default() +function will actually add a target named +.B $FOO +to the list of default targets, +while the second call to the +.B env.Default() +construction environment method +will expand the value +and add a target named +.B foo +to the list of default targets. +For more on construction variable expansion, +see the next section on +construction variables. + +Construction environment methods +and global functions supported by +.B scons +include: + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Action( action ", [" cmd/str/fun ", [" var ", ...]] [" option = value ", ...])" +.TP +.IR env .Action( action ", [" cmd/str/fun ", [" var ", ...]] [" option = value ", ...])" +Creates an Action object for +the specified +.IR action . +See the section "Action Objects," +below, for a complete explanation of the arguments and behavior. + +Note that the +.BR env.Action () +form of the invocation will expand +construction variables in any argument strings, +including the +.I action +argument, at the time it is called +using the construction variables in the +.I env +construction environment through which +.BR env.Action () +was called. +The +.BR Action () +form delays all variable expansion +until the Action object is actually used. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI AddMethod( object, function ", [" name ]) +.TP +.RI env.AddMethod( function ", [" name ]) +When called with the +.BR AddMethod () +form, +adds the specified +.I function +to the specified +.I object +as the specified method +.IR name . +When called with the +.BR env.AddMethod () +form, +adds the specified +.I function +to the construction environment +.I env +as the specified method +.IR name . +In both cases, if +.I name +is omitted or +.BR None , +the name of the +specified +.I function +itself is used for the method name. + +Examples: + +.ES +# Note that the first argument to the function to +# be attached as a method must be the object through +# which the method will be called; the Python +# convention is to call it 'self'. +def my_method(self, arg): + print "my_method() got", arg + +# Use the global AddMethod() function to add a method +# to the Environment class. This +AddMethod(Environment, my_method) +env = Environment() +env.my_method('arg') + +# Add the function as a method, using the function +# name for the method call. +env = Environment() +env.AddMethod(my_method, 'other_method_name') +env.other_method_name('another arg') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI AddOption( arguments ) +This function adds a new command-line option to be recognized. +The specified +.I arguments +are the same as supported by the standard Python +.BR optparse.add_option () +method (with a few additional capabilities noted below); +see the documentation for +.B optparse +for a thorough discussion of its option-processing capabities. +(Note that although the +.B optparse +module was not a standard module until Python 2.3, +.B scons +contains a compatible version of the module +that is used to provide identical functionality +when run by earlier Python versions.) + +In addition to the arguments and values supported by the +.B optparse.add_option () +method, +the SCons +.BR AddOption () +function allows you to set the +.B nargs +keyword value to +.B '?' +(a string with just the question mark) +to indicate that the specified long option(s) take(s) an +.I optional +argument. +When +.B "nargs = '?'" +is passed to the +.BR AddOption () +function, the +.B const +keyword argument +may be used to supply the "default" +value that should be used when the +option is specified on the command line +without an explicit argument. + +If no +.B default= +keyword argument is supplied when calling +.BR AddOption (), +the option will have a default value of +.BR None . + +Once a new command-line option has been added with +.BR AddOption (), +the option value may be accessed using +.BR GetOption () +or +.BR env.GetOption (). +\" NOTE: in SCons 1.x or 2.0, user options will be settable, but not yet. +\" Uncomment this when that works. See tigris issue 2105. +\" The value may also be set, using +\" .BR SetOption () +\" or +\" .BR env.SetOption (), +\" if conditions in a +\" .B SConscript +\" require overriding any default value. +\" Note, however, that a +\" value specified on the command line will +\" .I always +\" override a value set by any SConscript file. + +Any specified +.B help= +strings for the new option(s) +will be displayed by the +.B -H +or +.B -h +options +(the latter only if no other help text is +specified in the SConscript files). +The help text for the local options specified by +.BR AddOption () +will appear below the SCons options themselves, +under a separate +.B "Local Options" +heading. +The options will appear in the help text +in the order in which the +.BR AddOption () +calls occur. + +Example: + +.ES +AddOption('--prefix', + dest='prefix', + nargs=1, type='string', + action='store', + metavar='DIR', + help='installation prefix') +env = Environment(PREFIX = GetOption('prefix')) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI AddPostAction( target ", " action ) +.TP +.RI env.AddPostAction( target ", " action ) +Arranges for the specified +.I action +to be performed +after the specified +.I target +has been built. +The specified action(s) may be +an Action object, or anything that +can be converted into an Action object +(see below). + +When multiple targets are supplied, +the action may be called multiple times, +once after each action that generates +one or more targets in the list. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI AddPreAction( target ", " action ) +.TP +.RI env.AddPreAction( target ", " action ) +Arranges for the specified +.I action +to be performed +before the specified +.I target +is built. +The specified action(s) may be +an Action object, or anything that +can be converted into an Action object +(see below). + +When multiple targets are specified, +the action(s) may be called multiple times, +once before each action that generates +one or more targets in the list. + +Note that if any of the targets are built in multiple steps, +the action will be invoked just +before the "final" action that specifically +generates the specified target(s). +For example, when building an executable program +from a specified source +.B .c +file via an intermediate object file: + +.ES +foo = Program('foo.c') +AddPreAction(foo, 'pre_action') +.EE + +The specified +.B pre_action +would be executed before +.B scons +calls the link command that actually +generates the executable program binary +.BR foo , +not before compiling the +.B foo.c +file into an object file. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Alias( alias ", [" targets ", [" action ]]) +.TP +.RI env.Alias( alias ", [" targets ", [" action ]]) +Creates one or more phony targets that +expand to one or more other targets. +An optional +.I action +(command) +or list of actions +can be specified that will be executed +whenever the any of the alias targets are out-of-date. +Returns the Node object representing the alias, +which exists outside of any file system. +This Node object, or the alias name, +may be used as a dependency of any other target, +including another alias. +.B Alias +can be called multiple times for the same +alias to add additional targets to the alias, +or additional actions to the list for this alias. + +Examples: + +.ES +Alias('install') +Alias('install', '/usr/bin') +Alias(['install', 'install-lib'], '/usr/local/lib') + +env.Alias('install', ['/usr/local/bin', '/usr/local/lib']) +env.Alias('install', ['/usr/local/man']) + +env.Alias('update', ['file1', 'file2'], "update_database $SOURCES") +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI AllowSubstExceptions([ exception ", ...])" +Specifies the exceptions that will be allowed +when expanding construction variables. +By default, +any construction variable expansions that generate a +.B NameError +or +.BR IndexError +exception will expand to a +.B '' +(a null string) and not cause scons to fail. +All exceptions not in the specified list +will generate an error message +and terminate processing. + +If +.B AllowSubstExceptions +is called multiple times, +each call completely overwrites the previous list +of allowed exceptions. + +Example: + +.ES +# Requires that all construction variable names exist. +# (You may wish to do this if you want to enforce strictly +# that all construction variables must be defined before use.) +AllowSubstExceptions() + +# Also allow a string containing a zero-division expansion +# like '${1 / 0}' to evalute to ''. +AllowSubstExceptions(IndexError, NameError, ZeroDivisionError) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI AlwaysBuild( target ", ...)" +.TP +.RI env.AlwaysBuild( target ", ...)" +Marks each given +.I target +so that it is always assumed to be out of date, +and will always be rebuilt if needed. +Note, however, that +.BR AlwaysBuild () +does not add its target(s) to the default target list, +so the targets will only be built +if they are specified on the command line, +or are a dependent of a target specified on the command line--but +they will +.I always +be built if so specified. +Multiple targets can be passed in to a single call to +.BR AlwaysBuild (). + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.Append( key = val ", [...])" +Appends the specified keyword arguments +to the end of construction variables in the environment. +If the Environment does not have +the specified construction variable, +it is simply added to the environment. +If the values of the construction variable +and the keyword argument are the same type, +then the two values will be simply added together. +Otherwise, the construction variable +and the value of the keyword argument +are both coerced to lists, +and the lists are added together. +(See also the Prepend method, below.) + +Example: + +.ES +env.Append(CCFLAGS = ' -g', FOO = ['foo.yyy']) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.AppendENVPath( name ", " newpath ", [" envname ", " sep ", " delete_existing ]) +This appends new path elements to the given path in the +specified external environment +.RB ( ENV +by default). +This will only add +any particular path once (leaving the last one it encounters and +ignoring the rest, to preserve path order), +and to help assure this, +will normalize all paths (using +.B os.path.normpath +and +.BR os.path.normcase ). +This can also handle the +case where the given old path variable is a list instead of a +string, in which case a list will be returned instead of a string. + +If +.I delete_existing +is 0, then adding a path that already exists +will not move it to the end; it will stay where it is in the list. + +Example: + +.ES +print 'before:',env['ENV']['INCLUDE'] +include_path = '/foo/bar:/foo' +env.AppendENVPath('INCLUDE', include_path) +print 'after:',env['ENV']['INCLUDE'] + +yields: +before: /foo:/biz +after: /biz:/foo/bar:/foo +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.AppendUnique( key = val ", [...], delete_existing=0)" +Appends the specified keyword arguments +to the end of construction variables in the environment. +If the Environment does not have +the specified construction variable, +it is simply added to the environment. +If the construction variable being appended to is a list, +then any value(s) that already exist in the +construction variable will +.I not +be added again to the list. +However, if delete_existing is 1, +existing matching values are removed first, so +existing values in the arg list move to the end of the list. + +Example: + +.ES +env.AppendUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +env.BitKeeper() +A factory function that +returns a Builder object +to be used to fetch source files +using BitKeeper. +The returned Builder +is intended to be passed to the +.B SourceCode +function. + +Example: + +.ES +env.SourceCode('.', env.BitKeeper()) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI BuildDir( build_dir ", " src_dir ", [" duplicate ]) +.TP +.RI env.BuildDir( build_dir ", " src_dir ", [" duplicate ]) +Deprecated synonyms for +.BR VariantDir () +and +.BR env.VariantDir (). +The +.I build_dir +argument becomes the +.I variant_dir +argument of +.BR VariantDir () +or +.BR env.VariantDir (). + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Builder( action ", [" arguments ]) +.TP +.RI env.Builder( action ", [" arguments ]) +Creates a Builder object for +the specified +.IR action . +See the section "Builder Objects," +below, for a complete explanation of the arguments and behavior. + +Note that the +.BR env.Builder () +form of the invocation will expand +construction variables in any arguments strings, +including the +.I action +argument, +at the time it is called +using the construction variables in the +.B env +construction environment through which +.BR env.Builder () +was called. +The +.BR Builder () +form delays all variable expansion +until after the Builder object is actually called. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI CacheDir( cache_dir ) +.TP +.RI env.CacheDir( cache_dir ) +Specifies that +.B scons +will maintain a cache of derived files in +.I cache_dir . +The derived files in the cache will be shared +among all the builds using the same +.BR CacheDir () +call. +Specifying a +.I cache_dir +of +.B None +disables derived file caching. + +Calling +.BR env.CacheDir () +will only affect targets built +through the specified construction environment. +Calling +.BR CacheDir () +sets a global default +that will be used by all targets built +through construction environments +that do +.I not +have an +.BR env.CacheDir () +specified. + +When a +.BR CacheDir () +is being used and +.B scons +finds a derived file that needs to be rebuilt, +it will first look in the cache to see if a +derived file has already been built +from identical input files and an identical build action +(as incorporated into the MD5 build signature). +If so, +.B scons +will retrieve the file from the cache. +If the derived file is not present in the cache, +.B scons +will rebuild it and +then place a copy of the built file in the cache +(identified by its MD5 build signature), +so that it may be retrieved by other +builds that need to build the same derived file +from identical inputs. + +Use of a specified +.BR CacheDir() +may be disabled for any invocation +by using the +.B --cache-disable +option. + +If the +.B --cache-force +option is used, +.B scons +will place a copy of +.I all +derived files in the cache, +even if they already existed +and were not built by this invocation. +This is useful to populate a cache +the first time +.BR CacheDir () +is added to a build, +or after using the +.B --cache-disable +option. + +When using +.BR CacheDir (), +.B scons +will report, +"Retrieved `file' from cache," +unless the +.B --cache-show +option is being used. +When the +.B --cache-show +option is used, +.B scons +will print the action that +.I would +have been used to build the file, +without any indication that +the file was actually retrieved from the cache. +This is useful to generate build logs +that are equivalent regardless of whether +a given derived file has been built in-place +or retrieved from the cache. + +The +.BR NoCache () +method can be used to disable caching of specific files. This can be +useful if inputs and/or outputs of some tool are impossible to +predict or prohibitively large. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Clean( targets ", " files_or_dirs ) +.TP +.RI env.Clean( targets ", " files_or_dirs ) +This specifies a list of files or directories which should be removed +whenever the targets are specified with the +.B -c +command line option. +The specified targets may be a list +or an individual target. +Multiple calls to +.BR Clean () +are legal, +and create new targets or add files and directories to the +clean list for the specified targets. + +Multiple files or directories should be specified +either as separate arguments to the +.BR Clean () +method, or as a list. +.BR Clean () +will also accept the return value of any of the construction environment +Builder methods. +Examples: + +The related +.BR NoClean () +function overrides calling +.BR Clean () +for the same target, +and any targets passed to both functions will +.I not +be removed by the +.B -c +option. + +Examples: + +.ES +Clean('foo', ['bar', 'baz']) +Clean('dist', env.Program('hello', 'hello.c')) +Clean(['foo', 'bar'], 'something_else_to_clean') +.EE + +In this example, +installing the project creates a subdirectory for the documentation. +This statement causes the subdirectory to be removed +if the project is deinstalled. +.ES +Clean(docdir, os.path.join(docdir, projectname)) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Command( target ", " source ", " action ", [" key = val ", ...])" +.TP +.RI env.Command( target ", " source ", " action ", [" key = val ", ...])" +Executes a specific action +(or list of actions) +to build a target file or files. +This is more convenient +than defining a separate Builder object +for a single special-case build. + +As a special case, the +.B source_scanner +keyword argument can +be used to specify +a Scanner object +that will be used to scan the sources. +(The global +.B DirScanner +object can be used +if any of the sources will be directories +that must be scanned on-disk for +changes to files that aren't +already specified in other Builder of function calls.) + +Any other keyword arguments specified override any +same-named existing construction variables. + +An action can be an external command, +specified as a string, +or a callable Python object; +see "Action Objects," below, +for more complete information. +Also note that a string specifying an external command +may be preceded by an +.B @ +(at-sign) +to suppress printing the command in question, +or by a +.B \- +(hyphen) +to ignore the exit status of the external command. + +Examples: + +.ES +env.Command('foo.out', 'foo.in', + "$FOO_BUILD < $SOURCES > $TARGET") + +env.Command('bar.out', 'bar.in', + ["rm -f $TARGET", + "$BAR_BUILD < $SOURCES > $TARGET"], + ENV = {'PATH' : '/usr/local/bin/'}) + +def rename(env, target, source): + import os + os.rename('.tmp', str(target[0])) + +env.Command('baz.out', 'baz.in', + ["$BAZ_BUILD < $SOURCES > .tmp", + rename ]) +.EE + +.IP +Note that the +.BR Command () +function will usually assume, by default, +that the specified targets and/or sources are Files, +if no other part of the configuration +identifies what type of entry it is. +If necessary, you can explicitly specify +that targets or source nodes should +be treated as directoriese +by using the +.BR Dir () +or +.BR env.Dir () +functions. + +Examples: + +.ES +env.Command('ddd.list', Dir('ddd'), 'ls -l $SOURCE > $TARGET') + +env['DISTDIR'] = 'destination/directory' +env.Command(env.Dir('$DISTDIR')), None, make_distdir) +.EE + +.IP +(Also note that SCons will usually +automatically create any directory necessary to hold a target file, +so you normally don't need to create directories by hand.) + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Configure( env ", [" custom_tests ", " conf_dir ", " log_file ", " config_h ]) +.TP +.RI env.Configure([ custom_tests ", " conf_dir ", " log_file ", " config_h ]) +Creates a Configure object for integrated +functionality similar to GNU autoconf. +See the section "Configure Contexts," +below, for a complete explanation of the arguments and behavior. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.Clone([ key = val ", ...])" +Return a separate copy of a construction environment. +If there are any keyword arguments specified, +they are added to the returned copy, +overwriting any existing values +for the keywords. + +Example: + +.ES +env2 = env.Clone() +env3 = env.Clone(CCFLAGS = '-g') +.EE +.IP +Additionally, a list of tools and a toolpath may be specified, as in +the Environment constructor: + +.ES +def MyTool(env): env['FOO'] = 'bar' +env4 = env.Clone(tools = ['msvc', MyTool]) +.EE + +The +.I parse_flags +keyword argument is also recognized: + +.ES +# create an environment for compiling programs that use wxWidgets +wx_env = env.Clone(parse_flags = '!wx-config --cflags --cxxflags') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.Copy([ key = val ", ...])" +A now-deprecated synonym for +.BR env.Clone() . + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.CVS( repository ", " module ) +A factory function that +returns a Builder object +to be used to fetch source files +from the specified +CVS +.IR repository . +The returned Builder +is intended to be passed to the +.B SourceCode +function. + +The optional specified +.I module +will be added to the beginning +of all repository path names; +this can be used, in essence, +to strip initial directory names +from the repository path names, +so that you only have to +replicate part of the repository +directory hierarchy in your +local build directory. + +Examples: + +.ES +# Will fetch foo/bar/src.c +# from /usr/local/CVSROOT/foo/bar/src.c. +env.SourceCode('.', env.CVS('/usr/local/CVSROOT')) + +# Will fetch bar/src.c +# from /usr/local/CVSROOT/foo/bar/src.c. +env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo')) + +# Will fetch src.c +# from /usr/local/CVSROOT/foo/bar/src.c. +env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo/bar')) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Decider( function ) +.TP +.RI env.Decider( function ) +Specifies that all up-to-date decisions for +targets built through this construction environment +will be handled by the specified +.IR function . +The +.I function +can be one of the following strings +that specify the type of decision function +to be performed: + +.RS 10 +.HP 6 +.B timestamp-newer +Specifies that a target shall be considered out of date and rebuilt +if the dependency's timestamp is newer than the target file's timestamp. +This is the behavior of the classic Make utility, +and +.B make +can be used a synonym for +.BR timestamp-newer . + +.HP 6 +.B timestamp-match +Specifies that a target shall be considered out of date and rebuilt +if the dependency's timestamp is different than the +timestamp recorded the last time the target was built. +This provides behavior very similar to the classic Make utility +(in particular, files are not opened up so that their +contents can be checksummed) +except that the target will also be rebuilt if a +dependency file has been restored to a version with an +.I earlier +timestamp, such as can happen when restoring files from backup archives. + +.HP 6 +.B MD5 +Specifies that a target shall be considered out of date and rebuilt +if the dependency's content has changed sine the last time +the target was built, +as determined be performing an MD5 checksum +on the dependency's contents +and comparing it to the checksum recorded the +last time the target was built. +.B content +can be used as a synonym for +.BR MD5 . + +.HP 6 +.B MD5-timestamp +Specifies that a target shall be considered out of date and rebuilt +if the dependency's content has changed sine the last time +the target was built, +except that dependencies with a timestamp that matches +the last time the target was rebuilt will be +assumed to be up-to-date and +.I not +rebuilt. +This provides behavior very similar +to the +.B MD5 +behavior of always checksumming file contents, +with an optimization of not checking +the contents of files whose timestamps haven't changed. +The drawback is that SCons will +.I not +detect if a file's content has changed +but its timestamp is the same, +as might happen in an automated script +that runs a build, +updates a file, +and runs the build again, +all within a single second. +.RE + +.IP +Examples: + +.ES +# Use exact timestamp matches by default. +Decider('timestamp-match') + +# Use MD5 content signatures for any targets built +# with the attached construction environment. +env.Decider('content') +.EE + +.IP +In addition to the above already-available functions, +the +.I function +argument may be an actual Python function +that takes the following three arguments: + +.RS 10 +.IP dependency +The Node (file) which +should cause the +.I target +to be rebuilt +if it has "changed" since the last tme +.I target was built. + +.IP target +The Node (file) being built. +In the normal case, +this is what should get rebuilt +if the +.I dependency +has "changed." + +.IP prev_ni +Stored information about the state of the +.I dependency +the last time the +.I target +was built. +This can be consulted to match various +file characteristics +such as the timestamp, +size, or content signature. +.RE + +.IP +The +.I function +should return a +.B True +(non-zero) +value if the +.I dependency +has "changed" since the last time +the +.I target +was built +(indicating that the target +.I should +be rebuilt), +and +.B False +(zero) +otherwise +(indicating that the target should +.I not +be rebuilt). +Note that the decision can be made +using whatever criteria are appopriate. +Ignoring some or all of the function arguments +is perfectly normal. + +Example: + +.ES +def my_decider(dependency, target, prev_ni): + return not os.path.exists(str(target)) + +env.Decider(my_decider) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Default( targets ) +.TP +.RI env.Default( targets ) +This specifies a list of default targets, +which will be built by +.B scons +if no explicit targets are given on the command line. +Multiple calls to +.BR Default () +are legal, +and add to the list of default targets. + +Multiple targets should be specified as +separate arguments to the +.BR Default () +method, or as a list. +.BR Default () +will also accept the Node returned by any +of a construction environment's +builder methods. + +Examples: + +.ES +Default('foo', 'bar', 'baz') +env.Default(['a', 'b', 'c']) +hello = env.Program('hello', 'hello.c') +env.Default(hello) +.EE +.IP +An argument to +.BR Default () +of +.B None +will clear all default targets. +Later calls to +.BR Default () +will add to the (now empty) default-target list +like normal. + +The current list of targets added using the +.BR Default () +function or method is available in the +.B DEFAULT_TARGETS +list; +see below. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI DefaultEnvironment([ args ]) +Creates and returns a default construction environment object. +This construction environment is used internally by SCons +in order to execute many of the global functions in this list, +and to fetch source files transparently +from source code management systems. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Depends( target ", " dependency ) +.TP +.RI env.Depends( target ", " dependency ) +Specifies an explicit dependency; +the +.I target +will be rebuilt +whenever the +.I dependency +has changed. +Both the specified +.I target +and +.I dependency +can be a string +(usually the path name of a file or directory) +or Node objects, +or a list of strings or Node objects +(such as returned by a Builder call). +This should only be necessary +for cases where the dependency +is not caught by a Scanner +for the file. + +Example: + +.ES +env.Depends('foo', 'other-input-file-for-foo') + +mylib = env.Library('mylib.c') +installed_lib = env.Install('lib', mylib) +bar = env.Program('bar.c') + +# Arrange for the library to be copied into the installation +# directory before trying to build the "bar" program. +# (Note that this is for example only. A "real" library +# dependency would normally be configured through the $LIBS +# and $LIBPATH variables, not using an env.Depends() call.) + +env.Depends(bar, installed_lib) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.Dictionary([ vars ]) +Returns a dictionary object +containing copies of all of the +construction variables in the environment. +If there are any variable names specified, +only the specified construction +variables are returned in the dictionary. + +Example: + +.ES +dict = env.Dictionary() +cc_dict = env.Dictionary('CC', 'CCFLAGS', 'CCCOM') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Dir( name ", [" directory ]) +.TP +.RI env.Dir( name ", [" directory ]) +This returns a Directory Node, +an object that represents the specified directory +.IR name . +.I name +can be a relative or absolute path. +.I directory +is an optional directory that will be used as the parent directory. +If no +.I directory +is specified, the current script's directory is used as the parent. + +If +.I name +is a list, SCons returns a list of Dir nodes. +Construction variables are expanded in +.IR name . + +Directory Nodes can be used anywhere you +would supply a string as a directory name +to a Builder method or function. +Directory Nodes have attributes and methods +that are useful in many situations; +see "File and Directory Nodes," below. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.Dump([ key ]) +Returns a pretty printable representation of the environment. +.IR key , +if not +.IR None , +should be a string containing the name of the variable of interest. + +This SConstruct: +.ES +env=Environment() +print env.Dump('CCCOM') +.EE +.IP +will print: +.ES +\&'$CC -c -o $TARGET $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $SOURCES' +.EE + +.ES +env=Environment() +print env.Dump() +.EE +.IP +will print: +.ES +{ 'AR': 'ar', + 'ARCOM': '$AR $ARFLAGS $TARGET $SOURCES\n$RANLIB $RANLIBFLAGS $TARGET', + 'ARFLAGS': ['r'], + 'AS': 'as', + 'ASCOM': '$AS $ASFLAGS -o $TARGET $SOURCES', + 'ASFLAGS': [], + ... +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI EnsurePythonVersion( major ", " minor ) +.TP +.RI env.EnsurePythonVersion( major ", " minor ) +Ensure that the Python version is at least +.IR major . minor . +This function will +print out an error message and exit SCons with a non-zero exit code if the +actual Python version is not late enough. + +Example: + +.ES +EnsurePythonVersion(2,2) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI EnsureSConsVersion( major ", " minor ", [" revision ]) +.TP +.RI env.EnsureSConsVersion( major ", " minor ", [" revision ]) +Ensure that the SCons version is at least +.IR major.minor , +or +.IR major.minor.revision . +if +.I revision +is specified. +This function will +print out an error message and exit SCons with a non-zero exit code if the +actual SCons version is not late enough. + +Examples: + +.ES +EnsureSConsVersion(0,14) + +EnsureSConsVersion(0,96,90) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Environment([ key = value ", ...])" +.TP +.RI env.Environment([ key = value ", ...])" +Return a new construction environment +initialized with the specified +.IR key = value +pairs. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Execute( action ", [" strfunction ", " varlist ]) +.TP +.RI env.Execute( action ", [" strfunction ", " varlist ]) +Executes an Action object. +The specified +.IR action +may be an Action object +(see the section "Action Objects," +below, for a complete explanation of the arguments and behavior), +or it may be a command-line string, +list of commands, +or executable Python function, +each of which will be converted +into an Action object +and then executed. +The exit value of the command +or return value of the Python function +will be returned. + +Note that +.B scons +will print an error message if the executed +.I action +fails--that is, +exits with or returns a non-zero value. +.B scons +will +.I not , +however, +automatically terminate the build +if the specified +.I action +fails. +If you want the build to stop in response to a failed +.BR Execute () +call, +you must explicitly check for a non-zero return value: + +.ES +Execute(Copy('file.out', 'file.in')) + +if Execute("mkdir sub/dir/ectory"): + # The mkdir failed, don't try to build. + Exit(1) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Exit([ value ]) +.TP +.RI env.Exit([ value ]) +This tells +.B scons +to exit immediately +with the specified +.IR value . +A default exit value of +.B 0 +(zero) +is used if no value is specified. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Export( vars ) +.TP +.RI env.Export( vars ) +This tells +.B scons +to export a list of variables from the current +SConscript file to all other SConscript files. +The exported variables are kept in a global collection, +so subsequent calls to +.BR Export () +will over-write previous exports that have the same name. +Multiple variable names can be passed to +.BR Export () +as separate arguments or as a list. +Keyword arguments can be used to provide names and their values. +A dictionary can be used to map variables to a different name when exported. +Both local variables and global variables can be exported. + +Examples: + +.ES +env = Environment() +# Make env available for all SConscript files to Import(). +Export("env") + +package = 'my_name' +# Make env and package available for all SConscript files:. +Export("env", "package") + +# Make env and package available for all SConscript files: +Export(["env", "package"]) + +# Make env available using the name debug: +Export(debug = env) + +# Make env available using the name debug: +Export({"debug":env}) +.EE + +.IP +Note that the +.BR SConscript () +function supports an +.I exports +argument that makes it easier to to export a variable or +set of variables to a single SConscript file. +See the description of the +.BR SConscript () +function, below. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI File( name ", [" directory ]) +.TP +.RI env.File( name ", [" directory ]) +This returns a +File Node, +an object that represents the specified file +.IR name . +.I name +can be a relative or absolute path. +.I directory +is an optional directory that will be used as the parent directory. + +If +.I name +is a list, SCons returns a list of File nodes. +Construction variables are expanded in +.IR name . + +File Nodes can be used anywhere you +would supply a string as a file name +to a Builder method or function. +File Nodes have attributes and methods +that are useful in many situations; +see "File and Directory Nodes," below. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI FindFile( file ", " dirs ) +.TP +.RI env.FindFile( file ", " dirs ) +Search for +.I file +in the path specified by +.IR dirs . +.I dirs +may be a list of directory names or a single directory name. +In addition to searching for files that exist in the filesytem, +this function also searches for derived files +that have not yet been built. + +Example: + +.ES +foo = env.FindFile('foo', ['dir1', 'dir2']) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI FindInstalledFiles( ) +.TP +.RI env.FindInstalledFiles( ) +Returns the list of targets set up by the +.B Install() +or +.B InstallAs() +builders. + +This function serves as a convenient method to select the contents of +a binary package. + +Example: + +.ES +Install( '/bin', [ 'executable_a', 'executable_b' ] ) + +# will return the file node list +# [ '/bin/executable_a', '/bin/executable_b' ] +FindInstalledFiles() + +Install( '/lib', [ 'some_library' ] ) + +# will return the file node list +# [ '/bin/executable_a', '/bin/executable_b', '/lib/some_library' ] +FindInstalledFiles() +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI FindSourceFiles( node = '"."' ) +.TP +.RI env.FindSourceFiles( node = '"."' ) + +Returns the list of nodes which serve as the source of the built files. +It does so by inspecting the dependency tree starting at the optional +argument +.B node +which defaults to the '"."'-node. It will then return all leaves of +.B node. +These are all children which have no further children. + +This function is a convenient method to select the contents of a Source +Package. + +Example: + +.ES +Program( 'src/main_a.c' ) +Program( 'src/main_b.c' ) +Program( 'main_c.c' ) + +# returns ['main_c.c', 'src/main_a.c', 'SConstruct', 'src/main_b.c'] +FindSourceFiles() + +# returns ['src/main_b.c', 'src/main_a.c' ] +FindSourceFiles( 'src' ) +.EE + +.IP +As you can see build support files (SConstruct in the above example) +will also be returned by this function. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI FindPathDirs( variable ) +Returns a function +(actually a callable Python object) +intended to be used as the +.B path_function +of a Scanner object. +The returned object will look up the specified +.I variable +in a construction environment +and treat the construction variable's value as a list of +directory paths that should be searched +(like +.BR CPPPATH , +.BR LIBPATH , +etc.). + +Note that use of +.BR FindPathDirs () +is generally preferable to +writing your own +.B path_function +for the following reasons: +1) The returned list will contain all appropriate directories +found in source trees +(when +.BR VariantDir () +is used) +or in code repositories +(when +.BR Repository () +or the +.B \-Y +option are used). +2) scons will identify expansions of +.I variable +that evaluate to the same list of directories as, +in fact, the same list, +and avoid re-scanning the directories for files, +when possible. + +Example: + +.ES +def my_scan(node, env, path, arg): + # Code to scan file contents goes here... + return include_files + +scanner = Scanner(name = 'myscanner', + function = my_scan, + path_function = FindPathDirs('MYPATH')) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Flatten( sequence ) +.TP +.RI env.Flatten( sequence ) +Takes a sequence (that is, a Python list or tuple) +that may contain nested sequences +and returns a flattened list containing +all of the individual elements in any sequence. +This can be helpful for collecting +the lists returned by calls to Builders; +other Builders will automatically +flatten lists specified as input, +but direct Python manipulation of +these lists does not. + +Examples: + +.ES +foo = Object('foo.c') +bar = Object('bar.c') + +# Because `foo' and `bar' are lists returned by the Object() Builder, +# `objects' will be a list containing nested lists: +objects = ['f1.o', foo, 'f2.o', bar, 'f3.o'] + +# Passing such a list to another Builder is all right because +# the Builder will flatten the list automatically: +Program(source = objects) + +# If you need to manipulate the list directly using Python, you need to +# call Flatten() yourself, or otherwise handle nested lists: +for object in Flatten(objects): + print str(object) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI GetBuildFailures() +Returns a list of exceptions for the +actions that failed while +attempting to build targets. +Each element in the returned list is a +.B BuildError +object +with the following attributes +that record various aspects +of the build failure: + +.B .node +The node that was being built +when the build failure occurred. + +.B .status +The numeric exit status +returned by the command or Python function +that failed when trying to build the +specified Node. + +.B .errstr +The SCons error string +describing the build failure. +(This is often a generic +message like "Error 2" +to indicate that an executed +command exited with a status of 2.) + +.B .filename +The name of the file or +directory that actually caused the failure. +This may be different from the +.B .node +attribute. +For example, +if an attempt to build a target named +.B sub/dir/target +fails because the +.B sub/dir +directory could not be created, +then the +.B .node +attribute will be +.B sub/dir/target +but the +.B .filename +attribute will be +.BR sub/dir . + +.B .executor +The SCons Executor object +for the target Node +being built. +This can be used to retrieve +the construction environment used +for the failed action. + +.B .action +The actual SCons Action object that failed. +This will be one specific action +out of the possible list of +actions that would have been +executed to build the target. + +.B .command +The actual expanded command that was executed and failed, +after expansion of +.BR $TARGET , +.BR $SOURCE , +and other construction variables. + +Note that the +.BR GetBuildFailures () +function +will always return an empty list +until any build failure has occurred, +which means that +.BR GetBuildFailures () +will always return an empty list +while the +.B SConscript +files are being read. +Its primary intended use is +for functions that will be +executed before SCons exits +by passing them to the +standard Python +.BR atexit.register () +function. +Example: + +.ES +import atexit + +def print_build_failures(): + from SCons.Script import GetBuildFailures + for bf in GetBuildFailures(): + print "%s failed: %s" % (bf.node, bf.errstr) + +atexit.register(print_build_failures) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI GetBuildPath( file ", [" ... ]) +.TP +.RI env.GetBuildPath( file ", [" ... ]) +Returns the +.B scons +path name (or names) for the specified +.I file +(or files). +The specified +.I file +or files +may be +.B scons +Nodes or strings representing path names. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI GetLaunchDir() +.TP +.RI env.GetLaunchDir() +Returns the absolute path name of the directory from which +.B scons +was initially invoked. +This can be useful when using the +.BR \-u , +.BR \-U +or +.BR \-D +options, which internally +change to the directory in which the +.B SConstruct +file is found. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI GetOption( name ) +.TP +.RI env.GetOption( name ) +This function provides a way to query the value of +SCons options set on scons command line +(or set using the +.IR SetOption () +function). +The options supported are: + +.RS 10 +.TP 6 +.B cache_debug +which corresponds to --cache-debug; +.TP 6 +.B cache_disable +which corresponds to --cache-disable; +.TP 6 +.B cache_force +which corresponds to --cache-force; +.TP 6 +.B cache_show +which corresponds to --cache-show; +.TP 6 +.B clean +which corresponds to -c, --clean and --remove; +.TP 6 +.B config +which corresponds to --config; +.TP 6 +.B directory +which corresponds to -C and --directory; +.TP 6 +.B diskcheck +which corresponds to --diskcheck +.TP 6 +.B duplicate +which corresponds to --duplicate; +.TP 6 +.B file +which corresponds to -f, --file, --makefile and --sconstruct; +.TP 6 +.B help +which corresponds to -h and --help; +.TP 6 +.B ignore_errors +which corresponds to --ignore-errors; +.TP 6 +.B implicit_cache +which corresponds to --implicit-cache; +.TP 6 +.B implicit_deps_changed +which corresponds to --implicit-deps-changed; +.TP 6 +.B implicit_deps_unchanged +which corresponds to --implicit-deps-unchanged; +.TP 6 +.B interactive +which corresponds to --interact and --interactive; +.TP 6 +.B keep_going +which corresponds to -k and --keep-going; +.TP 6 +.B max_drift +which corresponds to --max-drift; +.TP 6 +.B no_exec +which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; +.TP 6 +.B no_site_dir +which corresponds to --no-site-dir; +.TP 6 +.B num_jobs +which corresponds to -j and --jobs; +.TP 6 +.B profile_file +which corresponds to --profile; +.TP 6 +.B question +which corresponds to -q and --question; +.TP 6 +.B random +which corresponds to --random; +.TP 6 +.B repository +which corresponds to -Y, --repository and --srcdir; +.TP 6 +.B silent +which corresponds to -s, --silent and --quiet; +.TP 6 +.B site_dir +which corresponds to --site-dir; +.TP 6 +.B stack_size +which corresponds to --stack-size; +.TP 6 +.B taskmastertrace_file +which corresponds to --taskmastertrace; and +.TP 6 +.B warn +which corresponds to --warn and --warning. +.RE + +.IP +See the documentation for the +corresponding command line object for information about each specific +option. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Glob( pattern ", [" ondisk ", " source ", " strings ]) +.TP +.RI env.Glob( pattern ", [" ondisk ", " source ", " strings ]) +Returns Nodes (or strings) that match the specified +.IR pattern , +relative to the directory of the current +.B SConscript +file. +The +.BR env.Glob () +form performs string substition on +.I pattern +and returns whatever matches +the resulting expanded pattern. + +The specified +.I pattern +uses Unix shell style metacharacters for matching: + +.ES + * matches everything + ? matches any single character + [seq] matches any character in seq + [!seq] matches any char not in seq +.EE + +.IP +If the first character of a filename is a dot, +it must be matched explicitly. +Character matches do +.I not +span directory separators. + +The +.BR Glob () +knows about +repositories +(see the +.BR Repository () +function) +and source directories +(see the +.BR VariantDir () +function) +and +returns a Node (or string, if so configured) +in the local (SConscript) directory +if matching Node is found +anywhere in a corresponding +repository or source directory. + +The +.B ondisk +argument may be set to +.B False +(or any other non-true value) +to disable the search for matches on disk, +thereby only returning matches among +already-configured File or Dir Nodes. +The default behavior is to +return corresponding Nodes +for any on-disk matches found. + +The +.B source +argument may be set to +.B True +(or any equivalent value) +to specify that, +when the local directory is a +.BR VariantDir (), +the returned Nodes should be from the +corresponding source directory, +not the local directory. + +The +.B strings +argument may be set to +.B True +(or any equivalent value) +to have the +.BR Glob () +function return strings, not Nodes, +that represent the matched files or directories. +The returned strings will be relative to +the local (SConscript) directory. +(Note that This may make it easier to perform +arbitrary manipulation of file names, +but if the returned strings are +passed to a different +.B SConscript +file, +any Node translation will be relative +to the other +.B SConscript +directory, +not the original +.B SConscript +directory.) + +Examples: + +.ES +Program('foo', Glob('*.c')) +Zip('/tmp/everything', Glob('.??*') + Glob('*')) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +'\".TP +'\".RI GlobalBuilders( flag ) +'\"When +'\".B flag +'\"is non-zero, +'\"adds the names of the default builders +'\"(Program, Library, etc.) +'\"to the global name space +'\"so they can be called without an explicit construction environment. +'\"(This is the default.) +'\"When +'\".B +'\"flag is zero, +'\"the names of the default builders are removed +'\"from the global name space +'\"so that an explicit construction environment is required +'\"to call all builders. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Help( text ) +.TP +.RI env.Help( text ) +This specifies help text to be printed if the +.B -h +argument is given to +.BR scons . +If +.BR Help +is called multiple times, the text is appended together in the order +that +.BR Help +is called. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Ignore( target ", " dependency ) +.TP +.RI env.Ignore( target ", " dependency ) +The specified dependency file(s) +will be ignored when deciding if +the target file(s) need to be rebuilt. + +You can also use +.BR Ignore() +to remove a target from the default build. +In order to do this you must specify the directory the target will +be built in as the target, and the file you want to skip building +as the dependency. + +Note that this will only remove the dependencies listed from +the files built by default. It will still be built if that +dependency is needed by another object being built. +See the third and forth examples below. + +Examples: + +.ES +env.Ignore('foo', 'foo.c') +env.Ignore('bar', ['bar1.h', 'bar2.h']) +env.Ignore('.','foobar.obj') +env.Ignore('bar','bar/foobar.obj') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Import( vars ) +.TP +.RI env.Import( vars ) +This tells +.B scons +to import a list of variables into the current SConscript file. This +will import variables that were exported with +.BR Export () +or in the +.I exports +argument to +.BR SConscript (). +Variables exported by +.BR SConscript () +have precedence. +Multiple variable names can be passed to +.BR Import () +as separate arguments or as a list. The variable "*" can be used +to import all variables. + +Examples: + +.ES +Import("env") +Import("env", "variable") +Import(["env", "variable"]) +Import("*") +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Literal( string ) +.TP +.RI env.Literal( string ) +The specified +.I string +will be preserved as-is +and not have construction variables expanded. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Local( targets ) +.TP +.RI env.Local( targets ) +The specified +.I targets +will have copies made in the local tree, +even if an already up-to-date copy +exists in a repository. +Returns a list of the target Node or Nodes. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +\" .TP +\" .RI env.MergeShellPaths( arg ", [" prepend ]) +\" Merges the elements of the specified +\" .IR arg , +\" which must be a dictionary, to the construction +\" environment's copy of the shell environment +\" in env['ENV']. +\" (This is the environment which is passed +\" to subshells spawned by SCons.) +\" Note that +\" .I arg +\" must be a single value, +\" so multiple strings must +\" be passed in as a list, +\" not as separate arguments to +\" .BR env.MergeShellPaths (). + +\" New values are prepended to the environment variable by default, +\" unless prepend=0 is specified. +\" Duplicate values are always eliminated, +\" since this function calls +\" .B AppendENVPath +\" or +\" .B PrependENVPath +\" depending on the +\" .I prepend +\" argument. See those functions for more details. + +\" Examples: + +\" .ES +\" # Prepend a path to the shell PATH. +\" env.MergeShellPaths({'PATH':'/usr/local/bin'} ) +\" # Append two dirs to the shell INCLUDE. +\" env.MergeShellPaths({'INCLUDE':['c:/inc1', 'c:/inc2']}, prepend=0 ) + +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.MergeFlags( arg ", [" unique ]) +Merges the specified +.I arg +values to the construction environment's construction variables. +If the +.I arg +argument is not a dictionary, +it is converted to one by calling +.B env.ParseFlags() +on the argument +before the values are merged. +Note that +.I arg +must be a single value, +so multiple strings must +be passed in as a list, +not as separate arguments to +.BR env.MergeFlags (). + +By default, +duplicate values are eliminated; +you can, however, specify +.B unique=0 +to allow duplicate +values to be added. +When eliminating duplicate values, +any construction variables that end with +the string +.B PATH +keep the left-most unique value. +All other construction variables keep +the right-most unique value. + +Examples: + +.ES +# Add an optimization flag to $CCFLAGS. +env.MergeFlags('-O3') + +# Combine the flags returned from running pkg-config with an optimization +# flag and merge the result into the construction variables. +env.MergeFlags(['!pkg-config gtk+-2.0 --cflags', '-O3']) + +# Combine an optimization flag with the flags returned from running pkg-config +# twice and merge the result into the construction variables. +env.MergeFlags(['-O3', + '!pkg-config gtk+-2.0 --cflags --libs', + '!pkg-config libpng12 --cflags --libs']) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI NoCache( target ", ...)" +.TP +.RI env.NoCache( target ", ...)" +Specifies a list of files which should +.I not +be cached whenever the +.BR CacheDir () +method has been activated. +The specified targets may be a list +or an individual target. + +Multiple files should be specified +either as separate arguments to the +.BR NoCache () +method, or as a list. +.BR NoCache () +will also accept the return value of any of the construction environment +Builder methods. + +Calling +.BR NoCache () +on directories and other non-File Node types has no effect because +only File Nodes are cached. + +Examples: + +.ES +NoCache('foo.elf') +NoCache(env.Program('hello', 'hello.c')) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI NoClean( target ", ...)" +.TP +.RI env.NoClean( target ", ...)" +Specifies a list of files or directories which should +.I not +be removed whenever the targets (or their dependencies) +are specified with the +.B -c +command line option. +The specified targets may be a list +or an individual target. +Multiple calls to +.BR NoClean () +are legal, +and prevent each specified target +from being removed by calls to the +.B -c +option. + +Multiple files or directories should be specified +either as separate arguments to the +.BR NoClean () +method, or as a list. +.BR NoClean () +will also accept the return value of any of the construction environment +Builder methods. + +Calling +.BR NoClean () +for a target overrides calling +.BR Clean () +for the same target, +and any targets passed to both functions will +.I not +be removed by the +.B -c +option. + +Examples: + +.ES +NoClean('foo.elf') +NoClean(env.Program('hello', 'hello.c')) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.ParseConfig( command ", [" function ", " unique ]) +Calls the specified +.I function +to modify the environment as specified by the output of +.I command . +The default +.I function +is +.BR env.MergeFlags (), +which expects the output of a typical +.I *-config command +(for example, +.BR gtk-config ) +and adds the options +to the appropriate construction variables. +By default, +duplicate values are not +added to any construction variables; +you can specify +.B unique=0 +to allow duplicate +values to be added. + +Interpreted options +and the construction variables they affect +are as specified for the +.BR env.ParseFlags () +method (which this method calls). +See that method's description, below, +for a table of options and construction variables. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI ParseDepends( filename ", [" must_exist ", " only_one ]) +.TP +.RI env.ParseDepends( filename ", [" must_exist ", " only_one ]) +Parses the contents of the specified +.I filename +as a list of dependencies in the style of +.BR Make +or +.BR mkdep , +and explicitly establishes all of the listed dependencies. + +By default, +it is not an error +if the specified +.I filename +does not exist. +The optional +.I must_exist +argument may be set to a non-zero +value to have +scons +throw an exception and +generate an error if the file does not exist, +or is otherwise inaccessible. + +The optional +.I only_one +argument may be set to a non-zero +value to have +scons +thrown an exception and +generate an error +if the file contains dependency +information for more than one target. +This can provide a small sanity check +for files intended to be generated +by, for example, the +.B gcc -M +flag, +which should typically only +write dependency information for +one output file into a corresponding +.B .d +file. + +The +.I filename +and all of the files listed therein +will be interpreted relative to +the directory of the +.I SConscript +file which calls the +.B ParseDepends +function. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.ParseFlags( flags ", ...)" +Parses one or more strings containing +typical command-line flags for GCC tool chains +and returns a dictionary with the flag values +separated into the appropriate SCons construction variables. +This is intended as a companion to the +.BR env.MergeFlags () +method, but allows for the values in the returned dictionary +to be modified, if necessary, +before merging them into the construction environment. +(Note that +.BR env.MergeFlags () +will call this method if its argument is not a dictionary, +so it is usually not necessary to call +.BR env.ParseFlags () +directly unless you want to manipulate the values.) + +If the first character in any string is +an exclamation mark (!), +the rest of the string is executed as a command, +and the output from the command is +parsed as GCC tool chain command-line flags +and added to the resulting dictionary. + +Flag values are translated accordig to the prefix found, +and added to the following construction variables: + +.ES +-arch CCFLAGS, LINKFLAGS +-D CPPDEFINES +-framework FRAMEWORKS +-frameworkdir= FRAMEWORKPATH +-include CCFLAGS +-isysroot CCFLAGS, LINKFLAGS +-I CPPPATH +-l LIBS +-L LIBPATH +-mno-cygwin CCFLAGS, LINKFLAGS +-mwindows LINKFLAGS +-pthread CCFLAGS, LINKFLAGS +-std= CFLAGS +-Wa, ASFLAGS, CCFLAGS +-Wl,-rpath= RPATH +-Wl,-R, RPATH +-Wl,-R RPATH +-Wl, LINKFLAGS +-Wp, CPPFLAGS +- CCFLAGS ++ CCFLAGS, LINKFLAGS +.EE + +.IP +Any other strings not associated with options +are assumed to be the names of libraries +and added to the +.B LIBS +construction variable. + +Examples (all of which produce the same result): + +.ES +dict = env.ParseFlags('-O2 -Dfoo -Dbar=1') +dict = env.ParseFlags('-O2', '-Dfoo', '-Dbar=1') +dict = env.ParseFlags(['-O2', '-Dfoo -Dbar=1']) +dict = env.ParseFlags('-O2', '!echo -Dfoo -Dbar=1') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +env.Perforce() +A factory function that +returns a Builder object +to be used to fetch source files +from the Perforce source code management system. +The returned Builder +is intended to be passed to the +.B SourceCode +function. + +Example: + +.ES +env.SourceCode('.', env.Perforce()) +.EE +.IP +Perforce uses a number of external +environment variables for its operation. +Consequently, this function adds the +following variables from the user's external environment +to the construction environment's +ENV dictionary: +P4CHARSET, +P4CLIENT, +P4LANGUAGE, +P4PASSWD, +P4PORT, +P4USER, +SystemRoot, +USER, +and +USERNAME. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Platform( string ) +Returns a callable object +that can be used to initialize +a construction environment using the +platform keyword of the Environment() method. + +Example: + +.ES +env = Environment(platform = Platform('win32')) +.EE +.TP +.RI env.Platform( string ) +Applies the callable object for the specified platform +.I string +to the environment through which the method was called. + +.ES +env.Platform('posix') +.EE +.IP +Note that the +.B win32 +platform adds the +.B SystemDrive +and +.B SystemRoot +variables from the user's external environment +to the construction environment's +.B ENV +dictionary. +This is so that any executed commands +that use sockets to connect with other systems +(such as fetching source files from +external CVS repository specifications like +.BR :pserver:anonymous@cvs.sourceforge.net:/cvsroot/scons ) +will work on Windows systems. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Progress( callable ", [" interval ]) +.TP +.RI Progress( string ", [" interval ", " file ", " overwrite ]) +.TP +.RI Progress( list_of_strings ", [" interval ", " file ", " overwrite ]) +Allows SCons to show progress made during the build +by displaying a string or calling a function while +evaluating Nodes (e.g. files). + +If the first specified argument is a Python callable +(a function or an object that has a +.BR __call__ () +method), +the function will be called +once every +.I interval +times a Node is evaluated. +The callable will be passed the evaluated Node +as its only argument. +(For future compatibility, +it's a good idea to also add +.B *args +and +.B **kw +as arguments to your function or method. +This will prevent the code from breaking +if SCons ever changes the interface +to call the function with additional arguments in the future.) + +An example of a simple custom progress function +that prints a string containing the Node name +every 10 Nodes: + +.ES +def my_progress_function(node, *args, **kw): + print 'Evaluating node %s!' % node +Progress(my_progress_function, interval=10) +.EE +.IP +A more complicated example of a custom progress display object +that prints a string containing a count +every 100 evaluated Nodes. +Note the use of +.B \\\\r +(a carriage return) +at the end so that the string +will overwrite itself on a display: + +.ES +import sys +class ProgressCounter: + count = 0 + def __call__(self, node, *args, **kw): + self.count += 100 + sys.stderr.write('Evaluated %s nodes\\r' % self.count) +Progress(ProgressCounter(), interval=100) +.EE +.IP +If the first argument +.BR Progress () +is a string, +the string will be displayed +every +.I interval +evaluated Nodes. +The default is to print the string on standard output; +an alternate output stream +may be specified with the +.B file= +argument. +The following will print a series of dots +on the error output, +one dot for every 100 evaluated Nodes: + +.ES +import sys +Progress('.', interval=100, file=sys.stderr) +.EE +.IP +If the string contains the verbatim substring +.B $TARGET, +it will be replaced with the Node. +Note that, for performance reasons, this is +.I not +a regular SCons variable substition, +so you can not use other variables +or use curly braces. +The following example will print the name of +every evaluated Node, +using a +.B \\\\r +(carriage return) to cause each line to overwritten by the next line, +and the +.B overwrite= +keyword argument to make sure the previously-printed +file name is overwritten with blank spaces: + +.ES +import sys +Progress('$TARGET\\r', overwrite=True) +.EE +.IP +If the first argument to +.BR Progress () +is a list of strings, +then each string in the list will be displayed +in rotating fashion every +.I interval +evaluated Nodes. +This can be used to implement a "spinner" +on the user's screen as follows: + +.ES +Progress(['-\\r', '\\\\\\r', '|\\r', '/\\r'], interval=5) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Precious( target ", ...)" +.TP +.RI env.Precious( target ", ...)" +Marks each given +.I target +as precious so it is not deleted before it is rebuilt. Normally +.B scons +deletes a target before building it. +Multiple targets can be passed in to a single call to +.BR Precious (). + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.Prepend( key = val ", [...])" +Appends the specified keyword arguments +to the beginning of construction variables in the environment. +If the Environment does not have +the specified construction variable, +it is simply added to the environment. +If the values of the construction variable +and the keyword argument are the same type, +then the two values will be simply added together. +Otherwise, the construction variable +and the value of the keyword argument +are both coerced to lists, +and the lists are added together. +(See also the Append method, above.) + +Example: + +.ES +env.Prepend(CCFLAGS = '-g ', FOO = ['foo.yyy']) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.PrependENVPath( name ", " newpath ", [" envname ", " sep ", " delete_existing ]) +This appends new path elements to the given path in the +specified external environment +.RB ( ENV +by default). +This will only add +any particular path once (leaving the first one it encounters and +ignoring the rest, to preserve path order), +and to help assure this, +will normalize all paths (using +.B os.path.normpath +and +.BR os.path.normcase ). +This can also handle the +case where the given old path variable is a list instead of a +string, in which case a list will be returned instead of a string. + +If +.I delete_existing +is 0, then adding a path that already exists +will not move it to the beginning; +it will stay where it is in the list. + +Example: + +.ES +print 'before:',env['ENV']['INCLUDE'] +include_path = '/foo/bar:/foo' +env.PrependENVPath('INCLUDE', include_path) +print 'after:',env['ENV']['INCLUDE'] +.EE + +The above exmaple will print: + +.ES +before: /biz:/foo +after: /foo/bar:/foo:/biz +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.PrependUnique( key = val ", delete_existing=0, [...])" +Appends the specified keyword arguments +to the beginning of construction variables in the environment. +If the Environment does not have +the specified construction variable, +it is simply added to the environment. +If the construction variable being appended to is a list, +then any value(s) that already exist in the +construction variable will +.I not +be added again to the list. +However, if delete_existing is 1, +existing matching values are removed first, so +existing values in the arg list move to the front of the list. + +Example: + +.ES +env.PrependUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +env.RCS() +A factory function that +returns a Builder object +to be used to fetch source files +from RCS. +The returned Builder +is intended to be passed to the +.B SourceCode +function: + +Examples: + +.ES +env.SourceCode('.', env.RCS()) +.EE +.IP +Note that +.B scons +will fetch source files +from RCS subdirectories automatically, +so configuring RCS +as demonstrated in the above example +should only be necessary if +you are fetching from +RCS,v +files in the same +directory as the source files, +or if you need to explicitly specify RCS +for a specific subdirectory. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.Replace( key = val ", [...])" +Replaces construction variables in the Environment +with the specified keyword arguments. + +Example: + +.ES +env.Replace(CCFLAGS = '-g', FOO = 'foo.xxx') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Repository( directory ) +.TP +.RI env.Repository( directory ) +Specifies that +.I directory +is a repository to be searched for files. +Multiple calls to +.BR Repository () +are legal, +and each one adds to the list of +repositories that will be searched. + +To +.BR scons , +a repository is a copy of the source tree, +from the top-level directory on down, +which may contain +both source files and derived files +that can be used to build targets in +the local source tree. +The canonical example would be an +official source tree maintained by an integrator. +If the repository contains derived files, +then the derived files should have been built using +.BR scons , +so that the repository contains the necessary +signature information to allow +.B scons +to figure out when it is appropriate to +use the repository copy of a derived file, +instead of building one locally. + +Note that if an up-to-date derived file +already exists in a repository, +.B scons +will +.I not +make a copy in the local directory tree. +In order to guarantee that a local copy +will be made, +use the +.B Local() +method. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Requires( target ", " prerequisite ) +.TP +.RI env.Requires( target ", " prerequisite ) +Specifies an order-only relationship +between the specified target file(s) +and the specified prerequisite file(s). +The prerequisite file(s) +will be (re)built, if necessary, +.I before +the target file(s), +but the target file(s) do not actually +depend on the prerequisites +and will not be rebuilt simply because +the prerequisite file(s) change. + +Example: + +.ES +env.Requires('foo', 'file-that-must-be-built-before-foo') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Return([ vars "... , " stop= ]) +By default, +this stops processing the current SConscript +file and returns to the calling SConscript file +the values of the variables named in the +.I vars +string arguments. +Multiple strings contaning variable names may be passed to +.BR Return (). +Any strings that contain white space + +The optional +.B stop= +keyword argument may be set to a false value +to continue processing the rest of the SConscript +file after the +.BR Return () +call. +This was the default behavior prior to SCons 0.98. +However, the values returned +are still the values of the variables in the named +.I vars +at the point +.BR Return () +is called. + +Examples: + +.ES +# Returns without returning a value. +Return() + +# Returns the value of the 'foo' Python variable. +Return("foo") + +# Returns the values of the Python variables 'foo' and 'bar'. +Return("foo", "bar") + +# Returns the values of Python variables 'val1' and 'val2'. +Return('val1 val2') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Scanner( function ", [" argument ", " keys ", " path_function ", " node_class ", " node_factory ", " scan_check ", " recursive ]) +.TP +.RI env.Scanner( function ", [" argument ", " keys ", " path_function ", " node_class ", " node_factory ", " scan_check ", " recursive ]) +Creates a Scanner object for +the specified +.IR function . +See the section "Scanner Objects," +below, for a complete explanation of the arguments and behavior. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +env.SCCS() +A factory function that +returns a Builder object +to be used to fetch source files +from SCCS. +The returned Builder +is intended to be passed to the +.B SourceCode +function. + +Example: + +.ES +env.SourceCode('.', env.SCCS()) +.EE +.IP +Note that +.B scons +will fetch source files +from SCCS subdirectories automatically, +so configuring SCCS +as demonstrated in the above example +should only be necessary if +you are fetching from +.I s.SCCS +files in the same +directory as the source files, +or if you need to explicitly specify SCCS +for a specific subdirectory. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI SConscript( scripts ", [" exports ", " variant_dir ", " duplicate ]) +'\" .RI SConscript( scripts ", [" exports ", " variant_dir ", " src_dir ", " duplicate ]) +.TP +.RI env.SConscript( scripts ", [" exports ", " variant_dir ", " duplicate ]) +'\" .RI env.SConscript( scripts ", [" exports ", " variant_dir ", " src_dir ", " duplicate ]) +.TP +.RI SConscript(dirs= subdirs ", [name=" script ", " exports ", " variant_dir ", " duplicate ]) +'\" .RI SConscript(dirs= subdirs ", [name=" script ", " exports ", " variant_dir ", " src_dir ", " duplicate ]) +.TP +.RI env.SConscript(dirs= subdirs ", [name=" script ", " exports ", " variant_dir ", " duplicate ]) +'\" .RI env.SConscript(dirs= subdirs ", [name=" script ", " exports ", " variant_dir ", " src_dir ", " duplicate ]) +This tells +.B scons +to execute +one or more subsidiary SConscript (configuration) files. +Any variables returned by a called script using +.BR Return () +will be returned by the call to +.BR SConscript (). +There are two ways to call the +.BR SConscript () +function. + +The first way you can call +.BR SConscript () +is to explicitly specify one or more +.I scripts +as the first argument. +A single script may be specified as a string; +multiple scripts must be specified as a list +(either explicitly or as created by +a function like +.BR Split ()). +Examples: +.ES +SConscript('SConscript') # run SConscript in the current directory +SConscript('src/SConscript') # run SConscript in the src directory +SConscript(['src/SConscript', 'doc/SConscript']) +config = SConscript('MyConfig.py') +.EE + +The second way you can call +.BR SConscript () +is to specify a list of (sub)directory names +as a +.RI dirs= subdirs +keyword argument. +In this case, +.B scons +will, by default, +execute a subsidiary configuration file named +.B SConscript +in each of the specified directories. +You may specify a name other than +.B SConscript +by supplying an optional +.RI name= script +keyword argument. +The first three examples below have the same effect +as the first three examples above: +.ES +SConscript(dirs='.') # run SConscript in the current directory +SConscript(dirs='src') # run SConscript in the src directory +SConscript(dirs=['src', 'doc']) +SConscript(dirs=['sub1', 'sub2'], name='MySConscript') +.EE + +The optional +.I exports +argument provides a list of variable names or a dictionary of +named values to export to the +.IR script(s) . +These variables are locally exported only to the specified +.IR script(s) , +and do not affect the global pool of variables used by the +.BR Export () +function. +'\"If multiple dirs are provided, each script gets a fresh export. +The subsidiary +.I script(s) +must use the +.BR Import () +function to import the variables. +Examples: +.ES +foo = SConscript('sub/SConscript', exports='env') +SConscript('dir/SConscript', exports=['env', 'variable']) +SConscript(dirs='subdir', exports='env variable') +SConscript(dirs=['one', 'two', 'three'], exports='shared_info') +.EE + +If the optional +.I variant_dir +argument is present, it causes an effect equivalent to the +.BR VariantDir () +method described below. +(If +.I variant_dir +is not present, the +'\" .IR src_dir and +.I duplicate +'\" arguments are ignored.) +argument is ignored.) +The +.I variant_dir +'\" and +'\" .I src_dir +'\" arguments are interpreted relative to the directory of the calling +argument is interpreted relative to the directory of the calling +.BR SConscript file. +See the description of the +.BR VariantDir () +function below for additional details and restrictions. + +If +'\" .IR variant_dir " is present, but" +'\" .IR src_dir " is not," +.IR variant_dir " is present," +the source directory is relative to the called +.BR SConscript " file." +.ES +SConscript('src/SConscript', variant_dir = 'build') +.EE +is equivalent to +.ES +VariantDir('build', 'src') +SConscript('build/SConscript') +.EE +This later paradigm is often used when the sources are +in the same directory as the +.BR SConstruct file: +.ES +SConscript('SConscript', variant_dir = 'build') +.EE +is equivalent to +.ES +VariantDir('build', '.') +SConscript('build/SConscript') +.EE + +'\" If +'\" .IR variant_dir " and" +'\" .IR src_dir " are both present," +'\" xxxxx everything is in a state of confusion. +'\" .ES +'\" SConscript(dirs = 'src', variant_dir = 'build', src_dir = '.') +'\" runs src/SConscript in build/src, but +'\" SConscript(dirs = 'lib', variant_dir = 'build', src_dir = 'src') +'\" runs lib/SConscript (in lib!). However, +'\" SConscript(dirs = 'src', variant_dir = 'build', src_dir = 'src') +'\" runs src/SConscript in build. Moreover, +'\" SConscript(dirs = 'src/lib', variant_dir = 'build', src_dir = 'src') +'\" runs src/lib/SConscript in build/lib. Moreover, +'\" SConscript(dirs = 'build/src/lib', variant_dir = 'build', src_dir = 'src') +'\" can't find build/src/lib/SConscript, even though it ought to exist. +'\" .EE +'\" is equivalent to +'\" .ES +'\" ???????????????? +'\" .EE +'\" and what about this alternative? +'\"TODO??? SConscript('build/SConscript', src_dir='src') + +Here are some composite examples: + +.ES +# collect the configuration information and use it to build src and doc +shared_info = SConscript('MyConfig.py') +SConscript('src/SConscript', exports='shared_info') +SConscript('doc/SConscript', exports='shared_info') +.EE + +.ES +# build debugging and production versions. SConscript +# can use Dir('.').path to determine variant. +SConscript('SConscript', variant_dir='debug', duplicate=0) +SConscript('SConscript', variant_dir='prod', duplicate=0) +.EE + +.ES +# build debugging and production versions. SConscript +# is passed flags to use. +opts = { 'CPPDEFINES' : ['DEBUG'], 'CCFLAGS' : '-pgdb' } +SConscript('SConscript', variant_dir='debug', duplicate=0, exports=opts) +opts = { 'CPPDEFINES' : ['NODEBUG'], 'CCFLAGS' : '-O' } +SConscript('SConscript', variant_dir='prod', duplicate=0, exports=opts) +.EE + +.ES +# build common documentation and compile for different architectures +SConscript('doc/SConscript', variant_dir='build/doc', duplicate=0) +SConscript('src/SConscript', variant_dir='build/x86', duplicate=0) +SConscript('src/SConscript', variant_dir='build/ppc', duplicate=0) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI SConscriptChdir( value ) +.TP +.RI env.SConscriptChdir( value ) +By default, +.B scons +changes its working directory +to the directory in which each +subsidiary SConscript file lives. +This behavior may be disabled +by specifying either: + +.ES +SConscriptChdir(0) +env.SConscriptChdir(0) +.EE +.IP +in which case +.B scons +will stay in the top-level directory +while reading all SConscript files. +(This may be necessary when building from repositories, +when all the directories in which SConscript files may be found +don't necessarily exist locally.) +You may enable and disable +this ability by calling +SConscriptChdir() +multiple times. + +Example: + +.ES +env = Environment() +SConscriptChdir(0) +SConscript('foo/SConscript') # will not chdir to foo +env.SConscriptChdir(1) +SConscript('bar/SConscript') # will chdir to bar +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI SConsignFile([ file , dbm_module ]) +.TP +.RI env.SConsignFile([ file , dbm_module ]) +This tells +.B scons +to store all file signatures +in the specified database +.IR file . +If the +.I file +name is omitted, +.B .sconsign +is used by default. +(The actual file name(s) stored on disk +may have an appropriated suffix appended +by the +.IR dbm_module .) +If +.I file +is not an absolute path name, +the file is placed in the same directory as the top-level +.B SConstruct +file. + +If +.I file +is +.BR None , +then +.B scons +will store file signatures +in a separate +.B .sconsign +file in each directory, +not in one global database file. +(This was the default behavior +prior to SCons 0.96.91 and 0.97.) + +The optional +.I dbm_module +argument can be used to specify +which Python database module +The default is to use a custom +.B SCons.dblite +module that uses pickled +Python data structures, +and which works on all Python versions from 1.5.2 on. + +Examples: + +.ES +# Explicitly stores signatures in ".sconsign.dblite" +# in the top-level SConstruct directory (the +# default behavior). +SConsignFile() + +# Stores signatures in the file "etc/scons-signatures" +# relative to the top-level SConstruct directory. +SConsignFile("etc/scons-signatures") + +# Stores signatures in the specified absolute file name. +SConsignFile("/home/me/SCons/signatures") + +# Stores signatures in a separate .sconsign file +# in each directory. +SConsignFile(None) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.SetDefault(key = val ", [...])" +Sets construction variables to default values specified with the keyword +arguments if (and only if) the variables are not already set. +The following statements are equivalent: + +.ES +env.SetDefault(FOO = 'foo') + +if not env.has_key('FOO'): env['FOO'] = 'foo' +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI SetOption( name ", " value ) +.TP +.RI env.SetOption( name ", " value ) +This function provides a way to set a select subset of the scons command +line options from a SConscript file. The options supported are: + +.RS 10 +.TP 6 +.B clean +which corresponds to -c, --clean and --remove; +.TP 6 +.B duplicate +which corresponds to --duplicate; +.TP 6 +.B help +which corresponds to -h and --help; +.TP 6 +.B implicit_cache +which corresponds to --implicit-cache; +.TP 6 +.B max_drift +which corresponds to --max-drift; +.TP 6 +.B no_exec +which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; +.TP 6 +.B num_jobs +which corresponds to -j and --jobs; +.TP 6 +.B random +which corresponds to --random; and +.TP 6 +.B stack_size +which corresponds to --stack-size. +.RE + +.IP +See the documentation for the +corresponding command line object for information about each specific +option. + +Example: + +.ES +SetOption('max_drift', 1) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI SideEffect( side_effect ", " target ) +.TP +.RI env.SideEffect( side_effect ", " target ) +Declares +.I side_effect +as a side effect of building +.IR target . +Both +.I side_effect +and +.I target +can be a list, a file name, or a node. +A side effect is a target file that is created or updated +as a side effect of building other targets. +For example, a Windows PDB +file is created as a side effect of building the .obj +files for a static library, +and various log files are created updated +as side effects of various TeX commands. +If a target is a side effect of multiple build commands, +.B scons +will ensure that only one set of commands +is executed at a time. +Consequently, you only need to use this method +for side-effect targets that are built as a result of +multiple build commands. + +Because multiple build commands may update +the same side effect file, +by default the +.I side_effect +target is +.I not +automatically removed +when the +.I target +is removed by the +.B -c +option. +(Note, however, that the +.I side_effect +might be removed as part of +cleaning the directory in which it lives.) +If you want to make sure the +.I side_effect +is cleaned whenever a specific +.I target +is cleaned, +you must specify this explicitly +with the +.BR Clean () +or +.BR env.Clean () +function. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI SourceCode( entries ", " builder ) +.TP +.RI env.SourceCode( entries ", " builder ) +Arrange for non-existent source files to +be fetched from a source code management system +using the specified +.IR builder . +The specified +.I entries +may be a Node, string or list of both, +and may represent either individual +source files or directories in which +source files can be found. + +For any non-existent source files, +.B scons +will search up the directory tree +and use the first +.B SourceCode +builder it finds. +The specified +.I builder +may be +.BR None , +in which case +.B scons +will not use a builder to fetch +source files for the specified +.IR entries , +even if a +.B SourceCode +builder has been specified +for a directory higher up the tree. + +.B scons +will, by default, +fetch files from SCCS or RCS subdirectories +without explicit configuration. +This takes some extra processing time +to search for the necessary +source code management files on disk. +You can avoid these extra searches +and speed up your build a little +by disabling these searches as follows: + +.ES +env.SourceCode('.', None) +.EE + +.IP +Note that if the specified +.I builder +is one you create by hand, +it must have an associated +construction environment to use +when fetching a source file. + +.B scons +provides a set of canned factory +functions that return appropriate +Builders for various popular +source code management systems. +Canonical examples of invocation include: + +.ES +env.SourceCode('.', env.BitKeeper('/usr/local/BKsources')) +env.SourceCode('src', env.CVS('/usr/local/CVSROOT')) +env.SourceCode('/', env.RCS()) +env.SourceCode(['f1.c', 'f2.c'], env.SCCS()) +env.SourceCode('no_source.c', None) +.EE +'\"env.SourceCode('.', env.Subversion('file:///usr/local/Subversion')) + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.subst( input ", [" raw ", " target ", " source ", " conv ]) +Performs construction variable interpolation +on the specified string or sequence argument +.IR input . + +By default, +leading or trailing white space will +be removed from the result. +and all sequences of white space +will be compressed to a single space character. +Additionally, any +.B $( +and +.B $) +character sequences will be stripped from the returned string, +The optional +.I raw +argument may be set to +.B 1 +if you want to preserve white space and +.BR $( - $) +sequences. +The +.I raw +argument may be set to +.B 2 +if you want to strip +all characters between +any +.B $( +and +.B $) +pairs +(as is done for signature calculation). + +If the input is a sequence +(list or tuple), +the individual elements of +the sequence will be expanded, +and the results will be returned as a list. + +The optional +.I target +and +.I source +keyword arguments +must be set to lists of +target and source nodes, respectively, +if you want the +.BR $TARGET , +.BR $TARGETS , +.BR $SOURCE +and +.BR $SOURCES +to be available for expansion. +This is usually necessary if you are +calling +.BR env.subst () +from within a Python function used +as an SCons action. + +Returned string values or sequence elements +are converted to their string representation by default. +The optional +.I conv +argument +may specify a conversion function +that will be used in place of +the default. +For example, if you want Python objects +(including SCons Nodes) +to be returned as Python objects, +you can use the Python +.B lambda +idiom to pass in an unnamed function +that simply returns its unconverted argument. + +Example: + +.ES +print env.subst("The C compiler is: $CC") + +def compile(target, source, env): + sourceDir = env.subst("${SOURCE.srcdir}", + target=target, + source=source) + +source_nodes = env.subst('$EXPAND_TO_NODELIST', + conv=lambda x: x) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +'\".TP +'\".RI Subversion( repository ", " module ) +'\"A factory function that +'\"returns a Builder object +'\"to be used to fetch source files +'\"from the specified Subversion +'\".IR repository . +'\"The returned Builder +'\"is intended to be passed to the +'\".B SourceCode +'\"function. +'\" +'\"The optional specified +'\".I module +'\"will be added to the beginning +'\"of all repository path names; +'\"this can be used, in essence, +'\"to strip initial directory names +'\"from the repository path names, +'\"so that you only have to +'\"replicate part of the repository +'\"directory hierarchy in your +'\"local build directory. +'\" +'\"Example: +'\" +'\".ES +'\"# Will fetch foo/bar/src.c +'\"# from /usr/local/Subversion/foo/bar/src.c. +'\"env.SourceCode('.', env.Subversion('file:///usr/local/Subversion')) +'\" +'\"# Will fetch bar/src.c +'\"# from /usr/local/Subversion/foo/bar/src.c. +'\"env.SourceCode('.', env.Subversion('file:///usr/local/Subversion', 'foo')) +'\" +'\"# Will fetch src.c +'\"# from /usr/local/Subversion/foo/bar/src.c. +'\"env.SourceCode('.', env.Subversion('file:///usr/local/Subversion', 'foo/bar')) +'\".EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI SourceSignatures( type ) +.TP +.RI env.SourceSignatures( type ) +Note: Although it is not yet officially deprecated, +use of this function is discouraged. +See the +.BR Decider () +function for a more flexible and straightforward way +to configure SCons' decision-making. + +The +.BR SourceSignatures () +function tells +.B scons +how to decide if a source file +(a file that is not built from any other files) +has changed since the last time it +was used to build a particular target file. +Legal values are +.B "MD5" +or +.BR "timestamp" . + +If the environment method is used, +the specified type of source signature +is only used when deciding whether targets +built with that environment are up-to-date or must be rebuilt. +If the global function is used, +the specified type of source signature becomes the default +used for all decisions +about whether targets are up-to-date. + +.B "MD5" +means +.B scons +decides that a source file has changed +if the MD5 checksum of its contents has changed since +the last time it was used to rebuild a particular target file. + +.B "timestamp" +means +.B scons +decides that a source file has changed +if its timestamp (modification time) has changed since +the last time it was used to rebuild a particular target file. +(Note that although this is similar to the behavior of Make, +by default it will also rebuild if the dependency is +.I older +than the last time it was used to rebuild the target file.) + +There is no different between the two behaviors +for Python +.BR Value () +node objects. + +.B "MD5" +signatures take longer to compute, +but are more accurate than +.B "timestamp" +signatures. +The default value is +.BR "MD5" . + +Note that the default +.BR TargetSignatures () +setting (see below) +is to use this +.BR SourceSignatures () +setting for any target files that are used +to build other target files. +Consequently, changing the value of +.BR SourceSignatures () +will, by default, +affect the up-to-date decision for all files in the build +(or all files built with a specific construction environment +when +.BR env.SourceSignatures () +is used). + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Split( arg ) +.TP +.RI env.Split( arg ) +Returns a list of file names or other objects. +If arg is a string, +it will be split on strings of white-space characters +within the string, +making it easier to write long lists of file names. +If arg is already a list, +the list will be returned untouched. +If arg is any other type of object, +it will be returned as a list +containing just the object. + +Example: + +.ES +files = Split("f1.c f2.c f3.c") +files = env.Split("f4.c f5.c f6.c") +files = Split(""" + f7.c + f8.c + f9.c +""") +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Tag( node ", " tags ) +Annotates file or directory Nodes with +information about how the +.BR Package () +Builder should package those files or directories. +All tags are optional. + +Examples: + +.ES +# makes sure the built library will be installed with 0644 file +# access mode +Tag( Library( 'lib.c' ), UNIX_ATTR="0644" ) + +# marks file2.txt to be a documentation file +Tag( 'file2.txt', DOC ) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI TargetSignatures( type ) +.TP +.RI env.TargetSignatures( type ) +Note: Although it is not yet officially deprecated, +use of this function is discouraged. +See the +.BR Decider () +function for a more flexible and straightforward way +to configure SCons' decision-making. + +The +.BR TargetSignatures () +function tells +.B scons +how to decide if a target file +(a file that +.I is +built from any other files) +has changed since the last time it +was used to build some other target file. +Legal values are +.BR "build" ; +.BR "content" +(or its synonym +.BR "MD5" ); +.BR "timestamp" ; +or +.BR "source" . + +If the environment method is used, +the specified type of target signature is only used +for targets built with that environment. +If the global function is used, +the specified type of signature becomes the default +used for all target files that +don't have an explicit target signature type +specified for their environments. + +.B "content" +(or its synonym +.BR "MD5" ) +means +.B scons +decides that a target file has changed +if the MD5 checksum of its contents has changed since +the last time it was used to rebuild some other target file. +This means +.B scons +will open up +MD5 sum the contents +of target files after they're built, +and may decide that it does not need to rebuild +"downstream" target files if a file was +rebuilt with exactly the same contents as the last time. + +.B "timestamp" +means +.B scons +decides that a target file has changed +if its timestamp (modification time) has changed since +the last time it was used to rebuild some other target file. +(Note that although this is similar to the behavior of Make, +by default it will also rebuild if the dependency is +.I older +than the last time it was used to rebuild the target file.) + +.B "source" +means +.B scons +decides that a target file has changed +as specified by the corresponding +.BR SourceSignatures () +setting +.BR "" ( "MD5" +or +.BR "timestamp" ). +This means that +.B scons +will treat all input files to a target the same way, +regardless of whether they are source files +or have been built from other files. + +.B "build" +means +.B scons +decides that a target file has changed +if it has been rebuilt in this invocation +or if its content or timestamp have changed +as specified by the corresponding +.BR SourceSignatures () +setting. +This "propagates" the status of a rebuilt file +so that other "downstream" target files +will always be rebuilt, +even if the contents or the timestamp +have not changed. + +.B "build" +signatures are fastest because +.B "content" +(or +.BR "MD5" ) +signatures take longer to compute, +but are more accurate than +.B "timestamp" +signatures, +and can prevent unnecessary "downstream" rebuilds +when a target file is rebuilt to the exact same contents +as the previous build. +The +.B "source" +setting provides the most consistent behavior +when other target files may be rebuilt from +both source and target input files. +The default value is +.BR "source" . + +Because the default setting is +.BR "source" , +using +.BR SourceSignatures () +is generally preferable to +.BR TargetSignatures () , +so that the up-to-date decision +will be consistent for all files +(or all files built with a specific construction environment). +Use of +.BR TargetSignatures () +provides specific control for how built target files +affect their "downstream" dependencies. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Tool( string [, toolpath ", " **kw ]) +Returns a callable object +that can be used to initialize +a construction environment using the +tools keyword of the Environment() method. +The object may be called with a construction +environment as an argument, +in which case the object will +add the necessary variables +to the construction environment +and the name of the tool will be added to the +.B $TOOLS +construction variable. + +Additional keyword arguments are passed to the tool's +.B generate() +method. + +Examples: + +.ES +env = Environment(tools = [ Tool('msvc') ]) + +env = Environment() +t = Tool('msvc') +t(env) # adds 'msvc' to the TOOLS variable +u = Tool('opengl', toolpath = ['tools']) +u(env) # adds 'opengl' to the TOOLS variable +.EE +.TP +.RI env.Tool( string [, toolpath ", " **kw ]) +Applies the callable object for the specified tool +.I string +to the environment through which the method was called. + +Additional keyword arguments are passed to the tool's +.B generate() +method. + +.ES +env.Tool('gcc') +env.Tool('opengl', toolpath = ['build/tools']) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI Value( value ", [" built_value ]) +.TP +.RI env.Value( value ", [" built_value ]) +Returns a Node object representing the specified Python value. Value +Nodes can be used as dependencies of targets. If the result of +calling +.BR str( value ) +changes between SCons runs, any targets depending on +.BR Value( value ) +will be rebuilt. +(This is true even when using timestamps to decide if +files are up-to-date.) +When using timestamp source signatures, Value Nodes' +timestamps are equal to the system time when the Node is created. + +The returned Value Node object has a +.BR write () +method that can be used to "build" a Value Node +by setting a new value. +The optional +.I built_value +argument can be specified +when the Value Node is created +to indicate the Node should already be considered +"built." +There is a corresponding +.BR read () +method that will return the built value of the Node. + +Examples: + +.ES +env = Environment() + +def create(target, source, env): + # A function that will write a 'prefix=$SOURCE' + # string into the file name specified as the + # $TARGET. + f = open(str(target[0]), 'wb') + f.write('prefix=' + source[0].get_contents()) + +# Fetch the prefix= argument, if any, from the command +# line, and use /usr/local as the default. +prefix = ARGUMENTS.get('prefix', '/usr/local') + +# Attach a .Config() builder for the above function action +# to the construction environment. +env['BUILDERS']['Config'] = Builder(action = create) +env.Config(target = 'package-config', source = Value(prefix)) + +def build_value(target, source, env): + # A function that "builds" a Python Value by updating + # the the Python value with the contents of the file + # specified as the source of the Builder call ($SOURCE). + target[0].write(source[0].get_contents()) + +output = env.Value('before') +input = env.Value('after') + +# Attach a .UpdateValue() builder for the above function +# action to the construction environment. +env['BUILDERS']['UpdateValue'] = Builder(action = build_value) +env.UpdateValue(target = Value(output), source = Value(input)) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI VariantDir( variant_dir ", " src_dir ", [" duplicate ]) +.TP +.RI env.VariantDir( variant_dir ", " src_dir ", [" duplicate ]) +Use the +.BR VariantDir () +function to create a copy of your sources in another location: +if a name under +.IR variant_dir +is not found but exists under +.IR src_dir , +the file or directory is copied to +.IR variant_dir . +Target files can be built in a different directory +than the original sources by simply refering to the sources (and targets) +within the variant tree. + +.BR VariantDir () +can be called multiple times with the same +.I src_dir +to set up multiple builds with different options +.RI ( variants ). +The +.I src_dir +location must be in or underneath the SConstruct file's directory, and +.I variant_dir +may not be underneath +.IR src_dir . +'\"TODO: Can the above restrictions be clarified or relaxed? +'\"TODO: The latter restriction is clearly not completely right; +'\"TODO: src_dir = '.' works fine with a build dir under it. + +The default behavior is for +.B scons +to physically duplicate the source files in the variant tree. +Thus, a build performed in the variant tree is guaranteed to be identical +to a build performed in the source tree even if +intermediate source files are generated during the build, +or preprocessors or other scanners search for included files +relative to the source file, +or individual compilers or other invoked tools are hard-coded +to put derived files in the same directory as source files. + +If possible on the platform, +the duplication is performed by linking rather than copying; +see also the +.IR --duplicate +command-line option. +Moreover, only the files needed for the build are duplicated; +files and directories that are not used are not present in +.IR variant_dir . + +Duplicating the source tree may be disabled by setting the +.I duplicate +argument to 0 (zero). +This will cause +.B scons +to invoke Builders using the path names of source files in +.I src_dir +and the path names of derived files within +.IR variant_dir . +This is always more efficient than +.IR duplicate =1, +and is usually safe for most builds +(but see above for cases that may cause problems). + +Note that +.BR VariantDir () +works most naturally with a subsidiary SConscript file. +However, you would then call the subsidiary SConscript file +not in the source directory, but in the +.I variant_dir , +regardless of the value of +.IR duplicate . +This is how you tell +.B scons +which variant of a source tree to build: + +.ES +# run src/SConscript in two variant directories +VariantDir('build/variant1', 'src') +SConscript('build/variant1/SConscript') +VariantDir('build/variant2', 'src') +SConscript('build/variant2/SConscript') +.EE + +.IP +See also the +.BR SConscript () +function, described above, +for another way to specify a variant directory +in conjunction with calling a subsidiary SConscript file. + +Examples: + +.ES +# use names in the build directory, not the source directory +VariantDir('build', 'src', duplicate=0) +Program('build/prog', 'build/source.c') +.EE + +.ES +# this builds both the source and docs in a separate subtree +VariantDir('build', '.', duplicate=0) +SConscript(dirs=['build/src','build/doc']) +.EE + +.ES +# same as previous example, but only uses SConscript +SConscript(dirs='src', variant_dir='build/src', duplicate=0) +SConscript(dirs='doc', variant_dir='build/doc', duplicate=0) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI WhereIs( program ", [" path ", " pathext ", " reject ]) +.TP +.RI env.WhereIs( program ", [" path ", " pathext ", " reject ]) + +Searches for the specified executable +.I program, +returning the full path name to the program +if it is found, +and returning None if not. +Searches the specified +.I path, +the value of the calling environment's PATH +(env['ENV']['PATH']), +or the user's current external PATH +(os.environ['PATH']) +by default. +On Windows systems, searches for executable +programs with any of the file extensions +listed in the specified +.I pathext, +the calling environment's PATHEXT +(env['ENV']['PATHEXT']) +or the user's current PATHEXT +(os.environ['PATHEXT']) +by default. +Will not select any +path name or names +in the specified +.I reject +list, if any. + +.SS SConscript Variables +In addition to the global functions and methods, +.B scons +supports a number of Python variables +that can be used in SConscript files +to affect how you want the build to be performed. +These variables may be accessed from custom Python modules that you +import into an SConscript file by adding the following +to the Python module: + +.ES +from SCons.Script import * +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +ARGLIST +A list +.IR keyword = value +arguments specified on the command line. +Each element in the list is a tuple +containing the +.RI ( keyword , value ) +of the argument. +The separate +.I keyword +and +.I value +elements of the tuple +can be accessed by +subscripting for element +.B [0] +and +.B [1] +of the tuple, respectively. + +Example: + +.ES +print "first keyword, value =", ARGLIST[0][0], ARGLIST[0][1] +print "second keyword, value =", ARGLIST[1][0], ARGLIST[1][1] +third_tuple = ARGLIST[2] +print "third keyword, value =", third_tuple[0], third_tuple[1] +for key, value in ARGLIST: + # process key and value +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +ARGUMENTS +A dictionary of all the +.IR keyword = value +arguments specified on the command line. +The dictionary is not in order, +and if a given keyword has +more than one value assigned to it +on the command line, +the last (right-most) value is +the one in the +.B ARGUMENTS +dictionary. + +Example: + +.ES +if ARGUMENTS.get('debug', 0): + env = Environment(CCFLAGS = '-g') +else: + env = Environment() +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +BUILD_TARGETS +A list of the targets which +.B scons +will actually try to build, +regardless of whether they were specified on +the command line or via the +.BR Default () +function or method. +The elements of this list may be strings +.I or +nodes, so you should run the list through the Python +.B str +function to make sure any Node path names +are converted to strings. + +Because this list may be taken from the +list of targets specified using the +.BR Default () +function or method, +the contents of the list may change +on each successive call to +.BR Default (). +See the +.B DEFAULT_TARGETS +list, below, +for additional information. + +Example: + +.ES +if 'foo' in BUILD_TARGETS: + print "Don't forget to test the `foo' program!" +if 'special/program' in BUILD_TARGETS: + SConscript('special') +.EE +.IP +Note that the +.B BUILD_TARGETS +list only contains targets expected listed +on the command line or via calls to the +.BR Default () +function or method. +It does +.I not +contain all dependent targets that will be built as +a result of making the sure the explicitly-specified +targets are up to date. + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +COMMAND_LINE_TARGETS +A list of the targets explicitly specified on +the command line. +If there are no targets specified on the command line, +the list is empty. +This can be used, for example, +to take specific actions only +when a certain target or targets +is explicitly being built. + +Example: + +.ES +if 'foo' in COMMAND_LINE_TARGETS: + print "Don't forget to test the `foo' program!" +if 'special/program' in COMMAND_LINE_TARGETS: + SConscript('special') +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +DEFAULT_TARGETS +A list of the target +.I nodes +that have been specified using the +.BR Default () +function or method. +The elements of the list are nodes, +so you need to run them through the Python +.B str +function to get at the path name for each Node. + +Example: + +.ES +print str(DEFAULT_TARGETS[0]) +if 'foo' in map(str, DEFAULT_TARGETS): + print "Don't forget to test the `foo' program!" +.EE +.IP +The contents of the +.B DEFAULT_TARGETS +list change on on each successive call to the +.BR Default () +function: + +.ES +print map(str, DEFAULT_TARGETS) # originally [] +Default('foo') +print map(str, DEFAULT_TARGETS) # now a node ['foo'] +Default('bar') +print map(str, DEFAULT_TARGETS) # now a node ['foo', 'bar'] +Default(None) +print map(str, DEFAULT_TARGETS) # back to [] +.EE +.IP +Consequently, be sure to use +.B DEFAULT_TARGETS +only after you've made all of your +.BR Default () +calls, +or else simply be careful of the order +of these statements in your SConscript files +so that you don't look for a specific +default target before it's actually been added to the list. + +.SS Construction Variables +.\" XXX From Gary Ruben, 23 April 2002: +.\" I think it would be good to have an example with each construction +.\" variable description in the documentation. +.\" eg. +.\" CC The C compiler +.\" Example: env["CC"] = "c68x" +.\" Default: env["CC"] = "cc" +.\" +.\" CCCOM The command line ... +.\" Example: +.\" To generate the compiler line c68x -ps -qq -mr -o $TARGET $SOURCES +.\" env["CC"] = "c68x" +.\" env["CFLAGS"] = "-ps -qq -mr" +.\" env["CCCOM"] = "$CC $CFLAGS -o $TARGET $SOURCES +.\" Default: +.\" (I dunno what this is ;-) +A construction environment has an associated dictionary of +.I construction variables +that are used by built-in or user-supplied build rules. +Construction variables must follow the same rules for +Python identifiers: +the initial character must be an underscore or letter, +followed by any number of underscores, letters, or digits. + +A number of useful construction variables are automatically defined by +scons for each supported platform, and additional construction variables +can be defined by the user. The following is a list of the automatically +defined construction variables: + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +'\" BEGIN GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS +'\" +'\" The descriptions below of the various SCons construction variables +'\" are generated from the .xml files that live next to the various +'\" Python modules in the build enginer library. If you're reading +'\" this [gnt]roff file with an eye towards patching this man page, +'\" you can still submit a diff against this text, but it will have to +'\" be translated to a diff against the underlying .xml file before the +'\" patch is actually accepted. If you do that yourself, it will make +'\" it easier to integrate the patch. +'\" +'\" BEGIN GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.so variables.man +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +'\" END GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS +'\" +'\" The descriptions above of the various SCons construction variables +'\" are generated from the .xml files that live next to the various +'\" Python modules in the build enginer library. If you're reading +'\" this [gnt]roff file with an eye towards patching this man page, +'\" you can still submit a diff against this text, but it will have to +'\" be translated to a diff against the underlying .xml file before the +'\" patch is actually accepted. If you do that yourself, it will make +'\" it easier to integrate the patch. +'\" +'\" END GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +.LP +Construction variables can be retrieved and set using the +.B Dictionary +method of the construction environment: + +.ES +dict = env.Dictionary() +dict["CC"] = "cc" +.EE + +or using the [] operator: + +.ES +env["CC"] = "cc" +.EE + +Construction variables can also be passed to the construction environment +constructor: + +.ES +env = Environment(CC="cc") +.EE + +or when copying a construction environment using the +.B Clone +method: + +.ES +env2 = env.Clone(CC="cl.exe") +.EE + +.SS Configure Contexts + +.B scons +supports +.I configure contexts, +an integrated mechanism similar to the +various AC_CHECK macros in GNU autoconf +for testing for the existence of C header +files, libraries, etc. +In contrast to autoconf, +.B scons +does not maintain an explicit cache of the tested values, +but uses its normal dependency tracking to keep the checked values +up to date. However, users may override this behaviour with the +.B --config +command line option. + +The following methods can be used to perform checks: + +.TP +.RI Configure( env ", [" custom_tests ", " conf_dir ", " log_file ", " config_h ", " clean ", " help]) +.TP +.RI env.Configure([ custom_tests ", " conf_dir ", " log_file ", " config_h ", " clean ", " help]) +This creates a configure context, which can be used to perform checks. +.I env +specifies the environment for building the tests. +This environment may be modified when performing checks. +.I custom_tests +is a dictionary containing custom tests. +See also the section about custom tests below. +By default, no custom tests are added to the configure context. +.I conf_dir +specifies a directory where the test cases are built. +Note that this directory is not used for building +normal targets. +The default value is the directory +#/.sconf_temp. +.I log_file +specifies a file which collects the output from commands +that are executed to check for the existence of header files, libraries, etc. +The default is the file #/config.log. +If you are using the +.BR VariantDir () +method, +you may want to specify a subdirectory under your variant directory. +.I config_h +specifies a C header file where the results of tests +will be written, e.g. #define HAVE_STDIO_H, #define HAVE_LIBM, etc. +The default is to not write a +.B config.h +file. +You can specify the same +.B config.h +file in multiple calls to Configure, +in which case +.B scons +will concatenate all results in the specified file. +Note that SCons +uses its normal dependency checking +to decide if it's necessary to rebuild +the specified +.I config_h +file. +This means that the file is not necessarily re-built each +time scons is run, +but is only rebuilt if its contents will have changed +and some target that depends on the +.I config_h +file is being built. + +The optional +.B clean +and +.B help +arguments can be used to suppress execution of the configuration +tests when the +.B -c/--clean +or +.B -H/-h/--help +options are used, respectively. +The default behavior is always to execute +configure context tests, +since the results of the tests may +affect the list of targets to be cleaned +or the help text. +If the configure tests do not affect these, +then you may add the +.B clean=False +or +.B help=False +arguments +(or both) +to avoid unnecessary test execution. + +.EE +A created +.B Configure +instance has the following associated methods: + +.TP +.RI SConf.Finish( context ) +.TP +.IR sconf .Finish() +This method should be called after configuration is done. +It returns the environment as modified +by the configuration checks performed. +After this method is called, no further checks can be performed +with this configuration context. +However, you can create a new +.RI Configure +context to perform additional checks. +Only one context should be active at a time. + +The following Checks are predefined. +(This list will likely grow larger as time +goes by and developers contribute new useful tests.) + +.TP +.RI SConf.CheckHeader( context ", " header ", [" include_quotes ", " language ]) +.TP +.IR sconf .CheckHeader( header ", [" include_quotes ", " language ]) +Checks if +.I header +is usable in the specified language. +.I header +may be a list, +in which case the last item in the list +is the header file to be checked, +and the previous list items are +header files whose +.B #include +lines should precede the +header line being checked for. +The optional argument +.I include_quotes +must be +a two character string, where the first character denotes the opening +quote and the second character denotes the closing quote. +By default, both characters are " (double quote). +The optional argument +.I language +should be either +.B C +or +.B C++ +and selects the compiler to be used for the check. +Returns 1 on success and 0 on failure. + +.TP +.RI SConf.CheckCHeader( context ", " header ", [" include_quotes ]) +.TP +.IR sconf .CheckCHeader( header ", [" include_quotes ]) +This is a wrapper around +.B SConf.CheckHeader +which checks if +.I header +is usable in the C language. +.I header +may be a list, +in which case the last item in the list +is the header file to be checked, +and the previous list items are +header files whose +.B #include +lines should precede the +header line being checked for. +The optional argument +.I include_quotes +must be +a two character string, where the first character denotes the opening +quote and the second character denotes the closing quote (both default +to \N'34'). +Returns 1 on success and 0 on failure. + +.TP +.RI SConf.CheckCXXHeader( context ", " header ", [" include_quotes ]) +.TP +.IR sconf .CheckCXXHeader( header ", [" include_quotes ]) +This is a wrapper around +.B SConf.CheckHeader +which checks if +.I header +is usable in the C++ language. +.I header +may be a list, +in which case the last item in the list +is the header file to be checked, +and the previous list items are +header files whose +.B #include +lines should precede the +header line being checked for. +The optional argument +.I include_quotes +must be +a two character string, where the first character denotes the opening +quote and the second character denotes the closing quote (both default +to \N'34'). +Returns 1 on success and 0 on failure. + +.TP +.RI SConf.CheckFunc( context, ", " function_name ", [" header ", " language ]) +.TP +.IR sconf .CheckFunc( function_name ", [" header ", " language ]) +Checks if the specified +C or C++ function is available. +.I function_name +is the name of the function to check for. +The optional +.I header +argument is a string +that will be +placed at the top +of the test file +that will be compiled +to check if the function exists; +the default is: +.ES +#ifdef __cplusplus +extern "C" +#endif +char function_name(); +.EE +The optional +.I language +argument should be +.B C +or +.B C++ +and selects the compiler to be used for the check; +the default is "C". + +.TP +.RI SConf.CheckLib( context ", [" library ", " symbol ", " header ", " language ", " autoadd=1 ]) +.TP +.IR sconf .CheckLib([ library ", " symbol ", " header ", " language ", " autoadd=1 ]) +Checks if +.I library +provides +.IR symbol . +If the value of +.I autoadd +is 1 and the library provides the specified +.IR symbol , +appends the library to the LIBS construction environment variable. +.I library +may also be None (the default), +in which case +.I symbol +is checked with the current LIBS variable, +or a list of library names, +in which case each library in the list +will be checked for +.IR symbol . +If +.I symbol +is not set or is +.BR None , +then +.BR SConf.CheckLib () +just checks if +you can link against the specified +.IR library . +The optional +.I language +argument should be +.B C +or +.B C++ +and selects the compiler to be used for the check; +the default is "C". +The default value for +.I autoadd +is 1. +This method returns 1 on success and 0 on error. + +.TP +.RI SConf.CheckLibWithHeader( context ", " library ", " header ", " language ", [" call ", " autoadd ]) +.TP +.IR sconf .CheckLibWithHeader( library ", " header ", " language ", [" call ", " autoadd ]) + +In contrast to the +.RI SConf.CheckLib +call, this call provides a more sophisticated way to check against libraries. +Again, +.I library +specifies the library or a list of libraries to check. +.I header +specifies a header to check for. +.I header +may be a list, +in which case the last item in the list +is the header file to be checked, +and the previous list items are +header files whose +.B #include +lines should precede the +header line being checked for. +.I language +may be one of 'C','c','CXX','cxx','C++' and 'c++'. +.I call +can be any valid expression (with a trailing ';'). +If +.I call +is not set, +the default simply checks that you +can link against the specified +.IR library . +.I autoadd +specifies whether to add the library to the environment (only if the check +succeeds). This method returns 1 on success and 0 on error. + +.TP +.RI SConf.CheckType( context ", " type_name ", [" includes ", " language ]) +.TP +.IR sconf .CheckType( type_name ", [" includes ", " language ]) +Checks for the existence of a type defined by +.BR typedef . +.I type_name +specifies the typedef name to check for. +.I includes +is a string containing one or more +.B #include +lines that will be inserted into the program +that will be run to test for the existence of the type. +The optional +.I language +argument should be +.B C +or +.B C++ +and selects the compiler to be used for the check; +the default is "C". +Example: +.ES +sconf.CheckType('foo_type', '#include "my_types.h"', 'C++') +.EE + +.TP +.RI Configure.CheckCC( self ) +Checks whether the C compiler (as defined by the CC construction variable) works +by trying to compile a small source file. + +By default, SCons only detects if there is a program with the correct name, not +if it is a functioning compiler. + +This uses the exact same command than the one used by the object builder for C +source file, so it can be used to detect if a particular compiler flag works or +not. + +.TP +.RI Configure.CheckCXX( self ) +Checks whether the C++ compiler (as defined by the CXX construction variable) +works by trying to compile a small source file. By default, SCons only detects +if there is a program with the correct name, not if it is a functioning compiler. + +This uses the exact same command than the one used by the object builder for +CXX source files, so it can be used to detect if a particular compiler flag +works or not. + +.TP +.RI Configure.CheckSHCC( self ) +Checks whether the C compiler (as defined by the SHCC construction variable) works +by trying to compile a small source file. By default, SCons only detects if +there is a program with the correct name, not if it is a functioning compiler. + +This uses the exact same command than the one used by the object builder for C +source file, so it can be used to detect if a particular compiler flag works or +not. This does not check whether the object code can be used to build a shared +library, only that the compilation (not link) succeeds. + +.TP +.RI Configure.CheckSHCXX( self ) +Checks whether the C++ compiler (as defined by the SHCXX construction variable) +works by trying to compile a small source file. By default, SCons only detects +if there is a program with the correct name, not if it is a functioning compiler. + +This uses the exact same command than the one used by the object builder for +CXX source files, so it can be used to detect if a particular compiler flag +works or not. This does not check whether the object code can be used to build +a shared library, only that the compilation (not link) succeeds. + +.EE +Example of a typical Configure usage: + +.ES +env = Environment() +conf = Configure( env ) +if not conf.CheckCHeader( 'math.h' ): + print 'We really need math.h!' + Exit(1) +if conf.CheckLibWithHeader( 'qt', 'qapp.h', 'c++', + 'QApplication qapp(0,0);' ): + # do stuff for qt - usage, e.g. + conf.env.Append( CPPFLAGS = '-DWITH_QT' ) +env = conf.Finish() +.EE + +.TP +.RI SConf.CheckTypeSize( context ", " type_name ", [" header ", " language ", " expect ]) +.TP +.IR sconf .CheckTypeSize( type_name ", [" header ", " language ", " expect ]) +Checks for the size of a type defined by +.BR typedef . +.I type_name +specifies the typedef name to check for. +The optional +.I header +argument is a string +that will be +placed at the top +of the test file +that will be compiled +to check if the function exists; +the default is empty. +The optional +.I language +argument should be +.B C +or +.B C++ +and selects the compiler to be used for the check; +the default is "C". +The optional +.I expect +argument should be an integer. +If this argument is used, +the function will only check whether the type +given in type_name has the expected size (in bytes). +For example, +.B "CheckTypeSize('short', expect = 2)" +will return success only if short is two bytes. + +.ES +.EE + +.TP +.RI SConf.CheckDeclaration( context ", " symbol ", [" includes ", " language ]) +.TP +.IR sconf .CheckDeclaration( symbol ", [" includes ", " language ]) +Checks if the specified +.I symbol +is declared. +.I includes +is a string containing one or more +.B #include +lines that will be inserted into the program +that will be run to test for the existence of the type. +The optional +.I language +argument should be +.B C +or +.B C++ +and selects the compiler to be used for the check; +the default is "C". + +.TP +.RI SConf.Define( context ", " symbol ", [" value ", " comment ]) +.TP +.IR sconf .Define( symbol ", [" value ", " comment ]) +This function does not check for anything, but defines a +preprocessor symbol that will be added to the configuration header file. +It is the equivalent of AC_DEFINE, +and defines the symbol +.I name +with the optional +.B value +and the optional comment +.BR comment . + +.IP +Examples: + +.ES +env = Environment() +conf = Configure( env ) + +# Puts the following line in the config header file: +# #define A_SYMBOL +conf.Define('A_SYMBOL') + +# Puts the following line in the config header file: +# #define A_SYMBOL 1 +conf.Define('A_SYMBOL', 1) +.EE + +.IP +Be careful about quoting string values, though: + +.ES +env = Environment() +conf = Configure( env ) + +# Puts the following line in the config header file: +# #define A_SYMBOL YA +conf.Define('A_SYMBOL', "YA") + +# Puts the following line in the config header file: +# #define A_SYMBOL "YA" +conf.Define('A_SYMBOL', '"YA"') +.EE + +.IP +For comment: + +.ES +env = Environment() +conf = Configure( env ) + +# Puts the following lines in the config header file: +# /* Set to 1 if you have a symbol */ +# #define A_SYMBOL 1 +conf.Define('A_SYMBOL', 1, 'Set to 1 if you have a symbol') +.EE + +.EE +You can define your own custom checks. +in addition to the predefined checks. +These are passed in a dictionary to the Configure function. +This dictionary maps the names of the checks +to user defined Python callables +(either Python functions or class instances implementing the +.I __call__ +method). +The first argument of the call is always a +.I CheckContext +instance followed by the arguments, +which must be supplied by the user of the check. +These CheckContext instances define the following methods: + +.TP +.RI CheckContext.Message( self ", " text ) + +Usually called before the check is started. +.I text +will be displayed to the user, e.g. 'Checking for library X...' + +.TP +.RI CheckContext.Result( self, ", " res ) + +Usually called after the check is done. +.I res +can be either an integer or a string. In the former case, 'yes' (res != 0) +or 'no' (res == 0) is displayed to the user, in the latter case the +given string is displayed. + +.TP +.RI CheckContext.TryCompile( self ", " text ", " extension ) +Checks if a file with the specified +.I extension +(e.g. '.c') containing +.I text +can be compiled using the environment's +.B Object +builder. Returns 1 on success and 0 on failure. + +.TP +.RI CheckContext.TryLink( self ", " text ", " extension ) +Checks, if a file with the specified +.I extension +(e.g. '.c') containing +.I text +can be compiled using the environment's +.B Program +builder. Returns 1 on success and 0 on failure. + +.TP +.RI CheckContext.TryRun( self ", " text ", " extension ) +Checks, if a file with the specified +.I extension +(e.g. '.c') containing +.I text +can be compiled using the environment's +.B Program +builder. On success, the program is run. If the program +executes successfully +(that is, its return status is 0), +a tuple +.I (1, outputStr) +is returned, where +.I outputStr +is the standard output of the +program. +If the program fails execution +(its return status is non-zero), +then (0, '') is returned. + +.TP +.RI CheckContext.TryAction( self ", " action ", [" text ", " extension ]) +Checks if the specified +.I action +with an optional source file (contents +.I text +, extension +.I extension += '' +) can be executed. +.I action +may be anything which can be converted to a +.B scons +.RI Action. +On success, +.I (1, outputStr) +is returned, where +.I outputStr +is the content of the target file. +On failure +.I (0, '') +is returned. + +.TP +.RI CheckContext.TryBuild( self ", " builder ", [" text ", " extension ]) +Low level implementation for testing specific builds; +the methods above are based on this method. +Given the Builder instance +.I builder +and the optional +.I text +of a source file with optional +.IR extension , +this method returns 1 on success and 0 on failure. In addition, +.I self.lastTarget +is set to the build target node, if the build was successful. + +.EE +Example for implementing and using custom tests: + +.ES +def CheckQt(context, qtdir): + context.Message( 'Checking for qt ...' ) + lastLIBS = context.env['LIBS'] + lastLIBPATH = context.env['LIBPATH'] + lastCPPPATH= context.env['CPPPATH'] + context.env.Append(LIBS = 'qt', LIBPATH = qtdir + '/lib', CPPPATH = qtdir + '/include' ) + ret = context.TryLink(""" +#include <qapp.h> +int main(int argc, char **argv) { + QApplication qapp(argc, argv); + return 0; +} +""") + if not ret: + context.env.Replace(LIBS = lastLIBS, LIBPATH=lastLIBPATH, CPPPATH=lastCPPPATH) + context.Result( ret ) + return ret + +env = Environment() +conf = Configure( env, custom_tests = { 'CheckQt' : CheckQt } ) +if not conf.CheckQt('/usr/lib/qt'): + print 'We really need qt!' + Exit(1) +env = conf.Finish() +.EE + +.SS Command-Line Construction Variables + +Often when building software, +some variables must be specified at build time. +For example, libraries needed for the build may be in non-standard +locations, or site-specific compiler options may need to be passed to the +compiler. +.B scons +provides a +.B Variables +object to support overriding construction variables +on the command line: +.ES +$ scons VARIABLE=foo +.EE +The variable values can also be specified in a text-based SConscript file. +To create a Variables object, call the Variables() function: + +.TP +.RI Variables([ files "], [" args ]) +This creates a Variables object that will read construction variables from +the file or list of filenames specified in +.IR files . +If no files are specified, +or the +.I files +argument is +.BR None , +then no files will be read. +The optional argument +.I args +is a dictionary of +values that will override anything read from the specified files; +it is primarily intended to be passed the +.B ARGUMENTS +dictionary that holds variables +specified on the command line. +Example: + +.ES +vars = Variables('custom.py') +vars = Variables('overrides.py', ARGUMENTS) +vars = Variables(None, {FOO:'expansion', BAR:7}) +.EE + +Variables objects have the following methods: + +.TP +.RI Add( key ", [" help ", " default ", " validator ", " converter ]) +This adds a customizable construction variable to the Variables object. +.I key +is the name of the variable. +.I help +is the help text for the variable. +.I default +is the default value of the variable; +if the default value is +.B None +and there is no explicit value specified, +the construction variable will +.I not +be added to the construction environment. +.I validator +is called to validate the value of the variable, and should take three +arguments: key, value, and environment. +The recommended way to handle an invalid value is +to raise an exception (see example below). +.I converter +is called to convert the value before putting it in the environment, and +should take either a value, or the value and environment, as parameters. +The +.I converter +must return a value, +which will be converted into a string +before being validated by the +.I validator +(if any) +and then added to the environment. + +Examples: + +.ES +vars.Add('CC', 'The C compiler') + +def validate_color(key, val, env): + if not val in ['red', 'blue', 'yellow']: + raise "Invalid color value '%s'" % val +vars.Add('COLOR', validator=valid_color) +.EE + +.TP +.RI AddVariables( list ) +A wrapper script that adds +multiple customizable construction variables +to a Variables object. +.I list +is a list of tuple or list objects +that contain the arguments +for an individual call to the +.B Add +method. + +.ES +opt.AddVariables( + ('debug', '', 0), + ('CC', 'The C compiler'), + ('VALIDATE', 'An option for testing validation', + 'notset', validator, None), + ) +.EE + +.TP +.RI Update( env ", [" args ]) +This updates a construction environment +.I env +with the customized construction variables. +Any specified variables that are +.I not +configured for the Variables object +will be saved and may be +retrieved with the +.BR UnknownVariables () +method, below. + +Normally this method is not called directly, +but is called indirectly by passing the Variables object to +the Environment() function: + +.ES +env = Environment(variables=vars) +.EE + +.IP +The text file(s) that were specified +when the Variables object was created +are executed as Python scripts, +and the values of (global) Python variables set in the file +are added to the construction environment. + +Example: + +.ES +CC = 'my_cc' +.EE + +.TP +.RI UnknownVariables( ) +Returns a dictionary containing any +variables that were specified +either in the files or the dictionary +with which the Variables object was initialized, +but for which the Variables object was +not configured. + +.ES +env = Environment(variables=vars) +for key, value in vars.UnknownVariables(): + print "unknown variable: %s=%s" % (key, value) +.EE + +.TP +.RI Save( filename ", " env ) +This saves the currently set variables into a script file named +.I filename +that can be used on the next invocation to automatically load the current +settings. This method combined with the Variables method can be used to +support caching of variables between runs. + +.ES +env = Environment() +vars = Variables(['variables.cache', 'custom.py']) +vars.Add(...) +vars.Update(env) +vars.Save('variables.cache', env) +.EE + +.TP +.RI GenerateHelpText( env ", [" sort ]) +This generates help text documenting the customizable construction +variables suitable to passing in to the Help() function. +.I env +is the construction environment that will be used to get the actual values +of customizable variables. Calling with +an optional +.I sort +function +will cause the output to be sorted +by the specified argument. +The specific +.I sort +function +should take two arguments +and return +-1, 0 or 1 +(like the standard Python +.I cmp +function). + +.ES +Help(vars.GenerateHelpText(env)) +Help(vars.GenerateHelpText(env, sort=cmp)) +.EE + +.TP +.RI FormatVariableHelpText( env ", " opt ", " help ", " default ", " actual ) +This method returns a formatted string +containing the printable help text +for one option. +It is normally not called directly, +but is called by the +.IR GenerateHelpText () +method to create the returned help text. +It may be overridden with your own +function that takes the arguments specified above +and returns a string of help text formatted to your liking. +Note that the +.IR GenerateHelpText () +will not put any blank lines or extra +characters in between the entries, +so you must add those characters to the returned +string if you want the entries separated. + +.ES +def my_format(env, opt, help, default, actual): + fmt = "\n%s: default=%s actual=%s (%s)\n" + return fmt % (opt, default. actual, help) +vars.FormatVariableHelpText = my_format +.EE + +To make it more convenient to work with customizable Variables, +.B scons +provides a number of functions +that make it easy to set up +various types of Variables: + +.TP +.RI BoolVariable( key ", " help ", " default ) +Return a tuple of arguments +to set up a Boolean option. +The option will use +the specified name +.IR key , +have a default value of +.IR default , +and display the specified +.I help +text. +The option will interpret the values +.BR y , +.BR yes , +.BR t , +.BR true , +.BR 1 , +.B on +and +.B all +as true, +and the values +.BR n , +.BR no , +.BR f , +.BR false , +.BR 0 , +.B off +and +.B none +as false. + +.TP +.RI EnumVariable( key ", " help ", " default ", " allowed_values ", [" map ", " ignorecase ]) +Return a tuple of arguments +to set up an option +whose value may be one +of a specified list of legal enumerated values. +The option will use +the specified name +.IR key , +have a default value of +.IR default , +and display the specified +.I help +text. +The option will only support those +values in the +.I allowed_values +list. +The optional +.I map +argument is a dictionary +that can be used to convert +input values into specific legal values +in the +.I allowed_values +list. +If the value of +.I ignore_case +is +.B 0 +(the default), +then the values are case-sensitive. +If the value of +.I ignore_case +is +.BR 1 , +then values will be matched +case-insensitive. +If the value of +.I ignore_case +is +.BR 1 , +then values will be matched +case-insensitive, +and all input values will be +converted to lower case. + +.TP +.RI ListVariable( key ", " help ", " default ", " names ", [", map ]) +Return a tuple of arguments +to set up an option +whose value may be one or more +of a specified list of legal enumerated values. +The option will use +the specified name +.IR key , +have a default value of +.IR default , +and display the specified +.I help +text. +The option will only support the values +.BR all , +.BR none , +or the values in the +.I names +list. +More than one value may be specified, +with all values separated by commas. +The default may be a string of +comma-separated default values, +or a list of the default values. +The optional +.I map +argument is a dictionary +that can be used to convert +input values into specific legal values +in the +.I names +list. + +.TP +.RI PackageVariable( key ", " help ", " default ) +Return a tuple of arguments +to set up an option +whose value is a path name +of a package that may be +enabled, disabled or +given an explicit path name. +The option will use +the specified name +.IR key , +have a default value of +.IR default , +and display the specified +.I help +text. +The option will support the values +.BR yes , +.BR true , +.BR on , +.BR enable +or +.BR search , +in which case the specified +.I default +will be used, +or the option may be set to an +arbitrary string +(typically the path name to a package +that is being enabled). +The option will also support the values +.BR no , +.BR false , +.BR off +or +.BR disable +to disable use of the specified option. + +.TP +.RI PathVariable( key ", " help ", " default ", [" validator ]) +Return a tuple of arguments +to set up an option +whose value is expected to be a path name. +The option will use +the specified name +.IR key , +have a default value of +.IR default , +and display the specified +.I help +text. +An additional +.I validator +may be specified +that will be called to +verify that the specified path +is acceptable. +SCons supplies the +following ready-made validators: +.BR PathVariable.PathExists +(the default), +which verifies that the specified path exists; +.BR PathVariable.PathIsFile , +which verifies that the specified path is an existing file; +.BR PathVariable.PathIsDir , +which verifies that the specified path is an existing directory; +.BR PathVariable.PathIsDirCreate , +which verifies that the specified path is a directory +and will create the specified directory if the path does not exist; +and +.BR PathVariable.PathAccept , +which simply accepts the specific path name argument without validation, +and which is suitable if you want your users +to be able to specify a directory path that will be +created as part of the build process, for example. +You may supply your own +.I validator +function, +which must take three arguments +.RI ( key , +the name of the variable to be set; +.IR val , +the specified value being checked; +and +.IR env , +the construction environment) +and should raise an exception +if the specified value is not acceptable. + +.RE +These functions make it +convenient to create a number +of variables with consistent behavior +in a single call to the +.B AddVariables +method: + +.ES +vars.AddVariables( + BoolVariable('warnings', 'compilation with -Wall and similiar', 1), + EnumVariable('debug', 'debug output and symbols', 'no' + allowed_values=('yes', 'no', 'full'), + map={}, ignorecase=0), # case sensitive + ListVariable('shared', + 'libraries to build as shared libraries', + 'all', + names = list_of_libs), + PackageVariable('x11', + 'use X11 installed here (yes = search some places)', + 'yes'), + PathVariable('qtdir', 'where the root of Qt is installed', qtdir), + PathVariable('foopath', 'where the foo library is installed', foopath, + PathVariable.PathIsDir), + +) +.EE + +.SS File and Directory Nodes + +The +.IR File () +and +.IR Dir () +functions return +.I File +and +.I Dir +Nodes, respectively. +python objects, respectively. +Those objects have several user-visible attributes +and methods that are often useful: + +.IP path +The build path +of the given +file or directory. +This path is relative to the top-level directory +(where the +.B SConstruct +file is found). +The build path is the same as the source path if +.I variant_dir +is not being used. + +.IP abspath +The absolute build path of the given file or directory. + +.IP srcnode() +The +.IR srcnode () +method +returns another +.I File +or +.I Dir +object representing the +.I source +path of the given +.I File +or +.IR Dir . +The + +.ES +# Get the current build dir's path, relative to top. +Dir('.').path +# Current dir's absolute path +Dir('.').abspath +# Next line is always '.', because it is the top dir's path relative to itself. +Dir('#.').path +File('foo.c').srcnode().path # source path of the given source file. + +# Builders also return File objects: +foo = env.Program('foo.c') +print "foo will be built in %s"%foo.path +.EE + +A +.I Dir +Node or +.I File +Node can also be used to create +file and subdirectory Nodes relative to the generating Node. +A +.I Dir +Node will place the new Nodes within the directory it represents. +A +.I File +node will place the new Nodes within its parent directory +(that is, "beside" the file in question). +If +.I d +is a +.I Dir +(directory) Node and +.I f +is a +.I File +(file) Node, +then these methods are available: + +.TP +.IR d .Dir( name ) +Returns a directory Node for a subdirectory of +.I d +named +.IR name . + +.TP +.IR d .File( name ) +Returns a file Node for a file within +.I d +named +.IR name . + +.TP +.IR d .Entry( name ) +Returns an unresolved Node within +.I d +named +.IR name . + +.TP +.IR f .Dir( name ) +Returns a directory named +.I name +within the parent directory of +.IR f . + +.TP +.IR f .File( name ) +Returns a file named +.I name +within the parent directory of +.IR f . + +.TP +.IR f .Entry( name ) +Returns an unresolved Node named +.I name +within the parent directory of +.IR f . + +.RE +For example: + +.ES +# Get a Node for a file within a directory +incl = Dir('include') +f = incl.File('header.h') + +# Get a Node for a subdirectory within a directory +dist = Dir('project-3.2.1) +src = dist.Dir('src') + +# Get a Node for a file in the same directory +cfile = File('sample.c') +hfile = cfile.File('sample.h') + +# Combined example +docs = Dir('docs') +html = docs.Dir('html') +index = html.File('index.html') +css = index.File('app.css') +.EE + +.SH EXTENDING SCONS +.SS Builder Objects +.B scons +can be extended to build different types of targets +by adding new Builder objects +to a construction environment. +.IR "In general" , +you should only need to add a new Builder object +when you want to build a new type of file or other external target. +If you just want to invoke a different compiler or other tool +to build a Program, Object, Library, or any other +type of output file for which +.B scons +already has an existing Builder, +it is generally much easier to +use those existing Builders +in a construction environment +that sets the appropriate construction variables +(CC, LINK, etc.). + +Builder objects are created +using the +.B Builder +function. +The +.B Builder +function accepts the following arguments: + +.IP action +The command line string used to build the target from the source. +.B action +can also be: +a list of strings representing the command +to be executed and its arguments +(suitable for enclosing white space in an argument), +a dictionary +mapping source file name suffixes to +any combination of command line strings +(if the builder should accept multiple source file extensions), +a Python function; +an Action object +(see the next section); +or a list of any of the above. + +An action function +takes three arguments: +.I source +- a list of source nodes, +.I target +- a list of target nodes, +.I env +- the construction environment. + +.IP prefix +The prefix that will be prepended to the target file name. +This may be specified as a: + +.RS 10 +.HP 6 +* +.IR string , + +.HP 6 +* +.I callable object +- a function or other callable that takes +two arguments (a construction environment and a list of sources) +and returns a prefix, + +.HP 6 +* +.I dictionary +- specifies a mapping from a specific source suffix (of the first +source specified) to a corresponding target prefix. Both the source +suffix and target prefix specifications may use environment variable +substitution, and the target prefix (the 'value' entries in the +dictionary) may also be a callable object. The default target prefix +may be indicated by a dictionary entry with a key value of None. +.RE +.P + +.ES +b = Builder("build_it < $SOURCE > $TARGET" + prefix = "file-") + +def gen_prefix(env, sources): + return "file-" + env['PLATFORM'] + '-' +b = Builder("build_it < $SOURCE > $TARGET", + prefix = gen_prefix) + +b = Builder("build_it < $SOURCE > $TARGET", + suffix = { None: "file-", + "$SRC_SFX_A": gen_prefix }) +.EE + +.IP suffix +The suffix that will be appended to the target file name. +This may be specified in the same manner as the prefix above. +If the suffix is a string, then +.B scons +will append a '.' to the beginning of the suffix if it's not already +there. The string returned by callable object (or obtained from the +dictionary) is untouched and must append its own '.' to the beginning +if one is desired. + +.ES +b = Builder("build_it < $SOURCE > $TARGET" + suffix = "-file") + +def gen_suffix(env, sources): + return "." + env['PLATFORM'] + "-file" +b = Builder("build_it < $SOURCE > $TARGET", + suffix = gen_suffix) + +b = Builder("build_it < $SOURCE > $TARGET", + suffix = { None: ".sfx1", + "$SRC_SFX_A": gen_suffix }) +.EE + +.IP ensure_suffix +When set to any true value, causes +.B scons +to add the target suffix specified by the +.I suffix +keyword to any target strings +that have a different suffix. +(The default behavior is to leave untouched +any target file name that looks like it already has any suffix.) + +.ES +b1 = Builder("build_it < $SOURCE > $TARGET" + suffix = ".out") +b2 = Builder("build_it < $SOURCE > $TARGET" + suffix = ".out", + ensure_suffix) +env = Environment() +env['BUILDERS']['B1'] = b1 +env['BUILDERS']['B2'] = b2 + +# Builds "foo.txt" because ensure_suffix is not set. +env.B1('foo.txt', 'foo.in') + +# Builds "bar.txt.out" because ensure_suffix is set. +env.B2('bar.txt', 'bar.in') +.EE + +.IP src_suffix +The expected source file name suffix. This may be a string or a list +of strings. + +.IP target_scanner +A Scanner object that +will be invoked to find +implicit dependencies for this target file. +This keyword argument should be used +for Scanner objects that find +implicit dependencies +based only on the target file +and the construction environment, +.I not +for implicit +(See the section "Scanner Objects," below, +for information about creating Scanner objects.) + +.IP source_scanner +A Scanner object that +will be invoked to +find implicit dependences in +any source files +used to build this target file. +This is where you would +specify a scanner to +find things like +.B #include +lines in source files. +The pre-built +.B DirScanner +Scanner object may be used to +indicate that this Builder +should scan directory trees +for on-disk changes to files +that +.B scons +does not know about from other Builder or function calls. +(See the section "Scanner Objects," below, +for information about creating your own Scanner objects.) + +.IP target_factory +A factory function that the Builder will use +to turn any targets specified as strings into SCons Nodes. +By default, +SCons assumes that all targets are files. +Other useful target_factory +values include +.BR Dir , +for when a Builder creates a directory target, +and +.BR Entry , +for when a Builder can create either a file +or directory target. + +Example: + +.ES +MakeDirectoryBuilder = Builder(action=my_mkdir, target_factory=Dir) +env = Environment() +env.Append(BUILDERS = {'MakeDirectory':MakeDirectoryBuilder}) +env.MakeDirectory('new_directory', []) +.EE + +.IP +Note that the call to the MakeDirectory Builder +needs to specify an empty source list +to make the string represent the builder's target; +without that, it would assume the argument is the source, +and would try to deduce the target name from it, +which in the absence of an automatically-added prefix or suffix +would lead to a matching target and source name +and a circular dependency. + +.IP source_factory +A factory function that the Builder will use +to turn any sources specified as strings into SCons Nodes. +By default, +SCons assumes that all source are files. +Other useful source_factory +values include +.BR Dir , +for when a Builder uses a directory as a source, +and +.BR Entry , +for when a Builder can use files +or directories (or both) as sources. + +Example: + +.ES +CollectBuilder = Builder(action=my_mkdir, source_factory=Entry) +env = Environment() +env.Append(BUILDERS = {'Collect':CollectBuilder}) +env.Collect('archive', ['directory_name', 'file_name']) +.EE + +.IP emitter +A function or list of functions to manipulate the target and source +lists before dependencies are established +and the target(s) are actually built. +.B emitter +can also be a string containing a construction variable to expand +to an emitter function or list of functions, +or a dictionary mapping source file suffixes +to emitter functions. +(Only the suffix of the first source file +is used to select the actual emitter function +from an emitter dictionary.) + +An emitter function +takes three arguments: +.I source +- a list of source nodes, +.I target +- a list of target nodes, +.I env +- the construction environment. +An emitter must return a tuple containing two lists, +the list of targets to be built by this builder, +and the list of sources for this builder. + +Example: + +.ES +def e(target, source, env): + return (target + ['foo.foo'], source + ['foo.src']) + +# Simple association of an emitter function with a Builder. +b = Builder("my_build < $TARGET > $SOURCE", + emitter = e) + +def e2(target, source, env): + return (target + ['bar.foo'], source + ['bar.src']) + +# Simple association of a list of emitter functions with a Builder. +b = Builder("my_build < $TARGET > $SOURCE", + emitter = [e, e2]) + +# Calling an emitter function through a construction variable. +env = Environment(MY_EMITTER = e) +b = Builder("my_build < $TARGET > $SOURCE", + emitter = '$MY_EMITTER') + +# Calling a list of emitter functions through a construction variable. +env = Environment(EMITTER_LIST = [e, e2]) +b = Builder("my_build < $TARGET > $SOURCE", + emitter = '$EMITTER_LIST') + +# Associating multiple emitters with different file +# suffixes using a dictionary. +def e_suf1(target, source, env): + return (target + ['another_target_file'], source) +def e_suf2(target, source, env): + return (target, source + ['another_source_file']) +b = Builder("my_build < $TARGET > $SOURCE", + emitter = {'.suf1' : e_suf1, + '.suf2' : e_suf2}) +.EE + +.IP multi +Specifies whether this builder is allowed to be called multiple times for +the same target file(s). The default is 0, which means the builder +can not be called multiple times for the same target file(s). Calling a +builder multiple times for the same target simply adds additional source +files to the target; it is not allowed to change the environment associated +with the target, specify addition environment overrides, or associate a different +builder with the target. + +.IP env +A construction environment that can be used +to fetch source code using this Builder. +(Note that this environment is +.I not +used for normal builds of normal target files, +which use the environment that was +used to call the Builder for the target file.) + +.IP generator +A function that returns a list of actions that will be executed to build +the target(s) from the source(s). +The returned action(s) may be +an Action object, or anything that +can be converted into an Action object +(see the next section). + +The generator function +takes four arguments: +.I source +- a list of source nodes, +.I target +- a list of target nodes, +.I env +- the construction environment, +.I for_signature +- a Boolean value that specifies +whether the generator is being called +for generating a build signature +(as opposed to actually executing the command). +Example: + +.ES +def g(source, target, env, for_signature): + return [["gcc", "-c", "-o"] + target + source] + +b = Builder(generator=g) +.EE + +.IP +The +.I generator +and +.I action +arguments must not both be used for the same Builder. + +.IP src_builder +Specifies a builder to use when a source file name suffix does not match +any of the suffixes of the builder. Using this argument produces a +multi-stage builder. + +.IP single_source +Specifies that this builder expects exactly one source file per call. Giving +more than one source files without target files results in implicitely calling +the builder multiple times (once for each source given). Giving multiple +source files together with target files results in a UserError exception. + +.RE +.IP +The +.I generator +and +.I action +arguments must not both be used for the same Builder. + +.IP source_ext_match +When the specified +.I action +argument is a dictionary, +the default behavior when a builder is passed +multiple source files is to make sure that the +extensions of all the source files match. +If it is legal for this builder to be +called with a list of source files with different extensions, +this check can be suppressed by setting +.B source_ext_match +to +.B None +or some other non-true value. +When +.B source_ext_match +is disable, +.B scons +will use the suffix of the first specified +source file to select the appropriate action from the +.I action +dictionary. + +In the following example, +the setting of +.B source_ext_match +prevents +.B scons +from exiting with an error +due to the mismatched suffixes of +.B foo.in +and +.BR foo.extra . + +.ES +b = Builder(action={'.in' : 'build $SOURCES > $TARGET'}, + source_ext_match = None) + +env = Environment(BUILDERS = {'MyBuild':b}) +env.MyBuild('foo.out', ['foo.in', 'foo.extra']) +.EE + +.IP env +A construction environment that can be used +to fetch source code using this Builder. +(Note that this environment is +.I not +used for normal builds of normal target files, +which use the environment that was +used to call the Builder for the target file.) + +.ES +b = Builder(action="build < $SOURCE > $TARGET") +env = Environment(BUILDERS = {'MyBuild' : b}) +env.MyBuild('foo.out', 'foo.in', my_arg = 'xyzzy') +.EE + +.IP chdir +A directory from which scons +will execute the +action(s) specified +for this Builder. +If the +.B chdir +argument is +a string or a directory Node, +scons will change to the specified directory. +If the +.B chdir +is not a string or Node +and is non-zero, +then scons will change to the +target file's directory. + +Note that scons will +.I not +automatically modify +its expansion of +construction variables like +.B $TARGET +and +.B $SOURCE +when using the chdir +keyword argument--that is, +the expanded file names +will still be relative to +the top-level SConstruct directory, +and consequently incorrect +relative to the chdir directory. +Builders created using chdir keyword argument, +will need to use construction variable +expansions like +.B ${TARGET.file} +and +.B ${SOURCE.file} +to use just the filename portion of the +targets and source. + +.ES +b = Builder(action="build < ${SOURCE.file} > ${TARGET.file}", + chdir=1) +env = Environment(BUILDERS = {'MyBuild' : b}) +env.MyBuild('sub/dir/foo.out', 'sub/dir/foo.in') +.EE + +.B WARNING: +Python only keeps one current directory +location for all of the threads. +This means that use of the +.B chdir +argument +will +.I not +work with the SCons +.B -j +option, +because individual worker threads spawned +by SCons interfere with each other +when they start changing directory. + +.RE +Any additional keyword arguments supplied +when a Builder object is created +(that is, when the Builder() function is called) +will be set in the executing construction +environment when the Builder object is called. +The canonical example here would be +to set a construction variable to +the repository of a source code system. + +Any additional keyword arguments supplied +when a Builder +.I object +is called +will only be associated with the target +created by that particular Builder call +(and any other files built as a +result of the call). + +These extra keyword arguments are passed to the +following functions: +command generator functions, +function Actions, +and emitter functions. + +.SS Action Objects + +The +.BR Builder () +function will turn its +.B action +keyword argument into an appropriate +internal Action object. +You can also explicity create Action objects +using the +.BR Action () +global function, +which can then be passed to the +.BR Builder () +function. +This can be used to configure +an Action object more flexibly, +or it may simply be more efficient +than letting each separate Builder object +create a separate Action +when multiple +Builder objects need to do the same thing. + +The +.BR Action () +global function +returns an appropriate object for the action +represented by the type of the first argument: + +.IP Action +If the first argument is already an Action object, +the object is simply returned. + +.IP String +If the first argument is a string, +a command-line Action is returned. +Note that the command-line string +may be preceded by an +.B @ +(at-sign) +to suppress printing of the specified command line, +or by a +.B \- +(hyphen) +to ignore the exit status from the specified command: + +.ES +Action('$CC -c -o $TARGET $SOURCES') + +# Doesn't print the line being executed. +Action('@build $TARGET $SOURCES') + +# Ignores return value +Action('-build $TARGET $SOURCES') +.EE +.\" XXX From Gary Ruben, 23 April 2002: +.\" What would be useful is a discussion of how you execute command +.\" shell commands ie. what is the process used to spawn the shell, pass +.\" environment variables to it etc., whether there is one shell per +.\" environment or one per command etc. It might help to look at the Gnu +.\" make documentation to see what they think is important to discuss about +.\" a build system. I'm sure you can do a better job of organising the +.\" documentation than they have :-) + +.IP List +If the first argument is a list, +then a list of Action objects is returned. +An Action object is created as necessary +for each element in the list. +If an element +.I within +the list is itself a list, +the internal list is the +command and arguments to be executed via +the command line. +This allows white space to be enclosed +in an argument by defining +a command in a list within a list: + +.ES +Action([['cc', '-c', '-DWHITE SPACE', '-o', '$TARGET', '$SOURCES']]) +.EE + +.IP Function +If the first argument is a Python function, +a function Action is returned. +The Python function must take three keyword arguments, +.B target +(a Node object representing the target file), +.B source +(a Node object representing the source file) +and +.B env +(the construction environment +used for building the target file). +The +.B target +and +.B source +arguments may be lists of Node objects if there is +more than one target file or source file. +The actual target and source file name(s) may +be retrieved from their Node objects +via the built-in Python str() function: + +.ES +target_file_name = str(target) +source_file_names = map(lambda x: str(x), source) +.EE +.IP +The function should return +.B 0 +or +.B None +to indicate a successful build of the target file(s). +The function may raise an exception +or return a non-zero exit status +to indicate an unsuccessful build. + +.ES +def build_it(target = None, source = None, env = None): + # build the target from the source + return 0 + +a = Action(build_it) +.EE + +If the action argument is not one of the above, +None is returned. +.PP + +The second argument is optional and is used to define the output +which is printed when the Action is actually performed. +In the absence of this parameter, +or if it's an empty string, +a default output depending on the type of the action is used. +For example, a command-line action will print the executed command. +The argument must be either a Python function or a string. + +In the first case, +it's a function that returns a string to be printed +to describe the action being executed. +The function may also be specified by the +.IR strfunction = +keyword argument. +Like a function to build a file, +this function must take three keyword arguments: +.B target +(a Node object representing the target file), +.B source +(a Node object representing the source file) +and +.BR env +(a construction environment). +The +.B target +and +.B source +arguments may be lists of Node objects if there is +more than one target file or source file. + +In the second case, you provide the string itself. +The string may also be specified by the +.IR cmdstr = +keyword argument. +The string typically contains variables, notably +$TARGET(S) and $SOURCE(S), or consists of just a single +variable, which is optionally defined somewhere else. +SCons itself heavily uses the latter variant. + +Examples: + +.ES +def build_it(target, source, env): + # build the target from the source + return 0 + +def string_it(target, source, env): + return "building '%s' from '%s'" % (target[0], source[0]) + +# Use a positional argument. +f = Action(build_it, string_it) +s = Action(build_it, "building '$TARGET' from '$SOURCE'") + +# Alternatively, use a keyword argument. +f = Action(build_it, strfunction=string_it) +s = Action(build_it, cmdstr="building '$TARGET' from '$SOURCE'") + +# You can provide a configurable variable. +l = Action(build_it, '$STRINGIT') +.EE + +The third and succeeding arguments, if present, +may either be a construction variable or a list of construction variables +whose values will be included in the signature of the Action +when deciding whether a target should be rebuilt because the action changed. +The variables may also be specified by a +.IR varlist = +keyword parameter; +if both are present, they are combined. +This is necessary whenever you want a target to be rebuilt +when a specific construction variable changes. +This is not often needed for a string action, +as the expanded variables will normally be part of the command line, +but may be needed if a Python function action uses +the value of a construction variable when generating the command line. + +.ES +def build_it(target, source, env): + # build the target from the 'XXX' construction variable + open(target[0], 'w').write(env['XXX']) + return 0 + +# Use positional arguments. +a = Action(build_it, '$STRINGIT', ['XXX']) + +# Alternatively, use a keyword argument. +a = Action(build_it, varlist=['XXX']) +.EE + +The +.BR Action () +global function +can be passed the following +optional keyword arguments +to modify the Action object's behavior: + +.IP +.B chdir +The +.B chdir +keyword argument specifies that +scons will execute the action +after changing to the specified directory. +If the +.B chdir +argument is +a string or a directory Node, +scons will change to the specified directory. +If the +.B chdir +argument +is not a string or Node +and is non-zero, +then scons will change to the +target file's directory. + +Note that scons will +.I not +automatically modify +its expansion of +construction variables like +.B $TARGET +and +.B $SOURCE +when using the chdir +keyword argument--that is, +the expanded file names +will still be relative to +the top-level SConstruct directory, +and consequently incorrect +relative to the chdir directory. +Builders created using chdir keyword argument, +will need to use construction variable +expansions like +.B ${TARGET.file} +and +.B ${SOURCE.file} +to use just the filename portion of the +targets and source. + +.ES +a = Action("build < ${SOURCE.file} > ${TARGET.file}", + chdir=1) +.EE + +.IP +.B exitstatfunc +The +.BR Action () +global function +also takes an +.B exitstatfunc +keyword argument +which specifies a function +that is passed the exit status +(or return value) +from the specified action +and can return an arbitrary +or modified value. +This can be used, for example, +to specify that an Action object's +return value should be ignored +under special conditions +and SCons should, therefore, +consider that the action always suceeds: + +.ES +def always_succeed(s): + # Always return 0, which indicates success. + return 0 +a = Action("build < ${SOURCE.file} > ${TARGET.file}", + exitstatfunc=always_succeed) +.EE + +.IP +.B batch_key +The +.B batch_key +keyword argument can be used +to specify that the Action can create multiple target files +by processing multiple independent source files simultaneously. +(The canonical example is "batch compilation" +of multiple object files +by passing multiple source files +to a single invocation of a compiler +such as Microsoft's Visual C / C++ compiler.) +If the +.B batch_key +argument is any non-False, non-callable Python value, +the configured Action object will cause +.B scons +to collect all targets built with the Action object +and configured with the same construction environment +into single invocations of the Action object's +command line or function. +Command lines will typically want to use the +.BR CHANGED_SOURCES +construction variable +(and possibly +.BR CHANGED_TARGETS +as well) +to only pass to the command line those sources that +have actually changed since their targets were built. + +Example: + +.ES +a = Action('build $CHANGED_SOURCES', batch_key=True) +.EE + +The +.B batch_key +argument may also be +a callable function +that returns a key that +will be used to identify different +"batches" of target files to be collected +for batch building. +A +.B batch_key +function must take the following arguments: + +.IP action +The action object. + +.IP env +The construction environment +configured for the target. + +.IP target +The list of targets for a particular configured action. + +.IP source +The list of source for a particular configured action. + +The returned key should typically +be a tuple of values derived from the arguments, +using any appropriate logic to decide +how multiple invocations should be batched. +For example, a +.B batch_key +function may decide to return +the value of a specific construction +variable from the +.B env +argument +which will cause +.B scons +to batch-build targets +with matching values of that variable, +or perhaps return the +.BR id () +of the entire construction environment, +in which case +.B scons +will batch-build +all targets configured with the same construction environment. +Returning +.B None +indicates that +the particular target should +.I not +be part of any batched build, +but instead will be built +by a separate invocation of action's +command or function. +Example: + +.ES +def batch_key(action, env, target, source): + tdir = target[0].dir + if tdir.name == 'special': + # Don't batch-build any target + # in the special/ subdirectory. + return None + return (id(action), id(env), tdir) +a = Action('build $CHANGED_SOURCES', batch_key=batch_key) +.EE + +.SS Miscellaneous Action Functions + +.B scons +supplies a number of functions +that arrange for various common +file and directory manipulations +to be performed. +These are similar in concept to "tasks" in the +Ant build tool, +although the implementation is slightly different. +These functions do not actually +perform the specified action +at the time the function is called, +but instead return an Action object +that can be executed at the +appropriate time. +(In Object-Oriented terminology, +these are actually +Action +.I Factory +functions +that return Action objects.) + +In practice, +there are two natural ways +that these +Action Functions +are intended to be used. + +First, +if you need +to perform the action +at the time the SConscript +file is being read, +you can use the +.B Execute +global function to do so: +.ES +Execute(Touch('file')) +.EE + +Second, +you can use these functions +to supply Actions in a list +for use by the +.B Command +method. +This can allow you to +perform more complicated +sequences of file manipulation +without relying +on platform-specific +external commands: +that +.ES +env = Environment(TMPBUILD = '/tmp/builddir') +env.Command('foo.out', 'foo.in', + [Mkdir('$TMPBUILD'), + Copy('$TMPBUILD', '${SOURCE.dir}'), + "cd $TMPBUILD && make", + Delete('$TMPBUILD')]) +.EE + +.TP +.RI Chmod( dest ", " mode ) +Returns an Action object that +changes the permissions on the specified +.I dest +file or directory to the specified +.IR mode . +Examples: + +.ES +Execute(Chmod('file', 0755)) + +env.Command('foo.out', 'foo.in', + [Copy('$TARGET', '$SOURCE'), + Chmod('$TARGET', 0755)]) +.EE + +.TP +.RI Copy( dest ", " src ) +Returns an Action object +that will copy the +.I src +source file or directory to the +.I dest +destination file or directory. +Examples: + +.ES +Execute(Copy('foo.output', 'foo.input')) + +env.Command('bar.out', 'bar.in', + Copy('$TARGET', '$SOURCE')) +.EE + +.TP +.RI Delete( entry ", [" must_exist ]) +Returns an Action that +deletes the specified +.IR entry , +which may be a file or a directory tree. +If a directory is specified, +the entire directory tree +will be removed. +If the +.I must_exist +flag is set, +then a Python error will be thrown +if the specified entry does not exist; +the default is +.BR must_exist=0 , +that is, the Action will silently do nothing +if the entry does not exist. +Examples: + +.ES +Execute(Delete('/tmp/buildroot')) + +env.Command('foo.out', 'foo.in', + [Delete('${TARGET.dir}'), + MyBuildAction]) + +Execute(Delete('file_that_must_exist', must_exist=1)) +.EE + +.TP +.RI Mkdir( dir ) +Returns an Action +that creates the specified +directory +.I dir . +Examples: + +.ES +Execute(Mkdir('/tmp/outputdir')) + +env.Command('foo.out', 'foo.in', + [Mkdir('/tmp/builddir'), + Copy('/tmp/builddir/foo.in', '$SOURCE'), + "cd /tmp/builddir && make", + Copy('$TARGET', '/tmp/builddir/foo.out')]) +.EE + +.TP +.RI Move( dest ", " src ) +Returns an Action +that moves the specified +.I src +file or directory to +the specified +.I dest +file or directory. +Examples: + +.ES +Execute(Move('file.destination', 'file.source')) + +env.Command('output_file', 'input_file', + [MyBuildAction, + Move('$TARGET', 'file_created_by_MyBuildAction')]) +.EE + +.TP +.RI Touch( file ) +Returns an Action +that updates the modification time +on the specified +.IR file . +Examples: + +.ES +Execute(Touch('file_to_be_touched')) + +env.Command('marker', 'input_file', + [MyBuildAction, + Touch('$TARGET')]) +.EE + +.SS Variable Substitution + +Before executing a command, +.B scons +performs construction variable interpolation on the strings that make up +the command line of builders. +Variables are introduced by a +.B $ +prefix. +Besides construction variables, scons provides the following +variables for each command execution: + +.IP CHANGED_SOURCES +The file names of all sources of the build command +that have changed since the target was last built. + +.IP CHANGED_TARGETS +The file names of all targets that would be built +from sources that have changed since the target was last built. + +.IP SOURCE +The file name of the source of the build command, +or the file name of the first source +if multiple sources are being built. + +.IP SOURCES +The file names of the sources of the build command. + +.IP TARGET +The file name of the target being built, +or the file name of the first target +if multiple targets are being built. + +.IP TARGETS +The file names of all targets being built. + +.IP UNCHANGED_SOURCES +The file names of all sources of the build command +that have +.I not +changed since the target was last built. + +.IP UNCHANGED_TARGETS +The file names of all targets that would be built +from sources that have +.I not +changed since the target was last built. + +(Note that the above variables are reserved +and may not be set in a construction environment.) + +.LP +For example, given the construction variable CC='cc', targets=['foo'], and +sources=['foo.c', 'bar.c']: + +.ES +action='$CC -c -o $TARGET $SOURCES' +.EE + +would produce the command line: + +.ES +cc -c -o foo foo.c bar.c +.EE + +Variable names may be surrounded by curly braces ({}) +to separate the name from the trailing characters. +Within the curly braces, a variable name may have +a Python slice subscript appended to select one +or more items from a list. +In the previous example, the string: + +.ES +${SOURCES[1]} +.EE + +would produce: + +.ES +bar.c +.EE + +Additionally, a variable name may +have the following special +modifiers appended within the enclosing curly braces +to modify the interpolated string: + +.IP base +The base path of the file name, +including the directory path +but excluding any suffix. + +.IP dir +The name of the directory in which the file exists. + +.IP file +The file name, +minus any directory portion. + +.IP filebase +Just the basename of the file, +minus any suffix +and minus the directory. + +.IP suffix +Just the file suffix. + +.IP abspath +The absolute path name of the file. + +.IP posix +The POSIX form of the path, +with directories separated by +.B / +(forward slashes) +not backslashes. +This is sometimes necessary on Windows systems +when a path references a file on other (POSIX) systems. + +.IP srcpath +The directory and file name to the source file linked to this file through +.BR VariantDir (). +If this file isn't linked, +it just returns the directory and filename unchanged. + +.IP srcdir +The directory containing the source file linked to this file through +.BR VariantDir (). +If this file isn't linked, +it just returns the directory part of the filename. + +.IP rsrcpath +The directory and file name to the source file linked to this file through +.BR VariantDir (). +If the file does not exist locally but exists in a Repository, +the path in the Repository is returned. +If this file isn't linked, it just returns the +directory and filename unchanged. + +.IP rsrcdir +The Repository directory containing the source file linked to this file through +.BR VariantDir (). +If this file isn't linked, +it just returns the directory part of the filename. + +.LP +For example, the specified target will +expand as follows for the corresponding modifiers: + +.ES +$TARGET => sub/dir/file.x +${TARGET.base} => sub/dir/file +${TARGET.dir} => sub/dir +${TARGET.file} => file.x +${TARGET.filebase} => file +${TARGET.suffix} => .x +${TARGET.abspath} => /top/dir/sub/dir/file.x + +SConscript('src/SConscript', variant_dir='sub/dir') +$SOURCE => sub/dir/file.x +${SOURCE.srcpath} => src/file.x +${SOURCE.srcdir} => src + +Repository('/usr/repository') +$SOURCE => sub/dir/file.x +${SOURCE.rsrcpath} => /usr/repository/src/file.x +${SOURCE.rsrcdir} => /usr/repository/src +.EE + +Note that curly braces braces may also be used +to enclose arbitrary Python code to be evaluated. +(In fact, this is how the above modifiers are substituted, +they are simply attributes of the Python objects +that represent TARGET, SOURCES, etc.) +See the section "Python Code Substitution," below, +for more thorough examples of +how this can be used. + +Lastly, a variable name +may be a callable Python function +associated with a +construction variable in the environment. +The function should +take four arguments: +.I target +- a list of target nodes, +.I source +- a list of source nodes, +.I env +- the construction environment, +.I for_signature +- a Boolean value that specifies +whether the function is being called +for generating a build signature. +SCons will insert whatever +the called function returns +into the expanded string: + +.ES +def foo(target, source, env, for_signature): + return "bar" + +# Will expand $BAR to "bar baz" +env=Environment(FOO=foo, BAR="$FOO baz") +.EE + +You can use this feature to pass arguments to a +Python function by creating a callable class +that stores one or more arguments in an object, +and then uses them when the +.B __call__() +method is called. +Note that in this case, +the entire variable expansion must +be enclosed by curly braces +so that the arguments will +be associated with the +instantiation of the class: + +.ES +class foo: + def __init__(self, arg): + self.arg = arg + + def __call__(self, target, source, env, for_signature): + return self.arg + " bar" + +# Will expand $BAR to "my argument bar baz" +env=Environment(FOO=foo, BAR="${FOO('my argument')} baz") +.EE + +.LP +The special pseudo-variables +.B "$(" +and +.B "$)" +may be used to surround parts of a command line +that may change +.I without +causing a rebuild--that is, +which are not included in the signature +of target files built with this command. +All text between +.B "$(" +and +.B "$)" +will be removed from the command line +before it is added to file signatures, +and the +.B "$(" +and +.B "$)" +will be removed before the command is executed. +For example, the command line: + +.ES +echo Last build occurred $( $TODAY $). > $TARGET +.EE + +.LP +would execute the command: + +.ES +echo Last build occurred $TODAY. > $TARGET +.EE + +.LP +but the command signature added to any target files would be: + +.ES +echo Last build occurred . > $TARGET +.EE + +.SS Python Code Substitution + +Any python code within +.BR "${" - "}" +pairs gets evaluated by python 'eval', with the python globals set to +the current environment's set of construction variables. +So in the following case: +.ES +env['COND'] = 0 +env.Command('foo.out', 'foo.in', + '''echo ${COND==1 and 'FOO' or 'BAR'} > $TARGET''') +.EE +the command executed will be either +.ES +echo FOO > foo.out +.EE +or +.ES +echo BAR > foo.out +.EE +according to the current value of env['COND'] when the command is +executed. The evaluation occurs when the target is being +built, not when the SConscript is being read. So if env['COND'] is changed +later in the SConscript, the final value will be used. + +Here's a more interesting example. Note that all of COND, FOO, and +BAR are environment variables, and their values are substituted into +the final command. FOO is a list, so its elements are interpolated +separated by spaces. + +.ES +env=Environment() +env['COND'] = 0 +env['FOO'] = ['foo1', 'foo2'] +env['BAR'] = 'barbar' +env.Command('foo.out', 'foo.in', + 'echo ${COND==1 and FOO or BAR} > $TARGET') + +# Will execute this: +# echo foo1 foo2 > foo.out +.EE + +SCons uses the following rules when converting construction variables into +command lines: + +.IP String +When the value is a string it is interpreted as a space delimited list of +command line arguments. + +.IP List +When the value is a list it is interpreted as a list of command line +arguments. Each element of the list is converted to a string. + +.IP Other +Anything that is not a list or string is converted to a string and +interpreted as a single command line argument. + +.IP Newline +Newline characters (\\n) delimit lines. The newline parsing is done after +all other parsing, so it is not possible for arguments (e.g. file names) to +contain embedded newline characters. This limitation will likely go away in +a future version of SCons. + +.SS Scanner Objects + +You can use the +.B Scanner +function to define +objects to scan +new file types for implicit dependencies. +Scanner accepts the following arguments: + +.IP function +This can be either: +1) a Python function that will process +the Node (file) +and return a list of strings (file names) +representing the implicit +dependencies found in the contents; +or: +2) a dictionary that maps keys +(typically the file suffix, but see below for more discussion) +to other Scanners that should be called. + +If the argument is actually a Python function, +the function must take three or four arguments: + + def scanner_function(node, env, path): + + def scanner_function(node, env, path, arg=None): + +The +.B node +argument is the internal +SCons node representing the file. +Use +.B str(node) +to fetch the name of the file, and +.B node.get_contents() +to fetch contents of the file. +Note that the file is +.I not +guaranteed to exist before the scanner is called, +so the scanner function should check that +if there's any chance that the scanned file +might not exist +(for example, if it's built from other files). + +The +.B env +argument is the construction environment for the scan. +Fetch values from it using the +.B env.Dictionary() +method. + +The +.B path +argument is a tuple (or list) +of directories that can be searched +for files. +This will usually be the tuple returned by the +.B path_function +argument (see below). + +The +.B arg +argument is the argument supplied +when the scanner was created, if any. + +.IP name +The name of the Scanner. +This is mainly used +to identify the Scanner internally. + +.IP argument +An optional argument that, if specified, +will be passed to the scanner function +(described above) +and the path function +(specified below). + +.IP skeys +An optional list that can be used to +determine which scanner should be used for +a given Node. +In the usual case of scanning for file names, +this argument will be a list of suffixes +for the different file types that this +Scanner knows how to scan. +If the argument is a string, +then it will be expanded +into a list by the current environment. + +.IP path_function +A Python function that takes four or five arguments: +a construction environment, +a Node for the directory containing +the SConscript file in which +the first target was defined, +a list of target nodes, +a list of source nodes, +and an optional argument supplied +when the scanner was created. +The +.B path_function +returns a tuple of directories +that can be searched for files to be returned +by this Scanner object. +(Note that the +.BR FindPathDirs () +function can be used to return a ready-made +.B path_function +for a given construction variable name, +instead of having to write your own function from scratch.) + +.IP node_class +The class of Node that should be returned +by this Scanner object. +Any strings or other objects returned +by the scanner function +that are not of this class +will be run through the +.B node_factory +function. + +.IP node_factory +A Python function that will take a string +or other object +and turn it into the appropriate class of Node +to be returned by this Scanner object. + +.IP scan_check +An optional Python function that takes two arguments, +a Node (file) and a construction environment, +and returns whether the +Node should, in fact, +be scanned for dependencies. +This check can be used to eliminate unnecessary +calls to the scanner function when, +for example, the underlying file +represented by a Node does not yet exist. + +.IP recursive +An optional flag that +specifies whether this scanner should be re-invoked +on the dependency files returned by the scanner. +When this flag is not set, +the Node subsystem will +only invoke the scanner on the file being scanned, +and not (for example) also on the files +specified by the #include lines +in the file being scanned. +.I recursive +may be a callable function, +in which case it will be called with a list of +Nodes found and +should return a list of Nodes +that should be scanned recursively; +this can be used to select a specific subset of +Nodes for additional scanning. + +Note that +.B scons +has a global +.B SourceFileScanner +object that is used by +the +.BR Object (), +.BR SharedObject (), +and +.BR StaticObject () +builders to decide +which scanner should be used +for different file extensions. +You can using the +.BR SourceFileScanner.add_scanner () +method to add your own Scanner object +to the +.B scons +infrastructure +that builds target programs or +libraries from a list of +source files of different types: + +.ES +def xyz_scan(node, env, path): + contents = node.get_text_contents() + # Scan the contents and return the included files. + +XYZScanner = Scanner(xyz_scan) + +SourceFileScanner.add_scanner('.xyx', XYZScanner) + +env.Program('my_prog', ['file1.c', 'file2.f', 'file3.xyz']) +.EE + +.SH SYSTEM-SPECIFIC BEHAVIOR +SCons and its configuration files are very portable, +due largely to its implementation in Python. +There are, however, a few portability +issues waiting to trap the unwary. +.SS .C file suffix +SCons handles the upper-case +.B .C +file suffix differently, +depending on the capabilities of +the underlying system. +On a case-sensitive system +such as Linux or UNIX, +SCons treats a file with a +.B .C +suffix as a C++ source file. +On a case-insensitive system +such as Windows, +SCons treats a file with a +.B .C +suffix as a C source file. +.SS .F file suffix +SCons handles the upper-case +.B .F +file suffix differently, +depending on the capabilities of +the underlying system. +On a case-sensitive system +such as Linux or UNIX, +SCons treats a file with a +.B .F +suffix as a Fortran source file +that is to be first run through +the standard C preprocessor. +On a case-insensitive system +such as Windows, +SCons treats a file with a +.B .F +suffix as a Fortran source file that should +.I not +be run through the C preprocessor. +.SS Windows: Cygwin Tools and Cygwin Python vs. Windows Pythons +Cygwin supplies a set of tools and utilities +that let users work on a +Windows system using a more POSIX-like environment. +The Cygwin tools, including Cygwin Python, +do this, in part, +by sharing an ability to interpret UNIX-like path names. +For example, the Cygwin tools +will internally translate a Cygwin path name +like /cygdrive/c/mydir +to an equivalent Windows pathname +of C:/mydir (equivalent to C:\\mydir). + +Versions of Python +that are built for native Windows execution, +such as the python.org and ActiveState versions, +do not have the Cygwin path name semantics. +This means that using a native Windows version of Python +to build compiled programs using Cygwin tools +(such as gcc, bison, and flex) +may yield unpredictable results. +"Mixing and matching" in this way +can be made to work, +but it requires careful attention to the use of path names +in your SConscript files. + +In practice, users can sidestep +the issue by adopting the following rules: +When using gcc, +use the Cygwin-supplied Python interpreter +to run SCons; +when using Microsoft Visual C/C++ +(or some other Windows compiler) +use the python.org or ActiveState version of Python +to run SCons. +.SS Windows: scons.bat file +On Windows systems, +SCons is executed via a wrapper +.B scons.bat +file. +This has (at least) two ramifications: + +First, Windows command-line users +that want to use variable assignment +on the command line +may have to put double quotes +around the assignments: + +.ES +scons "FOO=BAR" "BAZ=BLEH" +.EE + +Second, the Cygwin shell does not +recognize this file as being the same +as an +.B scons +command issued at the command-line prompt. +You can work around this either by +executing +.B scons.bat +from the Cygwin command line, +or by creating a wrapper shell +script named +.B scons . + +.SS MinGW + +The MinGW bin directory must be in your PATH environment variable or the +PATH variable under the ENV construction variable for SCons +to detect and use the MinGW tools. When running under the native Windows +Python interpreter, SCons will prefer the MinGW tools over the Cygwin +tools, if they are both installed, regardless of the order of the bin +directories in the PATH variable. If you have both MSVC and MinGW +installed and you want to use MinGW instead of MSVC, +then you must explictly tell SCons to use MinGW by passing + +.ES +tools=['mingw'] +.EE + +to the Environment() function, because SCons will prefer the MSVC tools +over the MinGW tools. + +.SH EXAMPLES + +To help you get started using SCons, +this section contains a brief overview of some common tasks. + +.SS Basic Compilation From a Single Source File + +.ES +env = Environment() +env.Program(target = 'foo', source = 'foo.c') +.EE + +Note: Build the file by specifying +the target as an argument +("scons foo" or "scons foo.exe"). +or by specifying a dot ("scons ."). + +.SS Basic Compilation From Multiple Source Files + +.ES +env = Environment() +env.Program(target = 'foo', source = Split('f1.c f2.c f3.c')) +.EE + +.SS Setting a Compilation Flag + +.ES +env = Environment(CCFLAGS = '-g') +env.Program(target = 'foo', source = 'foo.c') +.EE + +.SS Search The Local Directory For .h Files + +Note: You do +.I not +need to set CCFLAGS to specify -I options by hand. +SCons will construct the right -I options from CPPPATH. + +.ES +env = Environment(CPPPATH = ['.']) +env.Program(target = 'foo', source = 'foo.c') +.EE + +.SS Search Multiple Directories For .h Files + +.ES +env = Environment(CPPPATH = ['include1', 'include2']) +env.Program(target = 'foo', source = 'foo.c') +.EE + +.SS Building a Static Library + +.ES +env = Environment() +env.StaticLibrary(target = 'foo', source = Split('l1.c l2.c')) +env.StaticLibrary(target = 'bar', source = ['l3.c', 'l4.c']) +.EE + +.SS Building a Shared Library + +.ES +env = Environment() +env.SharedLibrary(target = 'foo', source = ['l5.c', 'l6.c']) +env.SharedLibrary(target = 'bar', source = Split('l7.c l8.c')) +.EE + +.SS Linking a Local Library Into a Program + +.ES +env = Environment(LIBS = 'mylib', LIBPATH = ['.']) +env.Library(target = 'mylib', source = Split('l1.c l2.c')) +env.Program(target = 'prog', source = ['p1.c', 'p2.c']) +.EE + +.SS Defining Your Own Builder Object + +Notice that when you invoke the Builder, +you can leave off the target file suffix, +and SCons will add it automatically. + +.ES +bld = Builder(action = 'pdftex < $SOURCES > $TARGET' + suffix = '.pdf', + src_suffix = '.tex') +env = Environment(BUILDERS = {'PDFBuilder' : bld}) +env.PDFBuilder(target = 'foo.pdf', source = 'foo.tex') + +# The following creates "bar.pdf" from "bar.tex" +env.PDFBuilder(target = 'bar', source = 'bar') +.EE + +Note also that the above initialization +overwrites the default Builder objects, +so the Environment created above +can not be used call Builders like env.Program(), +env.Object(), env.StaticLibrary(), etc. + +.SS Adding Your Own Builder Object to an Environment + +.ES +bld = Builder(action = 'pdftex < $SOURCES > $TARGET' + suffix = '.pdf', + src_suffix = '.tex') +env = Environment() +env.Append(BUILDERS = {'PDFBuilder' : bld}) +env.PDFBuilder(target = 'foo.pdf', source = 'foo.tex') +env.Program(target = 'bar', source = 'bar.c') +.EE + +You also can use other Pythonic techniques to add +to the BUILDERS construction variable, such as: + +.ES +env = Environment() +env['BUILDERS]['PDFBuilder'] = bld +.EE + +.SS Defining Your Own Scanner Object + +The following example shows an extremely simple scanner (the +.BR kfile_scan () +function) +that doesn't use a search path at all +and simply returns the +file names present on any +.B include +lines in the scanned file. +This would implicitly assume that all included +files live in the top-level directory: + +.ES +import re + +'\" Note: the \\ in the following are for the benefit of nroff/troff, +'\" not inappropriate doubled escape characters within the r'' raw string. +include_re = re.compile(r'^include\\s+(\\S+)$', re.M) + +def kfile_scan(node, env, path, arg): + contents = node.get_text_contents() + includes = include_re.findall(contents) + return includes + +kscan = Scanner(name = 'kfile', + function = kfile_scan, + argument = None, + skeys = ['.k']) +scanners = Environment().Dictionary('SCANNERS') +env = Environment(SCANNERS = scanners + [kscan]) + +env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET') + +bar_in = File('bar.in') +env.Command('bar', bar_in, 'kprocess $SOURCES > $TARGET') +bar_in.target_scanner = kscan +.EE + +Here is a similar but more complete example that searches +a path of directories +(specified as the +.B MYPATH +construction variable) +for files that actually exist: + +.ES +include_re = re.compile(r'^include\\s+(\\S+)$', re.M) + +def my_scan(node, env, path, arg): + contents = node.get_text_contents() + includes = include_re.findall(contents) + if includes == []: + return [] + results = [] + for inc in includes: + for dir in path: + file = dir + os.sep + inc + if os.path.exists(file): + results.append(file) + break + return results + +scanner = Scanner(name = 'myscanner', + function = my_scan, + argument = None, + skeys = ['.x'], + path_function = FindPathDirs('MYPATH'), + ) +scanners = Environment().Dictionary('SCANNERS') +env = Environment(SCANNERS = scanners + [scanner]) +.EE + +The +.BR FindPathDirs () +function used in the previous example returns a function +(actually a callable Python object) +that will return a list of directories +specified in the +.B $MYPATH +construction variable. +If you need to customize how the search path is derived, +you would provide your own +.B path_function +argument when creating the Scanner object, +as follows: + +.ES +# MYPATH is a list of directories to search for files in +def pf(env, dir, target, source, arg): + top_dir = Dir('#').abspath + results = [] + if env.has_key('MYPATH'): + for p in env['MYPATH']: + results.append(top_dir + os.sep + p) + return results + +scanner = Scanner(name = 'myscanner', + function = my_scan, + argument = None, + skeys = ['.x'], + path_function = pf, + ) +.EE + +.SS Creating a Hierarchical Build + +Notice that the file names specified in a subdirectory's +SConscript +file are relative to that subdirectory. + +.ES +SConstruct: + + env = Environment() + env.Program(target = 'foo', source = 'foo.c') + + SConscript('sub/SConscript') + +sub/SConscript: + + env = Environment() + # Builds sub/foo from sub/foo.c + env.Program(target = 'foo', source = 'foo.c') + + SConscript('dir/SConscript') + +sub/dir/SConscript: + + env = Environment() + # Builds sub/dir/foo from sub/dir/foo.c + env.Program(target = 'foo', source = 'foo.c') +.EE + +.SS Sharing Variables Between SConscript Files + +You must explicitly Export() and Import() variables that +you want to share between SConscript files. + +.ES +SConstruct: + + env = Environment() + env.Program(target = 'foo', source = 'foo.c') + + Export("env") + SConscript('subdirectory/SConscript') + +subdirectory/SConscript: + + Import("env") + env.Program(target = 'foo', source = 'foo.c') +.EE + +.SS Building Multiple Variants From the Same Source + +Use the variant_dir keyword argument to +the SConscript function to establish +one or more separate variant build directory trees +for a given source directory: + +.ES +SConstruct: + + cppdefines = ['FOO'] + Export("cppdefines") + SConscript('src/SConscript', variant_dir='foo') + + cppdefines = ['BAR'] + Export("cppdefines") + SConscript('src/SConscript', variant_dir='bar') + +src/SConscript: + + Import("cppdefines") + env = Environment(CPPDEFINES = cppdefines) + env.Program(target = 'src', source = 'src.c') +.EE + +Note the use of the Export() method +to set the "cppdefines" variable to a different +value each time we call the SConscript function. + +.SS Hierarchical Build of Two Libraries Linked With a Program + +.ES +SConstruct: + + env = Environment(LIBPATH = ['#libA', '#libB']) + Export('env') + SConscript('libA/SConscript') + SConscript('libB/SConscript') + SConscript('Main/SConscript') + +libA/SConscript: + + Import('env') + env.Library('a', Split('a1.c a2.c a3.c')) + +libB/SConscript: + + Import('env') + env.Library('b', Split('b1.c b2.c b3.c')) + +Main/SConscript: + + Import('env') + e = env.Copy(LIBS = ['a', 'b']) + e.Program('foo', Split('m1.c m2.c m3.c')) +.EE + +The '#' in the LIBPATH directories specify that they're relative to the +top-level directory, so they don't turn into "Main/libA" when they're +used in Main/SConscript. + +Specifying only 'a' and 'b' for the library names +allows SCons to append the appropriate library +prefix and suffix for the current platform +(for example, 'liba.a' on POSIX systems, +\&'a.lib' on Windows). + +.SS Customizing construction variables from the command line. + +The following would allow the C compiler to be specified on the command +line or in the file custom.py. + +.ES +vars = Variables('custom.py') +vars.Add('CC', 'The C compiler.') +env = Environment(variables=vars) +Help(vars.GenerateHelpText(env)) +.EE + +The user could specify the C compiler on the command line: + +.ES +scons "CC=my_cc" +.EE + +or in the custom.py file: + +.ES +CC = 'my_cc' +.EE + +or get documentation on the options: + +.ES +$ scons -h + +CC: The C compiler. + default: None + actual: cc + +.EE + +.SS Using Microsoft Visual C++ precompiled headers + +Since windows.h includes everything and the kitchen sink, it can take quite +some time to compile it over and over again for a bunch of object files, so +Microsoft provides a mechanism to compile a set of headers once and then +include the previously compiled headers in any object file. This +technology is called precompiled headers. The general recipe is to create a +file named "StdAfx.cpp" that includes a single header named "StdAfx.h", and +then include every header you want to precompile in "StdAfx.h", and finally +include "StdAfx.h" as the first header in all the source files you are +compiling to object files. For example: + +StdAfx.h: +.ES +#include <windows.h> +#include <my_big_header.h> +.EE + +StdAfx.cpp: +.ES +#include <StdAfx.h> +.EE + +Foo.cpp: +.ES +#include <StdAfx.h> + +/* do some stuff */ +.EE + +Bar.cpp: +.ES +#include <StdAfx.h> + +/* do some other stuff */ +.EE + +SConstruct: +.ES +env=Environment() +env['PCHSTOP'] = 'StdAfx.h' +env['PCH'] = env.PCH('StdAfx.cpp')[0] +env.Program('MyApp', ['Foo.cpp', 'Bar.cpp']) +.EE + +For more information see the document for the PCH builder, and the PCH and +PCHSTOP construction variables. To learn about the details of precompiled +headers consult the MSDN documention for /Yc, /Yu, and /Yp. + +.SS Using Microsoft Visual C++ external debugging information + +Since including debugging information in programs and shared libraries can +cause their size to increase significantly, Microsoft provides a mechanism +for including the debugging information in an external file called a PDB +file. SCons supports PDB files through the PDB construction +variable. + +SConstruct: +.ES +env=Environment() +env['PDB'] = 'MyApp.pdb' +env.Program('MyApp', ['Foo.cpp', 'Bar.cpp']) +.EE + +For more information see the document for the PDB construction variable. + +.SH ENVIRONMENT + +.IP SCONS_LIB_DIR +Specifies the directory that contains the SCons Python module directory +(e.g. /home/aroach/scons-src-0.01/src/engine). + +.IP SCONSFLAGS +A string of options that will be used by scons in addition to those passed +on the command line. + +.SH "SEE ALSO" +.B scons +User Manual, +.B scons +Design Document, +.B scons +source code. + +.SH AUTHORS +Steven Knight <knight@baldmt.com> +.br +Anthony Roach <aroach@electriceyeball.com> + diff --git a/doc/man/sconsign.1 b/doc/man/sconsign.1 new file mode 100644 index 0000000..6694784 --- /dev/null +++ b/doc/man/sconsign.1 @@ -0,0 +1,208 @@ +.\" Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining +.\" a copy of this software and associated documentation files (the +.\" "Software"), to deal in the Software without restriction, including +.\" without limitation the rights to use, copy, modify, merge, publish, +.\" distribute, sublicense, and/or sell copies of the Software, and to +.\" permit persons to whom the Software is furnished to do so, subject to +.\" the following conditions: +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +.\" KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +.\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +.\" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +.\" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +.\" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +.\" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" doc/man/sconsign.1 4577 2009/12/27 19:44:43 scons +.\" +.\" ES - Example Start - indents and turns off line fill +.de ES +.RS +.nf +.. +.\" EE - Example End - ends indent and turns line fill back on +.de EE +.RE +.fi +.. +.TH SCONSIGN 1 "December 2009" +.SH NAME +sconsign \- print SCons .sconsign file information +.SH SYNOPSIS +.B sconsign +[ +.IR options ... +] +.IR file +[ ... ] +.SH DESCRIPTION + +The +.B sconsign +command +displays the contents of one or more +.B .sconsign +files specified by the user. + +By default, +.B sconsign +dumps the entire contents of the +specified file(s). +Each entry is printed in the following format: + + file: signature timestamp length + implicit_dependency_1: signature timestamp length + implicit_dependency_2: signature timestamp length + action_signature [action string] + +.B None +is printed +in place of any missing timestamp, bsig, or csig +values for +any entry +or any of its dependencies. +If the entry has no implicit dependencies, +or no build action, +the lines are simply omitted. + +By default, +.B sconsign +assumes that any +.I file +arguments that end with a +.B .dbm +suffix contains +signature entries for +more than one directory +(that is, +was specified by the +.B SConsignFile () +function). +Any +.I file +argument that does not end in +.B .dbm +is assumed to be a traditional +.B .sconsign +file containing the signature entries +for a single directory. +An explicit format +may be specified using the +.B -f +or +.B --file= +options. + +.SH OPTIONS + +Various options control what information is printed +and the format: + +.TP +-a, --act, --action +Prints the build action information +for all entries or the specified entries. + +.TP +-c, --csig +Prints the content signature (csig) information +for all entries or the specified entries. + +.TP +-d DIRECTORY, --dir=DIRECTORY +When the signatures are being +read from a +.B .dbm +file, or the +.B -f dbm +or +.B --format=dbm +options are used, +prints information about +only the signatures +for entries in the specified +.IR DIRECTORY . + +.TP +-e ENTRY, --entry=ENTRY +Prints information about only the specified +.IR ENTRY . +Multiple -e options may be used, +in which case information about each +.I ENTRY +is printed in the order in which the +options are specified on the command line. + +.TP +-f FORMAT, --format=FORMAT +The file(s) to be printed +are in the specified +.IR FORMAT . +Legal values are +.B dbm +(the DBM format used +when the +.BR SConsignFile () +function is used) +or +.B sconsign +(the default format +used for an individual +.B .sconsign +file in each directory). + +.TP +-h, --help +Prints a help message and exits. + +.TP +-i, --implicit +Prints the list of cached implicit dependencies +for all entries or the the specified entries. + +.TP +--raw +Prints a pretty-printed representation +of the raw Python dictionary that holds +build information about individual entry +(both the entry itself or its implicit dependencies). +An entry's build action is still printed in its usual format. + +.TP +-r, --readable +Prints timestamps in a human-readable string, +enclosed in single quotes. + +.TP +-t, --timestamp +Prints the timestamp information +for all entries or the specified entries. + +.TP +-v, --verbose +Prints labels identifying each field being printed. + +.SH ENVIRONMENT + +.IP SCONS_LIB_DIR +Specifies the directory that contains the SCons Python module directory +(e.g. /home/aroach/scons-src-0.01/src/engine). +on the command line. + +.SH "SEE ALSO" +.BR scons , +.B scons +User Manual, +.B scons +Design Document, +.B scons +source code. + +.SH AUTHORS +Steven Knight <knight at baldmt dot com> diff --git a/doc/python10/MANIFEST b/doc/python10/MANIFEST new file mode 100644 index 0000000..c9484d8 --- /dev/null +++ b/doc/python10/MANIFEST @@ -0,0 +1,16 @@ +abstract.xml +acks.xml +arch.fig +builder.fig +copyright.xml +design.xml +future.xml +install.xml +intro.xml +job-task.fig +main.xml +node.fig +process.xml +scanner.fig +scons.mod +sig.fig diff --git a/doc/python10/abstract.xml b/doc/python10/abstract.xml new file mode 100644 index 0000000..294180b --- /dev/null +++ b/doc/python10/abstract.xml @@ -0,0 +1,32 @@ +<para> + + &SCons; is a software construction tool (build tool, or make tool) + implemented in Python, which uses Python scripts as "configuration + files" for software builds. Based on the design which won the + Software Carpentry build tool competition, &SCons solves a number of + problems associated with other build tools, especially including the + classic and ubiquitous &Make; itself. + +</para> + +<para> + + Distinctive features of &SCons; include: a modular design that + lends itself to being embedded in other applications; a global + view of all dependencies in the source tree; an improved model for + parallel (<option>-j</option>) builds; automatic scanning of files for + dependencies; use of MD5 signatures for deciding whether a file + is up-to-date; use of traditional file timestamps instead of + MD5 signatures available as an option; + use of Python functions or objects to build target files; easy user + extensibility. + +</para> + +<para> + + This paper discusses the goals of the &SCons; project, gives an overview + of the design of &SCons; itself, describes the development process used, + and discusses future plans and directions for the tool. + +</para> diff --git a/doc/python10/acks.xml b/doc/python10/acks.xml new file mode 100644 index 0000000..895bad7 --- /dev/null +++ b/doc/python10/acks.xml @@ -0,0 +1,27 @@ +<para> + + First, many thanks to the great group of developers who dove in right + from the beginning and have contributed the code and ideas to make + &SCons; a success: Chad Austin, Charles Crain, Steve Leblanc, and + Anthony Roach. Thanks also to those on the scons-devel mailing list + who have contributed greatly to the discussion, notably including + David Abrahams, Trent Mick, and Steven Shaw. + +</para> + +<para> + + &SCons; would not exist today without the pioneering work of Bob + Sidebotham on the original &Cons; tool, and without Greg Wilson's + having started the Software Carpentry contest. + +</para> + +<para> + + Thanks also to Peter Miller for: Aegis; the testing discipline that it + enforces, without which creating a stable but flexible tool would be + impossible; the "Recursive Make Considered Harmful" paper which led me + to experiment with &Cons; in the first place. + +</para> diff --git a/doc/python10/arch.eps b/doc/python10/arch.eps new file mode 100644 index 0000000..1fdd51f --- /dev/null +++ b/doc/python10/arch.eps @@ -0,0 +1,134 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: build/doc/python10/arch.fig +%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d +%%CreationDate: Sun Jan 2 01:21:05 2005 +%%For: knight@casablanca.home.baldmt.com (Steven Knight) +%%BoundingBox: 0 0 218 182 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 182 moveto 0 0 lineto 218 0 lineto 218 182 lineto closepath clip newpath +-215.3 324.7 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit + 0.06000 0.06000 sc +% +% Fig objects follow +% +/Courier-Bold ff 300.00 scf sf +3825 2925 m +gs 1 -1 sc (scons) col0 sh gr +/Times-Roman ff 300.00 scf sf +3825 3225 m +gs 1 -1 sc (Script) col0 sh gr +/Times-Roman ff 300.00 scf sf +5100 4875 m +gs 1 -1 sc (Build Engine) col0 sh gr +/Courier-Bold ff 300.00 scf sf +4200 4875 m +gs 1 -1 sc (SCons) col0 sh gr +% Polyline +7.500 slw +n 3600 4200 m 7200 4200 l 7200 5400 l 3600 5400 l + cp gs col0 s gr +/Courier-Bold ff 300.00 scf sf +4725 4050 m +gs 1 -1 sc (SCons) col0 sh gr +/Times-Roman ff 300.00 scf sf +5625 4050 m +gs 1 -1 sc (API) col0 sh gr +% Polyline +n 3600 2400 m 3600 2400 l 3600 2400 l 3600 2400 l + cp gs col0 s gr +% Polyline +n 3600 2400 m 4800 2400 l 4800 3600 l 3600 3600 l + cp gs col0 s gr +% Polyline +n 3600 3600 m 7200 3600 l 7200 4200 l 3600 4200 l + cp gs col0 s gr +% Polyline + [60] 0 sd +n 6000 3600 m 7200 3600 l 7200 2400 l 6000 2400 l + cp gs col0 s gr [] 0 sd +/Times-Italic ff 300.00 scf sf +6300 2925 m +gs 1 -1 sc (other) col0 sh gr +/Times-Italic ff 300.00 scf sf +6150 3225 m +gs 1 -1 sc (interface) col0 sh gr +$F2psEnd +rs diff --git a/doc/python10/arch.fig b/doc/python10/arch.fig new file mode 100644 index 0000000..ae20bd4 --- /dev/null +++ b/doc/python10/arch.fig @@ -0,0 +1,35 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 3825 2775 4650 3300 +4 0 0 50 0 14 20 0.0000 4 135 825 3825 2925 scons\001 +4 0 0 50 0 0 20 0.0000 4 255 690 3825 3225 Script\001 +-6 +6 3600 4200 7200 5400 +6 4200 4650 6675 4950 +4 0 0 50 0 0 20 0.0000 4 255 1515 5100 4875 Build Engine\001 +4 0 0 50 0 14 20 0.0000 4 165 825 4200 4875 SCons\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3600 4200 7200 4200 7200 5400 3600 5400 3600 4200 +-6 +6 4725 3825 6150 4050 +4 0 0 50 0 14 20 0.0000 4 165 825 4725 4050 SCons\001 +4 0 0 50 0 0 20 0.0000 4 195 465 5625 4050 API\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3600 2400 3600 2400 3600 2400 3600 2400 3600 2400 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3600 2400 4800 2400 4800 3600 3600 3600 3600 2400 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3600 3600 7200 3600 7200 4200 3600 4200 3600 3600 +2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5 + 6000 3600 7200 3600 7200 2400 6000 2400 6000 3600 +4 0 0 50 0 1 20 0.0000 4 210 570 6300 2925 other\001 +4 0 0 50 0 1 20 0.0000 4 270 975 6150 3225 interface\001 diff --git a/doc/python10/arch.jpg b/doc/python10/arch.jpg Binary files differnew file mode 100644 index 0000000..4e69437 --- /dev/null +++ b/doc/python10/arch.jpg diff --git a/doc/python10/builder.eps b/doc/python10/builder.eps new file mode 100644 index 0000000..db87afc --- /dev/null +++ b/doc/python10/builder.eps @@ -0,0 +1,325 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: build/doc/python10/builder.fig +%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d +%%CreationDate: Sun Jan 2 01:21:05 2005 +%%For: knight@casablanca.home.baldmt.com (Steven Knight) +%%BoundingBox: 0 0 668 290 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 290 moveto 0 0 lineto 668 0 lineto 668 290 lineto closepath clip newpath +-53.3 342.7 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/reencdict 12 dict def /ReEncode { reencdict begin +/newcodesandnames exch def /newfontname exch def /basefontname exch def +/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def +basefontdict { exch dup /FID ne { dup /Encoding eq +{ exch dup length array copy newfont 3 1 roll put } +{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall +newfont /FontName newfontname put newcodesandnames aload pop +128 1 255 { newfont /Encoding get exch /.notdef put } for +newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat +newfontname newfont definefont pop end } def +/isovec [ +8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde +8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis +8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron +8#220 /dotlessi 8#230 /oe 8#231 /OE +8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling +8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis +8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot +8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus +8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph +8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine +8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf +8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute +8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring +8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute +8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute +8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve +8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply +8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex +8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave +8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring +8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute +8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute +8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve +8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide +8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex +8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def +/Times-Roman /Times-Roman-iso isovec ReEncode +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit + 0.06000 0.06000 sc +% +% Fig objects follow +% +% Polyline +7.500 slw +n 2700 1200 m 4500 1200 l 4500 1800 l 2700 1800 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +2925 1575 m +gs 1 -1 sc (Environment) col0 sh gr +% Polyline +n 2700 2400 m 4500 2400 l 4500 3000 l 2700 3000 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +3600 2775 m +gs 1 -1 sc (BuilderWrapper) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 2700 3600 m 4500 3600 l 4500 4200 l 2700 4200 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +3600 3975 m +gs 1 -1 sc (BuilderBase) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 8400 3600 m 9900 3600 l 9900 4200 l 8400 4200 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +9150 3975 m +gs 1 -1 sc (ActionBase) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman-iso ff 240.00 scf sf +4650 5175 m +gs 1 -1 sc (MultiStep-) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman-iso ff 240.00 scf sf +4650 5460 m +gs 1 -1 sc (Builder) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 3900 4800 m 5400 4800 l 5400 5700 l 3900 5700 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +2550 5175 m +gs 1 -1 sc (Composite-) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman-iso ff 240.00 scf sf +2550 5460 m +gs 1 -1 sc (Builder) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 1800 4800 m 3300 4800 l 3300 5700 l 1800 5700 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +7050 5175 m +gs 1 -1 sc (Command) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman-iso ff 240.00 scf sf +7050 5460 m +gs 1 -1 sc (Action) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 6300 4800 m 7800 4800 l 7800 5700 l 6300 5700 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +9150 5460 m +gs 1 -1 sc (Action) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman-iso ff 240.00 scf sf +9150 5175 m +gs 1 -1 sc (Function) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 8400 4800 m 9900 4800 l 9900 5700 l 8400 5700 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +11250 5175 m +gs 1 -1 sc (List) dup sw pop 2 div neg 0 rm col0 sh gr +/Times-Roman-iso ff 240.00 scf sf +11250 5460 m +gs 1 -1 sc (Action) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 10500 4800 m 12000 4800 l 12000 5700 l 10500 5700 l + cp gs col0 s gr +% Polyline +n 900 2400 m 2100 2400 l 2100 3000 l 900 3000 l + cp gs col0 s gr +/Times-Roman-iso ff 240.00 scf sf +1500 2775 m +gs 1 -1 sc (Node) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 3600 4200 m 3525 4350 l 3675 4350 l + cp gs col0 s gr +% Polyline +n 3150 4800 m 3150 4500 l 4050 4500 l + 4050 4800 l gs col0 s gr +% Polyline +n 3600 4350 m + 3600 4500 l gs col0 s gr +% Polyline +n 9150 4200 m 9075 4350 l 9225 4350 l + cp gs col0 s gr +% Polyline +n 7050 4800 m 7050 4500 l 10950 4500 l + 10950 4800 l gs col0 s gr +% Polyline +n 9150 4350 m + 9150 4800 l gs col0 s gr +% Polyline +gs clippath +9885 3870 m 9885 3930 l 10036 3930 l 9916 3900 l 10036 3870 l cp +eoclip +n 11550 4650 m 11550 3900 l + 9900 3900 l gs col0 s gr gr + +% arrowhead +n 10036 3870 m 9916 3900 l 10036 3930 l 10036 3870 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +8415 3930 m 8415 3870 l 8264 3870 l 8384 3900 l 8264 3930 l cp +eoclip +n 4650 3900 m + 8400 3900 l gs col0 s gr gr + +% arrowhead +n 8264 3930 m 8384 3900 l 8264 3870 l 8264 3930 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +3930 1785 m 3870 1785 l 3870 1936 l 3900 1816 l 3930 1936 l cp +eoclip +n 3900 2250 m + 3900 1800 l gs col0 s gr gr + +% arrowhead +n 3930 1936 m 3900 1816 l 3870 1936 l 3930 1936 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +3270 2415 m 3330 2415 l 3330 2264 l 3300 2384 l 3270 2264 l cp +eoclip +n 3300 1950 m + 3300 2400 l gs col0 s gr gr + +% arrowhead +n 3270 2264 m 3300 2384 l 3330 2264 l 3270 2264 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +3570 3615 m 3630 3615 l 3630 3464 l 3600 3584 l 3570 3464 l cp +eoclip +n 3600 3150 m + 3600 3600 l gs col0 s gr gr + +% arrowhead +n 3570 3464 m 3600 3584 l 3630 3464 l 3570 3464 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +4380 4185 m 4320 4185 l 4320 4336 l 4350 4216 l 4380 4336 l cp +eoclip +n 4350 4650 m + 4350 4200 l gs col0 s gr gr + +% arrowhead +n 4380 4336 m 4350 4216 l 4320 4336 l 4380 4336 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +2880 4185 m 2820 4185 l 2820 4336 l 2850 4216 l 2880 4336 l cp +eoclip +n 2850 4650 m + 2850 4200 l gs col0 s gr gr + +% arrowhead +n 2880 4336 m 2850 4216 l 2820 4336 l 2880 4336 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +2715 3930 m 2715 3870 l 2564 3870 l 2684 3900 l 2564 3930 l cp +eoclip +n 1500 3150 m 1500 3900 l + 2700 3900 l gs col0 s gr gr + +% arrowhead +n 2564 3930 m 2684 3900 l 2564 3870 l 2564 3930 l cp gs 0.00 setgray ef gr col0 s +% Polyline +n 4650 3900 m 4575 3860 l 4500 3900 l 4575 3940 l + cp gs col0 s gr +% Polyline +n 1500 3000 m 1460 3075 l 1500 3150 l 1540 3075 l + cp gs col0 s gr +% Polyline +n 3600 3000 m 3560 3075 l 3600 3150 l 3640 3075 l + cp gs col0 s gr +% Polyline +n 3300 1800 m 3260 1875 l 3300 1950 l 3340 1875 l + cp gs col0 s gr +% Polyline +n 3900 2250 m 3860 2325 l 3900 2400 l 3940 2325 l + cp gs col0 s gr +% Polyline +n 4350 4650 m 4310 4725 l 4350 4800 l 4390 4725 l + cp gs col0 s gr +% Polyline +n 2850 4650 m 2810 4725 l 2850 4800 l 2890 4725 l + cp gs col0 s gr +% Polyline +n 11550 4650 m 11510 4725 l 11550 4800 l 11590 4725 l + cp gs col0 s gr +% Polyline + [60] 0 sd +n 3600 1200 m + 3600 900 l gs col0 s gr [] 0 sd +$F2psEnd +rs diff --git a/doc/python10/builder.fig b/doc/python10/builder.fig new file mode 100644 index 0000000..75e5ec0 --- /dev/null +++ b/doc/python10/builder.fig @@ -0,0 +1,128 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 2700 1200 4500 1800 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2700 1200 4500 1200 4500 1800 2700 1800 2700 1200 +4 0 0 50 0 0 16 0.0000 4 165 1290 2925 1575 Environment\001 +-6 +6 2700 2400 4500 3000 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2700 2400 4500 2400 4500 3000 2700 3000 2700 2400 +4 1 0 50 0 0 16 0.0000 4 225 1620 3600 2775 BuilderWrapper\001 +-6 +6 2700 3600 4500 4200 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2700 3600 4500 3600 4500 4200 2700 4200 2700 3600 +4 1 0 50 0 0 16 0.0000 4 165 1215 3600 3975 BuilderBase\001 +-6 +6 8400 3600 9900 4200 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8400 3600 9900 3600 9900 4200 8400 4200 8400 3600 +4 1 0 50 0 0 16 0.0000 4 165 1140 9150 3975 ActionBase\001 +-6 +6 3900 4800 5400 5700 +6 4050 4950 5250 5475 +4 1 0 50 0 0 16 0.0000 4 225 1140 4650 5175 MultiStep-\001 +4 1 0 50 0 0 16 0.0000 4 165 750 4650 5460 Builder\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3900 4800 5400 4800 5400 5700 3900 5700 3900 4800 +-6 +6 1800 4800 3300 5700 +6 1950 4950 3150 5475 +4 1 0 50 0 0 16 0.0000 4 225 1200 2550 5175 Composite-\001 +4 1 0 50 0 0 16 0.0000 4 165 750 2550 5460 Builder\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1800 4800 3300 4800 3300 5700 1800 5700 1800 4800 +-6 +6 6300 4800 7800 5700 +6 6525 4950 7575 5475 +4 1 0 50 0 0 16 0.0000 4 165 1020 7050 5175 Command\001 +4 1 0 50 0 0 16 0.0000 4 165 675 7050 5460 Action\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 4800 7800 4800 7800 5700 6300 5700 6300 4800 +-6 +6 8400 4800 9900 5700 +6 8700 4950 9600 5475 +4 1 0 50 0 0 16 0.0000 4 165 675 9150 5460 Action\001 +4 1 0 50 0 0 16 0.0000 4 165 870 9150 5175 Function\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8400 4800 9900 4800 9900 5700 8400 5700 8400 4800 +-6 +6 10500 4800 12000 5700 +6 10875 4950 11625 5475 +4 1 0 50 0 0 16 0.0000 4 165 390 11250 5175 List\001 +4 1 0 50 0 0 16 0.0000 4 165 675 11250 5460 Action\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10500 4800 12000 4800 12000 5700 10500 5700 10500 4800 +-6 +6 900 2400 2100 3000 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 900 2400 2100 2400 2100 3000 900 3000 900 2400 +4 1 0 50 0 0 16 0.0000 4 165 525 1500 2775 Node\001 +-6 +2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 3600 4200 3525 4350 3675 4350 3600 4200 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 3150 4800 3150 4500 4050 4500 4050 4800 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 3600 4350 3600 4500 +2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 9150 4200 9075 4350 9225 4350 9150 4200 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 7050 4800 7050 4500 10950 4500 10950 4800 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 9150 4350 9150 4800 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 1 1 1.00 60.00 120.00 + 11550 4650 11550 3900 9900 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4650 3900 8400 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3900 2250 3900 1800 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3300 1950 3300 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3600 3150 3600 3600 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4350 4650 4350 4200 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2850 4650 2850 4200 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 1 1 1.00 60.00 120.00 + 1500 3150 1500 3900 2700 3900 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 4650 3900 4575 3860 4500 3900 4575 3940 4650 3900 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 1500 3000 1460 3075 1500 3150 1540 3075 1500 3000 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3600 3000 3560 3075 3600 3150 3640 3075 3600 3000 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3300 1800 3260 1875 3300 1950 3340 1875 3300 1800 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3900 2250 3860 2325 3900 2400 3940 2325 3900 2250 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 4350 4650 4310 4725 4350 4800 4390 4725 4350 4650 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 2850 4650 2810 4725 2850 4800 2890 4725 2850 4650 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 11550 4650 11510 4725 11550 4800 11590 4725 11550 4650 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 3600 1200 3600 900 diff --git a/doc/python10/builder.jpg b/doc/python10/builder.jpg Binary files differnew file mode 100644 index 0000000..e9085e8 --- /dev/null +++ b/doc/python10/builder.jpg diff --git a/doc/python10/copyright.xml b/doc/python10/copyright.xml new file mode 100644 index 0000000..d141fc6 --- /dev/null +++ b/doc/python10/copyright.xml @@ -0,0 +1,32 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<blockquote> + <para> + + Copyright (c) 2001, 2002 Steven Knight + + </para> +</blockquote> diff --git a/doc/python10/design.xml b/doc/python10/design.xml new file mode 100644 index 0000000..cb58af9 --- /dev/null +++ b/doc/python10/design.xml @@ -0,0 +1,898 @@ +<para> + + The &SCons; architecture consists of three layers: + +</para> + +<mediaobject> + <imageobject> + <imagedata fileref="arch" format="eps" align="center"> + </imageobject> + <imageobject> + <imagedata fileref="arch.jpg" format="jpg" align="center"> + </imageobject> + <!-- PDF files? + <imageobject> + <imagedata fileref="arch.pdf" align="center"> + </imageobject> + --> +</mediaobject> + +<itemizedlist> + + <listitem> + <para> + + The &SCons; <emphasis>Build Engine</emphasis>, a package of Python + modules that handle dependency management and updating out-of-date + objects. + + </para> + </listitem> + + <listitem> + <para> + + The &SCons; <emphasis>API</emphasis> (applications programming + interface) between the Build Engine + and the user interface. + + </para> + </listitem> + + <listitem> + <para> + + The &scons; <emphasis>script</emphasis> itself (note lower case + <emphasis>sc</emphasis>), which is the pre-provided interface to + the Build Engine. + + </para> + </listitem> + +</itemizedlist> + +<para> + + Notice that this architecture separates the internal workings of + &SCons; (the Build Engine) from the + external user interface. The benefit is that the &SCons; Build Engine + can be imported into any other software package written in Python + to support a variety of user interfaces—or, to look at it + in reverse, other software interfaces can use the &SCons; Build + Engine to manage dependencies between their objects. + +</para> + +<para> + + Because the + &SCons; package itself is modular, only those parts of the package + relevant to the embedding interface need be imported; for example, + a utility that wants to use only file timestamps for checking + whether a file is up-to-date + need not import the MD5 signature module. + +</para> + +<section> + <title>The &SCons; Build Engine</title> + + <para> + + The Build Engine is a package of Python modules that + form the heart of &SCons;. + + The Build Engine can be broadly divided into five + architectural subsystems, each responsible + for a crucial part of &SCons; functionality: + + </para> + + <itemizedlist> + + <listitem> + <para> + + A <emphasis>node</emphasis> subsystem, responsible for managing + the files (or other objects) to be built, and the dependency + relationships between them. + + </para> + </listitem> + + <listitem> + <para> + + A <emphasis>scanner</emphasis> subsystem, responsible for + scanning various file types for implicit dependencies. + + </para> + </listitem> + + <listitem> + <para> + + A <emphasis>signature</emphasis> subsystem, responsible for + deciding whether a given file (or other object) requires + rebuilding. + + </para> + </listitem> + + <listitem> + <para> + + A <emphasis>builder</emphasis> subsystem, responsible for + actually executing the necessary command or function to + build a file (or other object). + + </para> + </listitem> + + <listitem> + <para> + + A <emphasis>job/task</emphasis> subsystem, responsible for + handling parallelization of builds. + + </para> + </listitem> + + </itemizedlist> + + <para> + + The rest of this section will provide a high-level overview of the + class structure of each of these Build Engine subsystems. + + </para> + + <section> + <title>Node Subsystem</title> + + <para> + + The node subsystem of the Build Engine is + responsible for managing the knowledge in &SCons; of + the relationships among the external objects + (files) it is responsible for updating. + The most important of these relationships is + the dependency relationship between various &Node; objects, + which &SCons; uses to determine the order + in which builds should be performed. + + </para> + + <mediaobject> + <imageobject> + <imagedata fileref="node" format="eps" align="center"> + </imageobject> + <imageobject> + <imagedata fileref="node.jpg" format="jpg" align="center"> + </imageobject> + <!-- PDF files? + <imageobject> + <imagedata fileref="node.pdf" align="center"> + </imageobject> + --> + </mediaobject> + + <para> + + The &scons; script (or other + user interface) + tells the Build Engine + about dependencies + through its &consenv; API. + The Build Engine also discovers + dependencies automatically through the use of &Scanner; objects. + + </para> + + <para> + + Subclasses of the &Node; class maintain additional + relationships that reflect the real-world + existence of these objects. + For example, the &Node_FS; subclass + is responsible for managing a + representation of the directory hierarchy + of a file system. + + </para> + + <para> + + A &Walker; class is used by other subsystems + to walk the dependency tree maintained by the &Node; class. + The &Walker; class maintains a stack of &Node; objects + visited during its depth-first traversal of the + dependency tree, + and uses an intermediate node &Wrapper; class + to maintain state information about a + &Node; object's dependencies. + + </para> + + </section> + + <section> + <title>Scanner Subsystem</title> + + <para> + + The scanner subsystem is responsible for maintaining + objects that can scan the contents of a &Node;'s + for implicit dependencies. + + </para> + + <mediaobject> + <imageobject> + <imagedata fileref="scanner" format="eps" align="center"> + </imageobject> + <imageobject> + <imagedata fileref="scanner.jpg" format="jpg" align="center"> + </imageobject> + <!-- PDF files? + <imageobject> + <imagedata fileref="scanner.pdf" align="center"> + </imageobject> + --> + </mediaobject> + + <para> + + In practice, a given &Scanner; subclass object + functions as a prototype, + returning clones of itself + depending on the &consenv; + values governing how the &Node; + should be scanned. + + </para> + + </section> + + <section> + <title>Signature Subsystem</title> + + <para> + + The signature subsystem is responsible for computing + signature information for &Node; objects. + The signature subsystem in &SCons; + supports multiple ways to + determine whether a &Node is up-to-date + by using an abstract &Sig; class + as a strategy wrapper: + + </para> + + <mediaobject> + <imageobject> + <imagedata fileref="sig" format="eps" align="center"> + </imageobject> + <imageobject> + <imagedata fileref="sig.jpg" format="jpg" align="center"> + </imageobject> + <!-- PDF files? + <imageobject> + <imagedata fileref="sig.pdf" align="center"> + </imageobject> + --> + </mediaobject> + + <para> + + By default, &SCons; tracks dependencies by computing and + maintaining MD5 signatures for the contents of each source file + (or other object). The signature of a <emphasis>derived</emphasis> + file consists of the aggregate of the signatures of all the source + files <emphasis>plus</emphasis> the command-line string used to + build the file. These signatures are stored in a &sconsign; file + in each directory. + + </para> + + <para> + + If the contents of any of the source files changes, the change to its + MD5 signature is propogated to the signature of the derived file(s). The + simple fact that the new signature does not match the stored signature + indicates that the derived file is not up to date and must be rebuilt. + + </para> + + <para> + + A separate &TimeStamp; subclass of the &Sig; class supports + the use of traditional file timestamps for + deciding whether files are up-to-date. + + </para> + + </section> + + <section> + <title>Builder Subsystem</title> + + <para> + + The &SCons; Build Engine records how out-of-date files + (or other objects) should be rebuilt in &Builder; objects, + maintained by the builder subsystem: + + </para> + + <mediaobject> + <imageobject> + <imagedata fileref="builder" format="eps" align="center"> + </imageobject> + <imageobject> + <imagedata fileref="builder.jpg" format="jpg" align="center"> + </imageobject> + <!-- PDF files? + <imageobject> + <imagedata fileref="builder.pdf" align="center"> + </imageobject> + --> + </mediaobject> + + <para> + + The actual underlying class name is &BuilderBase;, + and there are subclasses that can encapsulate + multiple &Builder; objects for special purposes. + One subclass + (&CompositeBuilder;) + selects an appropriate encapsulated &Builder; + based on the file suffix of the target object. + The other + (&MultiStepBuilder;). + can chain together multiple + &Builder; objects, + for example, + to build an executable program from a source file + through an implicit intermediate object file. + + </para> + + <para> + + A &BuilderBase; object has an associated + &ActionBase; object + responsible for actually executing + the appropriate steps + to update the target file. + There are three subclasses, + one for externally executable commands + (&CommandAction;), + one for Python functions + (&FunctionAction;), + and one for lists of + multiple &Action; objects + (&ListAction;). + + </para> + + </section> + + <section> + <title>Job/Task Subsystem</title> + + <para> + + &SCons; supports parallel builds with a thread-based tasking + model, managed by the job/task subsystem. + + </para> + + <mediaobject> + <imageobject> + <imagedata fileref="job-task" format="eps" align="center"> + </imageobject> + <imageobject> + <imagedata fileref="job-task.jpg" format="jpg" align="center"> + </imageobject> + <!-- PDF files? + <imageobject> + <imagedata fileref="job-task.pdf" align="center"> + </imageobject> + --> + </mediaobject> + + <para> + + Instead of performing an outer-loop recursive descent + of the dependency tree and then forking a task when it finds a + file that needs updating, &SCons; starts as many threads as are + requested, each thread managed by the &Jobs; class. + As a performance optimization, + the &Jobs; class maintains an internal + distinction between + &Serial; and &Parallel; + build jobs, + so that serial builds + don't pay any performance penalty + by using a multi-threaded implementation + written for &Parallel; builds. + + </para> + + <para> + + Each &Jobs; object, running in its own thread, + then requests a &Task; from a central &Taskmaster;, + which is responsible + for handing out available &Task; objects for (re-)building + out-of-date nodes. A condition variable + makes sure that the &Jobs; objects + query the &Taskmaster; one at a time. + + </para> + + <para> + + The &Taskmaster uses the node subsystem's + &Walker; class to walk the dependency tree, + and the &Sig; class to use the + appropriate method + of deciding if a &Node; is up-to-date. + + </para> + + <para> + + This scheme has many advantages over the standard &Make; + implementation of <option>-j</option>. + Effective use of <option>-j</option> is difficult + with the usual recursive use of Make, + because the number of jobs started by <option>-j</option> multiply + at each level of the source tree. + This makes the actual number of jobs + executed at any moment very dependent on the size and layout of + the tree. &SCons;, in contrast, starts only as many jobs as are + requested, and keeps them constantly busy (excepting jobs that + block waiting for their dependency files to finish building). + + </para> + + </section> + +</section> + +<section> + <title>The &SCons; API</title> + + <para> + + This section provides an overview of the &SCons; interface. The + complete interface specification is both more detailed and flexible + than this overview. + + </para> + + <section> + <title>&ConsVars;</title> + + <para> + + In &SCons;, a &consenv; is an object through which an external + interface (such as the &scons; script) communicates dependency + information to the &SCons; Build Engine. + + </para> + + <para> + + A construction environment is implemented as a dictionary + containing: + + </para> + + <itemizedlist> + + <listitem> + <para> + + construction variables, string values that are substituted + into command lines or used by builder functions; + + </para> + </listitem> + + <listitem> + <para> + + one or more &Builder; objects that can be invoked to update a + file or other object; + + </para> + </listitem> + + <listitem> + <para> + + one or more &Scanner; objects that can be used to + scan a file automatically for dependencies (such as + files specified on <literal>#include</literal> lines). + + </para> + </listitem> + + </itemizedlist> + + <para> + + &Consenvs; are instantiated as follows: + + </para> + + <programlisting> + env = Environment() + env_debug = Environment(CCFLAGS = '-g') + </programlisting> + + </section> + + <section> + <title>&Builder; Objects</title> + + <para> + + An &SCons; &Builder; object encapsulates information about how to + build a specific type of file: an executable program, an object + file, a library, etc. A &Builder; object is associated with a + file through an associated &consenv; method and later invoked to + actually build the file. The &Builder; object will typically use + construction variables (such as &CCFLAGS;, &LIBPATH;) to influence + the specific build execution. + + </para> + + <para> + + &Builder; objects are instantiated as follows: + + </para> + + <programlisting> + bld = Builder(name = 'Program', action = "$CC -o $TARGET $SOURCES") + </programlisting> + + <para> + + In the above example, the <literal>action</literal> is a + command-line string in which the Build Engine will + interpolate the values of construction + variables before execution. The actual + <literal>action</literal> specified, though, + may be a function: + + </para> + + <programlisting> + def update(dest): + # [code to update the object] + return 0 + + bld = Builder(name = 'Program', function = update) + </programlisting> + + <para> + + Or a callable Python object (or class): + + </para> + + <programlisting> + class class_a: + def __call__(self, kw): + # build the desired object + return 0 + + builder = SCons.Builder.Builder(action = class_a()) + </programlisting> + + <para> + + A &Builder; object may have the <literal>prefix</literal> and + <literal>suffix</literal> of its target file type specified + as keyword arguments at instantiation. Additionally, the + suffix of the <emphasis>source files</emphasis> used by this + &Builder; to build its target files may be specified using the + <literal>src_suffix</literal> keyword argument: + + </para> + + <programlisting> + bld_lib = Builder(name = 'Library', action = "$AR r $TARGET $SOURCES", + prefix = 'lib', suffix = '.a', src_suffix = '.o') + </programlisting> + + <para> + + The specified <literal>prefix</literal> and + <literal>suffix</literal> will be appended to the name of any + target file built by this &Builder; object, if they are not + already part of the file name. The <literal>src_suffix</literal> + is used by the &SCons; Build Engine to chain together + multiple &Builder; objects to create, + for example, a library from the original source + files without having to specify the + intermediate <literal>.o</literal> files. + + </para> + + <para> + + &Builder; objects are associated with a &consenv; through a + &consvar; named &BUILDERS;, a list of the &Builder objects that + will be available for execution through the &consenv: + + </para> + + <programlisting> + env = Environment(BUILDERS = [ Object, Library, WebPage, Program ]) + </programlisting> + + </section> + + <section> + <title>&Scanner; Objects</title> + + <para> + + &Scanner; objects perform automatic checking for dependencies + by scanning the contents of files. The canonical + example is scanning a C source file or header file for + files specified on <literal>#include</literal> lines. + + </para> + + <para> + + A &Scanner; object is instantiated as follows: + + </para> + + <programlisting> + def c_scan(contents): + # scan contents of file + return # list of files found + + c_scanner = Scanner(name = 'CScan', function = c_scan, + argument = None, + skeys = ['.c', '.C', '.h', '.H') + </programlisting> + + <para> + + The <literal>skeys</literal> argument specifies a list of file + suffixes for file types that this &Scanner; knows how to scan. + + </para> + + <para> + + &Scanner; objects are associated with a &consenv; through a + &consvar; named &SCANNERS;, a list of the &Scanner; objects that + will be available through the &consenv: + + </para> + + <programlisting> + env = Environment(SCANNERS = [ CScan, M4Scan ]) + </programlisting> + + <para> + + For utilities that will build files with a variety of file + suffixes, or which require unusual scanning rules, a &Scanner; + object may be associated explicitly with a &Builder; object as + follows: + + </para> + + <programlisting> + def tool_scan(contents): + # scan contents of file + return # list of files found + + tool_scanner = Scanner(name = 'TScan', function = tool_scan) + + bld = Builder(name = 'Tool', scanner = tool_scanner) + </programlisting> + + </section> + + <section> + <title>&BuildDir;</title> + + <para> + + &SCons; supports a flexible mechanism for building target + files in a separate build directory from the source files. + The &BuildDir; syntax is straightforward: + + </para> + + <programlisting> + BuildDir(source = 'src', build = 'bld') + </programlisting> + + <para> + + By + default, source files are linked or copied into the build + directory, because exactly replicating the source directory + is sometimes necessary for certain combinations of use of + <literal>#include "..."</literal> and <option>-I</option> search + paths. + + An option exists to specify that only output files should be placed in + the build directory: + + </para> + + <programlisting> + BuildDir(source = 'src', build = 'bld', no_sources = 1) + </programlisting> + + </section> + + <section> + <title>&Repository;</title> + + <para> + + &SCons; supports the ability to search a list of code repositories + for source files and derived files. This works much like + &Make;'s <varname>VPATH</varname> feature, as implemented in + recent versions of GNU &Make;. + (The POSIX standard for &Make; specifies slightly + different behavior for <varname>VPATH</varname>.) + The syntax is: + + </para> + + <programlisting> + Repository('/home/source/1.1', '/home/source/1.0') + </programlisting> + + <para> + + A command-line <option>-Y</option> option exists to allow + repositories to be specified on the command line, or in the + &SCONSFLAGS; environment variable (not construction variable!). + This avoids a chicken-and-egg situation and allows the top-level + &SConstruct; file to be found in a repository as well. + + </para> + + </section> + + <section> + <title>&Cache;</title> + + <para> + + &SCons; supports a way for developers to share derived files. Again, the + syntax is straightforward: + + </para> + + <programlisting> + Cache('/var/build.cache/i386') + </programlisting> + + <para> + + Copies of any derived files built will be placed in the specified + directory with their MD5 signature. If another build results in an + out-of-date derived file with the same signature, the derived file + will be copied from the cache instead of being rebuilt. + + </para> + + </section> + +</section> + +<section> + <title>The &scons; Script</title> + + <para> + + The &scons; script provides an interface + that looks roughly equivalent to the + classic &Make; utility—that is, execution from the command + line, and dependency information read from configuration files. + + </para> + + <para> + + The most noticeable difference between &scons; and &Make;, or most + other build tools, is that the configuration files are actually + Python scripts, generically called "SConscripts" (although the + top-level "Makefile" is named &SConstruct). Users do not have to + learn a new language syntax, but instead configure dependency + information by making direct calls to the Python API of the + &SCons; Build Engine. Here is an example &SConstruct file which + builds a program in side-by-side normal and debug versions: + + </para> + + <programlisting> + env = Environment() + debug = env.Copy(CCFLAGS = '-g') + + source_files = ['f1.c', 'f2.c', 'f3.c'] + + env.Program(target = 'foo', sources = source_files) + debug.Program(target = 'foo-debug', sources = source_files) + </programlisting> + + <para> + + Notice the fact that this file is a Python script, which allows us + to define and re-use an array that lists the source files. + + </para> + + <para> + + Because quoting individul strings in long + lists of files can get tedious and error-prone, the &SCons; + methods support a short-cut of listing multiple files in a single + string, separated by white space. + This would change + the assignment in the above example to a more easily-readable: + + </para> + + <programlisting> + source_files = 'f1.c f2.c f3.c' + </programlisting> + + <para> + + The mechanism to establish hierarchical builds is to "include" any + subsidiary configuration files in the build by listing them explicitly + in a call to the &SConscript; function: + + </para> + + <programlisting> + SConscript('src/SConscript', 'lib/SConscript') + </programlisting> + + <para> + + By convention, configuration files in subdirectories are named + &SConscript;. + + </para> + + <para> + + The &scons; script has intentionally been made to look, from + the outside, as much like &Make; as is practical. To this + end, the &scons; script supports all of the same command-line + options supported by GNU &Make;: <option>-f</option> FILE, + <option>-j</option>, <option>-k</option>, <option>-s</option>, + etc. For compatibility, &scons; ignores those GNU &Make; options + that don't make sense for the &SCons; architecture, such as + <option>-b</option>, <option>-m</option>, <option>-S</option>, + and <option>-t</option>. The + intention is that, given an equivalent &SConstruct; file for a + &Makefile;, a user could use &SCons; as a drop-in replacement for + &Make;. Additional command-line options are, where possible, taken + from the Perl &Cons; utility on which the &SCons; design is based. + + </para> + +</section> diff --git a/doc/python10/future.xml b/doc/python10/future.xml new file mode 100644 index 0000000..272d508 --- /dev/null +++ b/doc/python10/future.xml @@ -0,0 +1,170 @@ +<para> + + There are a number of things we would like to do to continue to + improve &SCons; in the future. + +</para> + +<section> + <title>Distutils Cooperation</title> + + <para> + + There is a certain amount of overlap between what &SCons; does + to search out and make use of various compilers on a system, and + the impressively complete job that the Distutils do of describing + much the same thing. Collaborating to provide some sort of common + interface between the two tools would benefit both tools. + + </para> + +</section> + +<section> + <title>Additional Builder Support</title> + + <para> + + Adding additional builders would broaden the + potential user base. In rough order of importance: + + </para> + + <variablelist> + + <varlistentry> + <term>Java</term> + <listitem> + <para> + + Given the popularity of Java, support for it would greatly + increase the appeal of &SCons; in the large community of Java + users. + + </para> + + <para> + + Good support for Java is, however, a tricky + proposition. Because the Java compiler can make decisions + about compiling other files based on what classes it finds + in a file, it behaves "unpredictably" from the point of + view of an outside build tool like &SCons; or &Make;. Some + sort of sophisticated scanning of Java source code to + identify what other classes are likely to be compiled + would be an obvious first step, but notice that here + &SCons; would be scanning the file to find additional + targets to be built. This is the inverse of the sort of + <literal>#include</literal> scanning performed + for C files, in which &SCons; is looking for additional + <emphasis>dependencies</emphasis>. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Documentation toolchains</term> + <listitem> + <para> + + A number of early adopters + are using &SCons; to + build documents + from TeX or DocBook source files. + Built-in support for + various documentation toolchains + would be an obvious boon + for many people. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>C#</term> + <listitem> + <para> + + The reality is that anything that Microsoft does will doubtless + have a wide audience. Turning &SCons;' back on that would be + cutting off its nose to spite its face. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Fortran</term> + <listitem> + <para> + + Despite the fact that &SCons; is no longer directly + associated with Software Carpentry, it still shares the + same goal: to make programming easier for more than just + programmers. To that end, good Fortran support would + help a great many physical scientists and other computer + <emphasis>users</emphasis> out there who still rely on Fortran + for a great deal of their work. + + </para> + </listitem> + </varlistentry> + + </variablelist> + +</section> + +<section> + <title>Database Interface</title> + + <para> + + The Nodes in an &SCons; dependency graph aren't only restricted to + files. Creating an interface to mSQL or MySQL databases would allow + the possibility of updating external files in response to changes in + database fields, or vice versa. This could be handy, for example, + for generating a cache of static web pages from a database that only + need re-generating when the appropriate database objects change. + + </para> + +</section> + +<section> + <title>Tool Integration</title> + + <para> + + &SCons; should work well with as many popular Integrated Development + Environments (IDEs) and tool chains as possible: Komodo, Microsoft + Visual Studio, ClearCase, etc. Suggestions for additional tools are + welcome. + + </para> + +</section> + +<section> + <title>Makefile Interface</title> + + <para> + + Because the &SCons; Build Engine can be embedded in any Python + interface, there isn't any technical reason why a &Makefile; + interpreter couldn't be written in Python and use the &SCons; Build + Engine for its dependency analysis. + + </para> + + <para> + + Proof-of-concept for the idea already exists. Gary Holt's + <literal>make++</literal> (also known as <literal>makepp</literal>) + is a Perl implementation of just such a &Makefile; interpreter. It + could possible serve as a model for a Python version, in much the + same way the &Cons; design served as the prototype for &SCons;. + + </para> + +</section> diff --git a/doc/python10/install.xml b/doc/python10/install.xml new file mode 100644 index 0000000..d150beb --- /dev/null +++ b/doc/python10/install.xml @@ -0,0 +1,179 @@ +<para> + + Initial installation of a new utility provides the first, lasting + impression of how well the software is likely to perform. From the + start, &SCons; has made clean installation a priority. + +</para> + +<section> + <title>Version Control</title> + + <para> + + Distributing an application like &SCons; that depends + on a package normally found in a library poses a + problem. If the &scons; script and the &SCons; Build Engine + are installed separately, it could be easy + to introduce a version mismatch between the Build Engine + installed in + <filename>/usr/lib/python*/site-packages</filename> + and the &scons; script installed in + <filename>/usr/bin</filename>. + Such a mismatch + could possible mean exceptions that prevent builds, or even worse, + silently unreliable builds. + + </para> + + <para> + + To reduce the possibility of a version mismatch, + the &scons; script looks first for its + imported modules in <filename>/usr/lib/scons-{version}/</filename>, + then in <filename>/usr/lib/scons/</filename>, + and then in the normal &PYTHONPATH; locations, + including <filename>/usr/lib/python*/site-packages</filename>). + Searching in a version-specific library directory first + makes it convenient to install and use multiple + side-by-side versions of &SCons;, + which is sometimes important + when verifying that a new version does not introduce any + errors into the local build process. + Searching next in an &SCons;-specific library directory + makes it convenient for other software to find + the &SCons; Build Engine without having to worry about + installing separate copies for + multiple versions of Python. + + </para> + +</section> + +<section> + <title>Packages</title> + + <para> + + &SCons; is currently distributed in the following packages: + + </para> + + <table> + <title></title> + <tgroup cols="2"> + <tbody> + + <row valign="top"> + <entry> + <literal>scons-</literal><emphasis>version</emphasis><literal>.tar.gz</literal> + </entry> + <entry><para> + + The traditional <literal>.tar.gz</literal> file, + installable by running <filename>setup.py</filename>. + + </para></entry> + </row> + + <row valign="top"> + <entry> + <literal>scons-</literal><emphasis>version</emphasis><literal>.noarch.rpm</literal> + </entry> + <entry><para> + + An RPM file for typical installation. + + </para></entry> + </row> + + <row valign="top"> + <entry> + <literal>scons-</literal><emphasis>version</emphasis><literal>_all.deb</literal> + </entry> + <entry><para> + + A Debian package. + + </para></entry> + </row> + + <row valign="top"> + <entry> + <literal>scons-</literal><emphasis>version</emphasis><literal>.win32.exe</literal> + </entry> + <entry><para> + + A Windows installer. + + </para></entry> + </row> + + <row valign="top"> + <entry> + <literal>scons-</literal><emphasis>version</emphasis><literal>.src.rpm</literal> + </entry> + <entry><para> + + A source RPM file. + + </para></entry> + </row> + + <row valign="top"> + <entry> + <literal>scons-src-</literal><emphasis>version</emphasis><literal>.tar.gz</literal> + </entry> + <entry><para> + + A tarball of the &SCons; source tree, + including the full set of regression tests. + + </para></entry> + </row> + + </tbody> + </tgroup> + </table> + + <para> + + Like other software written in Python, &SCons; benefits greatly from + the tremendous effort put into the <literal>distutils</literal> by + Greg Ward and others. These take care of 90% of the work by making + it almost trivial to generate the appropriate RPM files, Debian + packages, and Windows installer. + + </para> + +</section> + +<section> + <title>Default Builder Objects</title> + + <para> + + As part of the installation process, &SCons; runs a set of scripts + that look for popular compilers and other tools and set up + appropriate default &Builder; objects for the tools found. These + &Builder; objects are then used to initialize the default &consenv; + values. + + </para> + +</section> + +<section> + <title>Default Scanner Objects</title> + + <para> + + Additionally, &SCons; comes with a stock set of &Scanner; objects + for the various file types that it supports out of the box. Any + unusal &Scanner; objects required for a specific tool will be + detected at installation time and associated with the appropriate + &Builder; object for the tool. + + </para> + +</section> diff --git a/doc/python10/intro.xml b/doc/python10/intro.xml new file mode 100644 index 0000000..d3057be --- /dev/null +++ b/doc/python10/intro.xml @@ -0,0 +1,212 @@ +<para> + + More than twenty years after its creation, the classic UNIX &Make; + utility and its descendants are still the dominant way in which + software is built. &Make; has maintained this position despite the + fact that the intervening years have revealed many + shortcomings of the &Make; model for building software: + +</para> + +<itemizedlist> + + <listitem> + <para> + + The use of timestamps to decide when a file has been updated is + imprecise and prone to error, especially across distributed file + systems such as NFS. + + </para> + </listitem> + + <listitem> + <para> + + Builds of typical large software systems still take hours, if not + days, despite the tremendous advances in CPU and disk speeds over + recent years. + + </para> + </listitem> + + <listitem> + <para> + + &Make; maintains static definitions of dependencies in its + &Makefiles;. Much effort has been put into + utilities (<application>mkdepend</application>, <application>gcc + -M</application>) and schemes (<filename>Makefile.d</filename> + files) to try to keep &Makefile; dependencies up-to-date, + but these only confirm that &Make;'s static dependencies are + inherently fragile. + + </para> + </listitem> + + <listitem> + <para> + + The standard recursive use of &Make; for build hierarchies leads + to incomplete dependency graphs, which must be overcome by + manually changing the order in which directories are built, or + through the use of multiple build passes. + + </para> + </listitem> + +</itemizedlist> + +<para> + + One need only look at the plethora of helper and wrapper utilities + (automake, easymake, imake, jmake, makeLib, maketool, mkmed, shake, + SMake, TMAKE) and complete alternatives to &Make; (Ant, bake, bau, + bras, Cake, Cons, Cook, Jam, jmk, jus, makeme, mash, MK, nmake, Odin, + VMake) that have been created over the years to realize that vanilla + &Make; is not satisfying everyone's build requirements. So why Yet + Another build tool? + +</para> + +<section> + <title>Enter Software Carpentry</title> + + <para> + + Most of the build tools just mentioned + were written by programmers and for + programmers. The fact that most programmer-friendly + utilities do a poor job of fulfilling the needs + of non-programmers prompted Greg Wilson to + organize the Software Carpentry competition in January 2000. + Software Carpentry was an + open design contest with the express goal of producing a set of + next-generation utilities, including a build tool, that would be + accessible + not only to + programmers + but also to computer <emphasis>users</emphasis> + such as physical scientists. + + </para> + + <para> + + The key to this usability would be that all of + these utilities, including the build tool, would be + written in Python. + This provided the catalyst for actually + pursuing an idea + that had been floating around one of the more + intriguing &Make; alternatives, + a Perl utility called &Cons;. + What if the friendlier syntax of Python + could be married to the + architectural advantages of &Cons;? + + </para> + + <para> + + The resulting merged design, at that time named &ScCons;, + won the Software Carpentry build tool competition. CodeSourcery (by + then the administrators of the competition) ultimately decided not to + fund development of the build tool, but the seed had been planted and the + design had taken root. + + </para> + +</section> + +<section> + <title>Cons</title> + + <para> + + It helps to know something about &Cons;. + &Cons; was first released in 1996 by Bob Sidebotham, + then an employee of Fore Systems, + and it has a number of + distinctive features that set it apart from most &Make;-alikes: + + </para> + + <itemizedlist> + + <listitem> + <para> + + &Cons; "configuration files" are not Yet Another + invented mini-language, but are actually <emphasis>Perl + scripts</emphasis>, which means the full power and flexibility of + a real scripting language can be applied to build problems. + + </para> + </listitem> + + <listitem> + <para> + + &Cons; builds everything from a single process at the top of the + source tree, with a global view of the dependencies. + + </para> + </listitem> + + <listitem> + <para> + + &Cons; scans files automatically for dependencies such as + files specified on <literal>#include</literal> lines. + + </para> + </listitem> + + <listitem> + <para> + + &Cons; decides if a file was out-of-date by using MD5 checksums of + the contents of files, not timestamps. + + </para> + </listitem> + + </itemizedlist> + + <para> + + Despite all of these intriguing architectural features, the great + strength of &Cons;—being written in Perl—was also one of + its weaknesses, turning away many potential users due to the + (real or perceived) steep learning curve of Perl. + + </para> + +</section> + +<section> + <title>&SCons;</title> + + <para> + + Through the &ScCons; contest entry, + &SCons; is the direct descendant of the &Cons; architecture, + and is currently + under active, supported development with a growing body of + users. Its first release was 13 December 2001, under the simple and + non-restrictive MIT license, and from the outset, the goal of the + members of the &SCons; project has been to deliver a stable, reliable + tool that can be used for industrial-strength software builds. + + </para> + + <para> + + The rest of this paper will give an overview of the &SCons; design + (including its architecture and interface), describe the development + methodology used, and discuss future directions for &SCons;. + + </para> + +</section> diff --git a/doc/python10/job-task.eps b/doc/python10/job-task.eps new file mode 100644 index 0000000..b3eeaff --- /dev/null +++ b/doc/python10/job-task.eps @@ -0,0 +1,238 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: build/doc/python10/job-task.fig +%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d +%%CreationDate: Sun Jan 2 01:21:05 2005 +%%For: knight@casablanca.home.baldmt.com (Steven Knight) +%%BoundingBox: 0 0 416 236 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 236 moveto 0 0 lineto 416 0 lineto 416 236 lineto closepath clip newpath +-35.3 342.7 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit + 0.06000 0.06000 sc +% +% Fig objects follow +% +% Polyline +7.500 slw +n 4200 3900 m 5100 3900 l 5100 4500 l 4200 4500 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +4650 4275 m +gs 1 -1 sc (Task) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 4200 5100 m 5100 5100 l 5100 5700 l 4200 5700 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +4650 5475 m +gs 1 -1 sc (Node) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 6300 2100 m 7200 2100 l 7200 2700 l 6300 2700 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +6750 2475 m +gs 1 -1 sc (Sig) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 6300 3300 m 7500 3300 l 7500 3900 l 6300 3900 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +6900 3675 m +gs 1 -1 sc (Walker) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 4200 2100 m 5700 2100 l 5700 2700 l 4200 2700 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +4950 2475 m +gs 1 -1 sc (TaskMaster) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 2400 3300 m 3600 3300 l 3600 3900 l 2400 3900 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +3000 3675 m +gs 1 -1 sc (Parallel) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 600 3300 m 1800 3300 l 1800 3900 l 600 3900 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +1200 3675 m +gs 1 -1 sc (Serial) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 1200 2100 m 3000 2100 l 3000 2700 l 1200 2700 l + cp gs col0 s gr +/Times-Roman ff 255.00 scf sf +2099 2475 m +gs 1 -1 sc (Jobs) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 2700 2700 m 2660 2775 l 2700 2850 l 2740 2775 l + cp gs col0 s gr +% Polyline +n 5700 2400 m 5775 2440 l 5850 2400 l 5775 2360 l + cp gs col0 s gr +% Polyline +n 5400 2700 m 5360 2775 l 5400 2850 l 5440 2775 l + cp gs col0 s gr +% Polyline +n 4650 2700 m 4610 2775 l 4650 2850 l 4690 2775 l + cp gs col0 s gr +% Polyline +n 1500 2700 m 1460 2775 l 1500 2850 l 1540 2775 l + cp gs col0 s gr +% Polyline +n 4650 4500 m 4610 4575 l 4650 4650 l 4690 4575 l + cp gs col0 s gr +% Polyline +gs clippath +1470 3315 m 1530 3315 l 1530 3164 l 1500 3284 l 1470 3164 l cp +eoclip +n 1500 2850 m + 1500 3300 l gs col0 s gr gr + +% arrowhead +n 1470 3164 m 1500 3284 l 1530 3164 l 1470 3164 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +2670 3315 m 2730 3315 l 2730 3164 l 2700 3284 l 2670 3164 l cp +eoclip +n 2700 2850 m + 2700 3300 l gs col0 s gr gr + +% arrowhead +n 2670 3164 m 2700 3284 l 2730 3164 l 2670 3164 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +4620 3915 m 4680 3915 l 4680 3764 l 4650 3884 l 4620 3764 l cp +eoclip +n 4650 2850 m + 4650 3900 l gs col0 s gr gr + +% arrowhead +n 4620 3764 m 4650 3884 l 4680 3764 l 4620 3764 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +4620 5115 m 4680 5115 l 4680 4964 l 4650 5084 l 4620 4964 l cp +eoclip +n 4650 4650 m + 4650 5100 l gs col0 s gr gr + +% arrowhead +n 4620 4964 m 4650 5084 l 4680 4964 l 4620 4964 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +6315 3630 m 6315 3570 l 6164 3570 l 6284 3600 l 6164 3630 l cp +eoclip +n 5400 2850 m 5400 3600 l + 6300 3600 l gs col0 s gr gr + +% arrowhead +n 6164 3630 m 6284 3600 l 6164 3570 l 6164 3630 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +6315 2430 m 6315 2370 l 6164 2370 l 6284 2400 l 6164 2430 l cp +eoclip +n 5850 2400 m + 6300 2400 l gs col0 s gr gr + +% arrowhead +n 6164 2430 m 6284 2400 l 6164 2370 l 6164 2430 l cp gs 0.00 setgray ef gr col0 s +% Polyline +n 3000 2400 m 3075 2440 l 3150 2400 l 3075 2360 l + cp gs col0 s gr +% Polyline +gs clippath +4215 2430 m 4215 2370 l 4064 2370 l 4184 2400 l 4064 2430 l cp +eoclip +n 3150 2400 m + 4200 2400 l gs col0 s gr gr + +% arrowhead +n 4064 2430 m 4184 2400 l 4064 2370 l 4064 2430 l cp gs 0.00 setgray ef gr col0 s +% Polyline + [60] 0 sd +n 2100 2100 m + 2100 1800 l gs col0 s gr [] 0 sd +% Polyline + [60] 0 sd +n 4950 2100 m + 4950 1800 l gs col0 s gr [] 0 sd +% Polyline + [60] 0 sd +n 6750 2100 m + 6750 1800 l gs col0 s gr [] 0 sd +$F2psEnd +rs diff --git a/doc/python10/job-task.fig b/doc/python10/job-task.fig new file mode 100644 index 0000000..6febd97 --- /dev/null +++ b/doc/python10/job-task.fig @@ -0,0 +1,90 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 4200 3900 5100 4500 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4200 3900 5100 3900 5100 4500 4200 4500 4200 3900 +4 1 0 50 0 0 16 0.0000 4 165 465 4650 4275 Task\001 +-6 +6 4200 5100 5100 5700 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4200 5100 5100 5100 5100 5700 4200 5700 4200 5100 +4 1 0 50 0 0 16 0.0000 4 165 525 4650 5475 Node\001 +-6 +6 6300 2100 7200 2700 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 2100 7200 2100 7200 2700 6300 2700 6300 2100 +4 1 0 50 0 0 16 0.0000 4 225 330 6750 2475 Sig\001 +-6 +6 6300 3300 7500 3900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 3300 7500 3300 7500 3900 6300 3900 6300 3300 +4 1 0 50 0 0 16 0.0000 4 165 735 6900 3675 Walker\001 +-6 +6 4200 2100 5700 2700 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4200 2100 5700 2100 5700 2700 4200 2700 4200 2100 +4 1 0 50 0 0 16 0.0000 4 165 1155 4950 2475 TaskMaster\001 +-6 +6 2400 3300 3600 3900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2400 3300 3600 3300 3600 3900 2400 3900 2400 3300 +4 1 0 50 0 0 16 0.0000 4 165 765 3000 3675 Parallel\001 +-6 +6 600 3300 1800 3900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 3300 1800 3300 1800 3900 600 3900 600 3300 +4 1 0 50 0 0 16 0.0000 4 165 585 1200 3675 Serial\001 +-6 +6 1200 2100 3000 2700 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1200 2100 3000 2100 3000 2700 1200 2700 1200 2100 +4 1 0 50 0 0 17 0.0000 4 165 420 2099 2475 Jobs\001 +-6 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 2700 2700 2660 2775 2700 2850 2740 2775 2700 2700 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 5700 2400 5775 2440 5850 2400 5775 2360 5700 2400 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 5400 2700 5360 2775 5400 2850 5440 2775 5400 2700 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 4650 2700 4610 2775 4650 2850 4690 2775 4650 2700 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 1500 2700 1460 2775 1500 2850 1540 2775 1500 2700 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 4650 4500 4610 4575 4650 4650 4690 4575 4650 4500 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1500 2850 1500 3300 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2700 2850 2700 3300 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4650 2850 4650 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4650 4650 4650 5100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 1 1 1.00 60.00 120.00 + 5400 2850 5400 3600 6300 3600 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 5850 2400 6300 2400 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3000 2400 3075 2440 3150 2400 3075 2360 3000 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3150 2400 4200 2400 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 2100 2100 2100 1800 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 4950 2100 4950 1800 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 6750 2100 6750 1800 diff --git a/doc/python10/job-task.jpg b/doc/python10/job-task.jpg Binary files differnew file mode 100644 index 0000000..ff3ded0 --- /dev/null +++ b/doc/python10/job-task.jpg diff --git a/doc/python10/main.xml b/doc/python10/main.xml new file mode 100644 index 0000000..42bc4af --- /dev/null +++ b/doc/python10/main.xml @@ -0,0 +1,221 @@ +<?xml version="1.0"?> + +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ + + <!ENTITY % scons SYSTEM "scons.mod"> + %scons; + + <!ENTITY abstract SYSTEM "abstract.xml"> + <!ENTITY acks SYSTEM "acks.xml"> + <!ENTITY copyright SYSTEM "copyright.xml"> + <!ENTITY design SYSTEM "design.xml"> + <!ENTITY future SYSTEM "future.xml"> + <!ENTITY install SYSTEM "install.xml"> + <!ENTITY intro SYSTEM "intro.xml"> + <!ENTITY process SYSTEM "process.xml"> + +]> + +<article> + <articleinfo> + <title>SCons Design and Implementation</title> + + <author> + <firstname>Steven</firstname> + <surname>Knight</surname> + </author> + + <copyright> + <year>2001</year> + <year>2002</year> + <holder>Steven Knight</holder> + </copyright> + + <pubdate>2002</pubdate> + + <confgroup> + <confdates>4-7 February 2002</confdates> + <conftitle>The Tenth International Python Conference</conftitle> + <address>Alexandria, Virginia</address> + </confgroup> + + <revhistory> + <revision> + <revnumber>0.2</revnumber> + <date>16 December 2001</date> + <revremark>Internal re-review.</revremark> + </revision> + <revision> + <revnumber>0.1</revnumber> + <date>8 October 2001</date> + <revremark>Submitted for Python10 conference.</revremark> + </revision> + </revhistory> + + </articleinfo> + + <abstract> + &abstract; + </abstract> + + <section id="sect-intro"> + <title>Introduction</title> + &intro; + </section> + + <section id="sect-design"> + <title>Architecture</title> + &design; + </section> + + <section id="sect-install"> + <title>Installation</title> + &install; + </section> + + <section id="sect-process"> + <title>Development Process</title> + &process; + </section> + + <section id="sect-future"> + <title>Future Directions</title> + &future; + </section> + + <section id="sect-summary"> + <title>Summary</title> + <para> + + This paper has introduced &SCons;, a next-generation build tool + with a modular, embeddable architecture and a direct Python + interface. &SCons; has a global view of the dependencies in a source + tree, uses MD5 signatures to decide if derived files are out of date, + and automatically scans files for dependencies, all of which make &SCons; + builds exceptionally reliable. The &SCons; development methodology has + been described, notable for its emphasis on automated regression + testing to ensure a robust and reliable tool from day one. Several + future directions for &SCons; have also been discussed. + + </para> + </section> + + <section id="sect-acks"> + <title>Acknowledgements</title> + &acks; + </section> + + <!-- + <section id="sect-refs"> + <title>References</title> + <para> + </para> + </section> + --> + + <bibliography id="sect-refs"> + <title>References</title> + + <biblioentry> + <abbrev>1</abbrev> + <authorgroup> + <author><firstname>Stuart I.</firstname><surname>Feldman</surname></author> + </authorgroup> + <copyright> + <year>Aug 1978</year> + </copyright> + <publisher> + <publishername>Bell Laboratories</publishername> + </publisher> + <title>Make - A Program for Maintaining Computer Programs</title> + </biblioentry> + + <biblioentry> + <abbrev>2</abbrev> + <authorgroup> + <author><firstname>Peter</firstname><surname>Miller</surname></author> + </authorgroup> + <copyright> + <year>1997</year> + <holder>Peter Miller</holder> + </copyright> + <title>Recursive Make Considered Harmful</title> + <!--http://www.pcug.org.au/~millerp/rmch/recu-make-cons-harm.html--> + </biblioentry> + + <biblioentry> + <abbrev>3</abbrev> + <authorgroup> + <author><firstname>Andrew</firstname><surname>Oram</surname></author> + <author><firstname>Steve</firstname><surname>Talbott</surname></author> + </authorgroup> + <copyright> + <year>1986</year> + <year>1991</year> + <holder>O'Reilly & Associates, Inc.</holder> + </copyright> + <publisher> + <publishername>O'Reilly & Associates, Inc.</publishername> + </publisher> + <title>Managing Projects with Make, 2nd Ed.</title> + </biblioentry> + + <biblioentry> + <abbrev>4</abbrev> + <authorgroup> + <author><firstname>Richard M.</firstname><surname>Stallman</surname></author> + <author><firstname>Roland</firstname><surname>McGrath</surname></author> + </authorgroup> + <copyright> + <year>1988</year> + <year>'89</year> + <year>'90</year> + <year>'91</year> + <year>'92</year> + <year>'93</year> + <year>'94</year> + <year>'95</year> + <year>'96</year> + <year>'97</year> + <year>'98</year> + <year>'99</year> + <year>2000</year> + <holder>Free Software Foundation, Inc.</holder> + </copyright> + <publisher> + <publishername>Free Software Foundation, Inc.</publishername> + </publisher> + <title>GNU Make</title> + <subtitle>A Program for Directing Recompilation</subtitle> + </biblioentry> + + </bibliography> + +</article> diff --git a/doc/python10/node.eps b/doc/python10/node.eps new file mode 100644 index 0000000..995235d --- /dev/null +++ b/doc/python10/node.eps @@ -0,0 +1,351 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: build/doc/python10/node.fig +%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d +%%CreationDate: Sun Jan 2 01:21:05 2005 +%%For: knight@casablanca.home.baldmt.com (Steven Knight) +%%BoundingBox: 0 0 452 362 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 362 moveto 0 0 lineto 452 0 lineto 452 362 lineto closepath clip newpath +0.7 414.7 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit + 0.06000 0.06000 sc +% +% Fig objects follow +% +% Polyline +7.500 slw +n 2700 1200 m 4500 1200 l 4500 1800 l 2700 1800 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +2925 1575 m +gs 1 -1 sc (Environment) col0 sh gr +% Polyline +n 2700 3600 m 4500 3600 l 4500 4200 l 2700 4200 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +3375 3975 m +gs 1 -1 sc (Node) col0 sh gr +% Polyline +n 5700 1800 m 6900 1800 l 6900 2400 l 5700 2400 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +5925 2175 m +gs 1 -1 sc (Walker) col0 sh gr +% Polyline +n 2100 2400 m 3300 2400 l 3300 3000 l 2100 3000 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +2325 2775 m +gs 1 -1 sc (Builder) col0 sh gr +% Polyline +n 3900 2400 m 5100 2400 l 5100 3000 l 3900 3000 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +4125 2775 m +gs 1 -1 sc (Scanner) col0 sh gr +% Polyline +n 2400 6300 m 3300 6300 l 3300 6900 l 2400 6900 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +2700 6675 m +gs 1 -1 sc (Dir) col0 sh gr +% Polyline +n 0 6300 m 900 6300 l 900 6900 l 0 6900 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +150 6675 m +gs 1 -1 sc (Entry) col0 sh gr +% Polyline +n 1200 6300 m 2100 6300 l 2100 6900 l 1200 6900 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +1425 6675 m +gs 1 -1 sc (File) col0 sh gr +% Polyline +n 1050 5100 m 2250 5100 l 2250 5700 l 1050 5700 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +1200 5475 m +gs 1 -1 sc (Node.FS) col0 sh gr +% Polyline +n 1650 5700 m 1575 5850 l 1725 5850 l + cp gs col0 s gr +% Polyline +n 450 6300 m 450 6000 l 2700 6000 l + 2700 6300 l gs col0 s gr +% Polyline +n 1650 6300 m + 1650 5850 l gs col0 s gr +% Polyline + [60] 0 sd +n 5100 6300 m 6300 6300 l 6300 6900 l 5100 6900 l + cp gs col0 s gr [] 0 sd +/Times-Roman ff 240.00 scf sf +5325 6675 m +gs 1 -1 sc (Record) col0 sh gr +% Polyline + [60] 0 sd +n 6600 6300 m 7500 6300 l 7500 6900 l 6600 6900 l + cp gs col0 s gr [] 0 sd +/Times-Roman ff 240.00 scf sf +6750 6675 m +gs 1 -1 sc (Field) col0 sh gr +% Polyline + [60] 0 sd +n 4950 5100 m 6150 5100 l 6150 5700 l 4950 5700 l + cp gs col0 s gr [] 0 sd +/Times-Roman ff 240.00 scf sf +5100 5475 m +gs 1 -1 sc (Node.DB) col0 sh gr +% Polyline +n 5550 5700 m 5475 5850 l 5625 5850 l + cp gs col0 s gr +% Polyline + [60] 0 sd +n 4350 6300 m 4350 6000 l 7050 6000 l + 7050 6300 l gs col0 s gr [] 0 sd +% Polyline + [60] 0 sd +n 5550 5850 m + 5550 6300 l gs col0 s gr [] 0 sd +% Polyline + [60] 0 sd +n 3900 6300 m 4800 6300 l 4800 6900 l 3900 6900 l + cp gs col0 s gr [] 0 sd +/Times-Roman ff 240.00 scf sf +4050 6675 m +gs 1 -1 sc (Table) col0 sh gr +% Polyline +n 5700 3000 m 6900 3000 l 6900 3600 l 5700 3600 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +5850 3375 m +gs 1 -1 sc (Wrapper) col0 sh gr +% Polyline +n 900 1200 m 1800 1200 l 1800 1800 l 900 1800 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +1200 1575 m +gs 1 -1 sc (FS) col0 sh gr +% Polyline +n 3600 4200 m 3525 4350 l 3675 4350 l + cp gs col0 s gr +% Polyline +n 1800 5100 m 1800 4800 l 5550 4800 l + 5550 5100 l gs col0 s gr +% Polyline +n 3600 4800 m + 3600 4350 l gs col0 s gr +% Polyline +n 4200 1800 m 4160 1875 l 4200 1950 l 4240 1875 l + cp gs col0 s gr +% Polyline +n 3000 6150 m 2960 6225 l 3000 6300 l 3040 6225 l + cp gs col0 s gr +% Polyline +n 6300 3600 m 6260 3675 l 6300 3750 l 6340 3675 l + cp gs col0 s gr +% Polyline +n 6300 2400 m 6260 2475 l 6300 2550 l 6340 2475 l + cp gs col0 s gr +% Polyline +n 3000 4200 m 2960 4275 l 3000 4350 l 3040 4275 l + cp gs col0 s gr +% Polyline +n 4200 3450 m 4160 3525 l 4200 3600 l 4240 3525 l + cp gs col0 s gr +% Polyline +n 3000 3450 m 2960 3525 l 3000 3600 l 3040 3525 l + cp gs col0 s gr +% Polyline +gs clippath +2235 5370 m 2235 5430 l 2386 5430 l 2266 5400 l 2386 5370 l cp +eoclip +n 3000 6150 m 3000 5400 l + 2250 5400 l gs col0 s gr gr + +% arrowhead +n 2386 5370 m 2266 5400 l 2386 5430 l 2386 5370 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +2715 3930 m 2715 3870 l 2564 3870 l 2684 3900 l 2564 3930 l cp +eoclip +n 3000 4350 m 3000 4500 l 1800 4500 l 1800 3900 l + 2700 3900 l gs col0 s gr gr + +% arrowhead +n 2564 3930 m 2684 3900 l 2564 3870 l 2564 3930 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +4485 3870 m 4485 3930 l 4636 3930 l 4516 3900 l 4636 3870 l cp +eoclip +n 6300 3750 m 6300 3900 l + 4500 3900 l gs col0 s gr gr + +% arrowhead +n 4636 3870 m 4516 3900 l 4636 3930 l 4636 3870 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +4230 2985 m 4170 2985 l 4170 3136 l 4200 3016 l 4230 3136 l cp +eoclip +n 4200 3450 m + 4200 3000 l gs col0 s gr gr + +% arrowhead +n 4230 3136 m 4200 3016 l 4170 3136 l 4230 3136 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +3030 2985 m 2970 2985 l 2970 3136 l 3000 3016 l 3030 3136 l cp +eoclip +n 3000 3450 m + 3000 3000 l gs col0 s gr gr + +% arrowhead +n 3030 3136 m 3000 3016 l 2970 3136 l 3030 3136 l cp gs 0.00 setgray ef gr col0 s +% Polyline +n 3000 1800 m 2960 1875 l 3000 1950 l 3040 1875 l + cp gs col0 s gr +% Polyline +gs clippath +2970 2415 m 3030 2415 l 3030 2264 l 3000 2384 l 2970 2264 l cp +eoclip +n 3000 1950 m + 3000 2400 l gs col0 s gr gr + +% arrowhead +n 2970 2264 m 3000 2384 l 3030 2264 l 2970 2264 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +4170 2415 m 4230 2415 l 4230 2264 l 4200 2384 l 4170 2264 l cp +eoclip +n 4200 1950 m + 4200 2400 l gs col0 s gr gr + +% arrowhead +n 4170 2264 m 4200 2384 l 4230 2264 l 4170 2264 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +6270 3015 m 6330 3015 l 6330 2864 l 6300 2984 l 6270 2864 l cp +eoclip +n 6300 2550 m + 6300 3000 l gs col0 s gr gr + +% arrowhead +n 6270 2864 m 6300 2984 l 6330 2864 l 6270 2864 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +4785 6570 m 4785 6630 l 4936 6630 l 4816 6600 l 4936 6570 l cp +eoclip +n 5100 6600 m + 4800 6600 l gs col0 s gr gr + +% arrowhead +n 4936 6570 m 4816 6600 l 4936 6630 l 4936 6570 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +6285 6570 m 6285 6630 l 6436 6630 l 6316 6600 l 6436 6570 l cp +eoclip +n 6600 6600 m + 6300 6600 l gs col0 s gr gr + +% arrowhead +n 6436 6570 m 6316 6600 l 6436 6630 l 6436 6570 l cp gs 0.00 setgray ef gr col0 s +% Polyline +n 1350 1800 m 1310 1875 l 1350 1950 l 1390 1875 l + cp gs col0 s gr +% Polyline +gs clippath +1320 5115 m 1380 5115 l 1380 4964 l 1350 5084 l 1320 4964 l cp +eoclip +n 1350 1950 m + 1350 5100 l gs col0 s gr gr + +% arrowhead +n 1320 4964 m 1350 5084 l 1380 4964 l 1320 4964 l cp gs 0.00 setgray ef gr col0 s +% Polyline + [60] 0 sd +n 1350 1200 m + 1350 900 l gs col0 s gr [] 0 sd +% Polyline + [60] 0 sd +n 3600 1200 m + 3600 900 l gs col0 s gr [] 0 sd +$F2psEnd +rs diff --git a/doc/python10/node.fig b/doc/python10/node.fig new file mode 100644 index 0000000..3c40f07 --- /dev/null +++ b/doc/python10/node.fig @@ -0,0 +1,165 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 2700 1200 4500 1800 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2700 1200 4500 1200 4500 1800 2700 1800 2700 1200 +4 0 0 50 0 0 16 0.0000 4 165 1290 2925 1575 Environment\001 +-6 +6 2700 3600 4500 4200 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2700 3600 4500 3600 4500 4200 2700 4200 2700 3600 +4 0 0 50 0 0 16 0.0000 4 165 525 3375 3975 Node\001 +-6 +6 5700 1800 6900 2400 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5700 1800 6900 1800 6900 2400 5700 2400 5700 1800 +4 0 0 50 0 0 16 0.0000 4 165 735 5925 2175 Walker\001 +-6 +6 2100 2400 3300 3000 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2100 2400 3300 2400 3300 3000 2100 3000 2100 2400 +4 0 0 50 0 0 16 0.0000 4 165 750 2325 2775 Builder\001 +-6 +6 3900 2400 5100 3000 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3900 2400 5100 2400 5100 3000 3900 3000 3900 2400 +4 0 0 50 0 0 16 0.0000 4 165 780 4125 2775 Scanner\001 +-6 +6 0 5100 3300 6900 +6 2400 6300 3300 6900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2400 6300 3300 6300 3300 6900 2400 6900 2400 6300 +4 0 0 50 0 0 16 0.0000 4 165 345 2700 6675 Dir\001 +-6 +6 0 6300 900 6900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 0 6300 900 6300 900 6900 0 6900 0 6300 +4 0 0 50 0 0 16 0.0000 4 225 555 150 6675 Entry\001 +-6 +6 1200 6300 2100 6900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1200 6300 2100 6300 2100 6900 1200 6900 1200 6300 +4 0 0 50 0 0 16 0.0000 4 165 390 1425 6675 File\001 +-6 +6 1050 5100 2250 5700 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1050 5100 2250 5100 2250 5700 1050 5700 1050 5100 +4 0 0 50 0 0 16 0.0000 4 165 855 1200 5475 Node.FS\001 +-6 +6 450 5700 2700 6300 +2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 1650 5700 1575 5850 1725 5850 1650 5700 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 450 6300 450 6000 2700 6000 2700 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 1650 6300 1650 5850 +-6 +-6 +6 3900 5100 7500 6900 +6 5100 6300 6300 6900 +2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5 + 5100 6300 6300 6300 6300 6900 5100 6900 5100 6300 +4 0 0 50 0 0 16 0.0000 4 165 705 5325 6675 Record\001 +-6 +6 6600 6300 7500 6900 +2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5 + 6600 6300 7500 6300 7500 6900 6600 6900 6600 6300 +4 0 0 50 0 0 16 0.0000 4 165 510 6750 6675 Field\001 +-6 +6 4950 5100 6150 5700 +2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5 + 4950 5100 6150 5100 6150 5700 4950 5700 4950 5100 +4 0 0 50 0 0 16 0.0000 4 165 930 5100 5475 Node.DB\001 +-6 +6 4350 5700 7050 6300 +2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 5550 5700 5475 5850 5625 5850 5550 5700 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4 + 4350 6300 4350 6000 7050 6000 7050 6300 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 5550 5850 5550 6300 +-6 +6 3900 6300 4800 6900 +2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5 + 3900 6300 4800 6300 4800 6900 3900 6900 3900 6300 +4 0 0 50 0 0 16 0.0000 4 165 555 4050 6675 Table\001 +-6 +-6 +6 5700 3000 6900 3600 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5700 3000 6900 3000 6900 3600 5700 3600 5700 3000 +4 0 0 50 0 0 16 0.0000 4 225 870 5850 3375 Wrapper\001 +-6 +6 900 1200 1800 1800 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 900 1200 1800 1200 1800 1800 900 1800 900 1200 +4 0 0 50 0 0 16 0.0000 4 165 270 1200 1575 FS\001 +-6 +2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 3600 4200 3525 4350 3675 4350 3600 4200 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 1800 5100 1800 4800 5550 4800 5550 5100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 3600 4800 3600 4350 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 4200 1800 4160 1875 4200 1950 4240 1875 4200 1800 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3000 6150 2960 6225 3000 6300 3040 6225 3000 6150 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 6300 3600 6260 3675 6300 3750 6340 3675 6300 3600 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 6300 2400 6260 2475 6300 2550 6340 2475 6300 2400 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3000 4200 2960 4275 3000 4350 3040 4275 3000 4200 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 4200 3450 4160 3525 4200 3600 4240 3525 4200 3450 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3000 3450 2960 3525 3000 3600 3040 3525 3000 3450 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 1 1 1.00 60.00 120.00 + 3000 6150 3000 5400 2250 5400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 5 + 1 1 1.00 60.00 120.00 + 3000 4350 3000 4500 1800 4500 1800 3900 2700 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 1 1 1.00 60.00 120.00 + 6300 3750 6300 3900 4500 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 4200 3450 4200 3000 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 3000 3450 3000 3000 +2 3 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5 + 3000 1800 2960 1875 3000 1950 3040 1875 3000 1800 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 3000 1950 3000 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 4200 1950 4200 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 6300 2550 6300 3000 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 5100 6600 4800 6600 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 6600 6600 6300 6600 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 1350 1800 1310 1875 1350 1950 1390 1875 1350 1800 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 1350 1950 1350 5100 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 1350 1200 1350 900 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 3600 1200 3600 900 diff --git a/doc/python10/node.jpg b/doc/python10/node.jpg Binary files differnew file mode 100644 index 0000000..98ceb5e --- /dev/null +++ b/doc/python10/node.jpg diff --git a/doc/python10/process.xml b/doc/python10/process.xml new file mode 100644 index 0000000..f1b2479 --- /dev/null +++ b/doc/python10/process.xml @@ -0,0 +1,353 @@ +<para> + + The &SCons; project has paid particular attention from day one to the + development process. One of the first internal documents produced was + a set of Developer's Guidelines to provide a loose framework for what + we were trying to accomplish and how we would go about accomplishing + it. These Guidelines cover things like: + +</para> + +<itemizedlist> + + <listitem> + <para> + + &SCons; will be written to Python version 1.5.2 (to ensure + usability by a wide install base). + + </para> + </listitem> + + <listitem> + <para> + + How &SCons; is be tested: which infrastructure modules to use, + what platforms to test on, etc. + + </para> + </listitem> + + <listitem> + <para> + + Expectations for developers (subscribe to the mailing list, + encouraged to register at SourceForge). + + </para> + </listitem> + + <listitem> + <para> + + Brief outline of how to use the change management systems (Aegis and + CVS) for &SCons; development;. + + </para> + </listitem> + +</itemizedlist> + +<para> + + Establishing these guidelines up front had two purposes: 1) + Demonstrate the seriousness of the project to anyone wondering about + joining the effort; 2) Give potential developers an idea up front as + to whether their development style would mesh with the rest of the + project. + +</para> + +<section> + <title>Aegis</title> + + <para> + + One of the most important aspects of the &SCons; development process + is the use of Peter Miller's Aegis change management system. I + had been using Aegis for personal projects for several years, and + found its development methodology vastly improved the quality of my + programming. I was consequently committed to using it for &SCons; + development. + + </para> + + <para> + + Aegis provides a number of things, including: + + </para> + + <itemizedlist> + + <listitem> + <para> + + A flexible source code control and branching model. + + </para> + </listitem> + + <listitem> + <para> + + A defined process with separate development, review and + integration steps. + + </para> + </listitem> + + <listitem> + <para> + + A distributed development model based on distribution of atomic + change sets. + + </para> + </listitem> + + </itemizedlist> + + <para> + + The single most important reason for using Aegis, however, is its + management of automated tests as part of the development process. + + </para> + +</section> + +<section> + <title>Testing, Testing, Testing</title> + + <para> + + The &SCons; project has made extensive use of automated tests from day + one, taking inspiration mostly from Aegis, partly from the eXtreme + Programming model, and with a little home-brew scripting for glue. + + </para> + + <section> + <title>Testing Criteria</title> + + <para> + + The underlying criteria for testing changes to the &SCons; code + are taken from Aegis: + + </para> + + <itemizedlist> + + <listitem> + <para> + + Every change must have one or more new or modified tests + checked in along with the code. + + </para> + </listitem> + + <listitem> + <para> + + The new code being checked in must pass all of the new and/or + modified tests. + + </para> + </listitem> + + <listitem> + <para> + + The <emphasis>old</emphasis>, already checked-in code in must + <emphasis>fail</emphasis> all of the new and/or modified + tests. + + </para> + </listitem> + + <listitem> + <para> + + The new code being checked in must pass all unmodified, + already checked-in tests. + + </para> + </listitem> + + </itemizedlist> + + <para> + + In practice, these restrictions can be overridden as necessaryfor + example, when changing comments or documentation. + + </para> + + <para> + + The criterion that surprises many people is having the old code + fail the tests in the change. This makes sure that the new tests + or modified tests really do exercise the bug fix or feature being + added by the change. + + </para> + + <para> + + Together, these criteria ensure that every newly checked-in + version &SCons; conforms to defined behavior, as defined by + the tests. Whenever a bug is found, its fix is checked in with + a new or modified test that guarantees the bug will not recur + in the future. We have already built up a regression test base + of almost 90 tests that cover the vast majority of &SCons;' + functionality. + + </para> + + </section> + + <section> + <title>Testing Infrastructure</title> + + <para> + + Testing standards are no good if they're too much of a burden for + developers, who will at best work around or ignore the testing + requirements, or at worst stop contributing code and go join a + project that's more fun. To this end, good testing infrastructure + that makes it easy to write tests is crucial. + + </para> + + <para> + + &SCons; development uses two development methodologies, one for + the individual modules in the build engine, and the other for + end-to-end tests of the &SCons; script. + + </para> + + <para> + + For the build engine modules, we use PyUnit. Every change to a + build engine module must have a change to its corresponding unit + tests, which live side-by-side in a separate file that imports + module. As we build up a large body of unit tests, this ensures + that the build engine will perform correctly whenever someone uses + it in some application other than the &SCons; script itself. + + </para> + + <para> + + For end-to-end script tests, we have developed two modules to make + writing tests easy. The first, <filename>TestCmd.py</filename>, + is a generic module for + testing commands or scripts (in any language, not just Python). + + The second module, <filename>TestScons.py</filename>, + is a subclass of the generic + <filename>TestCmd.py</filename> module. + <filename>TestScons.py</filename> + takes care of initialization and + displaying error conditions + specific to testing &SCons;. + + </para> + + <para> + + In practice, simple tests only + need to initialize a test object, use the object to write some + input files, run &SCons;, and then check whatever criteria + determine whether the test passed or failed. A complete test of + the &Program; method, for example, looks like this: + + </para> + + <programlisting> + test = TestSCons.TestSCons() + + test.write('SConstruct', + """env = Environment() + env.Program(target = 'foo', source = 'foo.c') + """) + + test.write('foo.c', + """ + int + main(int argc, char *argv[]) + { + argv[argc++] = "-"; /* dummy use of args */ + printf("foo.c successfully compiled\\n"); + exit (0); + } + """) + + test.run(arguments = 'foo') # runs SCons + + test.run(program = test.workpath('foo')) + + test.fail_test(test.stdout() != "foo.c successfully compiled\n") + + test.pass_test() + </programlisting> + + </section> + +</section> + +<section> + <title>SourceForge</title> + + <para> + + Registration of the &SCons; project was approved at SourceForge on + 29 June 2001. Within a week, the initial code base was checked in, + mailing lists were created, and the web site was set up. We started + making use of the task-list manager to track what we had to finish + for initial release. + + </para> + + <para> + + The obvious complication was how to use + structured testing methodology of Aegis when SourceForge uses + CVS for source control. Not using the SourceForge CVS tree would + have had two significant disadvantages: one, missing out on the + archiving and central location in the event of disaster; two, people + coming to the SourceForge project page wouldn't be able to browse + the source. The latter was particularly important in + the early stages of development, in order to avoid any impression + that this was Yet Another Project that starts with a bang and then + dwindles as the initial enthusiasm starts to wear off. + + </para> + + <para> + + The solution was to use the SourceForge CVS repository for read-only + access to the source. &SCons; developers are welcome to use CVS for + their development, but the changes are <emphasis>not</emphasis> + committed to the SourceForge repository. Instead, patches are sent + to the integrator for processing through Aegis. When the change + has been integrated into the Aegis repository, a home-brew + script translates the Aegis change into a virtual shell script + of commands that copy the necessary files from Aegis and check them + in to CVS at SourceForge. + + </para> + + <para> + + (In practice, write access is not actually disabled for registered + developers, but if they do make any changes directly at SourceForge, + they can be overwritten at the next Aegis update.) + + </para> + +</section> diff --git a/doc/python10/scanner.eps b/doc/python10/scanner.eps new file mode 100644 index 0000000..35614f8 --- /dev/null +++ b/doc/python10/scanner.eps @@ -0,0 +1,168 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: build/doc/python10/scanner.fig +%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d +%%CreationDate: Sun Jan 2 01:21:05 2005 +%%For: knight@casablanca.home.baldmt.com (Steven Knight) +%%BoundingBox: 0 0 398 200 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 200 moveto 0 0 lineto 398 0 lineto 398 200 lineto closepath clip newpath +-17.3 360.7 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit + 0.06000 0.06000 sc +% +% Fig objects follow +% +% Polyline +7.500 slw +n 2700 5400 m 4500 5400 l 4500 6000 l 2700 6000 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +3000 5775 m +gs 1 -1 sc (ProgScanner) col0 sh gr +% Polyline +n 2700 4200 m 4500 4200 l 4500 4800 l 2700 4800 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +3225 4575 m +gs 1 -1 sc (Scanner) col0 sh gr +% Polyline +n 2700 3000 m 4500 3000 l 4500 3600 l 2700 3600 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +2925 3375 m +gs 1 -1 sc (Environment) col0 sh gr +% Polyline + [60] 0 sd +n 5100 5400 m 6900 5400 l 6900 6000 l 5100 6000 l + cp gs col0 s gr [] 0 sd +/Times-Roman ff 240.00 scf sf +5400 5775 m +gs 1 -1 sc (JavaScanner) col0 sh gr +% Polyline +n 300 5400 m 2100 5400 l 2100 6000 l 300 6000 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +750 5775 m +gs 1 -1 sc (CScanner) col0 sh gr +% Polyline +n 600 3300 m 1500 3300 l 1500 3900 l 600 3900 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +825 3675 m +gs 1 -1 sc (Node) col0 sh gr +% Polyline +n 1200 5400 m 1200 5100 l 6000 5100 l + 6000 5400 l gs col0 s gr +% Polyline +n 3600 4950 m + 3600 5400 l gs col0 s gr +% Polyline +n 3600 4800 m 3525 4950 l 3675 4950 l + cp gs col0 s gr +% Polyline +n 3600 3600 m 3560 3675 l 3600 3750 l 3640 3675 l + cp gs col0 s gr +% Polyline +n 1050 3900 m 1010 3975 l 1050 4050 l 1090 3975 l + cp gs col0 s gr +% Polyline +gs clippath +2715 4530 m 2715 4470 l 2564 4470 l 2684 4500 l 2564 4530 l cp +eoclip +n 1050 4050 m 1050 4500 l + 2700 4500 l gs col0 s gr gr + +% arrowhead +n 2564 4530 m 2684 4500 l 2564 4470 l 2564 4530 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +3570 4215 m 3630 4215 l 3630 4064 l 3600 4184 l 3570 4064 l cp +eoclip +n 3600 3750 m + 3600 4200 l gs col0 s gr gr + +% arrowhead +n 3570 4064 m 3600 4184 l 3630 4064 l 3570 4064 l cp gs 0.00 setgray ef gr col0 s +% Polyline + [60] 0 sd +n 3600 3000 m + 3600 2700 l gs col0 s gr [] 0 sd +$F2psEnd +rs diff --git a/doc/python10/scanner.fig b/doc/python10/scanner.fig new file mode 100644 index 0000000..01488e8 --- /dev/null +++ b/doc/python10/scanner.fig @@ -0,0 +1,57 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 2700 5400 4500 6000 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2700 5400 4500 5400 4500 6000 2700 6000 2700 5400 +4 0 0 50 0 0 16 0.0000 4 225 1245 3000 5775 ProgScanner\001 +-6 +6 2700 4200 4500 4800 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2700 4200 4500 4200 4500 4800 2700 4800 2700 4200 +4 0 0 50 0 0 16 0.0000 4 165 780 3225 4575 Scanner\001 +-6 +6 2700 3000 4500 3600 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2700 3000 4500 3000 4500 3600 2700 3600 2700 3000 +4 0 0 50 0 0 16 0.0000 4 165 1290 2925 3375 Environment\001 +-6 +6 5100 5400 6900 6000 +2 2 1 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 5100 5400 6900 5400 6900 6000 5100 6000 5100 5400 +4 0 0 50 0 0 16 0.0000 4 165 1200 5400 5775 JavaScanner\001 +-6 +6 300 5400 2100 6000 +2 2 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 300 5400 2100 5400 2100 6000 300 6000 300 5400 +4 0 0 50 0 0 16 0.0000 4 165 945 750 5775 CScanner\001 +-6 +6 600 3300 1500 3900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 3300 1500 3300 1500 3900 600 3900 600 3300 +4 0 0 50 0 0 16 0.0000 4 165 525 825 3675 Node\001 +-6 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4 + 1200 5400 1200 5100 6000 5100 6000 5400 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 3600 4950 3600 5400 +2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 3600 4800 3525 4950 3675 4950 3600 4800 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 3600 3600 3560 3675 3600 3750 3640 3675 3600 3600 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 1050 3900 1010 3975 1050 4050 1090 3975 1050 3900 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 3 + 1 1 1.00 60.00 120.00 + 1050 4050 1050 4500 2700 4500 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3600 3750 3600 4200 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 3600 3000 3600 2700 diff --git a/doc/python10/scanner.jpg b/doc/python10/scanner.jpg Binary files differnew file mode 100644 index 0000000..08e5dcb --- /dev/null +++ b/doc/python10/scanner.jpg diff --git a/doc/python10/scons.mod b/doc/python10/scons.mod new file mode 100644 index 0000000..8df6d2c --- /dev/null +++ b/doc/python10/scons.mod @@ -0,0 +1,428 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + An SCons-specific DTD module, for use with SCons DocBook + documentation, that contains names, phrases, acronyms, etc. used + throughout the SCons documentation. + +--> + + + +<!-- + + Other applications that we reference. + +--> + +<!ENTITY Aegis "<application>Aegis</application>"> +<!ENTITY Ant "<application>Ant</application>"> +<!ENTITY Autoconf "<application>Autoconf</application>"> +<!ENTITY Automake "<application>Automake</application>"> +<!ENTITY cc "<application>cc</application>"> +<!ENTITY Cons "<application>Cons</application>"> +<!ENTITY cp "<application>cp</application>"> +<!ENTITY csh "<application>csh</application>"> +<!ENTITY gcc "<application>gcc</application>"> +<!ENTITY Jam "<application>Jam</application>"> +<!ENTITY jar "<application>jar</application>"> +<!ENTITY javac "<application>javac</application>"> +<!ENTITY javah "<application>javah</application>"> +<!ENTITY Make "<application>Make</application>"> +<!ENTITY Makepp "<application>Make++</application>"> +<!ENTITY Python "<application>Python</application>"> +<!ENTITY ranlib "<application>ranlib</application>"> +<!ENTITY rmic "<application>rmic</application>"> +<!ENTITY SCons "<application>SCons</application>"> +<!ENTITY scons "<application>scons</application>"> +<!ENTITY ScCons "<application>ScCons</application>"> +<!ENTITY tar "<application>tar</application>"> +<!ENTITY touch "<application>touch</application>"> +<!ENTITY zip "<application>zip</application>"> + + +<!-- + + Classes. + +--> + +<!ENTITY Action "<classname>Action</classname>"> +<!ENTITY ActionBase "<classname>ActionBase</classname>"> +<!ENTITY CommandAction "<classname>CommandAction</classname>"> +<!ENTITY FunctionAction "<classname>FunctionAction</classname>"> +<!ENTITY ListAction "<classname>ListAction</classname>"> +<!ENTITY Builder "<classname>Builder</classname>"> +<!ENTITY BuilderBase "<classname>BuilderBase</classname>"> +<!ENTITY CompositeBuilder "<classname>CompositeBuilder</classname>"> +<!ENTITY MultiStepBuilder "<classname>MultiStepBuilder</classname>"> +<!ENTITY Job "<classname>Job</classname>"> +<!ENTITY Jobs "<classname>Jobs</classname>"> +<!ENTITY Serial "<classname>Serial</classname>"> +<!ENTITY Parallel "<classname>Parallel</classname>"> +<!ENTITY Node "<classname>Node</classname>"> +<!ENTITY Node_FS "<classname>Node.FS</classname>"> +<!ENTITY Scanner "<classname>Scanner</classname>"> +<!ENTITY Sig "<classname>Sig</classname>"> +<!ENTITY Signature "<classname>Signature</classname>"> +<!ENTITY Taskmaster "<classname>Taskmaster</classname>"> +<!ENTITY TimeStamp "<classname>TimeStamp</classname>"> +<!ENTITY Walker "<classname>Walker</classname>"> +<!ENTITY Wrapper "<classname>Wrapper</classname>"> + + + +<!-- + + Options, command-line. + +--> + +<!ENTITY debug-explain "<literal>--debug=explain</literal>"> +<!ENTITY implicit-cache "<literal>--implicit-cache</literal>"> +<!ENTITY implicit-deps-changed "<literal>--implicit-deps-changed</literal>"> +<!ENTITY implicit-deps-unchanged "<literal>--implicit-deps-unchanged</literal>"> +<!ENTITY Q "<literal>-Q</literal>"> + +<!-- + + Options, SConscript-settable. + +--> + +<!ENTITY implicit_cache "<literal>implicit_cache</literal>"> +<!ENTITY implicit_deps_changed "<literal>implicit_deps_changed</literal>"> +<!ENTITY implicit_deps_unchanged "<literal>implicit_deps_unchanged</literal>"> + + + +<!-- + + File and directory names. + +--> + +<!ENTITY build "<filename>build</filename>"> +<!ENTITY Makefile "<filename>Makefile</filename>"> +<!ENTITY Makefiles "<filename>Makefiles</filename>"> +<!ENTITY SConscript "<filename>SConscript</filename>"> +<!ENTITY SConstruct "<filename>SConstruct</filename>"> +<!ENTITY Sconstruct "<filename>Sconstruct</filename>"> +<!ENTITY sconstruct "<filename>sconstruct</filename>"> +<!ENTITY sconsign "<filename>.sconsign</filename>"> +<!ENTITY src "<filename>src</filename>"> + + + +<!-- + + Methods and functions. This includes functions from both + the Build Engine and the Native Python Interface. + +--> + +<!ENTITY Add "<function>Add</function>"> +<!ENTITY AddOptions "<function>AddOptions</function>"> +<!ENTITY Alias "<function>Alias</function>"> +<!ENTITY Aliases "<function>Aliases</function>"> +<!ENTITY Append "<function>Append</function>"> +<!ENTITY BoolOption "<function>BoolOption</function>"> +<!ENTITY Build "<function>Build</function>"> +<!ENTITY CacheDir "<function>CacheDir</function>"> +<!ENTITY Clean "<function>Clean</function>"> +<!ENTITY Clone "<function>Clone</function>"> +<!ENTITY Command "<function>Command</function>"> +<!ENTITY Configure "<function>Configure</function>"> +<!ENTITY Copy "<function>Copy</function>"> +<!ENTITY Default "<function>Default</function>"> +<!ENTITY DefaultRules "<function>DefaultRules</function>"> +<!ENTITY Depends "<function>Depends</function>"> +<!ENTITY Dir "<function>Dir</function>"> +<!ENTITY Entry "<function>Entry</function>"> +<!ENTITY EnumOption "<function>EnumOption</function>"> +<!ENTITY Environment "<function>Environment</function>"> +<!ENTITY Export "<function>Export</function>"> +<!ENTITY File "<function>File</function>"> +<!ENTITY Finish "<function>Finish</function>"> +<!ENTITY GenerateHelpText "<function>GenerateHelpText</function>"> +<!ENTITY Help "<function>Help</function>"> +<!ENTITY Ignore "<function>Ignore</function>"> +<!ENTITY Import "<function>Import</function>"> +<!ENTITY Install "<function>Install</function>"> +<!ENTITY InstallAs "<function>InstallAs</function>"> +<!ENTITY Link "<function>Link</function>"> +<!ENTITY ListOption "<function>ListOption</function>"> +<!ENTITY Local "<function>Local</function>"> +<!ENTITY Module "<function>Module</function>"> +<!ENTITY Objects "<function>Objects</function>"> +<!ENTITY Options "<function>Options</function>"> +<!ENTITY PackageOption "<function>PackageOption</function>"> +<!ENTITY PathOption "<function>PathOption</function>"> +<!ENTITY Precious "<function>Precious</function>"> +<!ENTITY Prepend "<function>Prepend</function>"> +<!ENTITY Replace "<function>Replace</function>"> +<!ENTITY Repository "<function>Repository</function>"> +<!ENTITY Return "<function>Return</function>"> +<!ENTITY RuleSet "<function>RuleSet</function>"> +<!ENTITY Salt "<function>Salt</function>"> +<!ENTITY SetBuildSignatureType "<function>SetBuildSignatureType</function>"> +<!ENTITY SetContentSignatureType "<function>SetContentSignatureType</function>"> +<!ENTITY SourceSignature "<function>SourceSignature</function>"> +<!ENTITY SourceSignatures "<function>SourceSignatures</function>"> +<!ENTITY Split "<function>Split</function>"> +<!ENTITY TargetSignatures "<function>TargetSignatures</function>"> +<!ENTITY Task "<function>Task</function>"> + +<!-- Environment methods --> +<!ENTITY subst "<function>subst</function>"> + +<!-- Configure context functions --> +<!ENTITY Message "<function>Message</function>"> +<!ENTITY Result "<function>Result</function>"> +<!ENTITY CheckCHeader "<function>CheckCHeader</function>"> +<!ENTITY CheckCXXHeader "<function>CheckCXXHeader</function>"> +<!ENTITY CheckFunc "<function>CheckFunc</function>"> +<!ENTITY CheckHeader "<function>CheckHeader</function>"> +<!ENTITY CheckLib "<function>CheckLib</function>"> +<!ENTITY CheckLibWithHeader "<function>CheckLibWithHeader</function>"> +<!ENTITY CheckType "<function>CheckType</function>"> +<!ENTITY TryAction "<function>TryAction</function>"> +<!ENTITY TryBuild "<function>TryBuild</function>"> +<!ENTITY TryCompile "<function>TryCompile</function>"> +<!ENTITY TryLink "<function>TryLink</function>"> +<!ENTITY TryRun "<function>TryRun</function>"> + +<!-- Python functions --> +<!ENTITY str "<function>str</function>"> +<!ENTITY zipfile "<function>zipfile</function>"> + +<!-- Obsolete, but referenced in old documents. --> +<!ENTITY Cache "<function>Cache</function>"> + + + +<!-- + + Global variables. + +--> + +<!ENTITY ARGUMENTS "<varname>ARGUMENTS</varname>"> +<!ENTITY BUILD_TARGETS "<varname>BUILD_TARGETS</varname>"> +<!ENTITY COMMAND_LINE_TARGETS "<varname>COMMAND_LINE_TARGETS</varname>"> +<!ENTITY DEFAULT_TARGETS "<varname>DEFAULT_TARGETS</varname>"> + + + +<!-- + + Construction variables. + +--> + +<!ENTITY BUILDERMAP "<varname>BUILDERMAP</varname>"> +<!ENTITY BUILDERS "<varname>BUILDERS</varname>"> +<!ENTITY CC "<varname>CC</varname>"> +<!ENTITY CCFLAGS "<varname>CCFLAGS</varname>"> +<!ENTITY CCCOM "<varname>CCCOM</varname>"> +<!ENTITY COLOR "<varname>COLOR</varname>"> +<!ENTITY COLORS "<varname>COLORS</varname>"> +<!ENTITY CONFIG "<varname>CONFIG</varname>"> +<!ENTITY CPPDEFINES "<varname>CPPDEFINES</varname>"> +<!ENTITY ENV "<varname>ENV</varname>"> +<!ENTITY JAVACLASSDIR "<varname>JAVACLASSDIR</varname>"> +<!ENTITY LIBDIRPREFIX "<varname>LIBDIRPREFIX</varname>"> +<!ENTITY LIBDIRSUFFIX "<varname>LIBDIRSUFFIX</varname>"> +<!ENTITY LIBLINKPREFIX "<varname>LIBLINKPREFIX</varname>"> +<!ENTITY LIBLINKSUFFIX "<varname>LIBLINKSUFFIX</varname>"> +<!ENTITY LIBPATH "<varname>LIBPATH</varname>"> +<!ENTITY LIBS "<varname>LIBS</varname>"> +<!ENTITY LINK "<varname>LINK</varname>"> +<!ENTITY LINKCOM "<varname>LINKCOM</varname>"> +<!ENTITY LINKFLAGS "<varname>LINKFLAGS</varname>"> +<!ENTITY RELEASE "<varname>RELEASE</varname>"> +<!ENTITY RELEASE_BUILD "<varname>RELEASE_BUILD</varname>"> +<!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>"> +<!ENTITY SCANNERS "<varname>SCANNERS</varname>"> +<!ENTITY TARFLAGS "<varname>TARFLAGS</varname>"> +<!ENTITY TARSUFFIX "<varname>TARSUFFIX</varname>"> + + + +<!-- + + Environment variables. + +--> + +<!ENTITY PATH "<varname>PATH</varname>"> +<!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>"> +<!ENTITY SCONSFLAGS "<varname>SCONSFLAGS</varname>"> + + + +<!-- + + Function and method arguments. + +--> + +<!ENTITY allowed_values "<varname>allowed_values</varname>"> +<!ENTITY build_dir "<varname>build_dir</varname>"> +<!ENTITY map "<varname>map</varname>"> +<!ENTITY ignorecase "<varname>ignorecase</varname>"> +<!ENTITY options "<varname>options</varname>"> +<!ENTITY exports "<varname>exports</varname>"> +<!ENTITY source "<varname>source</varname>"> +<!ENTITY target "<varname>target</varname>"> + + + +<!-- + + Values of function and method arguments. + +--> + +<!ENTITY all "<literal>all</literal>"> +<!ENTITY none "<literal>none</literal>"> + + + +<!-- + + Builder and Scanner objects. + +--> + +<!ENTITY BuildDir "<function>BuildDir</function>"> +<!ENTITY CFile "<function>CFile</function>"> +<!ENTITY CXXFile "<function>CXXFile</function>"> +<!ENTITY DVI "<function>DVI</function>"> +<!ENTITY Jar "<function>Jar</function>"> +<!ENTITY Java "<function>Java</function>"> +<!ENTITY JavaH "<function>JavaH</function>"> +<!ENTITY Library "<function>Library</function>"> +<!ENTITY Object "<function>Object</function>"> +<!ENTITY PCH "<function>PCH</function>"> +<!ENTITY PDF "<function>PDF</function>"> +<!ENTITY PostScript "<function>PostScript</function>"> +<!ENTITY Program "<function>Program</function>"> +<!ENTITY RES "<function>RES</function>"> +<!ENTITY RMIC "<function>RMIC</function>"> +<!ENTITY SharedLibrary "<function>SharedLibrary</function>"> +<!ENTITY SharedObject "<function>SharedObject</function>"> +<!ENTITY StaticLibrary "<function>StaticLibrary</function>"> +<!ENTITY StaticObject "<function>StaticObject</function>"> +<!ENTITY Tar "<function>Tar</function>"> +<!ENTITY Zip "<function>Zip</function>"> + +<!-- Obsolete, but referenced in old documents. --> +<!ENTITY MakeBuilder "<function>Make</function>"> + + + +<!-- + + Terms. Define both singular and plural forms in various + case-sensitive combinations for use in titles, in-line, etc. + +--> + +<!ENTITY buildfunc "<literal>builder function</literal>"> +<!ENTITY builder_method "<literal>builder method</literal>"> + +<!ENTITY Configure_Contexts "<literal>Configure Contexts</literal>"> +<!ENTITY configure_context "<literal>configure context</literal>"> + +<!ENTITY ConsEnv "<literal>Construction Environment</literal>"> +<!ENTITY ConsEnvs "<literal>Construction Environments</literal>"> +<!ENTITY Consenv "<literal>Construction environment</literal>"> +<!ENTITY Consenvs "<literal>Construction environments</literal>"> +<!ENTITY consenv "<literal>construction environment</literal>"> +<!ENTITY consenvs "<literal>construction environments</literal>"> + +<!ENTITY ConsVar "<literal>Construction Variable</literal>"> +<!ENTITY ConsVars "<literal>Construction Variables</literal>"> +<!ENTITY Consvar "<literal>Construction variable</literal>"> +<!ENTITY Consvars "<literal>Construction variables</literal>"> +<!ENTITY consvar "<literal>construction variable</literal>"> +<!ENTITY consvars "<literal>construction variables</literal>"> + +<!ENTITY CPPPATH "<literal>CPPPATH</literal>"> + +<!ENTITY Dictionary "<literal>Dictionary</literal>"> + +<!ENTITY Emitter "<literal>Emitter</literal>"> +<!ENTITY emitter "<literal>emitter</literal>"> +<!ENTITY Generator "<literal>Generator</literal>"> +<!ENTITY generator "<literal>generator</literal>"> + +<!ENTITY Nodes "<literal>Nodes</literal>"> + +<!ENTITY signature "<literal>signature</literal>"> +<!ENTITY buildsignature "<literal>build signature</literal>"> + +<!ENTITY true "<literal>true</literal>"> +<!ENTITY false "<literal>false</literal>"> + +<!ENTITY typedef "<literal>typedef</literal>"> + +<!-- + + File and program names used in examples. + +--> + +<!ENTITY bar "<application>bar</application>"> +<!ENTITY common1_c "<filename>common1.c</filename>"> +<!ENTITY common2_c "<filename>common2.c</filename>"> +<!ENTITY custom_py "<filename>custom.py</filename>"> +<!ENTITY goodbye "<application>goodbye</application>"> +<!ENTITY goodbye_o "<filename>goodbye.o</filename>"> +<!ENTITY goodbye_obj "<filename>goodbye.obj</filename>"> +<!ENTITY file_dll "<filename>file.dll</filename>"> +<!ENTITY file_in "<filename>file.in</filename>"> +<!ENTITY file_lib "<filename>file.lib</filename>"> +<!ENTITY file_o "<filename>file.o</filename>"> +<!ENTITY file_obj "<filename>file.obj</filename>"> +<!ENTITY file_out "<filename>file.out</filename>"> +<!ENTITY foo "<application>foo</application>"> +<!ENTITY foo_o "<filename>foo.o</filename>"> +<!ENTITY foo_obj "<filename>foo.obj</filename>"> +<!ENTITY hello "<application>hello</application>"> +<!ENTITY hello_c "<filename>hello.c</filename>"> +<!ENTITY hello_exe "<filename>hello.exe</filename>"> +<!ENTITY hello_h "<filename>hello.h</filename>"> +<!ENTITY hello_o "<filename>hello.o</filename>"> +<!ENTITY hello_obj "<filename>hello.obj</filename>"> +<!ENTITY libfile_a "<filename>libfile_a</filename>"> +<!ENTITY libfile_so "<filename>libfile_so</filename>"> +<!ENTITY new_hello "<application>new_hello</application>"> +<!ENTITY new_hello_exe "<application>new_hello.exe</application>"> +<!ENTITY prog "<filename>prog</filename>"> +<!ENTITY prog1 "<filename>prog1</filename>"> +<!ENTITY prog2 "<filename>prog2</filename>"> +<!ENTITY prog_c "<filename>prog.c</filename>"> +<!ENTITY prog_exe "<filename>prog.exe</filename>"> +<!ENTITY stdio_h "<filename>stdio.h</filename>"> + +<!-- + + Punctuation. + +--> + +<!ENTITY plus "<literal>+</literal>"> +<!ENTITY hash "<literal>#</literal>"> + +<!-- + + Mailing lists + +--> + +<!ENTITY scons-announce "<literal>announce@scons.tigris.org</literal>"> +<!ENTITY scons-devel "<literal>dev@scons.tigris.org</literal>"> +<!ENTITY scons-users "<literal>users@scons.tigris.org</literal>"> diff --git a/doc/python10/sig.eps b/doc/python10/sig.eps new file mode 100644 index 0000000..26aabaa --- /dev/null +++ b/doc/python10/sig.eps @@ -0,0 +1,147 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: build/doc/python10/sig.fig +%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d +%%CreationDate: Sun Jan 2 01:21:05 2005 +%%For: knight@casablanca.home.baldmt.com (Steven Knight) +%%BoundingBox: 0 0 308 128 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 128 moveto 0 0 lineto 308 0 lineto 308 128 lineto closepath clip newpath +-71.3 288.7 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit + 0.06000 0.06000 sc +% +% Fig objects follow +% +% Polyline +7.500 slw +n 1200 3000 m 2700 3000 l 2700 3600 l 1200 3600 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +1950 3375 m +gs 1 -1 sc (Taskmaster) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 3300 4200 m 4500 4200 l 4500 4800 l 3300 4800 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +3900 4575 m +gs 1 -1 sc (MD5) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 5100 4200 m 6300 4200 l 6300 4800 l 5100 4800 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +5700 4575 m +gs 1 -1 sc (TStamp) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 4200 3000 m 5400 3000 l 5400 3600 l 4200 3600 l + cp gs col0 s gr +/Times-Roman ff 240.00 scf sf +4800 3375 m +gs 1 -1 sc (Sig) dup sw pop 2 div neg 0 rm col0 sh gr +% Polyline +n 2700 3300 m 2775 3340 l 2850 3300 l 2775 3260 l + cp gs col0 s gr +% Polyline +n 4800 3600 m 4725 3750 l 4875 3750 l + cp gs col0 s gr +% Polyline +n 3900 4200 m 3900 3900 l 5700 3900 l + 5700 4200 l gs col0 s gr +% Polyline +n 4800 3750 m + 4800 3900 l gs col0 s gr +% Polyline +gs clippath +4215 3330 m 4215 3270 l 4064 3270 l 4184 3300 l 4064 3330 l cp +eoclip +n 2850 3300 m + 4200 3300 l gs col0 s gr gr + +% arrowhead +n 4064 3330 m 4184 3300 l 4064 3270 l 4064 3330 l cp gs 0.00 setgray ef gr col0 s +% Polyline + [60] 0 sd +n 1950 3000 m + 1950 2700 l gs col0 s gr [] 0 sd +% Polyline + [60] 0 sd +n 4800 3000 m + 4800 2700 l gs col0 s gr [] 0 sd +$F2psEnd +rs diff --git a/doc/python10/sig.fig b/doc/python10/sig.fig new file mode 100644 index 0000000..823d59e --- /dev/null +++ b/doc/python10/sig.fig @@ -0,0 +1,44 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 1200 3000 2700 3600 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1200 3000 2700 3000 2700 3600 1200 3600 1200 3000 +4 1 0 50 0 0 16 0.0000 4 165 1125 1950 3375 Taskmaster\001 +-6 +6 3300 4200 4500 4800 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3300 4200 4500 4200 4500 4800 3300 4800 3300 4200 +4 1 0 50 0 0 16 0.0000 4 165 525 3900 4575 MD5\001 +-6 +6 5100 4200 6300 4800 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5100 4200 6300 4200 6300 4800 5100 4800 5100 4200 +4 1 0 50 0 0 16 0.0000 4 225 780 5700 4575 TStamp\001 +-6 +6 4200 3000 5400 3600 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4200 3000 5400 3000 5400 3600 4200 3600 4200 3000 +4 1 0 50 0 0 16 0.0000 4 225 330 4800 3375 Sig\001 +-6 +2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5 + 2700 3300 2775 3340 2850 3300 2775 3260 2700 3300 +2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 + 4800 3600 4725 3750 4875 3750 4800 3600 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 4 + 3900 4200 3900 3900 5700 3900 5700 4200 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 4800 3750 4800 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2850 3300 4200 3300 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 1950 3000 1950 2700 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 4800 3000 4800 2700 diff --git a/doc/python10/sig.jpg b/doc/python10/sig.jpg Binary files differnew file mode 100644 index 0000000..0c7e0df --- /dev/null +++ b/doc/python10/sig.jpg diff --git a/doc/reference/Alias.xml b/doc/reference/Alias.xml new file mode 100644 index 0000000..b87967d --- /dev/null +++ b/doc/reference/Alias.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &Alias; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/CFile.xml b/doc/reference/CFile.xml new file mode 100644 index 0000000..f76c390 --- /dev/null +++ b/doc/reference/CFile.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &CFile; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/CXXFile.xml b/doc/reference/CXXFile.xml new file mode 100644 index 0000000..c1c038e --- /dev/null +++ b/doc/reference/CXXFile.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &CXXFile; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/Command.xml b/doc/reference/Command.xml new file mode 100644 index 0000000..abb3a58 --- /dev/null +++ b/doc/reference/Command.xml @@ -0,0 +1,73 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head2 The C<Command> method + +The C<Command> method is a catchall method which can be used to arrange for +any build action to be executed to update the target. For this command, a +target file and list of inputs is provided. In addition, a build action +is specified as the last argument. The build action is typically a +command line or lines, but may also contain Perl code to be executed; +see the section above on build actions for details. + +The C<Command> method is called as follows: + + Command $env <target>, <inputs>, <build action>; + +The target is made dependent upon the list of input files specified, and the +inputs must be built successfully or Cons will not attempt to build the +target. + +To specify a command with multiple targets, you can specify a reference to a +list of targets. In Perl, a list reference can be created by enclosing a +list in square brackets. Hence the following command: + + Command $env ['foo.h', 'foo.c'], 'foo.template', q( + gen %1 + ); + +could be used in a case where the command C<gen> creates two files, both +F<foo.h> and F<foo.c>. + +--> + + <para> + + X + + </para> + + <section> + <title>The &Command; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/Install.xml b/doc/reference/Install.xml new file mode 100644 index 0000000..2d06e3b --- /dev/null +++ b/doc/reference/Install.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &Install; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/InstallAs.xml b/doc/reference/InstallAs.xml new file mode 100644 index 0000000..ed8cb78 --- /dev/null +++ b/doc/reference/InstallAs.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &InstallAs; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/Library.xml b/doc/reference/Library.xml new file mode 100644 index 0000000..19a3e96 --- /dev/null +++ b/doc/reference/Library.xml @@ -0,0 +1,152 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head2 The C<Library> method + +The C<Library> method arranges to create the specified library from the +specified object files. It is invoked as follows: + + Library $env <library name>, <source or object files>; + +The library name will have the value of the C<SUFLIB> construction +variable appended (by default, C<.lib> on Win32 systems, C<.a> on Unix +systems) if the suffix is not already present. + +Source files may be specified in place of objects files-,-the C<Objects> +method will be invoked to arrange the conversion of all the files into +object files, and hence all the observations about the C<Objects> method, +above, apply to this method also. + +The actual creation of the library will be handled by an external +command which results from expanding the C<ARCOM> construction variable, +with C<%E<lt>> set to the library members (in the order presented), +and C<%E<gt>> to the library to be created. (See the section above +on construction variable expansion for details.) The user may set +variables in the construction environment which will affect the +operation of the command. These include C<AR>, the archive program +to use, C<ARFLAGS>, which can be used to modify the flags given to +the program specified by C<AR>, and C<RANLIB>, the name of a archive +index generation program, if needed (if the particular need does not +require the latter functionality, then C<ARCOM> must be redefined to not +reference C<RANLIB>). + +The C<Library> method allows the same library to be specified in multiple +method invocations. All of the contributing objects from all the invocations +(which may be from different directories) are combined and generated by a +single archive command. Note, however, that if you prune a build so that +only part of a library is specified, then only that part of the library will +be generated (the rest will disappear!). + +--> + + <section> + <title>Linking With a Library</title> + + <programlisting> + env = Environment(CC = 'gcc', + LIBS = 'world') + env.Program('hello.c') + </programlisting> + + <literallayout> + % <userinput>scons</userinput> + gcc -c hello.c -o hello.o + gcc -c world.c -o world.o + gcc -o hello hello.o -lworld + </literallayout> + + </section> + + <section> + <title>Creating a Library</title> + + <programlisting> + env = Environment(CC = 'gcc', + LIBS = 'world') + env.Program('hello.c') + env.Library('world.c') + </programlisting> + + <literallayout> + % <userinput>scons</userinput> + gcc -c hello.c -o hello.o + gcc -c world.c -o world.o + ar r libworld.a world.o + ar: creating libworld.a + ranlib libworld.a + gcc -o hello hello.o libworld.a + </literallayout> + + </section> + +<!-- + +A key simplification of Cons is the idea of a B<construction environment>. A +construction environment is an B<object> characterized by a set of key/value +pairs and a set of B<methods>. In order to tell Cons how to build something, +you invoke the appropriate method via an appropriate construction +environment. Consider the following example: + + + + $env = new cons( + CC => 'gcc', + LIBS => 'libworld.a' + ); + + Program $env 'hello', 'hello.c'; + +In this case, rather than using the default construction environment, as is, +we have overridden the value of C<CC> so that the GNU C Compiler equivalent +is used, instead. Since this version of B<Hello, World!> requires a library, +F<libworld.a>, we have specified that any program linked in this environment +should be linked with that library. If the library exists already, well and +good, but if not, then we'll also have to include the statement: + + + + Library $env 'libworld', 'world.c'; + +Now if you type C<cons hello>, the library will be built before the program +is linked, and, of course, C<gcc> will be used to compile both modules: + + + + % cons hello + +--> + + <section> + <title>The &Library; Builder</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/MANIFEST b/doc/reference/MANIFEST new file mode 100644 index 0000000..438aada --- /dev/null +++ b/doc/reference/MANIFEST @@ -0,0 +1,21 @@ +Alias.xml +CFile.xml +CXXFile.xml +Command.xml +Install.xml +InstallAs.xml +Library.xml +Object.xml +PCH.xml +PDF.xml +PostScript.xml +Program.xml +RES.xml +SharedLibrary.xml +SharedObject.xml +StaticLibrary.xml +StaticObject.xml +copyright.xml +errors.xml +main.xml +preface.xml diff --git a/doc/reference/Object.xml b/doc/reference/Object.xml new file mode 100644 index 0000000..9e887d8 --- /dev/null +++ b/doc/reference/Object.xml @@ -0,0 +1,71 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head2 The C<Objects> method + +The C<Objects> method arranges to create the object files that correspond to +the specified source files. It is invoked as shown below: + + @files = Objects $env <source or object files>; + +Under Unix, source files ending in F<.s> and F<.c> are currently +supported, and will be compiled into a name of the same file ending +in F<.o>. By default, all files are created by invoking the external +command which results from expanding the C<CCCOM> construction variable, +with C<%E<lt>> and C<%E<gt>> set to the source and object files, +respectively. (See the section above on construction variable expansion +for details). The variable C<CPPPATH> is also used when scanning source +files for dependencies. This is a colon separated list of pathnames, and +is also used to create the construction variable C<_IFLAGS,> which will +contain the appropriate list of -C<I> options for the compilation. Any +relative pathnames in C<CPPPATH> is interpreted relative to the +directory in which the associated construction environment was created +(absolute and top-relative names may also be used). This variable is +used by C<CCCOM>. The behavior of this command can be modified by +changing any of the variables which are interpolated into C<CCCOM>, such +as C<CC>, C<CFLAGS>, and, indirectly, C<CPPPATH>. It's also possible +to replace the value of C<CCCOM>, itself. As a convenience, this file +returns the list of object filenames. + +--> + + <para> + + X + + </para> + + <section> + <title>The &Object; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/PCH.xml b/doc/reference/PCH.xml new file mode 100644 index 0000000..b2a4d75 --- /dev/null +++ b/doc/reference/PCH.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &PCH; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/PDF.xml b/doc/reference/PDF.xml new file mode 100644 index 0000000..b3a25dc --- /dev/null +++ b/doc/reference/PDF.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &PDF; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/PostScript.xml b/doc/reference/PostScript.xml new file mode 100644 index 0000000..f5a6579 --- /dev/null +++ b/doc/reference/PostScript.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &PostScript; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/Program.xml b/doc/reference/Program.xml new file mode 100644 index 0000000..30f90d2 --- /dev/null +++ b/doc/reference/Program.xml @@ -0,0 +1,77 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head2 The C<Program> method + +The C<Program> method arranges to link the specified program with the +specified object files. It is invoked in the following manner: + + Program $env <program name>, <source or object files>; + +The program name will have the value of the C<SUFEXE> construction +variable appended (by default, C<.exe> on Win32 systems, nothing on Unix +systems) if the suffix is not already present. + +Source files may be specified in place of objects files-,-the C<Objects> +method will be invoked to arrange the conversion of all the files into +object files, and hence all the observations about the C<Objects> method, +above, apply to this method also. + +The actual linking of the program will be handled by an external command +which results from expanding the C<LINKCOM> construction variable, with +C<%E<lt>> set to the object files to be linked (in the order presented), +and C<%E<gt>> set to the target. (See the section above on construction +variable expansion for details.) The user may set additional variables +in the construction environment, including C<LINK>, to define which +program to use for linking, C<LIBPATH>, a colon-separated list of +library search paths, for use with library specifications of the form +I<-llib>, and C<LIBS>, specifying the list of libraries to link against +(in either I<-llib> form or just as pathnames. Relative pathnames in +both C<LIBPATH> and C<LIBS> are interpreted relative to the directory +in which the associated construction environment is created (absolute +and top-relative names may also be used). Cons automatically sets up +dependencies on any libraries mentioned in C<LIBS>: those libraries will +be built before the command is linked. + +--> + + <para> + + X + + </para> + + <section> + <title>The &Program; Builder</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/RES.xml b/doc/reference/RES.xml new file mode 100644 index 0000000..15c0aea --- /dev/null +++ b/doc/reference/RES.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &RES; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/SharedLibrary.xml b/doc/reference/SharedLibrary.xml new file mode 100644 index 0000000..603dab1 --- /dev/null +++ b/doc/reference/SharedLibrary.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &SharedLibrary; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/SharedObject.xml b/doc/reference/SharedObject.xml new file mode 100644 index 0000000..0860769 --- /dev/null +++ b/doc/reference/SharedObject.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &SharedObject; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/StaticLibrary.xml b/doc/reference/StaticLibrary.xml new file mode 100644 index 0000000..ea7ae5b --- /dev/null +++ b/doc/reference/StaticLibrary.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &StaticLibrary; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/StaticObject.xml b/doc/reference/StaticObject.xml new file mode 100644 index 0000000..ff8dae8 --- /dev/null +++ b/doc/reference/StaticObject.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>The &StaticObject; Method</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/copyright.xml b/doc/reference/copyright.xml new file mode 100644 index 0000000..7f6059c --- /dev/null +++ b/doc/reference/copyright.xml @@ -0,0 +1,32 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<blockquote> + <para> + + SCons User's Guide Copyright (c) 2003 Steven Knight + + </para> +</blockquote> diff --git a/doc/reference/errors.xml b/doc/reference/errors.xml new file mode 100644 index 0000000..448777f --- /dev/null +++ b/doc/reference/errors.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>X</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/reference/main.xml b/doc/reference/main.xml new file mode 100644 index 0000000..ed122f6 --- /dev/null +++ b/doc/reference/main.xml @@ -0,0 +1,207 @@ +<?xml version="1.0"?> + +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ + + <!ENTITY % version SYSTEM "../version.xml"> + %version; + + <!ENTITY % scons SYSTEM "../scons.mod"> + %scons; + + <!-- Builders --> + <!ENTITY Alias_file SYSTEM "Alias.xml"> + <!ENTITY CFile_file SYSTEM "CFile.xml"> + <!ENTITY CXXFile_file SYSTEM "CXXFile.xml"> + <!ENTITY Command_file SYSTEM "Command.xml"> + <!ENTITY Install_file SYSTEM "Install.xml"> + <!ENTITY InstallAs_file SYSTEM "InstallAs.xml"> + <!ENTITY Library_file SYSTEM "Library.xml"> + <!ENTITY Object_file SYSTEM "Object.xml"> + <!ENTITY PCH_file SYSTEM "PCH.xml"> + <!ENTITY PDF_file SYSTEM "PDF.xml"> + <!ENTITY PostScript_file SYSTEM "PostScript.xml"> + <!ENTITY Program_file SYSTEM "Program.xml"> + <!ENTITY RES_file SYSTEM "RES.xml"> + <!ENTITY SharedLibrary_file SYSTEM "SharedLibrary.xml"> + <!ENTITY SharedObject_file SYSTEM "SharedObject.xml"> + <!ENTITY StaticLibrary_file SYSTEM "StaticLibrary.xml"> + <!ENTITY StaticObject_file SYSTEM "StaticObject.xml"> + + <!-- Construction Variables --> + + <!ENTITY copyright SYSTEM "copyright.xml"> + <!ENTITY errors SYSTEM "errors.xml"> + <!ENTITY preface SYSTEM "preface.xml"> + +]> + +<book> + <bookinfo> + <title>SCons Reference Manual &buildversion;</title> + + <author> + <firstname>Steven</firstname> + <surname>Knight</surname> + </author> + + <edition>Revision &buildrevision; (&builddate;)</edition> + + <pubdate>2003</pubdate> + + <copyright> + <year>2003</year> + <holder>Steven Knight</holder> + </copyright> + + <legalnotice> + ©right; + </legalnotice> + + <releaseinfo>version &buildversion;</releaseinfo> + + </bookinfo> + + <chapter id="chap-preface"> + <title>Preface</title> + &preface; + </chapter> + + <chapter id="chap-builders"> + <title>Builder Reference</title> + + <section id="sect-Alias"> + <title>The Alias Builder</title> + &Alias_file; + </section> + + <section id="sect-CFile"> + <title>The CFile Builder</title> + &CFile_file; + </section> + + <section id="sect-Command"> + <title>The Command Builder</title> + &Command_file; + </section> + + <section id="sect-CXXFile"> + <title>The CXXFile Builder</title> + &CXXFile_file; + </section> + + <section id="sect-Install"> + <title>The Install Builder</title> + &Install_file; + </section> + + <section id="sect-InstallAs"> + <title>The InstallAs Builder</title> + &InstallAs_file; + </section> + + <section id="sect-Library"> + <title>The Library Builder</title> + &Library_file; + </section> + + <section id="sect-Object"> + <title>The Object Builder</title> + &Object_file; + </section> + + <section id="sect-PCH"> + <title>The PCH Builder</title> + &PCH_file; + </section> + + <section id="sect-PDF"> + <title>The PDF Builder</title> + &PDF_file; + </section> + + <section id="sect-PostScript"> + <title>The PDF Builder</title> + &PostScript_file; + </section> + + <section id="sect-Program"> + <title>The Program Builder</title> + &Program_file; + </section> + + <section id="sect-RES"> + <title>The RES Builder</title> + &RES_file; + </section> + + <section id="sect-SharedLibrary"> + <title>The SharedLibrary Builder</title> + &SharedLibrary_file; + </section> + + <section id="sect-SharedObject"> + <title>The SharedObject Builder</title> + &SharedObject_file; + </section> + + <section id="sect-StaticLibrary"> + <title>The StaticLibrary Builder</title> + &StaticLibrary_file; + </section> + + <section id="sect-StaticObject"> + <title>The StaticObject Builder</title> + &StaticObject_file; + </section> + + </chapter> + + <chapter id="chap-variables"> + <title>&ConsVar; Reference</title> + + <section id="sect-AR"> + <title>AR</title> + + <para> + + X + + </para> + + </section> + + </chapter> + + <appendix id="chap-errors"> + <title>Errors Generated by &SCons;</title> + &errors; + </appendix> + +</book> diff --git a/doc/reference/preface.xml b/doc/reference/preface.xml new file mode 100644 index 0000000..82ea44a --- /dev/null +++ b/doc/reference/preface.xml @@ -0,0 +1,85 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + X + + </para> + + <section> + <title>Why &SCons;?</title> + + <para> + + X + + </para> + + </section> + + <section> + <title>History</title> + + <para> + + X + + </para> + + </section> + + <section> + <title>Conventions</title> + + <para> + + X + + </para> + + </section> + + <section> + <title>Acknowledgements</title> + + <para> + + X + + </para> + + </section> + + <section> + <title>Contact</title> + + <para> + + X + + </para> + + </section> diff --git a/doc/scons.mod b/doc/scons.mod new file mode 100644 index 0000000..8ac58ca --- /dev/null +++ b/doc/scons.mod @@ -0,0 +1,521 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + An SCons-specific DTD module, for use with SCons DocBook + documentation, that contains names, phrases, acronyms, etc. used + throughout the SCons documentation. + +--> + + + +<!-- + + Other applications that we reference. + +--> + +<!ENTITY Aegis "<application>Aegis</application>"> +<!ENTITY Ant "<application>Ant</application>"> +<!ENTITY ar "<application>ar</application>"> +<!ENTITY as "<application>as</application>"> +<!ENTITY Autoconf "<application>Autoconf</application>"> +<!ENTITY Automake "<application>Automake</application>"> +<!ENTITY bison "<application>bison</application>"> +<!ENTITY cc "<application>cc</application>"> +<!ENTITY Cons "<application>Cons</application>"> +<!ENTITY cp "<application>cp</application>"> +<!ENTITY csh "<application>csh</application>"> +<!ENTITY f77 "<application>f77</application>"> +<!ENTITY f90 "<application>f90</application>"> +<!ENTITY f95 "<application>f95</application>"> +<!ENTITY gas "<application>gas</application>"> +<!ENTITY gcc "<application>gcc</application>"> +<!ENTITY g77 "<application>g77</application>"> +<!ENTITY gXX "<application>gXX</application>"> +<!ENTITY Jam "<application>Jam</application>"> +<!ENTITY jar "<application>jar</application>"> +<!ENTITY javac "<application>javac</application>"> +<!ENTITY javah "<application>javah</application>"> +<!ENTITY latex "<application>latex</application>"> +<!ENTITY lex "<application>lex</application>"> +<!ENTITY m4 "<application>m4</application>"> +<!ENTITY Make "<application>Make</application>"> +<!ENTITY Makepp "<application>Make++</application>"> +<!ENTITY pdflatex "<application>pdflatex</application>"> +<!ENTITY pdftex "<application>pdftex</application>"> +<!ENTITY Python "<application>Python</application>"> +<!ENTITY ranlib "<application>ranlib</application>"> +<!ENTITY rmic "<application>rmic</application>"> +<!ENTITY SCons "<application>SCons</application>"> +<!ENTITY ScCons "<application>ScCons</application>"> +<!ENTITY swig "<application>swig</application>"> +<!ENTITY tar "<application>tar</application>"> +<!ENTITY tex "<application>tex</application>"> +<!ENTITY touch "<application>touch</application>"> +<!ENTITY yacc "<application>yacc</application>"> +<!ENTITY zip "<application>zip</application>"> + + +<!-- + + Classes. + +--> + +<!ENTITY Action "<classname>Action</classname>"> +<!ENTITY ActionBase "<classname>ActionBase</classname>"> +<!ENTITY CommandAction "<classname>CommandAction</classname>"> +<!ENTITY FunctionAction "<classname>FunctionAction</classname>"> +<!ENTITY ListAction "<classname>ListAction</classname>"> +<!ENTITY Builder "<classname>Builder</classname>"> +<!ENTITY BuilderBase "<classname>BuilderBase</classname>"> +<!ENTITY CompositeBuilder "<classname>CompositeBuilder</classname>"> +<!ENTITY MultiStepBuilder "<classname>MultiStepBuilder</classname>"> +<!ENTITY Job "<classname>Job</classname>"> +<!ENTITY Jobs "<classname>Jobs</classname>"> +<!ENTITY Serial "<classname>Serial</classname>"> +<!ENTITY Parallel "<classname>Parallel</classname>"> +<!ENTITY Node "<classname>Node</classname>"> +<!ENTITY Node_FS "<classname>Node.FS</classname>"> +<!ENTITY Scanner "<classname>Scanner</classname>"> +<!ENTITY Sig "<classname>Sig</classname>"> +<!ENTITY Signature "<classname>Signature</classname>"> +<!ENTITY Taskmaster "<classname>Taskmaster</classname>"> +<!ENTITY TimeStamp "<classname>TimeStamp</classname>"> +<!ENTITY Walker "<classname>Walker</classname>"> +<!ENTITY Wrapper "<classname>Wrapper</classname>"> + + + +<!-- + + Options, command-line. + +--> + +<!ENTITY config "<literal>--config</literal>"> +<!ENTITY debug-explain "<literal>--debug=explain</literal>"> +<!ENTITY debug-findlibs "<literal>--debug=findlibs</literal>"> +<!ENTITY debug-includes "<literal>--debug=includes</literal>"> +<!ENTITY debug-presub "<literal>--debug=presub</literal>"> +<!ENTITY debug-stacktrace "<literal>--debug=stacktrace</literal>"> +<!ENTITY implicit-cache "<literal>--implicit-cache</literal>"> +<!ENTITY implicit-deps-changed "<literal>--implicit-deps-changed</literal>"> +<!ENTITY implicit-deps-unchanged "<literal>--implicit-deps-unchanged</literal>"> +<!ENTITY profile "<literal>--profile</literal>"> +<!ENTITY taskmastertrace "<literal>--taskmastertrace</literal>"> +<!ENTITY tree "<literal>--tree</literal>"> +<!ENTITY Q "<literal>-Q</literal>"> + +<!-- + + Options, SConscript-settable. + +--> + +<!ENTITY implicit_cache "<literal>implicit_cache</literal>"> +<!ENTITY implicit_deps_changed "<literal>implicit_deps_changed</literal>"> +<!ENTITY implicit_deps_unchanged "<literal>implicit_deps_unchanged</literal>"> + + + +<!-- + + File and directory names. + +--> + +<!ENTITY build "<filename>build</filename>"> +<!ENTITY Makefile "<filename>Makefile</filename>"> +<!ENTITY Makefiles "<filename>Makefiles</filename>"> +<!ENTITY scons "<filename>scons</filename>"> +<!ENTITY SConscript "<filename>SConscript</filename>"> +<!ENTITY SConstruct "<filename>SConstruct</filename>"> +<!ENTITY Sconstruct "<filename>Sconstruct</filename>"> +<!ENTITY sconstruct "<filename>sconstruct</filename>"> +<!ENTITY sconsign "<filename>.sconsign</filename>"> +<!ENTITY src "<filename>src</filename>"> + + + +<!-- + + Methods and functions. This includes functions from both + the Build Engine and the Native Python Interface. + +--> + +<!ENTITY Add "<function>Add</function>"> +<!ENTITY AddMethod "<function>AddMethod</function>"> +<!ENTITY AddPostAction "<function>AddPostAction</function>"> +<!ENTITY AddPreAction "<function>AddPreAction</function>"> +<!ENTITY AddOption "<function>AddOption</function>"> +<!ENTITY AddOptions "<function>AddOptions</function>"> +<!ENTITY AddVariables "<function>AddVariables</function>"> +<!ENTITY Alias "<function>Alias</function>"> +<!ENTITY Aliases "<function>Aliases</function>"> +<!ENTITY AlwaysBuild "<function>AlwaysBuild</function>"> +<!ENTITY Append "<function>Append</function>"> +<!ENTITY AppendENVPath "<function>AppendENVPath</function>"> +<!ENTITY AppendUnique "<function>AppendUnique</function>"> +<!ENTITY BoolOption "<function>BoolOption</function>"> +<!ENTITY BoolVariable "<function>BoolVariable</function>"> +<!ENTITY Build "<function>Build</function>"> +<!ENTITY CacheDir "<function>CacheDir</function>"> +<!ENTITY Chmod "<function>Chmod</function>"> +<!ENTITY Clean "<function>Clean</function>"> +<!ENTITY Clone "<function>Clone</function>"> +<!ENTITY Command "<function>Command</function>"> +<!ENTITY Configure "<function>Configure</function>"> +<!ENTITY Copy "<function>Copy</function>"> +<!ENTITY Decider "<function>Decider</function>"> +<!ENTITY Default "<function>Default</function>"> +<!ENTITY DefaultEnvironment "<function>DefaultEnvironment</function>"> +<!ENTITY DefaultRules "<function>DefaultRules</function>"> +<!ENTITY Delete "<function>Delete</function>"> +<!ENTITY Depends "<function>Depends</function>"> +<!ENTITY Dir "<function>Dir</function>"> +<!ENTITY Dump "<function>Dump</function>"> +<!ENTITY Entry "<function>Entry</function>"> +<!ENTITY EnumOption "<function>EnumOption</function>"> +<!ENTITY EnumVariable "<function>EnumVariable</function>"> +<!ENTITY EnsurePythonVersion "<function>EnsurePythonVersion</function>"> +<!ENTITY EnsureSConsVersion "<function>EnsureSConsVersion</function>"> +<!ENTITY Environment "<function>Environment</function>"> +<!ENTITY Execute "<function>Execute</function>"> +<!ENTITY Exit "<function>Exit</function>"> +<!ENTITY Export "<function>Export</function>"> +<!ENTITY File "<function>File</function>"> +<!ENTITY FindFile "<function>FindFile</function>"> +<!ENTITY FindInstalledFiles "<function>FindInstalledFiles</function>"> +<!ENTITY Finish "<function>Finish</function>"> +<!ENTITY Flatten "<function>Flatten</function>"> +<!ENTITY GenerateHelpText "<function>GenerateHelpText</function>"> +<!ENTITY GetBuildFailures "<function>GetBuildFailures</function>"> +<!ENTITY GetLaunchDir "<function>GetLaunchDir</function>"> +<!ENTITY GetOption "<function>GetOption</function>"> +<!ENTITY Glob "<function>Glob</function>"> +<!ENTITY Help "<function>Help</function>"> +<!ENTITY Ignore "<function>Ignore</function>"> +<!ENTITY Import "<function>Import</function>"> +<!ENTITY Install "<function>Install</function>"> +<!ENTITY InstallAs "<function>InstallAs</function>"> +<!ENTITY Link "<function>Link</function>"> +<!ENTITY ListOption "<function>ListOption</function>"> +<!ENTITY ListVariable "<function>ListVariable</function>"> +<!ENTITY Local "<function>Local</function>"> +<!ENTITY MergeFlags "<function>MergeFlags</function>"> +<!ENTITY Mkdir "<function>Mkdir</function>"> +<!ENTITY Module "<function>Module</function>"> +<!ENTITY Move "<function>Move</function>"> +<!ENTITY NoClean "<function>NoClean</function>"> +<!ENTITY NoCache "<function>NoCache</function>"> +<!ENTITY Objects "<function>Objects</function>"> +<!ENTITY Options "<function>Options</function>"> +<!ENTITY Variables "<function>Variables</function>"> +<!ENTITY PackageOption "<function>PackageOption</function>"> +<!ENTITY PackageVariable "<function>PackageVariable</function>"> +<!ENTITY ParseConfig "<function>ParseConfig</function>"> +<!ENTITY ParseDepends "<function>ParseDepends</function>"> +<!ENTITY ParseFlags "<function>ParseFlags</function>"> +<!ENTITY PathOption "<function>PathOption</function>"> +<!ENTITY PathOption_PathAccept "<function>PathOption.PathAccept</function>"> +<!ENTITY PathOption_PathExists "<function>PathOption.PathExists</function>"> +<!ENTITY PathOption_PathIsDir "<function>PathOption.PathIsDir</function>"> +<!ENTITY PathOption_PathIsDirCreate "<function>PathOption.PathIsDirCreate</function>"> +<!ENTITY PathOption_PathIsFile "<function>PathOption.PathIsFile</function>"> +<!ENTITY PathVariable "<function>PathVariable</function>"> +<!ENTITY PathVariable_PathAccept "<function>PathVariable.PathAccept</function>"> +<!ENTITY PathVariable_PathExists "<function>PathVariable.PathExists</function>"> +<!ENTITY PathVariable_PathIsDir "<function>PathVariable.PathIsDir</function>"> +<!ENTITY PathVariable_PathIsDirCreate "<function>PathVariable.PathIsDirCreate</function>"> +<!ENTITY PathVariable_PathIsFile "<function>PathVariable.PathIsFile</function>"> +<!ENTITY Precious "<function>Precious</function>"> +<!ENTITY Prepend "<function>Prepend</function>"> +<!ENTITY PrependENVPath "<function>PrependENVPath</function>"> +<!ENTITY PrependUnique "<function>PrependUnique</function>"> +<!ENTITY Progress "<function>Progress</function>"> +<!ENTITY Replace "<function>Replace</function>"> +<!ENTITY Repository "<function>Repository</function>"> +<!ENTITY Requires "<function>Requires</function>"> +<!ENTITY Return "<function>Return</function>"> +<!ENTITY RuleSet "<function>RuleSet</function>"> +<!ENTITY Salt "<function>Salt</function>"> +<!ENTITY SetBuildSignatureType "<function>SetBuildSignatureType</function>"> +<!ENTITY SetContentSignatureType "<function>SetContentSignatureType</function>"> +<!ENTITY SetDefault "<function>SetDefault</function>"> +<!ENTITY SetOption "<function>SetOption</function>"> +<!ENTITY SideEffect "<function>SideEffect</function>"> +<!ENTITY SourceSignature "<function>SourceSignature</function>"> +<!ENTITY SourceSignatures "<function>SourceSignatures</function>"> +<!ENTITY Split "<function>Split</function>"> +<!ENTITY Tag "<function>Tag</function>"> +<!ENTITY TargetSignatures "<function>TargetSignatures</function>"> +<!ENTITY Task "<function>Task</function>"> +<!ENTITY Touch "<function>Touch</function>"> +<!ENTITY UnknownOptions "<function>UnknownOptions</function>"> +<!ENTITY UnknownVariables "<function>UnknownVariables</function>"> + +<!-- Environment methods --> +<!ENTITY subst "<function>subst</function>"> + +<!-- Configure context functions --> +<!ENTITY Message "<function>Message</function>"> +<!ENTITY Result "<function>Result</function>"> +<!ENTITY CheckCHeader "<function>CheckCHeader</function>"> +<!ENTITY CheckCXXHeader "<function>CheckCXXHeader</function>"> +<!ENTITY CheckFunc "<function>CheckFunc</function>"> +<!ENTITY CheckHeader "<function>CheckHeader</function>"> +<!ENTITY CheckLib "<function>CheckLib</function>"> +<!ENTITY CheckLibWithHeader "<function>CheckLibWithHeader</function>"> +<!ENTITY CheckType "<function>CheckType</function>"> +<!ENTITY TryAction "<function>TryAction</function>"> +<!ENTITY TryBuild "<function>TryBuild</function>"> +<!ENTITY TryCompile "<function>TryCompile</function>"> +<!ENTITY TryLink "<function>TryLink</function>"> +<!ENTITY TryRun "<function>TryRun</function>"> + + +<!-- Python functions --> +<!ENTITY str "<function>str</function>"> +<!ENTITY zipfile "<function>zipfile</function>"> + +<!-- Obsolete, but referenced in old documents. --> +<!ENTITY Cache "<function>Cache</function>"> + + + +<!-- + + Global variables. + +--> + +<!ENTITY ARGLIST "<varname>ARGLIST</varname>"> +<!ENTITY ARGUMENTS "<varname>ARGUMENTS</varname>"> +<!ENTITY BUILD_TARGETS "<varname>BUILD_TARGETS</varname>"> +<!ENTITY COMMAND_LINE_TARGETS "<varname>COMMAND_LINE_TARGETS</varname>"> +<!ENTITY DEFAULT_TARGETS "<varname>DEFAULT_TARGETS</varname>"> + + + +<!-- + + Construction variables. + +--> + +<!ENTITY BUILDERMAP "<varname>BUILDERMAP</varname>"> +<!ENTITY COLOR "<varname>COLOR</varname>"> +<!ENTITY COLORS "<varname>COLORS</varname>"> +<!ENTITY CONFIG "<varname>CONFIG</varname>"> +<!ENTITY CPPDEFINES "<varname>CPPDEFINES</varname>"> +<!ENTITY RELEASE "<varname>RELEASE</varname>"> +<!ENTITY RELEASE_BUILD "<varname>RELEASE_BUILD</varname>"> +<!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>"> +<!ENTITY TARFLAGS "<varname>TARFLAGS</varname>"> +<!ENTITY TARSUFFIX "<varname>TARSUFFIX</varname>"> + + + +<!-- + + Environment variables. + +--> + +<!ENTITY PATH "<varname>PATH</varname>"> +<!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>"> +<!ENTITY SCONSFLAGS "<varname>SCONSFLAGS</varname>"> + + + +<!-- + + Function and method arguments. + +--> + +<!ENTITY allowed_values "<varname>allowed_values</varname>"> +<!ENTITY build_dir "<varname>build_dir</varname>"> +<!ENTITY map "<varname>map</varname>"> +<!ENTITY ignorecase "<varname>ignorecase</varname>"> +<!ENTITY options "<varname>options</varname>"> +<!ENTITY exports "<varname>exports</varname>"> +<!ENTITY source "<varname>source</varname>"> +<!ENTITY target "<varname>target</varname>"> +<!ENTITY variables "<varname>variables</varname>"> +<!ENTITY variant_dir "<varname>variant_dir</varname>"> + + + +<!-- + + Values of function and method arguments. + +--> + +<!ENTITY all "<literal>all</literal>"> +<!ENTITY none "<literal>none</literal>"> + + + +<!-- + + Builder and Scanner objects. + +--> + +<!ENTITY BuildDir "<function>BuildDir</function>"> +<!ENTITY CFile "<function>CFile</function>"> +<!ENTITY CXXFile "<function>CXXFile</function>"> +<!ENTITY DVI "<function>DVI</function>"> +<!ENTITY Jar "<function>Jar</function>"> +<!ENTITY Java "<function>Java</function>"> +<!ENTITY JavaH "<function>JavaH</function>"> +<!ENTITY Library "<function>Library</function>"> +<!ENTITY Object "<function>Object</function>"> +<!ENTITY PCH "<function>PCH</function>"> +<!ENTITY PDF "<function>PDF</function>"> +<!ENTITY PostScript "<function>PostScript</function>"> +<!ENTITY Program "<function>Program</function>"> +<!ENTITY RES "<function>RES</function>"> +<!ENTITY RMIC "<function>RMIC</function>"> +<!ENTITY SharedLibrary "<function>SharedLibrary</function>"> +<!ENTITY SharedObject "<function>SharedObject</function>"> +<!ENTITY StaticLibrary "<function>StaticLibrary</function>"> +<!ENTITY StaticObject "<function>StaticObject</function>"> +<!ENTITY Substfile "<function>Substfile</function>"> +<!ENTITY Tar "<function>Tar</function>"> +<!ENTITY Textfile "<function>Textfile</function>"> +<!ENTITY VariantDir "<function>VariantDir</function>"> +<!ENTITY Zip "<function>Zip</function>"> + +<!-- Obsolete, but referenced in old documents. --> +<!ENTITY MakeBuilder "<function>Make</function>"> + + + +<!-- + + Terms. Define both singular and plural forms in various + case-sensitive combinations for use in titles, in-line, etc. + +--> + +<!ENTITY buildfunc "<literal>builder function</literal>"> +<!ENTITY build_action "<literal>build action</literal>"> +<!ENTITY build_actions "<literal>build actions</literal>"> +<!ENTITY builder_method "<literal>builder method</literal>"> + +<!ENTITY Configure_Contexts "<literal>Configure Contexts</literal>"> +<!ENTITY configure_context "<literal>configure context</literal>"> + +<!ENTITY ConsEnv "<literal>Construction Environment</literal>"> +<!ENTITY ConsEnvs "<literal>Construction Environments</literal>"> +<!ENTITY Consenv "<literal>Construction environment</literal>"> +<!ENTITY Consenvs "<literal>Construction environments</literal>"> +<!ENTITY consenv "<literal>construction environment</literal>"> +<!ENTITY consenvs "<literal>construction environments</literal>"> + +<!ENTITY ConsVar "<literal>Construction Variable</literal>"> +<!ENTITY ConsVars "<literal>Construction Variables</literal>"> +<!ENTITY Consvar "<literal>Construction variable</literal>"> +<!ENTITY Consvars "<literal>Construction variables</literal>"> +<!ENTITY consvar "<literal>construction variable</literal>"> +<!ENTITY consvars "<literal>construction variables</literal>"> + +<!ENTITY CPPPATH "<literal>CPPPATH</literal>"> + +<!ENTITY Dictionary "<literal>Dictionary</literal>"> + +<!ENTITY Emitter "<literal>Emitter</literal>"> +<!ENTITY emitter "<literal>emitter</literal>"> + +<!ENTITY factory "<literal>factory</literal>"> + +<!ENTITY Generator "<literal>Generator</literal>"> +<!ENTITY generator "<literal>generator</literal>"> + +<!ENTITY Nodes "<literal>Nodes</literal>"> + +<!ENTITY signature "<literal>signature</literal>"> +<!ENTITY buildsignature "<literal>build signature</literal>"> + +<!ENTITY true "<literal>true</literal>"> +<!ENTITY false "<literal>false</literal>"> + +<!ENTITY typedef "<literal>typedef</literal>"> + +<!-- + + Python keyword arguments + +--> + +<!ENTITY action "<literal>action=</literal>"> +<!ENTITY batch_key "<literal>batch_key=</literal>"> +<!ENTITY cmdstr "<literal>cmdstr=</literal>"> +<!ENTITY exitstatfunc "<literal>exitstatfunc=</literal>"> +<!ENTITY strfunction "<literal>strfunction=</literal>"> +<!ENTITY varlist "<literal>varlist=</literal>"> + +<!-- + + File and program names used in examples. + +--> + +<!ENTITY bar "<filename>bar</filename>"> +<!ENTITY common1_c "<filename>common1.c</filename>"> +<!ENTITY common2_c "<filename>common2.c</filename>"> +<!ENTITY custom_py "<filename>custom.py</filename>"> +<!ENTITY goodbye "<filename>goodbye</filename>"> +<!ENTITY goodbye_o "<filename>goodbye.o</filename>"> +<!ENTITY goodbye_obj "<filename>goodbye.obj</filename>"> +<!ENTITY file_dll "<filename>file.dll</filename>"> +<!ENTITY file_in "<filename>file.in</filename>"> +<!ENTITY file_lib "<filename>file.lib</filename>"> +<!ENTITY file_o "<filename>file.o</filename>"> +<!ENTITY file_obj "<filename>file.obj</filename>"> +<!ENTITY file_out "<filename>file.out</filename>"> +<!ENTITY foo "<filename>foo</filename>"> +<!ENTITY foo_o "<filename>foo.o</filename>"> +<!ENTITY foo_obj "<filename>foo.obj</filename>"> +<!ENTITY hello "<filename>hello</filename>"> +<!ENTITY hello_c "<filename>hello.c</filename>"> +<!ENTITY hello_exe "<filename>hello.exe</filename>"> +<!ENTITY hello_h "<filename>hello.h</filename>"> +<!ENTITY hello_o "<filename>hello.o</filename>"> +<!ENTITY hello_obj "<filename>hello.obj</filename>"> +<!ENTITY libfile_a "<filename>libfile_a</filename>"> +<!ENTITY libfile_so "<filename>libfile_so</filename>"> +<!ENTITY new_hello "<filename>new_hello</filename>"> +<!ENTITY new_hello_exe "<filename>new_hello.exe</filename>"> +<!ENTITY prog "<filename>prog</filename>"> +<!ENTITY prog1 "<filename>prog1</filename>"> +<!ENTITY prog2 "<filename>prog2</filename>"> +<!ENTITY prog_c "<filename>prog.c</filename>"> +<!ENTITY prog_exe "<filename>prog.exe</filename>"> +<!ENTITY stdio_h "<filename>stdio.h</filename>"> + +<!-- + + Punctuation. + +--> + +<!ENTITY plus "<literal>+</literal>"> +<!ENTITY hash "<literal>#</literal>"> + +<!-- + + Mailing lists + +--> + +<!ENTITY scons-announce "<literal>announce@scons.tigris.org</literal>"> +<!ENTITY scons-devel "<literal>dev@scons.tigris.org</literal>"> +<!ENTITY scons-users "<literal>users@scons.tigris.org</literal>"> diff --git a/doc/user/MANIFEST b/doc/user/MANIFEST new file mode 100644 index 0000000..ef273d3 --- /dev/null +++ b/doc/user/MANIFEST @@ -0,0 +1,50 @@ +actions.xml +add-method.xml +alias.xml +ant.xml +builders.xml +builders-built-in.xml +builders-commands.xml +builders-writing.xml +build-install.xml +caching.xml +command-line.xml +cons.pl +copyright.xml +depends.xml +environments.xml +errors.xml +example.xml +factories.xml +file-removal.xml +hierarchy.xml +install.xml +java.xml +libraries.xml +less-simple.xml +main.xml +make.xml +mergeflags.xml +misc.xml +nodes.xml +output.xml +parseconfig.xml +parseflags.xml +preface.xml +python.xml +repositories.xml +run.xml +scanners.xml +sconf.xml +separate.xml +simple.xml +sourcecode.xml +tasks.xml +tools.xml +troubleshoot.xml +variants.xml +variables.xml +SCons-win32-install-1.jpg +SCons-win32-install-2.jpg +SCons-win32-install-3.jpg +SCons-win32-install-4.jpg diff --git a/doc/user/README b/doc/user/README new file mode 100644 index 0000000..aef479a --- /dev/null +++ b/doc/user/README @@ -0,0 +1,21 @@ +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + +When adding a new file, add it to main.xml and MANIFEST. + +To build the .xml files from the .in files: + scons -D BUILDDOC=1 foo.xml +To build the whole PDF doc from this dir, for testing: + scons -D ../../build/doc/PDF/scons-user.pdf + +Writing examples: here's a simple template. + + <scons_example name="Foo"> + <file name="SConstruct"> + env = Environment() + print env.Dump("CC") + </file> + </scons_example> + + <scons_output example="Foo"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> diff --git a/doc/user/SCons-win32-install-1.jpg b/doc/user/SCons-win32-install-1.jpg Binary files differnew file mode 100644 index 0000000..ecc439d --- /dev/null +++ b/doc/user/SCons-win32-install-1.jpg diff --git a/doc/user/SCons-win32-install-2.jpg b/doc/user/SCons-win32-install-2.jpg Binary files differnew file mode 100644 index 0000000..f468526 --- /dev/null +++ b/doc/user/SCons-win32-install-2.jpg diff --git a/doc/user/SCons-win32-install-3.jpg b/doc/user/SCons-win32-install-3.jpg Binary files differnew file mode 100644 index 0000000..90d2ed4 --- /dev/null +++ b/doc/user/SCons-win32-install-3.jpg diff --git a/doc/user/SCons-win32-install-4.jpg b/doc/user/SCons-win32-install-4.jpg Binary files differnew file mode 100644 index 0000000..d37973b --- /dev/null +++ b/doc/user/SCons-win32-install-4.jpg diff --git a/doc/user/actions.in b/doc/user/actions.in new file mode 100644 index 0000000..1ea5c49 --- /dev/null +++ b/doc/user/actions.in @@ -0,0 +1,404 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Build actions + +Cons supports several types of B<build actions> that can be performed +to construct one or more target files. Usually, a build action is +a construction command, that is, a command-line string that invokes +an external command. Cons can also execute Perl code embedded in a +command-line string, and even supports an experimental ability to build +a target file by executing a Perl code reference directly. + +A build action is usually specified as the value of a construction +variable: + + $env = new cons( + CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>', + LINKCOM => '[perl] &link_executable("%>", "%<")', + ARCOM => sub { my($env, $target, @sources) = @_; + # code to create an archive + } + ); + +A build action may be associated directly with one or more target files +via the C<Command> method; see below. + +=head2 Construction commands + +A construction command goes through expansion of construction variables +and C<%-> pseudo-variables, as described above, to create the actual +command line that Cons will execute to generate the target file or +files. + +After substitution occurs, strings of white space are converted into +single blanks, and leading and trailing white space is eliminated. It +is therefore currently not possible to introduce variable length white +space in strings passed into a command. + +If a multi-line command string is provided, the commands are executed +sequentially. If any of the commands fails, then none of the rest are +executed, and the target is not marked as updated, i.e. a new signature is +not stored for the target. + +Normally, if all the commands succeed, and return a zero status (or whatever +platform-specific indication of success is required), then a new signature +is stored for the target. If a command erroneously reports success even +after a failure, then Cons will assume that the target file created by that +command is accurate and up-to-date. + +The first word of each command string, after expansion, is assumed to be an +executable command looked up on the C<PATH> environment variable (which is, +in turn, specified by the C<ENV> construction variable). If this command is +found on the path, then the target will depend upon it: the command will +therefore be automatically built, as necessary. It's possible to write +multi-part commands to some shells, separated by semi-colons. Only the first +command word will be depended upon, however, so if you write your command +strings this way, you must either explicitly set up a dependency (with the +C<Depends> method), or be sure that the command you are using is a system +command which is expected to be available. If it isn't available, you will, +of course, get an error. + +Cons normally prints a command before executing it. This behavior is +suppressed if the first character of the command is C<@>. Note that +you may need to separate the C<@> from the command name or escape it to +prevent C<@cmd> from looking like an array to Perl quote operators that +perform interpolation: + + # The first command line is incorrect, + # because "@cp" looks like an array + # to the Perl qq// function. + # Use the second form instead. + Command $env 'foo', 'foo.in', qq( + @cp %< tempfile + @ cp tempfile %> + ); + +If there are shell meta characters anywhere in the expanded command line, +such as C<E<lt>>, C<E<gt>>, quotes, or semi-colon, then the command +will actually be executed by invoking a shell. This means that a command +such as: + + cd foo + +alone will typically fail, since there is no command C<cd> on the path. But +the command string: + + cd $<:d; tar cf $>:f $<:f + +when expanded will still contain the shell meta character semi-colon, and a +shell will be invoked to interpret the command. Since C<cd> is interpreted +by this sub-shell, the command will execute as expected. + +=head2 Perl expressions + +If any command (even one within a multi-line command) begins with +C<[perl]>, the remainder of that command line will be evaluated by the +running Perl instead of being forked by the shell. If an error occurs +in parsing the Perl code, or if the Perl expression returns 0 or undef, +the command will be considered to have failed. For example, here is a +simple command which creates a file C<foo> directly from Perl: + + $env = new cons(); + Command $env 'foo', + qq([perl] open(FOO,'>foo');print FOO "hi\\n"; close(FOO); 1); + +Note that when the command is executed, you are in the same package as +when the F<Construct> or F<Conscript> file was read, so you can call +Perl functions you've defined in the same F<Construct> or F<Conscript> +file in which the C<Command> appears: + + $env = new cons(); + sub create_file { + my $file = shift; + open(FILE, ">$file"); + print FILE "hi\n"; + close(FILE); + return 1; + } + Command $env 'foo', "[perl] &create_file('%>')"; + +The Perl string will be used to generate the signature for the derived +file, so if you change the string, the file will be rebuilt. The contents +of any subroutines you call, however, are not part of the signature, +so if you modify a called subroutine such as C<create_file> above, +the target will I<not> be rebuilt. Caveat user. + +=head2 Perl code references [EXPERIMENTAL] + +Cons supports the ability to create a derived file by directly executing +a Perl code reference. This feature is considered EXPERIMENTAL and +subject to change in the future. + +A code reference may either be a named subroutine referenced by the +usual C<\&> syntax: + + sub build_output { + my($env, $target, @sources) = @_; + print "build_output building $target\n"; + open(OUT, ">$target"); + foreach $src (@sources) { + if (! open(IN, "<$src")) { + print STDERR "cannot open '$src': $!\n"; + return undef; + } + print OUT, <IN>; + } + close(OUT); + return 1; + } + Command $env 'output', \&build_output; + +or the code reference may be an anonymous subroutine: + + Command $env 'output', sub { + my($env, $target, @sources) = @_; + print "building $target\n"; + open(FILE, ">$target"); + print FILE "hello\n"; + close(FILE); + return 1; + }; + +To build the target file, the referenced subroutine is passed, in order: +the construction environment used to generate the target; the path +name of the target itself; and the path names of all the source files +necessary to build the target file. + +The code reference is expected to generate the target file, of course, +but may manipulate the source and target files in any way it chooses. +The code reference must return a false value (C<undef> or C<0>) if +the build of the file failed. Any true value indicates a successful +build of the target. + +Building target files using code references is considered EXPERIMENTAL +due to the following current limitations: + +=over 4 + +Cons does I<not> print anything to indicate the code reference is being +called to build the file. The only way to give the user any indication +is to have the code reference explicitly print some sort of "building" +message, as in the above examples. + +Cons does not generate any signatures for code references, so if the +code in the reference changes, the target will I<not> be rebuilt. + +Cons has no public method to allow a code reference to extract +construction variables. This would be good to allow generalization of +code references based on the current construction environment, but would +also complicate the problem of generating meaningful signatures for code +references. + +=back + +Support for building targets via code references has been released in +this version to encourage experimentation and the seeking of possible +solutions to the above limitations. + +--> + + <para> + + &SCons; supports several types of &build_actions; + that can be performed to build one or more target files. + Usually, a &build_action; is a command-line string + that invokes an external command. + A build action can also be an external command + specified as a list of arguments, + or even a Python function. + + </para> + + <para> + + Build action objects are created by the &Action; function. + This function is, in fact, what &SCons; uses + to interpret the &action; + keyword argument when you call the &Builder; function. + So the following line that creates a simple Builder: + + </para> + + <sconstruct> + b = Builder(action = 'build < $SOURCE > $TARGET') + </sconstruct> + + <para> + + Is equivalent to: + + </para> + + <sconstruct> + b = Builder(action = Action('build < $SOURCE > $TARGET')) + </sconstruct> + + <para> + + The advantage of using the &Action; function directly + is that it can take a number of additional options + to modify the action's behavior in many useful ways. + + </para> + + <section> + <title>Command Strings as Actions</title> + + <section> + <title>Suppressing Command-Line Printing</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Ignoring Exit Status</title> + + <para> + + XXX + + </para> + + </section> + + </section> + + <section> + <title>Argument Lists as Actions</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Python Functions as Actions</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Modifying How an Action is Printed</title> + + <section> + <title>XXX: the &strfunction; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>XXX: the &cmdstr; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + </section> + + <section> + <title>Making an Action Depend on Variable Contents: the &varlist; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>chdir=1</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Batch Building of Multiple Targets from Separate Sources: the &batch_key; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Manipulating the Exit Status of an Action: the &exitstatfunc; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + <!-- + + ??? + + <section> + <title>presub=</title> + + <para> + + XXX + + </para> + + </section> + + --> diff --git a/doc/user/actions.xml b/doc/user/actions.xml new file mode 100644 index 0000000..c3b8cf9 --- /dev/null +++ b/doc/user/actions.xml @@ -0,0 +1,404 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Build actions + +Cons supports several types of B<build actions> that can be performed +to construct one or more target files. Usually, a build action is +a construction command, that is, a command-line string that invokes +an external command. Cons can also execute Perl code embedded in a +command-line string, and even supports an experimental ability to build +a target file by executing a Perl code reference directly. + +A build action is usually specified as the value of a construction +variable: + + $env = new cons( + CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>', + LINKCOM => '[perl] &link_executable("%>", "%<")', + ARCOM => sub { my($env, $target, @sources) = @_; + # code to create an archive + } + ); + +A build action may be associated directly with one or more target files +via the C<Command> method; see below. + +=head2 Construction commands + +A construction command goes through expansion of construction variables +and C<%-> pseudo-variables, as described above, to create the actual +command line that Cons will execute to generate the target file or +files. + +After substitution occurs, strings of white space are converted into +single blanks, and leading and trailing white space is eliminated. It +is therefore currently not possible to introduce variable length white +space in strings passed into a command. + +If a multi-line command string is provided, the commands are executed +sequentially. If any of the commands fails, then none of the rest are +executed, and the target is not marked as updated, i.e. a new signature is +not stored for the target. + +Normally, if all the commands succeed, and return a zero status (or whatever +platform-specific indication of success is required), then a new signature +is stored for the target. If a command erroneously reports success even +after a failure, then Cons will assume that the target file created by that +command is accurate and up-to-date. + +The first word of each command string, after expansion, is assumed to be an +executable command looked up on the C<PATH> environment variable (which is, +in turn, specified by the C<ENV> construction variable). If this command is +found on the path, then the target will depend upon it: the command will +therefore be automatically built, as necessary. It's possible to write +multi-part commands to some shells, separated by semi-colons. Only the first +command word will be depended upon, however, so if you write your command +strings this way, you must either explicitly set up a dependency (with the +C<Depends> method), or be sure that the command you are using is a system +command which is expected to be available. If it isn't available, you will, +of course, get an error. + +Cons normally prints a command before executing it. This behavior is +suppressed if the first character of the command is C<@>. Note that +you may need to separate the C<@> from the command name or escape it to +prevent C<@cmd> from looking like an array to Perl quote operators that +perform interpolation: + + # The first command line is incorrect, + # because "@cp" looks like an array + # to the Perl qq// function. + # Use the second form instead. + Command $env 'foo', 'foo.in', qq( + @cp %< tempfile + @ cp tempfile %> + ); + +If there are shell meta characters anywhere in the expanded command line, +such as C<E<lt>>, C<E<gt>>, quotes, or semi-colon, then the command +will actually be executed by invoking a shell. This means that a command +such as: + + cd foo + +alone will typically fail, since there is no command C<cd> on the path. But +the command string: + + cd $<:d; tar cf $>:f $<:f + +when expanded will still contain the shell meta character semi-colon, and a +shell will be invoked to interpret the command. Since C<cd> is interpreted +by this sub-shell, the command will execute as expected. + +=head2 Perl expressions + +If any command (even one within a multi-line command) begins with +C<[perl]>, the remainder of that command line will be evaluated by the +running Perl instead of being forked by the shell. If an error occurs +in parsing the Perl code, or if the Perl expression returns 0 or undef, +the command will be considered to have failed. For example, here is a +simple command which creates a file C<foo> directly from Perl: + + $env = new cons(); + Command $env 'foo', + qq([perl] open(FOO,'>foo');print FOO "hi\\n"; close(FOO); 1); + +Note that when the command is executed, you are in the same package as +when the F<Construct> or F<Conscript> file was read, so you can call +Perl functions you've defined in the same F<Construct> or F<Conscript> +file in which the C<Command> appears: + + $env = new cons(); + sub create_file { + my $file = shift; + open(FILE, ">$file"); + print FILE "hi\n"; + close(FILE); + return 1; + } + Command $env 'foo', "[perl] &create_file('%>')"; + +The Perl string will be used to generate the signature for the derived +file, so if you change the string, the file will be rebuilt. The contents +of any subroutines you call, however, are not part of the signature, +so if you modify a called subroutine such as C<create_file> above, +the target will I<not> be rebuilt. Caveat user. + +=head2 Perl code references [EXPERIMENTAL] + +Cons supports the ability to create a derived file by directly executing +a Perl code reference. This feature is considered EXPERIMENTAL and +subject to change in the future. + +A code reference may either be a named subroutine referenced by the +usual C<\&> syntax: + + sub build_output { + my($env, $target, @sources) = @_; + print "build_output building $target\n"; + open(OUT, ">$target"); + foreach $src (@sources) { + if (! open(IN, "<$src")) { + print STDERR "cannot open '$src': $!\n"; + return undef; + } + print OUT, <IN>; + } + close(OUT); + return 1; + } + Command $env 'output', \&build_output; + +or the code reference may be an anonymous subroutine: + + Command $env 'output', sub { + my($env, $target, @sources) = @_; + print "building $target\n"; + open(FILE, ">$target"); + print FILE "hello\n"; + close(FILE); + return 1; + }; + +To build the target file, the referenced subroutine is passed, in order: +the construction environment used to generate the target; the path +name of the target itself; and the path names of all the source files +necessary to build the target file. + +The code reference is expected to generate the target file, of course, +but may manipulate the source and target files in any way it chooses. +The code reference must return a false value (C<undef> or C<0>) if +the build of the file failed. Any true value indicates a successful +build of the target. + +Building target files using code references is considered EXPERIMENTAL +due to the following current limitations: + +=over 4 + +Cons does I<not> print anything to indicate the code reference is being +called to build the file. The only way to give the user any indication +is to have the code reference explicitly print some sort of "building" +message, as in the above examples. + +Cons does not generate any signatures for code references, so if the +code in the reference changes, the target will I<not> be rebuilt. + +Cons has no public method to allow a code reference to extract +construction variables. This would be good to allow generalization of +code references based on the current construction environment, but would +also complicate the problem of generating meaningful signatures for code +references. + +=back + +Support for building targets via code references has been released in +this version to encourage experimentation and the seeking of possible +solutions to the above limitations. + +--> + + <para> + + &SCons; supports several types of &build_actions; + that can be performed to build one or more target files. + Usually, a &build_action; is a command-line string + that invokes an external command. + A build action can also be an external command + specified as a list of arguments, + or even a Python function. + + </para> + + <para> + + Build action objects are created by the &Action; function. + This function is, in fact, what &SCons; uses + to interpret the &action; + keyword argument when you call the &Builder; function. + So the following line that creates a simple Builder: + + </para> + + <programlisting> + b = Builder(action = 'build < $SOURCE > $TARGET') + </programlisting> + + <para> + + Is equivalent to: + + </para> + + <programlisting> + b = Builder(action = Action('build < $SOURCE > $TARGET')) + </programlisting> + + <para> + + The advantage of using the &Action; function directly + is that it can take a number of additional options + to modify the action's behavior in many useful ways. + + </para> + + <section> + <title>Command Strings as Actions</title> + + <section> + <title>Suppressing Command-Line Printing</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Ignoring Exit Status</title> + + <para> + + XXX + + </para> + + </section> + + </section> + + <section> + <title>Argument Lists as Actions</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Python Functions as Actions</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Modifying How an Action is Printed</title> + + <section> + <title>XXX: the &strfunction; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>XXX: the &cmdstr; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + </section> + + <section> + <title>Making an Action Depend on Variable Contents: the &varlist; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>chdir=1</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Batch Building of Multiple Targets from Separate Sources: the &batch_key; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Manipulating the Exit Status of an Action: the &exitstatfunc; keyword argument</title> + + <para> + + XXX + + </para> + + </section> + + <!-- + + ??? + + <section> + <title>presub=</title> + + <para> + + XXX + + </para> + + </section> + + --> diff --git a/doc/user/add-method.in b/doc/user/add-method.in new file mode 100644 index 0000000..61f13cc --- /dev/null +++ b/doc/user/add-method.in @@ -0,0 +1,127 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + The &AddMethod; function is used to add a method + to an environment. It's typically used to add a "pseudo-builder," + a function that looks like a &Builder; but + wraps up calls to multiple other &Builder;s + or otherwise processes its arguments + before calling one or more &Builder;s. + In the following example, + we want to install the program into the standard + <filename>/usr/bin</filename> directory hierarchy, + but also copy it into a local <filename>install/bin</filename> + directory from which a package might be built: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + def install_in_bin_dirs(env, source): + """Install source in both bin dirs""" + i1 = env.Install("$BIN", source) + i2 = env.Install("$LOCALBIN", source) + return [i1[0], i2[0]] # Return a list, like a normal builder + env = Environment(BIN='__ROOT__/usr/bin', LOCALBIN='#install/bin') + env.AddMethod(install_in_bin_dirs, "InstallInBinDirs") + env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + This produces the following: + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q /</scons_output_command> + </scons_output> + + <para> + + As mentioned, a psuedo-builder also provides more flexibility + in parsing arguments than you can get with a &Builder;. + The next example shows a pseudo-builder with a + named argument that modifies the filename, and a separate argument + for the resource file (rather than having the builder figure it out + by file extension). This example also demonstrates using the global + &AddMethod; function to add a method to the global Environment class, + so it will be used in all subsequently created environments. + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + def BuildTestProg(env, testfile, resourcefile, testdir="tests"): + """Build the test program; + prepends "test_" to src and target, + and puts target into testdir.""" + srcfile = "test_%s.c" % testfile + target = "%s/test_%s" % (testdir, testfile) + if env['PLATFORM'] == 'win32': + resfile = env.RES(resourcefile) + p = env.Program(target, [srcfile, resfile]) + else: + p = env.Program(target, srcfile) + return p + AddMethod(Environment, BuildTestProg) + + env = Environment() + env.BuildTestProg('stuff', resourcefile='res.rc') + </file> + <file name="test_stuff.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="res.rc"> + res.rc + </file> + </scons_example> + + <para> + This produces the following on Linux: + </para> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + And the following on Windows: + </para> + + <scons_output example="ex2" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + Using &AddMethod; is better than just adding an instance method + to a &consenv; because it gets called as a proper method, + and because &AddMethod; provides for copying the method + to any clones of the &consenv; instance. + </para> diff --git a/doc/user/add-method.xml b/doc/user/add-method.xml new file mode 100644 index 0000000..761765f --- /dev/null +++ b/doc/user/add-method.xml @@ -0,0 +1,135 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + The &AddMethod; function is used to add a method + to an environment. It's typically used to add a "pseudo-builder," + a function that looks like a &Builder; but + wraps up calls to multiple other &Builder;s + or otherwise processes its arguments + before calling one or more &Builder;s. + In the following example, + we want to install the program into the standard + <filename>/usr/bin</filename> directory hierarchy, + but also copy it into a local <filename>install/bin</filename> + directory from which a package might be built: + + </para> + + <programlisting> + def install_in_bin_dirs(env, source): + """Install source in both bin dirs""" + i1 = env.Install("$BIN", source) + i2 = env.Install("$LOCALBIN", source) + return [i1[0], i2[0]] # Return a list, like a normal builder + env = Environment(BIN='/usr/bin', LOCALBIN='#install/bin') + env.AddMethod(install_in_bin_dirs, "InstallInBinDirs") + env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs + </programlisting> + + <para> + This produces the following: + </para> + + <screen> + % <userinput>scons -Q /</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + Install file: "hello" as "/usr/bin/hello" + Install file: "hello" as "install/bin/hello" + </screen> + + <para> + + As mentioned, a psuedo-builder also provides more flexibility + in parsing arguments than you can get with a &Builder;. + The next example shows a pseudo-builder with a + named argument that modifies the filename, and a separate argument + for the resource file (rather than having the builder figure it out + by file extension). This example also demonstrates using the global + &AddMethod; function to add a method to the global Environment class, + so it will be used in all subsequently created environments. + + </para> + + <programlisting> + def BuildTestProg(env, testfile, resourcefile, testdir="tests"): + """Build the test program; + prepends "test_" to src and target, + and puts target into testdir.""" + srcfile = "test_%s.c" % testfile + target = "%s/test_%s" % (testdir, testfile) + if env['PLATFORM'] == 'win32': + resfile = env.RES(resourcefile) + p = env.Program(target, [srcfile, resfile]) + else: + p = env.Program(target, srcfile) + return p + AddMethod(Environment, BuildTestProg) + + env = Environment() + env.BuildTestProg('stuff', resourcefile='res.rc') + </programlisting> + + <para> + This produces the following on Linux: + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o test_stuff.o -c test_stuff.c + cc -o tests/test_stuff test_stuff.o + </screen> + + <para> + And the following on Windows: + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + rc /fores.res res.rc + cl /Fotest_stuff.obj /c test_stuff.c /nologo + link /nologo /OUT:tests\test_stuff.exe test_stuff.obj res.res + </screen> + + <para> + Using &AddMethod; is better than just adding an instance method + to a &consenv; because it gets called as a proper method, + and because &AddMethod; provides for copying the method + to any clones of the &consenv; instance. + </para> diff --git a/doc/user/alias.in b/doc/user/alias.in new file mode 100644 index 0000000..45a1534 --- /dev/null +++ b/doc/user/alias.in @@ -0,0 +1,102 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + We've already seen how you can use the &Alias; + function to create a target named <literal>install</literal>: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment() + hello = env.Program('hello.c') + env.Install('__ROOT__/usr/bin', hello) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + You can then use this alias on the command line + to tell &SCons; more naturally that you want to install files: + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> + + <para> + + Like other &Builder; methods, though, + the &Alias; method returns an object + representing the alias being built. + You can then use this object as input to anothother &Builder;. + This is especially useful if you use such an object + as input to another call to the &Alias; &Builder;, + allowing you to create a hierarchy + of nested aliases: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + env = Environment() + p = env.Program('foo.c') + l = env.Library('bar.c') + env.Install('__ROOT__/usr/bin', p) + env.Install('__ROOT__/usr/lib', l) + ib = env.Alias('install-bin', '__ROOT__/usr/bin') + il = env.Alias('install-lib', '__ROOT__/usr/lib') + env.Alias('install', [ib, il]) + </file> + <file name="foo.c"> + int main() { printf("foo.c\n"); } + </file> + <file name="bar.c"> + void bar() { printf("bar.c\n"); } + </file> + </scons_example> + + <para> + + This example defines separate <literal>install</literal>, + <literal>install-bin</literal>, + and <literal>install-lib</literal> aliases, + allowing you finer control over what gets installed: + + </para> + + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -Q install-bin</scons_output_command> + <scons_output_command>scons -Q install-lib</scons_output_command> + <scons_output_command>scons -Q -c __ROOT__/</scons_output_command> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> diff --git a/doc/user/alias.xml b/doc/user/alias.xml new file mode 100644 index 0000000..04ebd5f --- /dev/null +++ b/doc/user/alias.xml @@ -0,0 +1,112 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + We've already seen how you can use the &Alias; + function to create a target named <literal>install</literal>: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + env.Install('/usr/bin', hello) + env.Alias('install', '/usr/bin') + </programlisting> + + <para> + + You can then use this alias on the command line + to tell &SCons; more naturally that you want to install files: + + </para> + + <screen> + % <userinput>scons -Q install</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + Install file: "hello" as "/usr/bin/hello" + </screen> + + <para> + + Like other &Builder; methods, though, + the &Alias; method returns an object + representing the alias being built. + You can then use this object as input to anothother &Builder;. + This is especially useful if you use such an object + as input to another call to the &Alias; &Builder;, + allowing you to create a hierarchy + of nested aliases: + + </para> + + <programlisting> + env = Environment() + p = env.Program('foo.c') + l = env.Library('bar.c') + env.Install('/usr/bin', p) + env.Install('/usr/lib', l) + ib = env.Alias('install-bin', '/usr/bin') + il = env.Alias('install-lib', '/usr/lib') + env.Alias('install', [ib, il]) + </programlisting> + + <para> + + This example defines separate <literal>install</literal>, + <literal>install-bin</literal>, + and <literal>install-lib</literal> aliases, + allowing you finer control over what gets installed: + + </para> + + <screen> + % <userinput>scons -Q install-bin</userinput> + cc -o foo.o -c foo.c + cc -o foo foo.o + Install file: "foo" as "/usr/bin/foo" + % <userinput>scons -Q install-lib</userinput> + cc -o bar.o -c bar.c + ar rc libbar.a bar.o + ranlib libbar.a + Install file: "libbar.a" as "/usr/lib/libbar.a" + % <userinput>scons -Q -c /</userinput> + Removed foo.o + Removed foo + Removed /usr/bin/foo + Removed bar.o + Removed libbar.a + Removed /usr/lib/libbar.a + % <userinput>scons -Q install</userinput> + cc -o foo.o -c foo.c + cc -o foo foo.o + Install file: "foo" as "/usr/bin/foo" + cc -o bar.o -c bar.c + ar rc libbar.a bar.o + ranlib libbar.a + Install file: "libbar.a" as "/usr/lib/libbar.a" + </screen> diff --git a/doc/user/ant.in b/doc/user/ant.in new file mode 100644 index 0000000..41b441d --- /dev/null +++ b/doc/user/ant.in @@ -0,0 +1,52 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Differences Between &Ant; and &SCons;</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Advantages of &SCons; Over &Ant;</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/ant.xml b/doc/user/ant.xml new file mode 100644 index 0000000..41b441d --- /dev/null +++ b/doc/user/ant.xml @@ -0,0 +1,52 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Differences Between &Ant; and &SCons;</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Advantages of &SCons; Over &Ant;</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/build-install.in b/doc/user/build-install.in new file mode 100644 index 0000000..ab289b1 --- /dev/null +++ b/doc/user/build-install.in @@ -0,0 +1,719 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + This chapter will take you through the basic steps + of installing &SCons; on your system, + and building &SCons; if you don't have a + pre-built package available + (or simply prefer the flexibility of building it yourself). + Before that, however, this chapter will also describe the basic steps + involved in installing Python on your system, + in case that is necessary. + Fortunately, both &SCons; and Python + are very easy to install on almost any system, + and Python already comes installed on many systems. + + </para> + + <!-- + + <para> + + Lastly, this chapter also contains a section that + provides a brief overview of the Python programming language, + which is the language used to implement &SCons;, + and which forms the basis of the &SCons; configuration files. + Becoming familiar with some Python concepts will make it easier + to understand many of the examples in this User's Guide. + Nevertheless, it <emphasis>is</emphasis> possible + to configure simple &SCons; builds without knowing Python, + so you can skip this section if you + want to dive in and pick up things + by example- -or, of course, if you are + already familiar with Python. + + </para> + + --> + + <section> + <title>Installing Python</title> + + <para> + + Because &SCons; is written in Python, + you must obviously have Python installed on your system + to use &SCons;. + Before you try to install Python, + you should check to see if Python is already + available on your system by typing + <userinput>python -V</userinput> + (capital 'V') + or + <userinput>python --version</userinput> + at your system's command-line prompt. + + </para> + + <screen> + $ <userinput>python -V</userinput> + Python 2.5.1 + </screen> + + <para> + + And on a Windows system with Python installed: + + </para> + + <screen> + C:\><userinput>python -V</userinput> + Python 2.5.1 + </screen> + + <para> + + If Python is not installed on your system, + you will see an error message + stating something like "command not found" + (on UNIX or Linux) + or "'python' is not recognized + as an internal or external command, operable progam or batch file" + (on Windows). + In that case, you need to install Python + before you can install &SCons;. + + </para> + + <para> + + (Note that the <option>-V</option> option + was added to Python version 2.0, + so if your system only has an earlier version available + you may see an + <literal>"Unknown option: -V"</literal> + error message.) + + </para> + + <para> + + The standard location for information + about downloading and installing Python is + <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>. + See that page for information about + how to download and install Python on your system. + + </para> + + <para> + + &SCons; will work with any version of Python from 1.5.2 or later. + If you need to install Python and have a choice, + we recommend using the most recent Python 2.5 version available. + Python 2.5 has significant improvements + that help speed up the performance of &SCons;. + + </para> + + </section> + + <section> + <title>Installing &SCons; From Pre-Built Packages</title> + + <para> + + &SCons; comes pre-packaged for installation on a number of systems, + including Linux and Windows systems. + You do not need to read this entire section, + you should need to read only the section + appropriate to the type of system you're running on. + + </para> + + <section> + <title>Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems</title> + + <para> + + &SCons; comes in RPM (Red Hat Package Manager) format, + pre-built and ready to install on Red Hat Linux, + Fedora, + or any other Linux distribution that uses RPM. + Your distribution may + already have an &SCons; RPM built specifically for it; + many do, including SUSE, Mandrake and Fedora. + You can check for the availability of an &SCons; RPM + on your distribution's download servers, + or by consulting an RPM search site like + <ulink url="http://www.rpmfind.net/">http://www.rpmfind.net/</ulink> or + <ulink url="http://rpm.pbone.net/">http://rpm.pbone.net/</ulink>. + + </para> + + <para> + + If your distribution supports installation via + <application>yum</application>, + you should be able to install &SCons; by running: + + </para> + + <screen> + # <userinput>yum install scons</userinput> + </screen> + + <para> + + If your Linux distribution does not already have + a specific &SCons; RPM file, + you can download and install from the + generic RPM provided by the &SCons; project. + This will install the + SCons script(s) in <filename>/usr/bin</filename>, + and the SCons library modules in + <filename>/usr/lib/scons</filename>. + + </para> + + <para> + + To install from the command line, simply download the + appropriate <filename>.rpm</filename> file, + and then run: + + </para> + + <screen> + # <userinput>rpm -Uvh scons-1.2.0.d20091224-1.noarch.rpm</userinput> + </screen> + + <para> + + Or, you can use a graphical RPM package manager. + See your package manager application's documention + for specific instructions about + how to use it to install a downloaded RPM. + + </para> + + </section> + + <section> + <title>Installing &SCons; on Debian Linux Systems</title> + + <para> + + Debian Linux systems use a different package management + format that also makes it very easy to install &SCons;. + + </para> + + <para> + + If your system is connected to the Internet, + you can install the latest official Debian package + by running: + + </para> + + <screen> + # <userinput>apt-get install scons</userinput> + </screen> + + <!-- + + <para> + + Alternatively, + you can download the Debian package built + by the &SCons; project + and install it manually by running: + + </para> + + <screen> + # <userinput>db-XXX scons-*.deb</userinput> + </screen> + + --> + + </section> + + <section> + <title>Installing &SCons; on Windows Systems</title> + + <para> + + &SCons; provides a Windows installer + that makes installation extremely easy. + Download the <filename>scons-1.2.0.d20091224.win32.exe</filename> + file from the &SCons; download page at + <ulink url="http://www.scons.org/download.php">http://www.scons.org/download.php</ulink>. + Then all you need to do is execute the file + (usually by clicking on its icon in Windows Explorer). + These will take you through a small + sequence of windows that will install + &SCons; on your system. + + <!-- + Things are a little more complicated + if you are using the Cygwin version of Python. + This is because Cygwin + tries to make a Windows system look more + POSIX-like (or UNIX-like or Linux-like, if you prefer) + by having the Cygwin utilities, + including Cygwin Python, + interpret file name arguments on the command line + using the forward-slash (<filename>/</filename>) + as the directory separator, + instead of the normal Windows behavior of the + backslash (<filename>\</filename>) as the directory separator. + --> + + </para> + + <!-- + + <section> + <title>Installing &SCons; on Windows Systems Without Cygwin Python</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Installing &SCons; on Windows Systems With Cygwin Python</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <!-- + + XXX - don't have the kinks worked out on how to + get these to display properly in all formats, + so comment them out for now. + + <screenshot> + <mediaobject> + <imageobject> + <imagedata fileref="SCons-win32-install-1.jpg" format="jpg" align="center"> + </imageobject> + </mediaobject> + </screenshot> + + <screenshot> + <mediaobject> + <imageobject> + <imagedata fileref="SCons-win32-install-2.jpg" format="jpg" align="center"> + </imageobject> + </mediaobject> + </screenshot> + + <screenshot> + <mediaobject> + <imageobject> + <imagedata fileref="SCons-win32-install-3.jpg" format="jpg" align="center"> + </imageobject> + </mediaobject> + </screenshot> + + <screenshot> + <mediaobject> + <imageobject> + <imagedata fileref="SCons-win32-install-4.jpg" format="jpg" align="center"> + </imageobject> + </mediaobject> + </screenshot> + + --> + + </section> + + </section> + + <section> + <title>Building and Installing &SCons; on Any System</title> + + <para> + + If a pre-built &SCons; package is not available for your system, + then you can still easily build and install &SCons; using the native + Python <filename>distutils</filename> package. + + </para> + + <para> + + The first step is to download either the + <filename>scons-1.2.0.d20091224.tar.gz</filename> + or <filename>scons-1.2.0.d20091224.zip</filename>, + which are available from the SCons download page at + <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>. + + </para> + + <para> + + Unpack the archive you downloaded, + using a utility like <application>tar</application> + on Linux or UNIX, + or <application>WinZip</application> on Windows. + This will create a directory called + <filename>scons-1.2.0.d20091224</filename>, + usually in your local directory. + Then change your working directory to that directory + and install &SCons; by executing the following commands: + + </para> + + <screen> + # <userinput>cd scons-1.2.0.d20091224</userinput> + # <userinput>python setup.py install</userinput> + </screen> + + <para> + + This will build &SCons;, + install the &scons; script + in the default system scripts directory + (<filename>/usr/local/bin</filename> or + <filename>C:\Python25\Scripts</filename>), + and will install the &SCons; build engine + in an appropriate stand-alone library directory + (<filename>/usr/local/lib/scons</filename> or + <filename>C:\Python25\scons</filename>). + Because these are system directories, + you may need root (on Linux or UNIX) or Administrator (on Windows) + privileges to install &SCons; like this. + + </para> + + <!-- + + <section> + <title>Building and Installing &SCons; in the Standard Python Library Directories</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <section> + <title>Building and Installing Multiple Versions of &SCons; Side-by-Side</title> + + <para> + + The &SCons; <filename>setup.py</filename> script + has some extensions that support + easy installation of multiple versions of &SCons; + in side-by-side locations. + This makes it easier to download and + experiment with different versions of &SCons; + before moving your official build process to a new version, + for example. + + </para> + + <para> + + To install &SCons; in a version-specific location, + add the <option>--version-lib</option> option + when you call <filename>setup.py</filename>: + + </para> + + <screen> + # <userinput>python setup.py install --version-lib</userinput> + </screen> + + <para> + + This will install the &SCons; build engine + in the + <filename>/usr/lib/scons-1.2.0.d20091224</filename> + or + <filename>C:\Python25\scons-1.2.0.d20091224</filename> + directory, for example. + + </para> + + <para> + + If you use the <option>--version-lib</option> option + the first time you install &SCons;, + you do not need to specify it each time you install + a new version. + The &SCons; <filename>setup.py</filename> script + will detect the version-specific directory name(s) + and assume you want to install all versions + in version-specific directories. + You can override that assumption in the future + by explicitly specifying the <option>--standalone-lib</option> option. + + </para> + + </section> + + <section> + <title>Installing &SCons; in Other Locations</title> + + <para> + + You can install &SCons; in locations other than + the default by specifying the <option>--prefix=</option> option: + + </para> + + <screen> + # <userinput>python setup.py install --prefix=/opt/scons</userinput> + </screen> + + <para> + + This would + install the <application>scons</application> script in + <filename>/opt/scons/bin</filename> + and the build engine in + <filename>/opt/scons/lib/scons</filename>, + + </para> + + <para> + + Note that you can specify both the <option>--prefix=</option> + and the <option>--version-lib</option> options + at the same type, + in which case <filename>setup.py</filename> + will install the build engine + in a version-specific directory + relative to the specified prefix. + Adding <option>--version-lib</option> to the + above example would install the build engine in + <filename>/opt/scons/lib/scons-1.2.0.d20091224</filename>. + + </para> + + </section> + + <section> + <title>Building and Installing &SCons; Without Administrative Privileges</title> + + <para> + + If you don't have the right privileges to install &SCons; + in a system location, + simply use the <literal>--prefix=</literal> option + to install it in a location of your choosing. + For example, + to install &SCons; in appropriate locations + relative to the user's <literal>$HOME</literal> directory, + the &scons; script in + <filename>$HOME/bin</filename> + and the build engine in + <filename>$HOME/lib/scons</filename>, + simply type: + + </para> + + <screen> + $ <userinput>python setup.py install --prefix=$HOME</userinput> + </screen> + + <para> + + You may, of course, specify any other location you prefer, + and may use the <option>--version-lib</option> option + if you would like to install version-specific directories + relative to the specified prefix. + + </para> + + <para> + + This can also be used to experiment with a newer + version of &SCons; than the one installed + in your system locations. + Of course, the location in which you install the + newer version of the &scons; script + (<filename>$HOME/bin</filename> in the above example) + must be configured in your &PATH; variable + before the directory containing + the system-installed version + of the &scons; script. + + </para> + + </section> + + </section> + + <!-- + + <section> + <title>Python Basics</title> + + <para> + + This section will provide a brief overview of + the Python programming language. + Skip this section if you are already familiar with Python + (or you're really intent on diving into &SCons; + and just picking up things as you go). + + </para> + + <para> + + Python has a lot of good + documentation freely available on-line + to help you get started. + The standard tutorial is available at XXX. + + + </para> + + <para> + + Python is very easy to pick up. + + </para> + + <para> + + Python variables must be assigned to before they can be referenced. + + </para> + + <para> + + Assignment is like most programming languages: + + x = 1 + 2 + z = 3 * x + + </para> + + <para> + + Function calls look like most language function calls: + + a = f(g) + + </para> + + <para> + + Define functions like so: + + def func(arg1, arg2): + return arg1 * arg 2 + + The number of parameters + + </para> + + <para> + + Strings can be enclosed in single quotes or double quotes, + backslashes are used to escape characters, + triple-quote syntax lets you include quotes and newlines, + raw strings begin with 'r'. + + </para> + + <para> + + Lists are enclosed in square brackets, + list items are separated by commas. + List references use square brackets and integer index values, + slice notation lets you select, delete or replace a range. + + </para> + + <para> + + Dictionaries (hashes) are enclosed in curly brackets, + : separates keys from values, + , separates items. + Dictionary values are referenced using square brackets. + + </para> + + <para> + + Access class attributes (including methods) using a '.'. + + </para> + + <para> + + if: statements look like + + elif: statements look like + + else: statements look like + + </para> + + <para> + + for: statements look like + + while: statements look like + + break statements look like + + continue statements look like + + </para> + + <para> + + pass + + </para> + + </section> + + --> diff --git a/doc/user/build-install.xml b/doc/user/build-install.xml new file mode 100644 index 0000000..ab289b1 --- /dev/null +++ b/doc/user/build-install.xml @@ -0,0 +1,719 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + This chapter will take you through the basic steps + of installing &SCons; on your system, + and building &SCons; if you don't have a + pre-built package available + (or simply prefer the flexibility of building it yourself). + Before that, however, this chapter will also describe the basic steps + involved in installing Python on your system, + in case that is necessary. + Fortunately, both &SCons; and Python + are very easy to install on almost any system, + and Python already comes installed on many systems. + + </para> + + <!-- + + <para> + + Lastly, this chapter also contains a section that + provides a brief overview of the Python programming language, + which is the language used to implement &SCons;, + and which forms the basis of the &SCons; configuration files. + Becoming familiar with some Python concepts will make it easier + to understand many of the examples in this User's Guide. + Nevertheless, it <emphasis>is</emphasis> possible + to configure simple &SCons; builds without knowing Python, + so you can skip this section if you + want to dive in and pick up things + by example- -or, of course, if you are + already familiar with Python. + + </para> + + --> + + <section> + <title>Installing Python</title> + + <para> + + Because &SCons; is written in Python, + you must obviously have Python installed on your system + to use &SCons;. + Before you try to install Python, + you should check to see if Python is already + available on your system by typing + <userinput>python -V</userinput> + (capital 'V') + or + <userinput>python --version</userinput> + at your system's command-line prompt. + + </para> + + <screen> + $ <userinput>python -V</userinput> + Python 2.5.1 + </screen> + + <para> + + And on a Windows system with Python installed: + + </para> + + <screen> + C:\><userinput>python -V</userinput> + Python 2.5.1 + </screen> + + <para> + + If Python is not installed on your system, + you will see an error message + stating something like "command not found" + (on UNIX or Linux) + or "'python' is not recognized + as an internal or external command, operable progam or batch file" + (on Windows). + In that case, you need to install Python + before you can install &SCons;. + + </para> + + <para> + + (Note that the <option>-V</option> option + was added to Python version 2.0, + so if your system only has an earlier version available + you may see an + <literal>"Unknown option: -V"</literal> + error message.) + + </para> + + <para> + + The standard location for information + about downloading and installing Python is + <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>. + See that page for information about + how to download and install Python on your system. + + </para> + + <para> + + &SCons; will work with any version of Python from 1.5.2 or later. + If you need to install Python and have a choice, + we recommend using the most recent Python 2.5 version available. + Python 2.5 has significant improvements + that help speed up the performance of &SCons;. + + </para> + + </section> + + <section> + <title>Installing &SCons; From Pre-Built Packages</title> + + <para> + + &SCons; comes pre-packaged for installation on a number of systems, + including Linux and Windows systems. + You do not need to read this entire section, + you should need to read only the section + appropriate to the type of system you're running on. + + </para> + + <section> + <title>Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems</title> + + <para> + + &SCons; comes in RPM (Red Hat Package Manager) format, + pre-built and ready to install on Red Hat Linux, + Fedora, + or any other Linux distribution that uses RPM. + Your distribution may + already have an &SCons; RPM built specifically for it; + many do, including SUSE, Mandrake and Fedora. + You can check for the availability of an &SCons; RPM + on your distribution's download servers, + or by consulting an RPM search site like + <ulink url="http://www.rpmfind.net/">http://www.rpmfind.net/</ulink> or + <ulink url="http://rpm.pbone.net/">http://rpm.pbone.net/</ulink>. + + </para> + + <para> + + If your distribution supports installation via + <application>yum</application>, + you should be able to install &SCons; by running: + + </para> + + <screen> + # <userinput>yum install scons</userinput> + </screen> + + <para> + + If your Linux distribution does not already have + a specific &SCons; RPM file, + you can download and install from the + generic RPM provided by the &SCons; project. + This will install the + SCons script(s) in <filename>/usr/bin</filename>, + and the SCons library modules in + <filename>/usr/lib/scons</filename>. + + </para> + + <para> + + To install from the command line, simply download the + appropriate <filename>.rpm</filename> file, + and then run: + + </para> + + <screen> + # <userinput>rpm -Uvh scons-1.2.0.d20091224-1.noarch.rpm</userinput> + </screen> + + <para> + + Or, you can use a graphical RPM package manager. + See your package manager application's documention + for specific instructions about + how to use it to install a downloaded RPM. + + </para> + + </section> + + <section> + <title>Installing &SCons; on Debian Linux Systems</title> + + <para> + + Debian Linux systems use a different package management + format that also makes it very easy to install &SCons;. + + </para> + + <para> + + If your system is connected to the Internet, + you can install the latest official Debian package + by running: + + </para> + + <screen> + # <userinput>apt-get install scons</userinput> + </screen> + + <!-- + + <para> + + Alternatively, + you can download the Debian package built + by the &SCons; project + and install it manually by running: + + </para> + + <screen> + # <userinput>db-XXX scons-*.deb</userinput> + </screen> + + --> + + </section> + + <section> + <title>Installing &SCons; on Windows Systems</title> + + <para> + + &SCons; provides a Windows installer + that makes installation extremely easy. + Download the <filename>scons-1.2.0.d20091224.win32.exe</filename> + file from the &SCons; download page at + <ulink url="http://www.scons.org/download.php">http://www.scons.org/download.php</ulink>. + Then all you need to do is execute the file + (usually by clicking on its icon in Windows Explorer). + These will take you through a small + sequence of windows that will install + &SCons; on your system. + + <!-- + Things are a little more complicated + if you are using the Cygwin version of Python. + This is because Cygwin + tries to make a Windows system look more + POSIX-like (or UNIX-like or Linux-like, if you prefer) + by having the Cygwin utilities, + including Cygwin Python, + interpret file name arguments on the command line + using the forward-slash (<filename>/</filename>) + as the directory separator, + instead of the normal Windows behavior of the + backslash (<filename>\</filename>) as the directory separator. + --> + + </para> + + <!-- + + <section> + <title>Installing &SCons; on Windows Systems Without Cygwin Python</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Installing &SCons; on Windows Systems With Cygwin Python</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <!-- + + XXX - don't have the kinks worked out on how to + get these to display properly in all formats, + so comment them out for now. + + <screenshot> + <mediaobject> + <imageobject> + <imagedata fileref="SCons-win32-install-1.jpg" format="jpg" align="center"> + </imageobject> + </mediaobject> + </screenshot> + + <screenshot> + <mediaobject> + <imageobject> + <imagedata fileref="SCons-win32-install-2.jpg" format="jpg" align="center"> + </imageobject> + </mediaobject> + </screenshot> + + <screenshot> + <mediaobject> + <imageobject> + <imagedata fileref="SCons-win32-install-3.jpg" format="jpg" align="center"> + </imageobject> + </mediaobject> + </screenshot> + + <screenshot> + <mediaobject> + <imageobject> + <imagedata fileref="SCons-win32-install-4.jpg" format="jpg" align="center"> + </imageobject> + </mediaobject> + </screenshot> + + --> + + </section> + + </section> + + <section> + <title>Building and Installing &SCons; on Any System</title> + + <para> + + If a pre-built &SCons; package is not available for your system, + then you can still easily build and install &SCons; using the native + Python <filename>distutils</filename> package. + + </para> + + <para> + + The first step is to download either the + <filename>scons-1.2.0.d20091224.tar.gz</filename> + or <filename>scons-1.2.0.d20091224.zip</filename>, + which are available from the SCons download page at + <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>. + + </para> + + <para> + + Unpack the archive you downloaded, + using a utility like <application>tar</application> + on Linux or UNIX, + or <application>WinZip</application> on Windows. + This will create a directory called + <filename>scons-1.2.0.d20091224</filename>, + usually in your local directory. + Then change your working directory to that directory + and install &SCons; by executing the following commands: + + </para> + + <screen> + # <userinput>cd scons-1.2.0.d20091224</userinput> + # <userinput>python setup.py install</userinput> + </screen> + + <para> + + This will build &SCons;, + install the &scons; script + in the default system scripts directory + (<filename>/usr/local/bin</filename> or + <filename>C:\Python25\Scripts</filename>), + and will install the &SCons; build engine + in an appropriate stand-alone library directory + (<filename>/usr/local/lib/scons</filename> or + <filename>C:\Python25\scons</filename>). + Because these are system directories, + you may need root (on Linux or UNIX) or Administrator (on Windows) + privileges to install &SCons; like this. + + </para> + + <!-- + + <section> + <title>Building and Installing &SCons; in the Standard Python Library Directories</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <section> + <title>Building and Installing Multiple Versions of &SCons; Side-by-Side</title> + + <para> + + The &SCons; <filename>setup.py</filename> script + has some extensions that support + easy installation of multiple versions of &SCons; + in side-by-side locations. + This makes it easier to download and + experiment with different versions of &SCons; + before moving your official build process to a new version, + for example. + + </para> + + <para> + + To install &SCons; in a version-specific location, + add the <option>--version-lib</option> option + when you call <filename>setup.py</filename>: + + </para> + + <screen> + # <userinput>python setup.py install --version-lib</userinput> + </screen> + + <para> + + This will install the &SCons; build engine + in the + <filename>/usr/lib/scons-1.2.0.d20091224</filename> + or + <filename>C:\Python25\scons-1.2.0.d20091224</filename> + directory, for example. + + </para> + + <para> + + If you use the <option>--version-lib</option> option + the first time you install &SCons;, + you do not need to specify it each time you install + a new version. + The &SCons; <filename>setup.py</filename> script + will detect the version-specific directory name(s) + and assume you want to install all versions + in version-specific directories. + You can override that assumption in the future + by explicitly specifying the <option>--standalone-lib</option> option. + + </para> + + </section> + + <section> + <title>Installing &SCons; in Other Locations</title> + + <para> + + You can install &SCons; in locations other than + the default by specifying the <option>--prefix=</option> option: + + </para> + + <screen> + # <userinput>python setup.py install --prefix=/opt/scons</userinput> + </screen> + + <para> + + This would + install the <application>scons</application> script in + <filename>/opt/scons/bin</filename> + and the build engine in + <filename>/opt/scons/lib/scons</filename>, + + </para> + + <para> + + Note that you can specify both the <option>--prefix=</option> + and the <option>--version-lib</option> options + at the same type, + in which case <filename>setup.py</filename> + will install the build engine + in a version-specific directory + relative to the specified prefix. + Adding <option>--version-lib</option> to the + above example would install the build engine in + <filename>/opt/scons/lib/scons-1.2.0.d20091224</filename>. + + </para> + + </section> + + <section> + <title>Building and Installing &SCons; Without Administrative Privileges</title> + + <para> + + If you don't have the right privileges to install &SCons; + in a system location, + simply use the <literal>--prefix=</literal> option + to install it in a location of your choosing. + For example, + to install &SCons; in appropriate locations + relative to the user's <literal>$HOME</literal> directory, + the &scons; script in + <filename>$HOME/bin</filename> + and the build engine in + <filename>$HOME/lib/scons</filename>, + simply type: + + </para> + + <screen> + $ <userinput>python setup.py install --prefix=$HOME</userinput> + </screen> + + <para> + + You may, of course, specify any other location you prefer, + and may use the <option>--version-lib</option> option + if you would like to install version-specific directories + relative to the specified prefix. + + </para> + + <para> + + This can also be used to experiment with a newer + version of &SCons; than the one installed + in your system locations. + Of course, the location in which you install the + newer version of the &scons; script + (<filename>$HOME/bin</filename> in the above example) + must be configured in your &PATH; variable + before the directory containing + the system-installed version + of the &scons; script. + + </para> + + </section> + + </section> + + <!-- + + <section> + <title>Python Basics</title> + + <para> + + This section will provide a brief overview of + the Python programming language. + Skip this section if you are already familiar with Python + (or you're really intent on diving into &SCons; + and just picking up things as you go). + + </para> + + <para> + + Python has a lot of good + documentation freely available on-line + to help you get started. + The standard tutorial is available at XXX. + + + </para> + + <para> + + Python is very easy to pick up. + + </para> + + <para> + + Python variables must be assigned to before they can be referenced. + + </para> + + <para> + + Assignment is like most programming languages: + + x = 1 + 2 + z = 3 * x + + </para> + + <para> + + Function calls look like most language function calls: + + a = f(g) + + </para> + + <para> + + Define functions like so: + + def func(arg1, arg2): + return arg1 * arg 2 + + The number of parameters + + </para> + + <para> + + Strings can be enclosed in single quotes or double quotes, + backslashes are used to escape characters, + triple-quote syntax lets you include quotes and newlines, + raw strings begin with 'r'. + + </para> + + <para> + + Lists are enclosed in square brackets, + list items are separated by commas. + List references use square brackets and integer index values, + slice notation lets you select, delete or replace a range. + + </para> + + <para> + + Dictionaries (hashes) are enclosed in curly brackets, + : separates keys from values, + , separates items. + Dictionary values are referenced using square brackets. + + </para> + + <para> + + Access class attributes (including methods) using a '.'. + + </para> + + <para> + + if: statements look like + + elif: statements look like + + else: statements look like + + </para> + + <para> + + for: statements look like + + while: statements look like + + break statements look like + + continue statements look like + + </para> + + <para> + + pass + + </para> + + </section> + + --> diff --git a/doc/user/builders-built-in.in b/doc/user/builders-built-in.in new file mode 100644 index 0000000..245cb8c --- /dev/null +++ b/doc/user/builders-built-in.in @@ -0,0 +1,963 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; provides the ability to build a lot of different + types of files right "out of the box." + So far, we've been using &SCons;' ability to build + programs, objects and libraries to + illustrate much of the underlying functionality of &SCons; + This section will describe all of the different + types of files that you can build with &SCons;, + and the built-in &Builder; objects used to build them. + By default, all of the &Builder; objects in this section + can be built either with or without an explicit + construction environment. + + </para> + + <section> + <title>Programs: the &Program; Builder</title> + + <para> + + As we've seen, the &b-link-Program; Builder + is used to build an executable program. + The &source; argument is one or more + source-code files or object files, + and the ⌖ argument is the + name of the executable program name to be created. + For example: + + </para> + + <programlisting> + Program('prog', 'file1.o') + </programlisting> + + <para> + + Will create the &prog; + executable on a POSIX system, + the &prog_exe; executable on a Windows system. + + </para> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-PROGPREFIX; + and + &cv-link-PROGSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(PROGPREFIX='my', PROGSUFFIX='.xxx') + env.Program('prog', ['file1.o', 'file2.o']) + </programlisting> + + <para> + + Will create a program named + <filename>myprog.xxx</filename> + regardless of the system on which it is run. + + </para> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + becomes the base of the target + program created. + For example: + + </para> + + <programlisting> + Program(['hello.c', 'goodbye.c']) + </programlisting> + + <para> + + Will create the &hello; + executable on a POSIX system, + the &hello_exe; executable on a Windows system. + + </para> + + <para> + + Two construction variables control what libraries + will be linked with the resulting program. + The &cv-link-LIBS; variable is a list of the names of + libraries that will be linked into any programs, + and the &cv-link-LIBPATH; variables is a list of + directories that will be searched for + the specified libraries. + &SCons; will construct the right command-line + options for the running system. + For example: + + </para> + + <scons_example name="libs"> + <file name="SConstruct" printme="1"> + env = Environment(LIBS = ['foo1', 'foo2'], + LIBPATH = ['/usr/dir1', 'dir2']) + env.Program(['hello.c', 'goodbye.c']) + </file> + <file name="hello.c"> + int hello() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int goodbye() { printf("Goodbye, world!\n"); } + </file> + </scons_example> + + <para> + + Will execute as follows on a POSIX system: + + </para> + + <scons_output example="libs" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And execute as follows on a Windows system: + + </para> + + <scons_output example="libs" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + The &cv-LIBS; construction variable + is turned into command line options + by appending the &cv-link-LIBLINKPREFIX; and &cv-link-LIBLINKSUFFIX; + construction variables to the beginning and end, + respectively, of each specified library. + + </para> + + <para> + + The &cv-LIBPATH; construction variable + is turned into command line options + by appending the &cv-link-LIBDIRPREFIX; and &cv-link-LIBDIRSUFFIX; + construction variables to the beginning and end, + respectively, of each specified library. + + </para> + + <para> + + Other relevant construction variables + include those used by the &b-link-Object; + builders to affect how the + source files specified as input to the &t-Program; + builders are turned into object files; + see the next section. + + </para> + + <para> + + The command line used to control how a program is linked + is specified by the &cv-link-LINKCOM; construction variable. + By default, it uses the + &cv-link-LINK; construction variable + and the &cv-link-LINKFLAGS; construction variable. + + </para> + + </section> + + <section> + <title>Object-File Builders</title> + + <para> + + &SCons; provides separate Builder objects + to create static and shared object files. + The distinction becomes especially important when + archiving object files into different types of libraries. + + </para> + + <section> + <title>The &StaticObject; Builder</title> + + <para> + + The &b-link-StaticObject; Builder + is used to build an object file + suitable for static linking into a program, + or for inclusion in a static library. + The &source; argument is a single source-code file, + and the ⌖ argument is the + name of the static object file to be created. + For example: + + </para> + + <programlisting> + StaticObject('file', 'file.c') + </programlisting> + + <para> + + Will create the &file_o; + object file on a POSIX system, + the &file_obj; executable on a Windows system. + + </para> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-OBJPREFIX; + and + &cv-link-OBJSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(OBJPREFIX='my', OBJSUFFIX='.xxx') + env.StaticObject('file', 'file.c') + </programlisting> + + <para> + + Will create an object file named + <filename>myfile.xxx</filename> + regardless of the system on which it is run. + + </para> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + beomces the base of the name + of the static object file to be created. + For example: + + </para> + + <programlisting> + StaticObject('file.c') + </programlisting> + + <para> + + Will create the &file_o; + executable on a POSIX system, + the &file_obj; executable on a Windows system. + + </para> + + </section> + + <section> + <title>The &SharedObject; Builder</title> + + <para> + + The &b-link-SharedObject; Builder + is used to build an object file + suitable for shared linking into a program, + or for inclusion in a shared library. + The &source; argument is a single source-code file, + and the ⌖ argument is the + name of the shared object file to be created. + For example: + + </para> + + <programlisting> + SharedObject('file', 'file.c') + </programlisting> + + <para> + + Will create the &file_o; + object file on a POSIX system, + the &file_obj; executable on a Windows system. + + </para> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-SHOBJPREFIX; + and + &cv-link-SHOBJSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(SHOBJPREFIX='my', SHOBJSUFFIX='.xxx') + env.SharedObject('file', 'file.c') + </programlisting> + + <para> + + Will create an object file named + <filename>myfile.xxx</filename> + regardless of the system on which it is run. + + </para> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + becomes the base of the name + of the shared object file to be created. + For example: + + </para> + + <programlisting> + SharedObject('file.c') + </programlisting> + + <para> + + Will create the &file_o; + executable on a POSIX system, + the &file_obj; executable on a Windows system. + + </para> + + </section> + + <section> + <title>The &Object; Builder</title> + + <para> + + The &b-link-Object; Builder is a synonym for &b-link-StaticObject; + and is completely equivalent. + + </para> + + </section> + + </section> + + <section> + <title>Library Builders</title> + + <para> + + &SCons; provides separate Builder objects + to create static and shared libraries. + + </para> + + <section> + <title>The &StaticLibrary; Builder</title> + + <para> + + The &b-link-StaticLibrary; Builder + is used to create a library + suitable for static linking into a program. + The &source; argument is one or more + source-code files or object files, + and the ⌖ argument is the + name of the static library to be created. + For example: + + </para> + + <programlisting> + StaticLibrary('foo', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-LIBPREFIX; + and + &cv-link-LIBSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(LIBPREFIX='my', LIBSUFFIX='.xxx') + env.StaticLibrary('lib', ['file1.o', 'file2.o']) + </programlisting> + + <para> + + Will create an object file named + <filename>mylib.xxx</filename> + regardless of the system on which it is run. + + </para> + + <programlisting> + StaticLibrary('foo', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + becomes the base of the name of the static object file to be created. + For example: + + </para> + + <programlisting> + StaticLibrary(['file.c', 'another.c']) + </programlisting> + + <para> + + Will create the &libfile_a; + library on a POSIX system, + the &file_lib; library on a Windows system. + + </para> + + </section> + + <section> + <title>The &SharedLibrary; Builder</title> + + <para> + + The &b-link-SharedLibrary; Builder + is used to create a shared library + suitable for linking with a program. + The &source; argument is one or more + source-code files or object files, + and the ⌖ argument is the + name of the shared library to be created. + For example: + + </para> + + <programlisting> + SharedLibrary('foo', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-SHLIBPREFIX; + and + &cv-link-SHLIBSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(SHLIBPREFIX='my', SHLIBSUFFIX='.xxx') + env.SharedLibrary('shared', ['file1.o', 'file2.o']) + </programlisting> + + <para> + + Will create an object file named + <filename>myshared.xxx</filename> + regardless of the system on which it is run. + + </para> + + <programlisting> + SharedLibrary('foo', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + becomes the base of the name of the shared library to be created. + For example: + + </para> + + <programlisting> + SharedLibrary(['file.c', 'another.c']) + </programlisting> + + <para> + + Will create the &libfile_so; + library on a POSIX system, + the &file_dll; library on a Windows system. + + </para> + + </section> + + <section> + <title>The &Library; Builder</title> + + <para> + + The &b-link-Library; Builder is a synonym for &b-link-StaticLibrary; + and is completely equivalent. + + </para> + + </section> + + </section> + + <section> + <title>Pre-Compiled Headers: the &PCH; Builder</title> + + <para> + + XXX PCH() + + </para> + + </section> + + <section> + <title>Microsoft Visual C++ Resource Files: the &RES; Builder</title> + + <para> + + XXX RES() + + </para> + + </section> + + <section> + <title>Source Files</title> + + <para> + + By default + &SCons; supports two Builder objects + that know how to build source files + from other input files. + These are typically invoked "internally" + to turn files that need preprocessing into other source files. + + </para> + + <section> + <title>The &CFile; Builder</title> + + <para> + + XXX CFile() + + </para> + + <programlisting> + XXX CFile() programlisting + </programlisting> + + <screen> + XXX CFile() screen + </screen> + + </section> + + <section> + <title>The &CXXFile; Builder</title> + + <para> + + XXX CXXFILE() + + </para> + + <programlisting> + XXX CXXFILE() programlisting + </programlisting> + + <screen> + XXX CXXFILE() screen + </screen> + + </section> + + </section> + + <section> + <title>Documents</title> + + <para> + + &SCons; provides a number of Builder objects + for creating different types of documents. + + </para> + + <section> + <title>The &DVI; Builder</title> + + <para> + + XXX DVI() para + + </para> + + <programlisting> + XXX DVI() programlisting + </programlisting> + + <screen> + XXX DVI() screen + </screen> + + </section> + + <section> + <title>The &PDF; Builder</title> + + <para> + + XXX PDF() para + + </para> + + </section> + + <section> + <title>The &PostScript; Builder</title> + + <para> + + XXX PostScript() para + + </para> + + <programlisting> + XXX PostScript() programlisting + </programlisting> + + <screen> + XXX PostScript() screen + </screen> + + </section> + + </section> + + <section> + <title>Archives</title> + + <para> + + &SCons; provides Builder objects + for creating two different types of archive files. + + </para> + + <section> + <title>The &Tar; Builder</title> + + <para> + + The &b-link-Tar; Builder object uses the &tar; + utility to create archives of files + and/or directory trees: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Tar('out1.tar', ['file1', 'file2']) + env.Tar('out2', 'directory') + </file> + <file name="file1"> + file1 + </file> + <file name="file2"> + file2 + </file> + <file name="directory/file3"> + directory/file3 + </file> + </scons_example> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> + + <para> + + One common requirement when creating a &tar; archive + is to create a compressed archive using the + <option>-z</option> option. + This is easily handled by specifying + the value of the &cv-link-TARFLAGS; variable + when you create the construction environment. + Note, however, that the <option>-c</option> used to + to instruct &tar; to create the archive + is part of the default value of &cv-TARFLAGS;, + so you need to set it both options: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + env = Environment(TARFLAGS = '-c -z') + env.Tar('out.tar.gz', 'directory') + </file> + <file name="directory/file"> + directory/file + </file> + </scons_example> + + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> + + <para> + + you may also wish to set the value of the + &cv-link-TARSUFFIX; construction variable + to your desired suffix for compress &tar; archives, + so that &SCons; can append it to the target file name + without your having to specify it explicitly: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> + env = Environment(TARFLAGS = '-c -z', + TARSUFFIX = '.tgz') + env.Tar('out', 'directory') + </file> + <file name="directory/file"> + directory/file + </file> + </scons_example> + + <scons_output example="ex3" os="posix"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> + + </section> + + <section> + <title>The &Zip; Builder</title> + + <para> + + The &b-link-Zip; Builder object creates archives of files + and/or directory trees in the ZIP file format. + Python versions 1.6 or later + contain an internal &zipfile; module + that &SCons; will use. + In this case, given the following + &SConstruct; file: + + </para> + + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Zip('out', ['file1', 'file2']) + </file> + <file name="file1"> + file1 + </file> + <file name="file2"> + file2 + </file> + </scons_example> + + <para> + + Your output will reflect the fact + that an internal Python function + is being used to create the output ZIP archive: + + </para> + + <scons_output example="ex4" os="posix"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> + + <para> + + If you're using Python version 1.5.2 to run &SCons;, + then &SCons; will try to use an external + &zip; program as follows: + + </para> + + <screen> + % <userinput>scons -Q .</userinput> + zip /home/my/project/zip.out file1 file2 + </screen> + + </section> + + </section> + + <section> + <title>Java</title> + + <para> + + &SCons; provides Builder objects + for creating various types of Java output files. + + </para> + + <section> + <title>Building Class Files: the &Java; Builder</title> + + <para> + + The &b-link-Java; builder takes one or more input + <filename>.java</filename> files + and turns them into one or more + <filename>.class</filename> files + Unlike most builders, however, + the &Java; builder takes + target and source <emphasis>directories</emphasis>, + not files, as input. + + </para> + + <programlisting> + env = Environment() + env.Java(target = 'classes', source = 'src') + </programlisting> + + <para> + + The &Java; builder will then + search the specified source directory + tree for all <filename>.java</filename> files, + and pass any out-of-date + + </para> + + <screen> + XXX Java() screen + </screen> + + </section> + + <section> + <title>The &Jar; Builder</title> + + <para> + + XXX The &Jar; builder object + + </para> + + <programlisting> + env = Environment() + env.Java(target = 'classes', source = 'src') + env.Jar(target = '', source = 'classes') + </programlisting> + + <screen> + XXX Jar() screen + </screen> + + </section> + + <section> + <title>Building C header and stub files: the &JavaH; Builder</title> + + <para> + + XXX JavaH() para + + </para> + + <programlisting> + XXX JavaH() programlisting + </programlisting> + + <screen> + XXX JavaH() screen + </screen> + + </section> + + <section> + <title>Building RMI stub and skeleton class files: the &RMIC; Builder</title> + + <para> + + XXX RMIC() para + + </para> + + <programlisting> + XXX RMIC() programlisting + </programlisting> + + <screen> + XXX RMIC() screen + </screen> + + </section> + + </section> diff --git a/doc/user/builders-built-in.xml b/doc/user/builders-built-in.xml new file mode 100644 index 0000000..bee5b38 --- /dev/null +++ b/doc/user/builders-built-in.xml @@ -0,0 +1,949 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; provides the ability to build a lot of different + types of files right "out of the box." + So far, we've been using &SCons;' ability to build + programs, objects and libraries to + illustrate much of the underlying functionality of &SCons; + This section will describe all of the different + types of files that you can build with &SCons;, + and the built-in &Builder; objects used to build them. + By default, all of the &Builder; objects in this section + can be built either with or without an explicit + construction environment. + + </para> + + <section> + <title>Programs: the &Program; Builder</title> + + <para> + + As we've seen, the &b-link-Program; Builder + is used to build an executable program. + The &source; argument is one or more + source-code files or object files, + and the ⌖ argument is the + name of the executable program name to be created. + For example: + + </para> + + <programlisting> + Program('prog', 'file1.o') + </programlisting> + + <para> + + Will create the &prog; + executable on a POSIX system, + the &prog_exe; executable on a Windows system. + + </para> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-PROGPREFIX; + and + &cv-link-PROGSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(PROGPREFIX='my', PROGSUFFIX='.xxx') + env.Program('prog', ['file1.o', 'file2.o']) + </programlisting> + + <para> + + Will create a program named + <filename>myprog.xxx</filename> + regardless of the system on which it is run. + + </para> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + becomes the base of the target + program created. + For example: + + </para> + + <programlisting> + Program(['hello.c', 'goodbye.c']) + </programlisting> + + <para> + + Will create the &hello; + executable on a POSIX system, + the &hello_exe; executable on a Windows system. + + </para> + + <para> + + Two construction variables control what libraries + will be linked with the resulting program. + The &cv-link-LIBS; variable is a list of the names of + libraries that will be linked into any programs, + and the &cv-link-LIBPATH; variables is a list of + directories that will be searched for + the specified libraries. + &SCons; will construct the right command-line + options for the running system. + For example: + + </para> + + <programlisting> + env = Environment(LIBS = ['foo1', 'foo2'], + LIBPATH = ['/usr/dir1', 'dir2']) + env.Program(['hello.c', 'goodbye.c']) + </programlisting> + + <para> + + Will execute as follows on a POSIX system: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o goodbye.o -c goodbye.c + cc -o hello.o -c hello.c + cc -o hello hello.o goodbye.o -L/usr/dir1 -Ldir2 -lfoo1 -lfoo2 + </screen> + + <para> + + And execute as follows on a Windows system: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fogoodbye.obj /c goodbye.c /nologo + cl /Fohello.obj /c hello.c /nologo + link /nologo /OUT:hello.exe /LIBPATH:\usr\dir1 /LIBPATH:dir2 foo1.lib foo2.lib hello.obj goodbye.obj + </screen> + + <para> + + The &cv-LIBS; construction variable + is turned into command line options + by appending the &cv-link-LIBLINKPREFIX; and &cv-link-LIBLINKSUFFIX; + construction variables to the beginning and end, + respectively, of each specified library. + + </para> + + <para> + + The &cv-LIBPATH; construction variable + is turned into command line options + by appending the &cv-link-LIBDIRPREFIX; and &cv-link-LIBDIRSUFFIX; + construction variables to the beginning and end, + respectively, of each specified library. + + </para> + + <para> + + Other relevant construction variables + include those used by the &b-link-Object; + builders to affect how the + source files specified as input to the &t-Program; + builders are turned into object files; + see the next section. + + </para> + + <para> + + The command line used to control how a program is linked + is specified by the &cv-link-LINKCOM; construction variable. + By default, it uses the + &cv-link-LINK; construction variable + and the &cv-link-LINKFLAGS; construction variable. + + </para> + + </section> + + <section> + <title>Object-File Builders</title> + + <para> + + &SCons; provides separate Builder objects + to create static and shared object files. + The distinction becomes especially important when + archiving object files into different types of libraries. + + </para> + + <section> + <title>The &StaticObject; Builder</title> + + <para> + + The &b-link-StaticObject; Builder + is used to build an object file + suitable for static linking into a program, + or for inclusion in a static library. + The &source; argument is a single source-code file, + and the ⌖ argument is the + name of the static object file to be created. + For example: + + </para> + + <programlisting> + StaticObject('file', 'file.c') + </programlisting> + + <para> + + Will create the &file_o; + object file on a POSIX system, + the &file_obj; executable on a Windows system. + + </para> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-OBJPREFIX; + and + &cv-link-OBJSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(OBJPREFIX='my', OBJSUFFIX='.xxx') + env.StaticObject('file', 'file.c') + </programlisting> + + <para> + + Will create an object file named + <filename>myfile.xxx</filename> + regardless of the system on which it is run. + + </para> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + beomces the base of the name + of the static object file to be created. + For example: + + </para> + + <programlisting> + StaticObject('file.c') + </programlisting> + + <para> + + Will create the &file_o; + executable on a POSIX system, + the &file_obj; executable on a Windows system. + + </para> + + </section> + + <section> + <title>The &SharedObject; Builder</title> + + <para> + + The &b-link-SharedObject; Builder + is used to build an object file + suitable for shared linking into a program, + or for inclusion in a shared library. + The &source; argument is a single source-code file, + and the ⌖ argument is the + name of the shared object file to be created. + For example: + + </para> + + <programlisting> + SharedObject('file', 'file.c') + </programlisting> + + <para> + + Will create the &file_o; + object file on a POSIX system, + the &file_obj; executable on a Windows system. + + </para> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-SHOBJPREFIX; + and + &cv-link-SHOBJSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(SHOBJPREFIX='my', SHOBJSUFFIX='.xxx') + env.SharedObject('file', 'file.c') + </programlisting> + + <para> + + Will create an object file named + <filename>myfile.xxx</filename> + regardless of the system on which it is run. + + </para> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + becomes the base of the name + of the shared object file to be created. + For example: + + </para> + + <programlisting> + SharedObject('file.c') + </programlisting> + + <para> + + Will create the &file_o; + executable on a POSIX system, + the &file_obj; executable on a Windows system. + + </para> + + </section> + + <section> + <title>The &Object; Builder</title> + + <para> + + The &b-link-Object; Builder is a synonym for &b-link-StaticObject; + and is completely equivalent. + + </para> + + </section> + + </section> + + <section> + <title>Library Builders</title> + + <para> + + &SCons; provides separate Builder objects + to create static and shared libraries. + + </para> + + <section> + <title>The &StaticLibrary; Builder</title> + + <para> + + The &b-link-StaticLibrary; Builder + is used to create a library + suitable for static linking into a program. + The &source; argument is one or more + source-code files or object files, + and the ⌖ argument is the + name of the static library to be created. + For example: + + </para> + + <programlisting> + StaticLibrary('foo', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-LIBPREFIX; + and + &cv-link-LIBSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(LIBPREFIX='my', LIBSUFFIX='.xxx') + env.StaticLibrary('lib', ['file1.o', 'file2.o']) + </programlisting> + + <para> + + Will create an object file named + <filename>mylib.xxx</filename> + regardless of the system on which it is run. + + </para> + + <programlisting> + StaticLibrary('foo', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + becomes the base of the name of the static object file to be created. + For example: + + </para> + + <programlisting> + StaticLibrary(['file.c', 'another.c']) + </programlisting> + + <para> + + Will create the &libfile_a; + library on a POSIX system, + the &file_lib; library on a Windows system. + + </para> + + </section> + + <section> + <title>The &SharedLibrary; Builder</title> + + <para> + + The &b-link-SharedLibrary; Builder + is used to create a shared library + suitable for linking with a program. + The &source; argument is one or more + source-code files or object files, + and the ⌖ argument is the + name of the shared library to be created. + For example: + + </para> + + <programlisting> + SharedLibrary('foo', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + &cv-link-SHLIBPREFIX; + and + &cv-link-SHLIBSUFFIX; + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(SHLIBPREFIX='my', SHLIBSUFFIX='.xxx') + env.SharedLibrary('shared', ['file1.o', 'file2.o']) + </programlisting> + + <para> + + Will create an object file named + <filename>myshared.xxx</filename> + regardless of the system on which it is run. + + </para> + + <programlisting> + SharedLibrary('foo', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + becomes the base of the name of the shared library to be created. + For example: + + </para> + + <programlisting> + SharedLibrary(['file.c', 'another.c']) + </programlisting> + + <para> + + Will create the &libfile_so; + library on a POSIX system, + the &file_dll; library on a Windows system. + + </para> + + </section> + + <section> + <title>The &Library; Builder</title> + + <para> + + The &b-link-Library; Builder is a synonym for &b-link-StaticLibrary; + and is completely equivalent. + + </para> + + </section> + + </section> + + <section> + <title>Pre-Compiled Headers: the &PCH; Builder</title> + + <para> + + XXX PCH() + + </para> + + </section> + + <section> + <title>Microsoft Visual C++ Resource Files: the &RES; Builder</title> + + <para> + + XXX RES() + + </para> + + </section> + + <section> + <title>Source Files</title> + + <para> + + By default + &SCons; supports two Builder objects + that know how to build source files + from other input files. + These are typically invoked "internally" + to turn files that need preprocessing into other source files. + + </para> + + <section> + <title>The &CFile; Builder</title> + + <para> + + XXX CFile() + + </para> + + <programlisting> + XXX CFile() programlisting + </programlisting> + + <screen> + XXX CFile() screen + </screen> + + </section> + + <section> + <title>The &CXXFile; Builder</title> + + <para> + + XXX CXXFILE() + + </para> + + <programlisting> + XXX CXXFILE() programlisting + </programlisting> + + <screen> + XXX CXXFILE() screen + </screen> + + </section> + + </section> + + <section> + <title>Documents</title> + + <para> + + &SCons; provides a number of Builder objects + for creating different types of documents. + + </para> + + <section> + <title>The &DVI; Builder</title> + + <para> + + XXX DVI() para + + </para> + + <programlisting> + XXX DVI() programlisting + </programlisting> + + <screen> + XXX DVI() screen + </screen> + + </section> + + <section> + <title>The &PDF; Builder</title> + + <para> + + XXX PDF() para + + </para> + + </section> + + <section> + <title>The &PostScript; Builder</title> + + <para> + + XXX PostScript() para + + </para> + + <programlisting> + XXX PostScript() programlisting + </programlisting> + + <screen> + XXX PostScript() screen + </screen> + + </section> + + </section> + + <section> + <title>Archives</title> + + <para> + + &SCons; provides Builder objects + for creating two different types of archive files. + + </para> + + <section> + <title>The &Tar; Builder</title> + + <para> + + The &b-link-Tar; Builder object uses the &tar; + utility to create archives of files + and/or directory trees: + + </para> + + <programlisting> + env = Environment() + env.Tar('out1.tar', ['file1', 'file2']) + env.Tar('out2', 'directory') + </programlisting> + + <screen> + % <userinput>scons -Q .</userinput> + tar -c -f out1.tar file1 file2 + tar -c -f out2.tar directory + </screen> + + <para> + + One common requirement when creating a &tar; archive + is to create a compressed archive using the + <option>-z</option> option. + This is easily handled by specifying + the value of the &cv-link-TARFLAGS; variable + when you create the construction environment. + Note, however, that the <option>-c</option> used to + to instruct &tar; to create the archive + is part of the default value of &cv-TARFLAGS;, + so you need to set it both options: + + </para> + + <programlisting> + env = Environment(TARFLAGS = '-c -z') + env.Tar('out.tar.gz', 'directory') + </programlisting> + + <screen> + % <userinput>scons -Q .</userinput> + tar -c -z -f out.tar.gz directory + </screen> + + <para> + + you may also wish to set the value of the + &cv-link-TARSUFFIX; construction variable + to your desired suffix for compress &tar; archives, + so that &SCons; can append it to the target file name + without your having to specify it explicitly: + + </para> + + <programlisting> + env = Environment(TARFLAGS = '-c -z', + TARSUFFIX = '.tgz') + env.Tar('out', 'directory') + </programlisting> + + <screen> + % <userinput>scons -Q .</userinput> + tar -c -z -f out.tgz directory + </screen> + + </section> + + <section> + <title>The &Zip; Builder</title> + + <para> + + The &b-link-Zip; Builder object creates archives of files + and/or directory trees in the ZIP file format. + Python versions 1.6 or later + contain an internal &zipfile; module + that &SCons; will use. + In this case, given the following + &SConstruct; file: + + </para> + + <programlisting> + env = Environment() + env.Zip('out', ['file1', 'file2']) + </programlisting> + + <para> + + Your output will reflect the fact + that an internal Python function + is being used to create the output ZIP archive: + + </para> + + <screen> + % <userinput>scons -Q .</userinput> + zip(["out.zip"], ["file1", "file2"]) + </screen> + + <para> + + If you're using Python version 1.5.2 to run &SCons;, + then &SCons; will try to use an external + &zip; program as follows: + + </para> + + <screen> + % <userinput>scons -Q .</userinput> + zip /home/my/project/zip.out file1 file2 + </screen> + + </section> + + </section> + + <section> + <title>Java</title> + + <para> + + &SCons; provides Builder objects + for creating various types of Java output files. + + </para> + + <section> + <title>Building Class Files: the &Java; Builder</title> + + <para> + + The &b-link-Java; builder takes one or more input + <filename>.java</filename> files + and turns them into one or more + <filename>.class</filename> files + Unlike most builders, however, + the &Java; builder takes + target and source <emphasis>directories</emphasis>, + not files, as input. + + </para> + + <programlisting> + env = Environment() + env.Java(target = 'classes', source = 'src') + </programlisting> + + <para> + + The &Java; builder will then + search the specified source directory + tree for all <filename>.java</filename> files, + and pass any out-of-date + + </para> + + <screen> + XXX Java() screen + </screen> + + </section> + + <section> + <title>The &Jar; Builder</title> + + <para> + + XXX The &Jar; builder object + + </para> + + <programlisting> + env = Environment() + env.Java(target = 'classes', source = 'src') + env.Jar(target = '', source = 'classes') + </programlisting> + + <screen> + XXX Jar() screen + </screen> + + </section> + + <section> + <title>Building C header and stub files: the &JavaH; Builder</title> + + <para> + + XXX JavaH() para + + </para> + + <programlisting> + XXX JavaH() programlisting + </programlisting> + + <screen> + XXX JavaH() screen + </screen> + + </section> + + <section> + <title>Building RMI stub and skeleton class files: the &RMIC; Builder</title> + + <para> + + XXX RMIC() para + + </para> + + <programlisting> + XXX RMIC() programlisting + </programlisting> + + <screen> + XXX RMIC() screen + </screen> + + </section> + + </section> diff --git a/doc/user/builders-commands.in b/doc/user/builders-commands.in new file mode 100644 index 0000000..687d12d --- /dev/null +++ b/doc/user/builders-commands.in @@ -0,0 +1,156 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <!-- + + =head2 The C<Command> method + + + The C<Command> method is called as follows: + + Command $env <target>, <inputs>, <build action>; + + The target is made dependent upon the list of input files specified, and the + inputs must be built successfully or Cons will not attempt to build the + target. + + To specify a command with multiple targets, you can specify a reference to a + list of targets. In Perl, a list reference can be created by enclosing a + list in square brackets. Hence the following command: + + Command $env ['foo.h', 'foo.c'], 'foo.template', q( + gen %1 + ); + + could be used in a case where the command C<gen> creates two files, both + F<foo.h> and F<foo.c>. + + --> + + <para> + + Creating a &Builder; and attaching it to a &consenv; + allows for a lot of flexibility when you + want to re-use actions + to build multiple files of the same type. + This can, however, be cumbersome + if you only need to execute one specific command + to build a single file (or group of files). + For these situations, &SCons; supports a + &Command; &Builder; that arranges + for a specific action to be executed + to build a specific file or files. + This looks a lot like the other builders + (like &b-link-Program;, &b-link-Object;, etc.), + but takes as an additional argument + the command to be executed to build the file: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET") + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> + + <para> + + When executed, + &SCons; runs the specified command, + substituting &cv-link-SOURCE; and &cv-link-TARGET; + as expected: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + This is often more convenient than + creating a &Builder; object + and adding it to the &cv-link-BUILDERS; variable + of a &consenv; + + </para> + + <para> + + Note that the action you specify to the + &Command; &Builder; can be any legal &SCons; &Action;, + such as a Python function: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + env = Environment() + def build(target, source, env): + # Whatever it takes to build + return None + env.Command('foo.out', 'foo.in', build) + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> + + <para> + + Which executes as follows: + + </para> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded + in the source and target as well as of SCons 1.1, + so you can write: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> + env.Command('${SOURCE.basename}.out', 'foo.in', build) + </file> + </scons_example> + + + <para> + + which does the same thing as the previous example, but allows you + to avoid repeating yourself. + + </para> + diff --git a/doc/user/builders-commands.xml b/doc/user/builders-commands.xml new file mode 100644 index 0000000..111b1d2 --- /dev/null +++ b/doc/user/builders-commands.xml @@ -0,0 +1,146 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <!-- + + =head2 The C<Command> method + + + The C<Command> method is called as follows: + + Command $env <target>, <inputs>, <build action>; + + The target is made dependent upon the list of input files specified, and the + inputs must be built successfully or Cons will not attempt to build the + target. + + To specify a command with multiple targets, you can specify a reference to a + list of targets. In Perl, a list reference can be created by enclosing a + list in square brackets. Hence the following command: + + Command $env ['foo.h', 'foo.c'], 'foo.template', q( + gen %1 + ); + + could be used in a case where the command C<gen> creates two files, both + F<foo.h> and F<foo.c>. + + --> + + <para> + + Creating a &Builder; and attaching it to a &consenv; + allows for a lot of flexibility when you + want to re-use actions + to build multiple files of the same type. + This can, however, be cumbersome + if you only need to execute one specific command + to build a single file (or group of files). + For these situations, &SCons; supports a + &Command; &Builder; that arranges + for a specific action to be executed + to build a specific file or files. + This looks a lot like the other builders + (like &b-link-Program;, &b-link-Object;, etc.), + but takes as an additional argument + the command to be executed to build the file: + + </para> + + <programlisting> + env = Environment() + env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET") + </programlisting> + + <para> + + When executed, + &SCons; runs the specified command, + substituting &cv-link-SOURCE; and &cv-link-TARGET; + as expected: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + sed 's/x/y/' < foo.in > foo.out + </screen> + + <para> + + This is often more convenient than + creating a &Builder; object + and adding it to the &cv-link-BUILDERS; variable + of a &consenv; + + </para> + + <para> + + Note that the action you specify to the + &Command; &Builder; can be any legal &SCons; &Action;, + such as a Python function: + + </para> + + <programlisting> + env = Environment() + def build(target, source, env): + # Whatever it takes to build + return None + env.Command('foo.out', 'foo.in', build) + </programlisting> + + <para> + + Which executes as follows: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + build(["foo.out"], ["foo.in"]) + </screen> + + <para> + + Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded + in the source and target as well as of SCons 1.1, + so you can write: + + </para> + + <programlisting> + env.Command('${SOURCE.basename}.out', 'foo.in', build) + </programlisting> + + + <para> + + which does the same thing as the previous example, but allows you + to avoid repeating yourself. + + </para> + diff --git a/doc/user/builders-writing.in b/doc/user/builders-writing.in new file mode 100644 index 0000000..4f54d99 --- /dev/null +++ b/doc/user/builders-writing.in @@ -0,0 +1,1087 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head2 Adding new methods + +For slightly more demanding changes, you may wish to add new methods to the +C<cons> package. Here's an example of a very simple extension, +C<InstallScript>, which installs a tcl script in a requested location, but +edits the script first to reflect a platform-dependent path that needs to be +installed in the script: + + # cons::InstallScript - Create a platform dependent version of a shell + # script by replacing string ``#!your-path-here'' with platform specific + # path $BIN_DIR. + + sub cons::InstallScript { + my ($env, $dst, $src) = @_; + Command $env $dst, $src, qq( + sed s+your-path-here+$BIN_DIR+ %< > %> + chmod oug+x %> + ); + } + +Notice that this method is defined directly in the C<cons> package (by +prefixing the name with C<cons::>). A change made in this manner will be +globally visible to all environments, and could be called as in the +following example: + + InstallScript $env "$BIN/foo", "foo.tcl"; + +For a small improvement in generality, the C<BINDIR> variable could be +passed in as an argument or taken from the construction environment-,-as +C<%BINDIR>. + + +=head2 Overriding methods + +Instead of adding the method to the C<cons> name space, you could define a +new package which inherits existing methods from the C<cons> package and +overrides or adds others. This can be done using Perl's inheritance +mechanisms. + +The following example defines a new package C<cons::switch> which +overrides the standard C<Library> method. The overridden method builds +linked library modules, rather than library archives. A new +constructor is provided. Environments created with this constructor +will have the new library method; others won't. + + package cons::switch; + BEGIN {@ISA = 'cons'} + + sub new { + shift; + bless new cons(@_); + } + + sub Library { + my($env) = shift; + my($lib) = shift; + my(@objs) = Objects $env @_; + Command $env $lib, @objs, q( + %LD -r %LDFLAGS %< -o %> + ); + } + +This functionality could be invoked as in the following example: + + $env = new cons::switch(@overrides); + ... + Library $env 'lib.o', 'foo.c', 'bar.c'; + +--> + + <para> + + Although &SCons; provides many useful methods + for building common software products: + programs, libraries, documents. + you frequently want to be + able to build some other type of file + not supported directly by &SCons;. + Fortunately, &SCons; makes it very easy + to define your own &Builder; objects + for any custom file types you want to build. + (In fact, the &SCons; interfaces for creating + &Builder; objects are flexible enough and easy enough to use + that all of the the &SCons; built-in &Builder; objects + are created the mechanisms described in this section.) + + </para> + + <section> + <title>Writing Builders That Execute External Commands</title> + + <para> + + The simplest &Builder; to create is + one that executes an external command. + For example, if we want to build + an output file by running the contents + of the input file through a command named + <literal>foobuild</literal>, + creating that &Builder; might look like: + + </para> + + <programlisting> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + </programlisting> + + <para> + + All the above line does is create a free-standing + &Builder; object. + The next section will show us how to actually use it. + + </para> + + </section> + + <section> + <title>Attaching a Builder to a &ConsEnv;</title> + + <para> + + A &Builder; object isn't useful + until it's attached to a &consenv; + so that we can call it to arrange + for files to be built. + This is done through the &cv-link-BUILDERS; + &consvar; in an environment. + The &cv-BUILDERS; variable is a Python dictionary + that maps the names by which you want to call + various &Builder; objects to the objects themselves. + For example, if we want to call the + &Builder; we just defined by the name + <function>Foo</function>, + our &SConstruct; file might look like: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct"> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env = Environment(BUILDERS = {'Foo' : bld}) + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + env.Foo('file.foo', 'file.input') + </file> + <file name="file.input"> + file.input + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> + + <sconstruct> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env = Environment(BUILDERS = {'Foo' : bld}) + </sconstruct> + + <para> + + With the &Builder; attached to our &consenv; + with the name <function>Foo</function>, + we can now actually call it like so: + + </para> + + <programlisting> + env.Foo('file.foo', 'file.input') + </programlisting> + + <para> + + Then when we run &SCons; it looks like: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note, however, that the default &cv-BUILDERS; + variable in a &consenv; + comes with a default set of &Builder; objects + already defined: + &b-link-Program;, &b-link-Library;, etc. + And when we explicitly set the &cv-BUILDERS; variable + when we create the &consenv;, + the default &Builder;s are no longer part of + the environment: + + </para> + + <!-- + The ToolSurrogate stuff that's used to capture output initializes + SCons.Defaults.ConstructionEnvironment with its own list of TOOLS. + In this next example, we want to show the user that when they + set the BUILDERS explicitly, the call to env.Program() generates + an AttributeError. This won't happen with all of the default + ToolSurrogates in the default construction environment. To make the + AttributeError show up, we have to overwite the default construction + environment's TOOLS variable so Program() builder doesn't show up. + + We do this by executing a slightly different SConstruct file than the + one we print in the guide, with two extra statements at the front + that overwrite the TOOLS variable as described. Note that we have + to jam those statements on to the first line to keep the line number + in the generated error consistent with what the user will see in the + User's Guide. + --> + <scons_example name="ex2"> + <file name="SConstruct"> + import SCons.Defaults; SCons.Defaults.ConstructionEnvironment['TOOLS'] = {}; bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </file> + <file name="SConstruct.printme" printme="1"> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </file> + <file name="file.input"> + file.input + </file> + <file name="hello.c"> + hello.c + </file> + </scons_example> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + To be able to use both our own defined &Builder; objects + and the default &Builder; objects in the same &consenv;, + you can either add to the &cv-BUILDERS; variable + using the &Append; function: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct"> + env = Environment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env.Append(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </file> + <file name="file.input"> + file.input + </file> + <file name="hello.c"> + hello.c + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> + + <sconstruct> + env = Environment() + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env.Append(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </sconstruct> + + <para> + + Or you can explicitly set the appropriately-named + key in the &cv-BUILDERS; dictionary: + + </para> + + <sconstruct> + env = Environment() + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env['BUILDERS']['Foo'] = bld + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </sconstruct> + + <para> + + Either way, the same &consenv; + can then use both the newly-defined + <function>Foo</function> &Builder; + and the default &b-link-Program; &Builder;: + + </para> + + <scons_output example="ex3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Letting &SCons; Handle The File Suffixes</title> + + <para> + + By supplying additional information + when you create a &Builder;, + you can let &SCons; add appropriate file + suffixes to the target and/or the source file. + For example, rather than having to specify + explicitly that you want the <literal>Foo</literal> + &Builder; to build the <literal>file.foo</literal> + target file from the <literal>file.input</literal> source file, + you can give the <literal>.foo</literal> + and <literal>.input</literal> suffixes to the &Builder;, + making for more compact and readable calls to + the <literal>Foo</literal> &Builder;: + + </para> + + <scons_example name="ex4"> + <file name="SConstruct"> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET', + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + env.Foo('file1') + env.Foo('file2') + </file> + <file name="file1.input"> + file1.input + </file> + <file name="file2.input"> + file2.input + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> + + <sconstruct> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET', + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file1') + env.Foo('file2') + </sconstruct> + + <scons_output example="ex4"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + You can also supply a <literal>prefix</literal> keyword argument + if it's appropriate to have &SCons; append a prefix + to the beginning of target file names. + + </para> + + </section> + + <section> + <title>Builders That Execute Python Functions</title> + + <para> + + In &SCons;, you don't have to call an external command + to build a file. + You can, instead, define a Python function + that a &Builder; object can invoke + to build your target file (or files). + Such a &buildfunc; definition looks like: + + </para> + + <programlisting> + def build_function(target, source, env): + # Code to build "target" from "source" + return None + </programlisting> + + <para> + + The arguments of a &buildfunc; are: + + </para> + + <variablelist> + + <varlistentry> + <term>target</term> + + <listitem> + <para> + + A list of Node objects representing + the target or targets to be + built by this builder function. + The file names of these target(s) + may be extracted using the Python &str; function. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>source</term> + + <listitem> + <para> + + A list of Node objects representing + the sources to be + used by this builder function to build the targets. + The file names of these source(s) + may be extracted using the Python &str; function. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>env</term> + + <listitem> + <para> + + The &consenv; used for building the target(s). + The builder function may use any of the + environment's construction variables + in any way to affect how it builds the targets. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + The builder function must + return a <literal>0</literal> or <literal>None</literal> value + if the target(s) are built successfully. + The builder function + may raise an exception + or return any non-zero value + to indicate that the build is unsuccessful, + + </para> + + <para> + + Once you've defined the Python function + that will build your target file, + defining a &Builder; object for it is as + simple as specifying the name of the function, + instead of an external command, + as the &Builder;'s + <literal>action</literal> + argument: + + </para> + + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> + def build_function(target, source, env): + # Code to build "target" from "source" + return None + bld = Builder(action = build_function, + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + </file> + <file name="file.input"> + file.input + </file> + </scons_example> + + <para> + + And notice that the output changes slightly, + reflecting the fact that a Python function, + not an external command, + is now called to build the target file: + + </para> + + <scons_output example="ex5"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Builders That Create Actions Using a &Generator;</title> + + <para> + + &SCons; Builder objects can create an action "on the fly" + by using a function called a &generator;. + This provides a great deal of flexibility to + construct just the right list of commands + to build your target. + A &generator; looks like: + + </para> + + <programlisting> + def generate_actions(source, target, env, for_signature): + return 'foobuild < %s > %s' % (target[0], source[0]) + </programlisting> + + <para> + + The arguments of a &generator; are: + + </para> + + <variablelist> + + <varlistentry> + <term>source</term> + + <listitem> + <para> + + A list of Node objects representing + the sources to be built + by the command or other action + generated by this function. + The file names of these source(s) + may be extracted using the Python &str; function. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>target</term> + + <listitem> + <para> + + A list of Node objects representing + the target or targets to be built + by the command or other action + generated by this function. + The file names of these target(s) + may be extracted using the Python &str; function. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>env</term> + + <listitem> + <para> + + The &consenv; used for building the target(s). + The generator may use any of the + environment's construction variables + in any way to determine what command + or other action to return. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>for_signature</term> + + <listitem> + <para> + + A flag that specifies whether the + generator is being called to contribute to a build signature, + as opposed to actually executing the command. + + <!-- XXX NEED MORE HERE, describe generators use in signatures --> + + </para> + </listitem> + + </varlistentry> + + </variablelist> + + <para> + + The &generator; must return a + command string or other action that will be used to + build the specified target(s) from the specified source(s). + + </para> + + <para> + + Once you've defined a &generator;, + you create a &Builder; to use it + by specifying the generator keyword argument + instead of <literal>action</literal>. + + </para> + + <scons_example name="ex6"> + <file name="SConstruct"> + def generate_actions(source, target, env, for_signature): + return 'foobuild < %s > %s' % (source[0], target[0]) + bld = Builder(generator = generate_actions, + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + env.Foo('file') + </file> + <file name="file.input"> + file.input + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> + + <sconstruct> + def generate_actions(source, target, env, for_signature): + return 'foobuild < %s > %s' % (source[0], target[0]) + bld = Builder(generator = generate_actions, + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + </sconstruct> + + <scons_output example="ex6"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that it's illegal to specify both an + <literal>action</literal> + and a + <literal>generator</literal> + for a &Builder;. + + </para> + + </section> + + <section> + <title>Builders That Modify the Target or Source Lists Using an &Emitter;</title> + + <para> + + &SCons; supports the ability for a Builder to modify the + lists of target(s) from the specified source(s). + You do this by defining an &emitter; function + that takes as its arguments + the list of the targets passed to the builder, + the list of the sources passed to the builder, + and the construction environment. + The emitter function should return the modified + lists of targets that should be built + and sources from which the targets will be built. + + </para> + + <para> + + For example, suppose you want to define a Builder + that always calls a <filename>foobuild</filename> program, + and you want to automatically add + a new target file named + <filename>new_target</filename> + and a new source file named + <filename>new_source</filename> + whenever it's called. + The &SConstruct; file might look like this: + + </para> + + <scons_example name="ex7"> + <file name="SConstruct"> + def modify_targets(target, source, env): + target.append('new_target') + source.append('new_source') + return target, source + bld = Builder(action = 'foobuild $TARGETS - $SOURCES', + suffix = '.foo', + src_suffix = '.input', + emitter = modify_targets) + env = Environment(BUILDERS = {'Foo' : bld}) + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + env.Foo('file') + </file> + <file name="file.input"> + file.input + </file> + <file name="new_source"> + new_source + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> + + <sconstruct> + def modify_targets(target, source, env): + target.append('new_target') + source.append('new_source') + return target, source + bld = Builder(action = 'foobuild $TARGETS - $SOURCES', + suffix = '.foo', + src_suffix = '.input', + emitter = modify_targets) + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + </sconstruct> + + <para> + + And would yield the following output: + + </para> + + <scons_output example="ex7"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + One very flexible thing that you can do is + use a construction variable to specify + different emitter functions for different + construction variable. + To do this, specify a string + containing a construction variable + expansion as the emitter when you call + the &Builder; function, + and set that construction variable to + the desired emitter function + in different construction environments: + + </para> + + <scons_example name="MY_EMITTER"> + + <file name="SConstruct" printme="1"> + bld = Builder(action = 'my_command $SOURCES > $TARGET', + suffix = '.foo', + src_suffix = '.input', + emitter = '$MY_EMITTER') + def modify1(target, source, env): + return target, source + ['modify1.in'] + def modify2(target, source, env): + return target, source + ['modify2.in'] + env1 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify1) + env2 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify2) + env1.Foo('file1') + env2.Foo('file2') + import os + env1['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() + env2['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() + </file> + <file name="file1.input"> + file1.input + </file> + <file name="file2.input"> + file2.input + </file> + <file name="modify1.in"> + modify1.input + </file> + <file name="modify2.in"> + modify2.input + </file> + <file name="my_command" chmod="0755"> + cat + </file> + </file> + + </scons_example> + + <sconstruct> + bld = Builder(action = 'my_command $SOURCES > $TARGET', + suffix = '.foo', + src_suffix = '.input', + emitter = '$MY_EMITTER') + def modify1(target, source, env): + return target, source + ['modify1.in'] + def modify2(target, source, env): + return target, source + ['modify2.in'] + env1 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify1) + env2 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify2) + env1.Foo('file1') + env2.Foo('file2') + </file> + </sconstruct> + + <para> + + In this example, the <filename>modify1.in</filename> + and <filename>modify2.in</filename> files + get added to the source lists + of the different commands: + + </para> + + <scons_output example="MY_EMITTER"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <!-- + + <section> + <title>target_factor=, source_factory=</title> + + </section> + + <section> + <title>target_scanner=, source_scanner=</title> + + </section> + + <section> + <title>multi=</title> + + </section> + + <section> + <title>single_source=</title> + + </section> + + <section> + <title>src_builder=</title> + + </section> + + <section> + <title>ensure_suffix=</title> + + </section> + + --> + + <section> + <title>Where To Put Your Custom Builders and Tools</title> + + <para> + + The <filename>site_scons</filename> directory gives you a place to + put Python modules you can import into your SConscripts + (site_scons), add-on tools that can integrate into &SCons; + (site_scons/site_tools), and a site_scons/site_init.py file that + gets read before any &SConstruct; or &SConscript;, allowing you to + change &SCons;'s default behavior. + + </para> + + <para> + + If you get a tool from somewhere (the &SCons; wiki or a third party, + for instance) and you'd like to use it in your project, the + <filename>site_scons</filename> dir is the simplest place to put it. + Tools come in two flavors; either a Python function that operates on + an &Environment; or a Python file containing two functions, exists() + and generate(). + + </para> + + <para> + + A single-function Tool can just be included in your + <filename>site_scons/site_init.py</filename> file where it will be + parsed and made available for use. For instance, you could have a + <filename>site_scons/site_init.py</filename> file like this: + + </para> + + <scons_example name="site1"> + <file name="site_scons/site_init.py" printme=1> + def TOOL_ADD_HEADER(env): + """A Tool to add a header from $HEADER to the source file""" + add_header = Builder(action=['echo "$HEADER" > $TARGET', + 'cat $SOURCE >> $TARGET']) + env.Append(BUILDERS = {'AddHeader' : add_header}) + env['HEADER'] = '' # set default value + </file> + <file name="SConstruct"> + env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====") + env.AddHeader('tgt', 'src') + </file> + <file name="src"> + hi there + </file> + </scons_example> + + <para> + + and a &SConstruct; like this: + + </para> + + <sconstruct> + # Use TOOL_ADD_HEADER from site_scons/site_init.py + env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====") + env.AddHeader('tgt', 'src') + </sconstruct> + + <para> + + The <function>TOOL_ADD_HEADER</function> tool method will be + called to add the <function>AddHeader</function> tool to the + environment. + + </para> + + <!-- + <scons_output example="site1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + --> + + <para> + Similarly, a more full-fledged tool with + <function>exists()</function> and <function>generate()</function> + methods can be installed in + <filename>site_scons/site_tools/toolname.py</filename>. Since + <filename>site_scons/site_tools</filename> is automatically added + to the head of the tool search path, any tool found there will be + available to all environments. Furthermore, a tool found there + will override a built-in tool of the same name, so if you need to + change the behavior of a built-in tool, site_scons gives you the + hook you need. + </para> + + <para> + Many people have a library of utility Python functions they'd like + to include in &SConscript;s; just put that module in + <filename>site_scons/my_utils.py</filename> or any valid Python module name of your + choice. For instance you can do something like this in + <filename>site_scons/my_utils.py</filename> to add build_id and MakeWorkDir functions: + </para> + + <scons_example name="site2"> + <file name="site_scons/my_utils.py" printme=1> + from SCons.Script import * # for Execute and Mkdir + def build_id(): + """Return a build ID (stub version)""" + return "100" + def MakeWorkDir(workdir): + """Create the specified dir immediately""" + Execute(Mkdir(workdir)) + </file> + <file name="SConscript"> + import my_utils + MakeWorkDir('/tmp/work') + print "build_id=" + my_utils.build_id() + </file> + </scons_example> + + <para> + + And then in your &SConscript; or any sub-&SConscript; anywhere in + your build, you can import <filename>my_utils</filename> and use it: + + </para> + + <sconstruct> + import my_utils + print "build_id=" + my_utils.build_id() + my_utils.MakeWorkDir('/tmp/work') + </sconstruct> + + <para> + Note that although you can put this library in + <filename>site_scons/site_init.py</filename>, + it is no better there than <filename>site_scons/my_utils.py</filename> + since you still have to import that module into your &SConscript;. + Also note that in order to refer to objects in the SCons namespace + such as &Environment; or &Mkdir; or &Execute; in any file other + than a &SConstruct; or &SConscript; you always need to do + </para> + <sconstruct> + from SCons.Script import * + </sconstruct> + + <para> + This is true in modules in <filename>site_scons</filename> such as + <filename>site_scons/site_init.py</filename> as well. + </para> + + <para> + + If you have a machine-wide site dir you'd like to use instead of + <filename>./site_scons</filename>, use the + <literal>--site-dir</literal> option to point to your dir. + <filename>site_init.py</filename> and + <filename>site_tools</filename> will be located under that dir. + To avoid using a <filename>site_scons</filename> dir at all, even + if it exists, use the <literal>--no-site-dir</literal> option. + + </para> + + </section> + + + <!-- + + <section> + <title>Builders That Use Other Builders</title> + + <para> + + XXX para + + </para> + + <scons_example name="ex8"> + <file name="SConstruct" printme="1"> + env = Environment() + #env.SourceCode('.', env.BitKeeper('my_command')) + env.Program('hello.c') + </file> + <file name="hello.c"> + hello.c + </file> + </scons_example> + + <scons_output example="ex8"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + --> diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml new file mode 100644 index 0000000..b05cce6 --- /dev/null +++ b/doc/user/builders-writing.xml @@ -0,0 +1,953 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head2 Adding new methods + +For slightly more demanding changes, you may wish to add new methods to the +C<cons> package. Here's an example of a very simple extension, +C<InstallScript>, which installs a tcl script in a requested location, but +edits the script first to reflect a platform-dependent path that needs to be +installed in the script: + + # cons::InstallScript - Create a platform dependent version of a shell + # script by replacing string ``#!your-path-here'' with platform specific + # path $BIN_DIR. + + sub cons::InstallScript { + my ($env, $dst, $src) = @_; + Command $env $dst, $src, qq( + sed s+your-path-here+$BIN_DIR+ %< > %> + chmod oug+x %> + ); + } + +Notice that this method is defined directly in the C<cons> package (by +prefixing the name with C<cons::>). A change made in this manner will be +globally visible to all environments, and could be called as in the +following example: + + InstallScript $env "$BIN/foo", "foo.tcl"; + +For a small improvement in generality, the C<BINDIR> variable could be +passed in as an argument or taken from the construction environment-,-as +C<%BINDIR>. + + +=head2 Overriding methods + +Instead of adding the method to the C<cons> name space, you could define a +new package which inherits existing methods from the C<cons> package and +overrides or adds others. This can be done using Perl's inheritance +mechanisms. + +The following example defines a new package C<cons::switch> which +overrides the standard C<Library> method. The overridden method builds +linked library modules, rather than library archives. A new +constructor is provided. Environments created with this constructor +will have the new library method; others won't. + + package cons::switch; + BEGIN {@ISA = 'cons'} + + sub new { + shift; + bless new cons(@_); + } + + sub Library { + my($env) = shift; + my($lib) = shift; + my(@objs) = Objects $env @_; + Command $env $lib, @objs, q( + %LD -r %LDFLAGS %< -o %> + ); + } + +This functionality could be invoked as in the following example: + + $env = new cons::switch(@overrides); + ... + Library $env 'lib.o', 'foo.c', 'bar.c'; + +--> + + <para> + + Although &SCons; provides many useful methods + for building common software products: + programs, libraries, documents. + you frequently want to be + able to build some other type of file + not supported directly by &SCons;. + Fortunately, &SCons; makes it very easy + to define your own &Builder; objects + for any custom file types you want to build. + (In fact, the &SCons; interfaces for creating + &Builder; objects are flexible enough and easy enough to use + that all of the the &SCons; built-in &Builder; objects + are created the mechanisms described in this section.) + + </para> + + <section> + <title>Writing Builders That Execute External Commands</title> + + <para> + + The simplest &Builder; to create is + one that executes an external command. + For example, if we want to build + an output file by running the contents + of the input file through a command named + <literal>foobuild</literal>, + creating that &Builder; might look like: + + </para> + + <programlisting> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + </programlisting> + + <para> + + All the above line does is create a free-standing + &Builder; object. + The next section will show us how to actually use it. + + </para> + + </section> + + <section> + <title>Attaching a Builder to a &ConsEnv;</title> + + <para> + + A &Builder; object isn't useful + until it's attached to a &consenv; + so that we can call it to arrange + for files to be built. + This is done through the &cv-link-BUILDERS; + &consvar; in an environment. + The &cv-BUILDERS; variable is a Python dictionary + that maps the names by which you want to call + various &Builder; objects to the objects themselves. + For example, if we want to call the + &Builder; we just defined by the name + <function>Foo</function>, + our &SConstruct; file might look like: + + </para> + + + + <programlisting> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env = Environment(BUILDERS = {'Foo' : bld}) + </programlisting> + + <para> + + With the &Builder; attached to our &consenv; + with the name <function>Foo</function>, + we can now actually call it like so: + + </para> + + <programlisting> + env.Foo('file.foo', 'file.input') + </programlisting> + + <para> + + Then when we run &SCons; it looks like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + foobuild < file.input > file.foo + </screen> + + <para> + + Note, however, that the default &cv-BUILDERS; + variable in a &consenv; + comes with a default set of &Builder; objects + already defined: + &b-link-Program;, &b-link-Library;, etc. + And when we explicitly set the &cv-BUILDERS; variable + when we create the &consenv;, + the default &Builder;s are no longer part of + the environment: + + </para> + + <!-- + The ToolSurrogate stuff that's used to capture output initializes + SCons.Defaults.ConstructionEnvironment with its own list of TOOLS. + In this next example, we want to show the user that when they + set the BUILDERS explicitly, the call to env.Program() generates + an AttributeError. This won't happen with all of the default + ToolSurrogates in the default construction environment. To make the + AttributeError show up, we have to overwite the default construction + environment's TOOLS variable so Program() builder doesn't show up. + + We do this by executing a slightly different SConstruct file than the + one we print in the guide, with two extra statements at the front + that overwrite the TOOLS variable as described. Note that we have + to jam those statements on to the first line to keep the line number + in the generated error consistent with what the user will see in the + User's Guide. + --> + <programlisting> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + AttributeError: SConsEnvironment instance has no attribute 'Program': + File "/home/my/project/SConstruct", line 4: + env.Program('hello.c') + </screen> + + <para> + + To be able to use both our own defined &Builder; objects + and the default &Builder; objects in the same &consenv;, + you can either add to the &cv-BUILDERS; variable + using the &Append; function: + + </para> + + + + <programlisting> + env = Environment() + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env.Append(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </programlisting> + + <para> + + Or you can explicitly set the appropriately-named + key in the &cv-BUILDERS; dictionary: + + </para> + + <programlisting> + env = Environment() + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env['BUILDERS']['Foo'] = bld + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </programlisting> + + <para> + + Either way, the same &consenv; + can then use both the newly-defined + <function>Foo</function> &Builder; + and the default &b-link-Program; &Builder;: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + foobuild < file.input > file.foo + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Letting &SCons; Handle The File Suffixes</title> + + <para> + + By supplying additional information + when you create a &Builder;, + you can let &SCons; add appropriate file + suffixes to the target and/or the source file. + For example, rather than having to specify + explicitly that you want the <literal>Foo</literal> + &Builder; to build the <literal>file.foo</literal> + target file from the <literal>file.input</literal> source file, + you can give the <literal>.foo</literal> + and <literal>.input</literal> suffixes to the &Builder;, + making for more compact and readable calls to + the <literal>Foo</literal> &Builder;: + + </para> + + + + <programlisting> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET', + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file1') + env.Foo('file2') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + foobuild < file1.input > file1.foo + foobuild < file2.input > file2.foo + </screen> + + <para> + + You can also supply a <literal>prefix</literal> keyword argument + if it's appropriate to have &SCons; append a prefix + to the beginning of target file names. + + </para> + + </section> + + <section> + <title>Builders That Execute Python Functions</title> + + <para> + + In &SCons;, you don't have to call an external command + to build a file. + You can, instead, define a Python function + that a &Builder; object can invoke + to build your target file (or files). + Such a &buildfunc; definition looks like: + + </para> + + <programlisting> + def build_function(target, source, env): + # Code to build "target" from "source" + return None + </programlisting> + + <para> + + The arguments of a &buildfunc; are: + + </para> + + <variablelist> + + <varlistentry> + <term>target</term> + + <listitem> + <para> + + A list of Node objects representing + the target or targets to be + built by this builder function. + The file names of these target(s) + may be extracted using the Python &str; function. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>source</term> + + <listitem> + <para> + + A list of Node objects representing + the sources to be + used by this builder function to build the targets. + The file names of these source(s) + may be extracted using the Python &str; function. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>env</term> + + <listitem> + <para> + + The &consenv; used for building the target(s). + The builder function may use any of the + environment's construction variables + in any way to affect how it builds the targets. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + The builder function must + return a <literal>0</literal> or <literal>None</literal> value + if the target(s) are built successfully. + The builder function + may raise an exception + or return any non-zero value + to indicate that the build is unsuccessful, + + </para> + + <para> + + Once you've defined the Python function + that will build your target file, + defining a &Builder; object for it is as + simple as specifying the name of the function, + instead of an external command, + as the &Builder;'s + <literal>action</literal> + argument: + + </para> + + <programlisting> + def build_function(target, source, env): + # Code to build "target" from "source" + return None + bld = Builder(action = build_function, + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + </programlisting> + + <para> + + And notice that the output changes slightly, + reflecting the fact that a Python function, + not an external command, + is now called to build the target file: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + build_function(["file.foo"], ["file.input"]) + </screen> + + </section> + + <section> + <title>Builders That Create Actions Using a &Generator;</title> + + <para> + + &SCons; Builder objects can create an action "on the fly" + by using a function called a &generator;. + This provides a great deal of flexibility to + construct just the right list of commands + to build your target. + A &generator; looks like: + + </para> + + <programlisting> + def generate_actions(source, target, env, for_signature): + return 'foobuild < %s > %s' % (target[0], source[0]) + </programlisting> + + <para> + + The arguments of a &generator; are: + + </para> + + <variablelist> + + <varlistentry> + <term>source</term> + + <listitem> + <para> + + A list of Node objects representing + the sources to be built + by the command or other action + generated by this function. + The file names of these source(s) + may be extracted using the Python &str; function. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>target</term> + + <listitem> + <para> + + A list of Node objects representing + the target or targets to be built + by the command or other action + generated by this function. + The file names of these target(s) + may be extracted using the Python &str; function. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>env</term> + + <listitem> + <para> + + The &consenv; used for building the target(s). + The generator may use any of the + environment's construction variables + in any way to determine what command + or other action to return. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>for_signature</term> + + <listitem> + <para> + + A flag that specifies whether the + generator is being called to contribute to a build signature, + as opposed to actually executing the command. + + <!-- XXX NEED MORE HERE, describe generators use in signatures --> + + </para> + </listitem> + + </varlistentry> + + </variablelist> + + <para> + + The &generator; must return a + command string or other action that will be used to + build the specified target(s) from the specified source(s). + + </para> + + <para> + + Once you've defined a &generator;, + you create a &Builder; to use it + by specifying the generator keyword argument + instead of <literal>action</literal>. + + </para> + + + + <programlisting> + def generate_actions(source, target, env, for_signature): + return 'foobuild < %s > %s' % (source[0], target[0]) + bld = Builder(generator = generate_actions, + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + foobuild < file.input > file.foo + </screen> + + <para> + + Note that it's illegal to specify both an + <literal>action</literal> + and a + <literal>generator</literal> + for a &Builder;. + + </para> + + </section> + + <section> + <title>Builders That Modify the Target or Source Lists Using an &Emitter;</title> + + <para> + + &SCons; supports the ability for a Builder to modify the + lists of target(s) from the specified source(s). + You do this by defining an &emitter; function + that takes as its arguments + the list of the targets passed to the builder, + the list of the sources passed to the builder, + and the construction environment. + The emitter function should return the modified + lists of targets that should be built + and sources from which the targets will be built. + + </para> + + <para> + + For example, suppose you want to define a Builder + that always calls a <filename>foobuild</filename> program, + and you want to automatically add + a new target file named + <filename>new_target</filename> + and a new source file named + <filename>new_source</filename> + whenever it's called. + The &SConstruct; file might look like this: + + </para> + + + + <programlisting> + def modify_targets(target, source, env): + target.append('new_target') + source.append('new_source') + return target, source + bld = Builder(action = 'foobuild $TARGETS - $SOURCES', + suffix = '.foo', + src_suffix = '.input', + emitter = modify_targets) + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + </programlisting> + + <para> + + And would yield the following output: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + foobuild file.foo new_target - file.input new_source + </screen> + + <para> + + One very flexible thing that you can do is + use a construction variable to specify + different emitter functions for different + construction variable. + To do this, specify a string + containing a construction variable + expansion as the emitter when you call + the &Builder; function, + and set that construction variable to + the desired emitter function + in different construction environments: + + </para> + + <programlisting> + bld = Builder(action = 'my_command $SOURCES > $TARGET', + suffix = '.foo', + src_suffix = '.input', + emitter = '$MY_EMITTER') + def modify1(target, source, env): + return target, source + ['modify1.in'] + def modify2(target, source, env): + return target, source + ['modify2.in'] + env1 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify1) + env2 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify2) + env1.Foo('file1') + env2.Foo('file2') + import os + env1['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() + env2['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() + + + </programlisting> + + <programlisting> + bld = Builder(action = 'my_command $SOURCES > $TARGET', + suffix = '.foo', + src_suffix = '.input', + emitter = '$MY_EMITTER') + def modify1(target, source, env): + return target, source + ['modify1.in'] + def modify2(target, source, env): + return target, source + ['modify2.in'] + env1 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify1) + env2 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify2) + env1.Foo('file1') + env2.Foo('file2') + + </programlisting> + + <para> + + In this example, the <filename>modify1.in</filename> + and <filename>modify2.in</filename> files + get added to the source lists + of the different commands: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + my_command file1.input modify1.in > file1.foo + my_command file2.input modify2.in > file2.foo + </screen> + + </section> + + <!-- + + <section> + <title>target_factor=, source_factory=</title> + + </section> + + <section> + <title>target_scanner=, source_scanner=</title> + + </section> + + <section> + <title>multi=</title> + + </section> + + <section> + <title>single_source=</title> + + </section> + + <section> + <title>src_builder=</title> + + </section> + + <section> + <title>ensure_suffix=</title> + + </section> + + --> + + <section> + <title>Where To Put Your Custom Builders and Tools</title> + + <para> + + The <filename>site_scons</filename> directory gives you a place to + put Python modules you can import into your SConscripts + (site_scons), add-on tools that can integrate into &SCons; + (site_scons/site_tools), and a site_scons/site_init.py file that + gets read before any &SConstruct; or &SConscript;, allowing you to + change &SCons;'s default behavior. + + </para> + + <para> + + If you get a tool from somewhere (the &SCons; wiki or a third party, + for instance) and you'd like to use it in your project, the + <filename>site_scons</filename> dir is the simplest place to put it. + Tools come in two flavors; either a Python function that operates on + an &Environment; or a Python file containing two functions, exists() + and generate(). + + </para> + + <para> + + A single-function Tool can just be included in your + <filename>site_scons/site_init.py</filename> file where it will be + parsed and made available for use. For instance, you could have a + <filename>site_scons/site_init.py</filename> file like this: + + </para> + + <programlisting> + def TOOL_ADD_HEADER(env): + """A Tool to add a header from $HEADER to the source file""" + add_header = Builder(action=['echo "$HEADER" > $TARGET', + 'cat $SOURCE >> $TARGET']) + env.Append(BUILDERS = {'AddHeader' : add_header}) + env['HEADER'] = '' # set default value + </programlisting> + + <para> + + and a &SConstruct; like this: + + </para> + + <programlisting> + # Use TOOL_ADD_HEADER from site_scons/site_init.py + env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====") + env.AddHeader('tgt', 'src') + </programlisting> + + <para> + + The <function>TOOL_ADD_HEADER</function> tool method will be + called to add the <function>AddHeader</function> tool to the + environment. + + </para> + + <!-- + <scons_output example="site1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + --> + + <para> + Similarly, a more full-fledged tool with + <function>exists()</function> and <function>generate()</function> + methods can be installed in + <filename>site_scons/site_tools/toolname.py</filename>. Since + <filename>site_scons/site_tools</filename> is automatically added + to the head of the tool search path, any tool found there will be + available to all environments. Furthermore, a tool found there + will override a built-in tool of the same name, so if you need to + change the behavior of a built-in tool, site_scons gives you the + hook you need. + </para> + + <para> + Many people have a library of utility Python functions they'd like + to include in &SConscript;s; just put that module in + <filename>site_scons/my_utils.py</filename> or any valid Python module name of your + choice. For instance you can do something like this in + <filename>site_scons/my_utils.py</filename> to add build_id and MakeWorkDir functions: + </para> + + <programlisting> + from SCons.Script import * # for Execute and Mkdir + def build_id(): + """Return a build ID (stub version)""" + return "100" + def MakeWorkDir(workdir): + """Create the specified dir immediately""" + Execute(Mkdir(workdir)) + </programlisting> + + <para> + + And then in your &SConscript; or any sub-&SConscript; anywhere in + your build, you can import <filename>my_utils</filename> and use it: + + </para> + + <programlisting> + import my_utils + print "build_id=" + my_utils.build_id() + my_utils.MakeWorkDir('/tmp/work') + </programlisting> + + <para> + Note that although you can put this library in + <filename>site_scons/site_init.py</filename>, + it is no better there than <filename>site_scons/my_utils.py</filename> + since you still have to import that module into your &SConscript;. + Also note that in order to refer to objects in the SCons namespace + such as &Environment; or &Mkdir; or &Execute; in any file other + than a &SConstruct; or &SConscript; you always need to do + </para> + <programlisting> + from SCons.Script import * + </programlisting> + + <para> + This is true in modules in <filename>site_scons</filename> such as + <filename>site_scons/site_init.py</filename> as well. + </para> + + <para> + + If you have a machine-wide site dir you'd like to use instead of + <filename>./site_scons</filename>, use the + <literal>--site-dir</literal> option to point to your dir. + <filename>site_init.py</filename> and + <filename>site_tools</filename> will be located under that dir. + To avoid using a <filename>site_scons</filename> dir at all, even + if it exists, use the <literal>--no-site-dir</literal> option. + + </para> + + </section> + + + <!-- + + <section> + <title>Builders That Use Other Builders</title> + + <para> + + XXX para + + </para> + + <scons_example name="ex8"> + <file name="SConstruct" printme="1"> + env = Environment() + #env.SourceCode('.', env.BitKeeper('my_command')) + env.Program('hello.c') + </file> + <file name="hello.c"> + hello.c + </file> + </scons_example> + + <scons_output example="ex8"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + --> diff --git a/doc/user/builders.in b/doc/user/builders.in new file mode 100644 index 0000000..a2f94ce --- /dev/null +++ b/doc/user/builders.in @@ -0,0 +1,57 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> + +<refentry id="Command"> + +<refmeta> +<refentrytitle>Command</refentrytitle> +</refmeta> + +<methodsynopsis> + <methodname>env.Command</methodname> + <methodparam>foo</methodparam> + <methodparam>bar</methodparam> +</methodsynopsis> + +</refentry> +--> + +<para> + +This appendix contains descriptions of all of the +Builders that are <emphasis>potentially</emphasis> +available "out of the box" in this version of SCons. + +</para> + +<variablelist> + +&builders-gen; + +</variablelist> diff --git a/doc/user/builders.xml b/doc/user/builders.xml new file mode 100644 index 0000000..a2f94ce --- /dev/null +++ b/doc/user/builders.xml @@ -0,0 +1,57 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> + +<refentry id="Command"> + +<refmeta> +<refentrytitle>Command</refentrytitle> +</refmeta> + +<methodsynopsis> + <methodname>env.Command</methodname> + <methodparam>foo</methodparam> + <methodparam>bar</methodparam> +</methodsynopsis> + +</refentry> +--> + +<para> + +This appendix contains descriptions of all of the +Builders that are <emphasis>potentially</emphasis> +available "out of the box" in this version of SCons. + +</para> + +<variablelist> + +&builders-gen; + +</variablelist> diff --git a/doc/user/caching.in b/doc/user/caching.in new file mode 100644 index 0000000..31b1103 --- /dev/null +++ b/doc/user/caching.in @@ -0,0 +1,502 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + On multi-developer software projects, + you can sometimes speed up every developer's builds a lot by + allowing them to share the derived files that they build. + &SCons; makes this easy, as well as reliable. + + </para> + + <section> + <title>Specifying the Shared Cache Directory</title> + + <para> + + To enable sharing of derived files, + use the &CacheDir; function + in any &SConscript; file: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct"> + env = Environment() + env.Program('hello.c') + CacheDir('cache') + </file> + <file name="hello.c"> + hello.c + </file> + <directory name="cache"> + </directory> + <file name="not_used" printme="1"> + CacheDir('/usr/local/build_cache') + </file> + </scons_example> + + <para> + + Note that the directory you specify must already exist + and be readable and writable by all developers + who will be sharing derived files. + It should also be in some central location + that all builds will be able to access. + In environments where developers are using separate systems + (like individual workstations) for builds, + this directory would typically be + on a shared or NFS-mounted file system. + + </para> + + <para> + + Here's what happens: + When a build has a &CacheDir; specified, + every time a file is built, + it is stored in the shared cache directory + along with its MD5 build signature. + <footnote> + <para> + Actually, the MD5 signature is used as the name of the file + in the shared cache directory in which the contents are stored. + </para> + </footnote> + On subsequent builds, + before an action is invoked to build a file, + &SCons; will check the shared cache directory + to see if a file with the exact same build + signature already exists. + If so, the derived file will not be built locally, + but will be copied into the local build directory + from the shared cache directory, + like so: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that the &CacheDir; feature still calculates + MD5 build sigantures for the shared cache file names + even if you configure &SCons; to use timestamps + to decide if files are up to date. + (See the <xref linkend="chap-depends"></xref> + chapter for information about the &Decider; function.) + Consequently, using &CacheDir; may reduce or eliminate any + potential performance improvements + from using timestamps for up-to-date decisions. + + </para> + + </section> + + <section> + <title>Keeping Build Output Consistent</title> + + <para> + + One potential drawback to using a shared cache + is that the output printed by &SCons; + can be inconsistent from invocation to invocation, + because any given file may be rebuilt one time + and retrieved from the shared cache the next time. + This can make analyzing build output more difficult, + especially for automated scripts that + expect consistent output each time. + + </para> + + <para> + + If, however, you use the <literal>--cache-show</literal> option, + &SCons; will print the command line that it + <emphasis>would</emphasis> have executed + to build the file, + even when it is retrieving the file from the shared cache. + This makes the build output consistent + every time the build is run: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q --cache-show</scons_output_command> + </scons_output> + + <para> + + The trade-off, of course, is that you no longer + know whether or not &SCons; + has retrieved a derived file from cache + or has rebuilt it locally. + + </para> + + </section> + + <section> + <title>Not Using the Shared Cache for Specific Files</title> + + <para> + + You may want to disable caching for certain + specific files in your configuration. + For example, if you only want to put + executable files in a central cache, + but not the intermediate object files, + you can use the &NoCache; + function to specify that the + object files should not be cached: + + </para> + + <scons_example name="ex-NoCache"> + <file name="SConstruct" printme="1"> + env = Environment() + obj = env.Object('hello.c') + env.Program('hello.c') + CacheDir('cache') + NoCache('hello.o') + </file> + <file name="hello.c"> + hello.c + </file> + <directory name="cache"> + </directory> + </scons_example> + + <para> + + Then when you run &scons; after cleaning + the built targets, + it will recompile the object file locally + (since it doesn't exist in the shared cache directory), + but still realize that the shared cache directory + contains an up-to-date executable program + that can be retrieved instead of re-linking: + + </para> + + <!-- + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q -c</userinput> + Removed hello.o + Removed hello + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + Retrieved `hello' from cache + </screen> + + </section> + + <section> + <title>Disabling the Shared Cache</title> + + <para> + + Retrieving an already-built file + from the shared cache + is usually a significant time-savings + over rebuilding the file, + but how much of a savings + (or even whether it saves time at all) + can depend a great deal on your + system or network configuration. + For example, retrieving cached files + from a busy server over a busy network + might end up being slower than + rebuilding the files locally. + + </para> + + <para> + + In these cases, you can specify + the <literal>--cache-disable</literal> + command-line option to tell &SCons; + to not retrieve already-built files from the + shared cache directory: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q --cache-disable</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Populating a Shared Cache With Already-Built Files</title> + + <para> + + Sometimes, you may have one or more derived files + already built in your local build tree + that you wish to make available to other people doing builds. + For example, you may find it more effective to perform + integration builds with the cache disabled + (per the previous section) + and only populate the shared cache directory + with the built files after the integration build + has completed successfully. + This way, the cache will only get filled up + with derived files that are part of a complete, successful build + not with files that might be later overwritten + while you debug integration problems. + + </para> + + <para> + + In this case, you can use the + the <literal>--cache-force</literal> option + to tell &SCons; to put all derived files in the cache, + even if the files already exist in your local tree + from having been built by a previous invocation: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q --cache-disable</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q --cache-disable</scons_output_command> + <scons_output_command>scons -Q --cache-force</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Notice how the above sample run + demonstrates that the <literal>--cache-disable</literal> + option avoids putting the built + <filename>hello.o</filename> + and + <filename>hello</filename> files in the cache, + but after using the <literal>--cache-force</literal> option, + the files have been put in the cache + for the next invocation to retrieve. + + </para> + + </section> + + <section> + <title>Minimizing Cache Contention: the <literal>--random</literal> Option</title> + + <para> + + If you allow multiple builds to update the + shared cache directory simultaneously, + two builds that occur at the same time + can sometimes start "racing" + with one another to build the same files + in the same order. + If, for example, + you are linking multiple files into an executable program: + + </para> + + <scons_example name="ex-random"> + <file name="SConstruct" printme="1"> + Program('prog', + ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) + </file> + <file name="f1.c">f1.c</file> + <file name="f2.c">f2.c</file> + <file name="f3.c">f3.c</file> + <file name="f4.c">f4.c</file> + <file name="f5.c">f5.c</file> + <file name="f6.c">f6.c</file> + </scons_example> + + <para> + + &SCons; will normally build the input object files + on which the program depends in their normal, sorted order: + + </para> + + <scons_output example="ex-random"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + But if two such builds take place simultaneously, + they may each look in the cache at nearly the same + time and both decide that <filename>f1.o</filename> + must be rebuilt and pushed into the shared cache directory, + then both decide that <filename>f2.o</filename> + must be rebuilt (and pushed into the shared cache directory), + then both decide that <filename>f3.o</filename> + must be rebuilt... + This won't cause any actual build problems--both + builds will succeed, + generate correct output files, + and populate the cache--but + it does represent wasted effort. + + </para> + + <para> + + To alleviate such contention for the cache, + you can use the <literal>--random</literal> command-line option + to tell &SCons; to build dependencies + in a random order: + + </para> + + <!-- + + The following <screen> output was generated by this: + + <scons_output example="ex-random"> + <scons_output_command>scons -Q - -random</scons_output_command> + </scons_output> + + We captured it directly here to guarantee a "random" order, + guarding against the potential for - -random to happen + to return things in the original sorted order. + + --> + + <screen> + % <userinput>scons -Q --random</userinput> + cc -o f3.o -c f3.c + cc -o f1.o -c f1.c + cc -o f5.o -c f5.c + cc -o f2.o -c f2.c + cc -o f4.o -c f4.c + cc -o prog f1.o f2.o f3.o f4.o f5.o + </screen> + + <para> + + Multiple builds using the <literal>--random</literal> option + will usually build their dependencies in different, + random orders, + which minimizes the chances for a lot of + contention for same-named files + in the shared cache directory. + Multiple simultaneous builds might still race to try to build + the same target file on occasion, + but long sequences of inefficient contention + should be rare. + + </para> + + <para> + + Note, of course, + the <literal>--random</literal> option + will cause the output that &SCons; prints + to be inconsistent from invocation to invocation, + which may be an issue when + trying to compare output from different build runs. + + </para> + + <para> + + If you want to make sure dependencies will be built + in a random order without having to specify + the <literal>--random</literal> on very command line, + you can use the &SetOption; function to + set the <literal>random</literal> option + within any &SConscript; file: + + </para> + + <scons_example name="ex-random"> + <file name="SConstruct" printme="1"> + SetOption('random', 1) + Program('prog', + ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) + </file> + <file name="f1.c">f1.c</file> + <file name="f2.c">f2.c</file> + <file name="f3.c">f3.c</file> + <file name="f4.c">f4.c</file> + <file name="f5.c">f5.c</file> + <file name="f6.c">f6.c</file> + </scons_example> + + </section> + + <!-- + + <section> + <title>Troubleshooting Shared Caching: the &cache-debug; Option</title> + + <para> + + XXX describe the - - cache-debug option + XXX maybe point to the troubleshooting appendix? + + </para> + + </section> + + --> + + <!-- + + <section> + + <para> + + XXX describe CacheDir management: monitoring, deleting, etc. + + </para> + + </section> + + --> diff --git a/doc/user/caching.xml b/doc/user/caching.xml new file mode 100644 index 0000000..073539c --- /dev/null +++ b/doc/user/caching.xml @@ -0,0 +1,506 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + On multi-developer software projects, + you can sometimes speed up every developer's builds a lot by + allowing them to share the derived files that they build. + &SCons; makes this easy, as well as reliable. + + </para> + + <section> + <title>Specifying the Shared Cache Directory</title> + + <para> + + To enable sharing of derived files, + use the &CacheDir; function + in any &SConscript; file: + + </para> + + <programlisting> + CacheDir('/usr/local/build_cache') + </programlisting> + + <para> + + Note that the directory you specify must already exist + and be readable and writable by all developers + who will be sharing derived files. + It should also be in some central location + that all builds will be able to access. + In environments where developers are using separate systems + (like individual workstations) for builds, + this directory would typically be + on a shared or NFS-mounted file system. + + </para> + + <para> + + Here's what happens: + When a build has a &CacheDir; specified, + every time a file is built, + it is stored in the shared cache directory + along with its MD5 build signature. + <footnote> + <para> + Actually, the MD5 signature is used as the name of the file + in the shared cache directory in which the contents are stored. + </para> + </footnote> + On subsequent builds, + before an action is invoked to build a file, + &SCons; will check the shared cache directory + to see if a file with the exact same build + signature already exists. + If so, the derived file will not be built locally, + but will be copied into the local build directory + from the shared cache directory, + like so: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q -c</userinput> + Removed hello.o + Removed hello + % <userinput>scons -Q</userinput> + Retrieved `hello.o' from cache + Retrieved `hello' from cache + </screen> + + <para> + + Note that the &CacheDir; feature still calculates + MD5 build sigantures for the shared cache file names + even if you configure &SCons; to use timestamps + to decide if files are up to date. + (See the <xref linkend="chap-depends"></xref> + chapter for information about the &Decider; function.) + Consequently, using &CacheDir; may reduce or eliminate any + potential performance improvements + from using timestamps for up-to-date decisions. + + </para> + + </section> + + <section> + <title>Keeping Build Output Consistent</title> + + <para> + + One potential drawback to using a shared cache + is that the output printed by &SCons; + can be inconsistent from invocation to invocation, + because any given file may be rebuilt one time + and retrieved from the shared cache the next time. + This can make analyzing build output more difficult, + especially for automated scripts that + expect consistent output each time. + + </para> + + <para> + + If, however, you use the <literal>--cache-show</literal> option, + &SCons; will print the command line that it + <emphasis>would</emphasis> have executed + to build the file, + even when it is retrieving the file from the shared cache. + This makes the build output consistent + every time the build is run: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q -c</userinput> + Removed hello.o + Removed hello + % <userinput>scons -Q --cache-show</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + The trade-off, of course, is that you no longer + know whether or not &SCons; + has retrieved a derived file from cache + or has rebuilt it locally. + + </para> + + </section> + + <section> + <title>Not Using the Shared Cache for Specific Files</title> + + <para> + + You may want to disable caching for certain + specific files in your configuration. + For example, if you only want to put + executable files in a central cache, + but not the intermediate object files, + you can use the &NoCache; + function to specify that the + object files should not be cached: + + </para> + + <programlisting> + env = Environment() + obj = env.Object('hello.c') + env.Program('hello.c') + CacheDir('cache') + NoCache('hello.o') + </programlisting> + + <para> + + Then when you run &scons; after cleaning + the built targets, + it will recompile the object file locally + (since it doesn't exist in the shared cache directory), + but still realize that the shared cache directory + contains an up-to-date executable program + that can be retrieved instead of re-linking: + + </para> + + <!-- + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q -c</userinput> + Removed hello.o + Removed hello + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + Retrieved `hello' from cache + </screen> + + </section> + + <section> + <title>Disabling the Shared Cache</title> + + <para> + + Retrieving an already-built file + from the shared cache + is usually a significant time-savings + over rebuilding the file, + but how much of a savings + (or even whether it saves time at all) + can depend a great deal on your + system or network configuration. + For example, retrieving cached files + from a busy server over a busy network + might end up being slower than + rebuilding the files locally. + + </para> + + <para> + + In these cases, you can specify + the <literal>--cache-disable</literal> + command-line option to tell &SCons; + to not retrieve already-built files from the + shared cache directory: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q -c</userinput> + Removed hello.o + Removed hello + % <userinput>scons -Q</userinput> + Retrieved `hello.o' from cache + Retrieved `hello' from cache + % <userinput>scons -Q -c</userinput> + Removed hello.o + Removed hello + % <userinput>scons -Q --cache-disable</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Populating a Shared Cache With Already-Built Files</title> + + <para> + + Sometimes, you may have one or more derived files + already built in your local build tree + that you wish to make available to other people doing builds. + For example, you may find it more effective to perform + integration builds with the cache disabled + (per the previous section) + and only populate the shared cache directory + with the built files after the integration build + has completed successfully. + This way, the cache will only get filled up + with derived files that are part of a complete, successful build + not with files that might be later overwritten + while you debug integration problems. + + </para> + + <para> + + In this case, you can use the + the <literal>--cache-force</literal> option + to tell &SCons; to put all derived files in the cache, + even if the files already exist in your local tree + from having been built by a previous invocation: + + </para> + + <screen> + % <userinput>scons -Q --cache-disable</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q -c</userinput> + Removed hello.o + Removed hello + % <userinput>scons -Q --cache-disable</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q --cache-force</userinput> + scons: `.' is up to date. + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + </screen> + + <para> + + Notice how the above sample run + demonstrates that the <literal>--cache-disable</literal> + option avoids putting the built + <filename>hello.o</filename> + and + <filename>hello</filename> files in the cache, + but after using the <literal>--cache-force</literal> option, + the files have been put in the cache + for the next invocation to retrieve. + + </para> + + </section> + + <section> + <title>Minimizing Cache Contention: the <literal>--random</literal> Option</title> + + <para> + + If you allow multiple builds to update the + shared cache directory simultaneously, + two builds that occur at the same time + can sometimes start "racing" + with one another to build the same files + in the same order. + If, for example, + you are linking multiple files into an executable program: + + </para> + + <programlisting> + Program('prog', + ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) + </programlisting> + + <para> + + &SCons; will normally build the input object files + on which the program depends in their normal, sorted order: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o f1.o -c f1.c + cc -o f2.o -c f2.c + cc -o f3.o -c f3.c + cc -o f4.o -c f4.c + cc -o f5.o -c f5.c + cc -o prog f1.o f2.o f3.o f4.o f5.o + </screen> + + <para> + + But if two such builds take place simultaneously, + they may each look in the cache at nearly the same + time and both decide that <filename>f1.o</filename> + must be rebuilt and pushed into the shared cache directory, + then both decide that <filename>f2.o</filename> + must be rebuilt (and pushed into the shared cache directory), + then both decide that <filename>f3.o</filename> + must be rebuilt... + This won't cause any actual build problems--both + builds will succeed, + generate correct output files, + and populate the cache--but + it does represent wasted effort. + + </para> + + <para> + + To alleviate such contention for the cache, + you can use the <literal>--random</literal> command-line option + to tell &SCons; to build dependencies + in a random order: + + </para> + + <!-- + + The following <screen> output was generated by this: + + <scons_output example="ex-random"> + <scons_output_command>scons -Q - -random</scons_output_command> + </scons_output> + + We captured it directly here to guarantee a "random" order, + guarding against the potential for - -random to happen + to return things in the original sorted order. + + --> + + <screen> + % <userinput>scons -Q --random</userinput> + cc -o f3.o -c f3.c + cc -o f1.o -c f1.c + cc -o f5.o -c f5.c + cc -o f2.o -c f2.c + cc -o f4.o -c f4.c + cc -o prog f1.o f2.o f3.o f4.o f5.o + </screen> + + <para> + + Multiple builds using the <literal>--random</literal> option + will usually build their dependencies in different, + random orders, + which minimizes the chances for a lot of + contention for same-named files + in the shared cache directory. + Multiple simultaneous builds might still race to try to build + the same target file on occasion, + but long sequences of inefficient contention + should be rare. + + </para> + + <para> + + Note, of course, + the <literal>--random</literal> option + will cause the output that &SCons; prints + to be inconsistent from invocation to invocation, + which may be an issue when + trying to compare output from different build runs. + + </para> + + <para> + + If you want to make sure dependencies will be built + in a random order without having to specify + the <literal>--random</literal> on very command line, + you can use the &SetOption; function to + set the <literal>random</literal> option + within any &SConscript; file: + + </para> + + <programlisting> + Program('prog', + ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) + + SetOption('random', 1) + Program('prog', + ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) + </programlisting> + + </section> + + <!-- + + <section> + <title>Troubleshooting Shared Caching: the &cache-debug; Option</title> + + <para> + + XXX describe the - - cache-debug option + XXX maybe point to the troubleshooting appendix? + + </para> + + </section> + + --> + + <!-- + + <section> + + <para> + + XXX describe CacheDir management: monitoring, deleting, etc. + + </para> + + </section> + + --> diff --git a/doc/user/command-line.in b/doc/user/command-line.in new file mode 100644 index 0000000..686146e --- /dev/null +++ b/doc/user/command-line.in @@ -0,0 +1,2327 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; provides a number of ways + for the writer of the &SConscript; files + to give the users who will run &SCons; + a great deal of control over the build execution. + The arguments that the user can specify on + the command line are broken down into three types: + + </para> + + <variablelist> + + <varlistentry> + <term>Options</term> + + <listitem> + <para> + + Command-line options always begin with + one or two <literal>-</literal> (hyphen) characters. + &SCons; provides ways for you to examine + and set options values from within your &SConscript; files, + as well as the ability to define your own + custom options. + See <xref linkend="sect-command-line-options"></xref>, below. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Variables</term> + + <listitem> + <para> + + Any command-line argument containing an <literal>=</literal> + (equal sign) is considered a variable setting with the form + <varname>variable</varname>=<varname>value</varname> + &SCons; provides direct access to + all of the command-line variable settings, + the ability to apply command-line variable settings + to construction environments, + and functions for configuring + specific types of variables + (Boolean values, path names, etc.) + with automatic validation of the user's specified values. + See <xref linkend="sect-command-line-variables"></xref>, below. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Targets</term> + + <listitem> + <para> + + Any command-line argument that is not an option + or a variable setting + (does not begin with a hyphen + and does not contain an equal sign) + is considered a target that the user + (presumably) wants &SCons; to build. + A list of Node objects representing + the target or targets to build. + &SCons; provides access to the list of specified targets, + as well as ways to set the default list of targets + from within the &SConscript; files. + See <xref linkend="sect-command-line-targets"></xref>, below. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <section id="sect-command-line-options"> + <title>Command-Line Options</title> + + <para> + + &SCons; has many <emphasis>command-line options</emphasis> + that control its behavior. + A &SCons; <emphasis>command-line option</emphasis> + always begins with one or two <literal>-</literal> (hyphen) + characters. + + </para> + + <section> + <title>Not Having to Specify Command-Line Options Each Time: the &SCONSFLAGS; Environment Variable</title> + + <para> + + Users may find themselves supplying + the same command-line options every time + they run &SCons;. + For example, you might find it saves time + to specify a value of <literal>-j 2</literal> + to have &SCons; run up to two build commands in parallel. + To avoid having to type <literal>-j 2</literal> by hand + every time, + you can set the external environment variable + &SCONSFLAGS; to a string containing + command-line options that you want &SCons; to use. + + </para> + + <para> + + If, for example, + you're using a POSIX shell that's + compatible with the Bourne shell, + and you always want &SCons; to use the + <literal>-Q</literal> option, + you can set the &SCONSFLAGS; + environment as follows: + + </para> + + <scons_example name="SCONSFLAGS"> + <file name="SConstruct"> + def b(target, source, env): + pass + def s(target, source, env): + return " ... [build output] ..." + a = Action(b, strfunction = s) + env = Environment(BUILDERS = {'A' : Builder(action=a)}) + env.A('foo.out', 'foo.in') + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> + + <scons_output example="SCONSFLAGS"> + <scons_output_command>scons</scons_output_command> + <scons_output_command>export SCONSFLAGS="-Q"</scons_output_command> + <scons_output_command environment="SCONSFLAGS=-Q">scons</scons_output_command> + </scons_output> + + <para> + + Users of &csh;-style shells on POSIX systems + can set the &SCONSFLAGS; environment as follows: + + </para> + + <screen> + $ <userinput>setenv SCONSFLAGS "-Q"</userinput> + </screen> + + <para> + + Windows users may typically want to set the + &SCONSFLAGS; in the appropriate tab of the + <literal>System Properties</literal> window. + + </para> + + </section> + + <section> + <title>Getting Values Set by Command-Line Options: the &GetOption; Function</title> + + <para> + + &SCons; provides the &GetOption; function + to get the values set by the various command-line options. + One common use of this is to check whether or not + the <literal>-h</literal> or <literal>--help</literal> option + has been specified. + Normally, &SCons; does not print its help text + until after it has read all of the &SConscript; files, + because it's possible that help text has been added + by some subsidiary &SConscript; file deep in the + source tree hierarchy. + Of course, reading all of the &SConscript; files + takes extra time. + + </para> + + <para> + + If you know that your configuration does not define + any additional help text in subsidiary &SConscript; files, + you can speed up the command-line help available to users + by using the &GetOption; function to load the + subsidiary &SConscript; files only if the + the user has <emphasis>not</emphasis> specified + the <literal>-h</literal> or <literal>--help</literal> option, + like so: + + </para> + + <sconstruct) + if not GetOption('help'): + SConscript('src/SConscript', export='env') + </sconstruct> + + <para> + + In general, the string that you pass to the + &GetOption; function to fetch the value of a command-line + option setting is the same as the "most common" long option name + (beginning with two hyphen characters), + although there are some exceptions. + The list of &SCons; command-line options + and the &GetOption; strings for fetching them, + are available in the + <xref linkend="sect-command-line-option-strings"></xref> section, + below. + + </para> + + </section> + + <section> + <title>Setting Values of Command-Line Options: the &SetOption; Function</title> + + <para> + + You can also set the values of &SCons; + command-line options from within the &SConscript; files + by using the &SetOption; function. + The strings that you use to set the values of &SCons; + command-line options are available in the + <xref linkend="sect-command-line-option-strings"></xref> section, + below. + + </para> + + <para> + + One use of the &SetOption; function is to + specify a value for the <literal>-j</literal> + or <literal>--jobs</literal> option, + so that users get the improved performance + of a parallel build without having to specify the option by hand. + A complicating factor is that a good value + for the <literal>-j</literal> option is + somewhat system-dependent. + One rough guideline is that the more processors + your system has, + the higher you want to set the + <literal>-j</literal> value, + in order to take advantage of the number of CPUs. + + </para> + + <para> + + For example, suppose the administrators + of your development systems + have standardized on setting a + <varname>NUM_CPU</varname> environment variable + to the number of processors on each system. + A little bit of Python code + to access the environment variable + and the &SetOption; function + provide the right level of flexibility: + + </para> + + <scons_example name="SetOption"> + <file name="SConstruct" printme="1"> + import os + num_cpu = int(os.environ.get('NUM_CPU', 2)) + SetOption('num_jobs', num_cpu) + print "running with -j", GetOption('num_jobs') + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> + + <para> + + The above snippet of code + sets the value of the <literal>--jobs</literal> option + to the value specified in the + <varname>$NUM_CPU</varname> environment variable. + (This is one of the exception cases + where the string is spelled differently from + the from command-line option. + The string for fetching or setting the <literal>--jobs</literal> + value is <literal>num_jobs</literal> + for historical reasons.) + The code in this example prints the <literal>num_jobs</literal> + value for illustrative purposes. + It uses a default value of <literal>2</literal> + to provide some minimal parallelism even on + single-processor systems: + + </para> + + <scons_output example="SetOption"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + But if the <varname>$NUM_CPU</varname> + environment variable is set, + then we use that for the default number of jobs: + + </para> + + <scons_output example="SetOption"> + <scons_output_command>export NUM_CPU="4"</scons_output_command> + <scons_output_command environment="NUM_CPU=4">scons -Q</scons_output_command> + </scons_output> + + <para> + + But any explicit + <literal>-j</literal> or <literal>--jobs</literal> + value the user specifies an the command line is used first, + regardless of whether or not + the <varname>$NUM_CPU</varname> environment + variable is set: + + </para> + + <scons_output example="SetOption"> + <scons_output_command>scons -Q -j 7</scons_output_command> + <scons_output_command>export NUM_CPU="4"</scons_output_command> + <scons_output_command environment="NUM_CPU=4">scons -Q -j 3</scons_output_command> + </scons_output> + + </section> + + <section id="sect-command-line-option-strings"> + <title>Strings for Getting or Setting Values of &SCons; Command-Line Options</title> + + <para> + + The strings that you can pass to the &GetOption; + and &SetOption; functions usually correspond to the + first long-form option name + (beginning with two hyphen characters: <literal>--</literal>), + after replacing any remaining hyphen characters + with underscores. + + </para> + + <para> + + The full list of strings and the variables they + correspond to is as follows: + + </para> + + <informaltable> + <tgroup cols="2" align="left"> + + <thead> + + <row> + <entry>String for &GetOption; and &SetOption;</entry> + <entry>Command-Line Option(s)</entry> + </row> + + </thead> + + <tbody> + + <row> + <entry><literal>cache_debug</literal></entry> + <entry><option>--cache-debug</option></entry> + </row> + + <row> + <entry><literal>cache_disable</literal></entry> + <entry><option>--cache-disable</option></entry> + </row> + + <row> + <entry><literal>cache_force</literal></entry> + <entry><option>--cache-force</option></entry> + </row> + + <row> + <entry><literal>cache_show</literal></entry> + <entry><option>--cache-show</option></entry> + </row> + + <row> + <entry><literal>clean</literal></entry> + <entry><option>-c</option>, + <option>--clean</option>, + <option>--remove</option></entry> + </row> + + <row> + <entry><literal>config</literal></entry> + <entry><option>--config</option></entry> + </row> + + <row> + <entry><literal>directory</literal></entry> + <entry><option>-C</option>, + <option>--directory</option></entry> + </row> + + <row> + <entry><literal>diskcheck</literal></entry> + <entry><option>--diskcheck</option></entry> + </row> + + <row> + <entry><literal>duplicate</literal></entry> + <entry><option>--duplicate</option></entry> + </row> + + <row> + <entry><literal>file</literal></entry> + <entry><option>-f</option>, + <option>--file</option>, + <option>--makefile </option>, + <option>--sconstruct</option></entry> + </row> + + <row> + <entry><literal>help</literal></entry> + <entry><option>-h</option>, + <option>--help</option></entry> + </row> + + <row> + <entry><literal>ignore_errors</literal></entry> + <entry><option>--ignore-errors</option></entry> + </row> + + <row> + <entry><literal>implicit_cache</literal></entry> + <entry><option>--implicit-cache</option></entry> + </row> + + <row> + <entry><literal>implicit_deps_changed</literal></entry> + <entry><option>--implicit-deps-changed</option></entry> + </row> + + <row> + <entry><literal>implicit_deps_unchanged</literal></entry> + <entry><option>--implicit-deps-unchanged</option></entry> + </row> + + <row> + <entry><literal>interactive</literal></entry> + <entry><option>--interact</option>, + <option>--interactive</option></entry> + </row> + + <row> + <entry><literal>keep_going</literal></entry> + <entry><option>-k</option>, + <option>--keep-going</option></entry> + </row> + + <row> + <entry><literal>max_drift</literal></entry> + <entry><option>--max-drift</option></entry> + </row> + + <row> + <entry><literal>no_exec</literal></entry> + <entry><option>-n</option>, + <option>--no-exec</option>, + <option>--just-print</option>, + <option>--dry-run</option>, + <option>--recon</option></entry> + </row> + + <row> + <entry><literal>no_site_dir</literal></entry> + <entry><option>--no-site-dir</option></entry> + </row> + + <row> + <entry><literal>num_jobs</literal></entry> + <entry><option>-j</option>, + <option>--jobs</option></entry> + </row> + + <row> + <entry><literal>profile_file</literal></entry> + <entry><option>--profile</option></entry> + </row> + + <row> + <entry><literal>question</literal></entry> + <entry><option>-q</option>, + <option>--question</option></entry> + </row> + + <row> + <entry><literal>random</literal></entry> + <entry><option>--random</option></entry> + </row> + + <row> + <entry><literal>repository</literal></entry> + <entry><option>-Y</option>, + <option>--repository</option>, + <option>--srcdir</option></entry> + </row> + + <row> + <entry><literal>silent</literal></entry> + <entry><option>-s</option>, + <option>--silent</option>, + <option>--quiet</option></entry> + </row> + + <row> + <entry><literal>site_dir</literal></entry> + <entry><option>--site-dir</option></entry> + </row> + + <row> + <entry><literal>stack_size</literal></entry> + <entry><option>--stack-size</option></entry> + </row> + + <row> + <entry><literal>taskmastertrace_file</literal></entry> + <entry><option>--taskmastertrace</option></entry> + </row> + + <row> + <entry><literal>warn</literal></entry> + <entry><option>--warn</option> <option>--warning</option></entry> + </row> + + </tbody> + + </tgroup> + </informaltable> + + </section> + + <section> + <title>Adding Custom Command-Line Options: the &AddOption; Function</title> + + <para> + + &SCons; also allows you to define your own + command-line options with the &AddOption; function. + The &AddOption; function takes the same arguments + as the <function>optparse.add_option</function> function + from the standard Python library. + <footnote> + <para> + The &AddOption; function is, + in fact, implemented using a subclass + of the <classname>optparse.OptionParser</classname>. + </para> + </footnote> + Once you have added a custom command-line option + with the &AddOption; function, + the value of the option (if any) is immediately available + using the standard &GetOption; function. + (The value can also be set using &SetOption;, + although that's not very useful in practice + because a default value can be specified in + directly in the &AddOption; call.) + + </para> + + <para> + + One useful example of using this functionality + is to provide a <option>--prefix</option> for users: + + </para> + + <scons_example name="AddOption"> + <file name="SConstruct" printme="1"> + AddOption('--prefix', + dest='prefix', + type='string', + nargs=1, + action='store', + metavar='DIR', + help='installation prefix') + + env = Environment(PREFIX = GetOption('prefix')) + + installed_foo = env.Install('$PREFIX/usr/bin', 'foo.in') + Default(installed_foo) + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> + + <para> + + The above code uses the &GetOption; function + to set the <varname>$PREFIX</varname> + construction variable to any + value that the user specifies with a command-line + option of <literal>--prefix</literal>. + Because <varname>$PREFIX</varname> + will expand to a null string if it's not initialized, + running &SCons; without the + option of <literal>--prefix</literal> + will install the file in the + <filename>/usr/bin/</filename> directory: + + </para> + + <scons_output example="AddOption"> + <scons_output_command>scons -Q -n</scons_output_command> + </scons_output> + + <para> + + But specifying <literal>--prefix=/tmp/install</literal> + on the command line causes the file to be installed in the + <filename>/tmp/install/usr/bin/</filename> directory: + + </para> + + <scons_output example="AddOption"> + <scons_output_command>scons -Q -n --prefix=/tmp/install</scons_output_command> + </scons_output> + + </section> + + </section> + + <section id="sect-command-line-variables"> + <title>Command-Line <varname>variable</varname>=<varname>value</varname> Build Variables</title> + + <para> + + You may want to control various aspects + of your build by allowing the user + to specify <varname>variable</varname>=<varname>value</varname> + values on the command line. + For example, suppose you + want users to be able to + build a debug version of a program + by running &SCons; as follows: + + </para> + + <screen> + % <userinput>scons -Q debug=1</userinput> + </screen> + + <para> + + &SCons; provides an &ARGUMENTS; dictionary + that stores all of the + <varname>variable</varname>=<varname>value</varname> + assignments from the command line. + This allows you to modify + aspects of your build in response + to specifications on the command line. + (Note that unless you want to require + that users <emphasis>always</emphasis> + specify a variable, + you probably want to use + the Python + <literal>ARGUMENTS.get()</literal> function, + which allows you to specify a default value + to be used if there is no specification + on the command line.) + + </para> + + <para> + + The following code sets the &cv-link-CCFLAGS; construction + variable in response to the <varname>debug</varname> + flag being set in the &ARGUMENTS; dictionary: + + </para> + + <scons_example name="ARGUMENTS"> + <file name="SConstruct" printme="1"> + env = Environment() + debug = ARGUMENTS.get('debug', 0) + if int(debug): + env.Append(CCFLAGS = '-g') + env.Program('prog.c') + </file> + <file name="prog.c"> + prog.c + </file> + </scons_example> + + <para> + + This results in the <varname>-g</varname> + compiler option being used when + <literal>debug=1</literal> + is used on the command line: + + </para> + + <scons_output example="ARGUMENTS"> + <scons_output_command>scons -Q debug=0</scons_output_command> + <scons_output_command>scons -Q debug=0</scons_output_command> + <scons_output_command>scons -Q debug=1</scons_output_command> + <scons_output_command>scons -Q debug=1</scons_output_command> + </scons_output> + + <para> + + Notice that &SCons; keeps track of + the last values used to build the object files, + and as a result correctly rebuilds + the object and executable files + only when the value of the <literal>debug</literal> + argument has changed. + + </para> + + <para> + + The &ARGUMENTS; dictionary has two minor drawbacks. + First, because it is a dictionary, + it can only store one value for each specified keyword, + and thus only "remembers" the last setting + for each keyword on the command line. + This makes the &ARGUMENTS; dictionary + inappropriate if users should be able to + specify multiple values + on the command line for a given keyword. + Second, it does not preserve + the order in which the variable settings + were specified, + which is a problem if + you want the configuration to + behave differently in response + to the order in which the build + variable settings were specified on the command line. + + </para> + + <para> + + To accomodate these requirements, + &SCons; provides an &ARGLIST; variable + that gives you direct access to + <varname>variable</varname>=<varname>value</varname> + settings on the command line, + in the exact order they were specified, + and without removing any duplicate settings. + Each element in the &ARGLIST; variable + is itself a two-element list + containing the keyword and the value + of the setting, + and you must loop through, + or otherwise select from, + the elements of &ARGLIST; to + process the specific settings you want + in whatever way is appropriate for your configuration. + For example, + the following code to let the user + add to the &CPPDEFINES; construction variable + by specifying multiple + <varname>define=</varname> + settings on the command line: + + </para> + + <scons_example name="ARGLIST"> + <file name="SConstruct" printme="1"> + cppdefines = [] + for key, value in ARGLIST: + if key == 'define': + cppdefines.append(value) + env = Environment(CPPDEFINES = cppdefines) + env.Object('prog.c') + </file> + <file name="prog.c"> + prog.c + </file> + </scons_example> + + <para> + + Yields the following output: + + </para> + + <scons_output example="ARGLIST"> + <scons_output_command>scons -Q define=FOO</scons_output_command> + <scons_output_command>scons -Q define=FOO define=BAR</scons_output_command> + </scons_output> + + <para> + + Note that the &ARGLIST; and &ARGUMENTS; + variables do not interfere with each other, + but merely provide slightly different views + into how the user specified + <varname>variable</varname>=<varname>value</varname> + settings on the command line. + You can use both variables in the same + &SCons; configuration. + In general, the &ARGUMENTS; dictionary + is more convenient to use, + (since you can just fetch variable + settings through a dictionary access), + and the &ARGLIST; list + is more flexible + (since you can examine the + specific order in which + the user's command-line variabe settings). + + </para> + + <section> + <title>Controlling Command-Line Build Variables</title> + + <para> + + Being able to use a command-line build variable like + <literal>debug=1</literal> is handy, + but it can be a chore to write specific Python code + to recognize each such variable, + check for errors and provide appropriate messages, + and apply the values to a construction variable. + To help with this, + &SCons; supports a class to + define such build variables easily, + and a mechanism to apply the + build variables to a construction environment. + This allows you to control how the build variables affect + construction environments. + + </para> + + <para> + + For example, suppose that you want users to set + a &RELEASE; construction variable on the + command line whenever the time comes to build + a program for release, + and that the value of this variable + should be added to the command line + with the appropriate <literal>-D</literal> option + (or other command line option) + to pass the value to the C compiler. + Here's how you might do that by setting + the appropriate value in a dictionary for the + &cv-link-CPPDEFINES; construction variable: + + </para> + + <scons_example name="Variables1"> + <file name="SConstruct" printme="1"> + vars = Variables() + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + </file> + <file name="foo.c"> + foo.c + </file> + <file name="bar.c"> + bar.c + </file> + </scons_example> + + <para> + + This &SConstruct; file first creates a &Variables; object + (the <literal>vars = Variables()</literal> call), + and then uses the object's &Add; + method to indicate that the &RELEASE; + variable can be set on the command line, + and that its default value will be <literal>0</literal> + (the third argument to the &Add; method). + The second argument is a line of help text; + we'll learn how to use it in the next section. + + </para> + + <para> + + We then pass the created &Variables; + object as a &variables; keyword argument + to the &Environment; call + used to create the construction environment. + This then allows a user to set the + &RELEASE; build variable on the command line + and have the variable show up in + the command line used to build each object from + a C source file: + + </para> + + <scons_output example="Variables1"> + <scons_output_command>scons -Q RELEASE=1</scons_output_command> + </scons_output> + + <para> + + NOTE: Before &SCons; release 0.98.1, these build variables + were known as "command-line build options." + The class was actually named the &Options; class, + and in the sections below, + the various functions were named + &BoolOption;, &EnumOption;, &ListOption;, + &PathOption;, &PackageOption; and &AddOptions;. + These older names still work, + and you may encounter them in older + &SConscript; fles, + but their use is discouraged + and will be officially deprecated some day. + + </para> + + </section> + + <section> + <title>Providing Help for Command-Line Build Variables</title> + + <para> + + To make command-line build variables most useful, + you ideally want to provide + some help text that will describe + the available variables + when the user runs <literal>scons -h</literal>. + You could write this text by hand, + but &SCons; provides an easier way. + &Variables; objects support a + &GenerateHelpText; method + that will, as its name suggests, + generate text that describes + the various variables that + have been added to it. + You then pass the output from this method to + the &Help; function: + + </para> + + <scons_example name="Variables_Help"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars) + Help(vars.GenerateHelpText(env)) + </file> + </scons_example> + + <para> + + &SCons; will now display some useful text + when the <literal>-h</literal> option is used: + + </para> + + <scons_output example="Variables_Help"> + <scons_output_command>scons -Q -h</scons_output_command> + </scons_output> + + <para> + + Notice that the help output shows the default value, + and the current actual value of the build variable. + + </para> + + </section> + + <section> + <title>Reading Build Variables From a File</title> + + <para> + + Giving the user a way to specify the + value of a build variable on the command line + is useful, + but can still be tedious + if users must specify the variable + every time they run &SCons;. + We can let users provide customized build variable settings + in a local file by providing a + file name when we create the + &Variables; object: + + </para> + + <scons_example name="Variables_custom_py_1"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + Help(vars.GenerateHelpText(env)) + </file> + <file name="foo.c"> + foo.c + </file> + <file name="bar.c"> + bar.c + </file> + <file name="custom.py"> + RELEASE = 1 + </file> + </scons_example> + + <para> + + This then allows the user to control the &RELEASE; + variable by setting it in the &custom_py; file: + + </para> + + <scons_example_file example="Variables_custom_py_1" name="custom.py"></scons_example_file> + + <para> + + Note that this file is actually executed + like a Python script. + Now when we run &SCons;: + + </para> + + <scons_output example="Variables_custom_py_1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And if we change the contents of &custom_py; to: + + </para> + + <scons_example name="Variables_custom_py_2"> + <file name="SConstruct"> + vars = Variables('custom.py') + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + Help(vars.GenerateHelpText(env)) + </file> + <file name="foo.c"> + foo.c + </file> + <file name="bar.c"> + bar.c + </file> + <file name="custom.py" printme="1"> + RELEASE = 0 + </file> + </scons_example> + + <para> + + The object files are rebuilt appropriately + with the new variable: + + </para> + + <scons_output example="Variables_custom_py_2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Pre-Defined Build Variable Functions</title> + + <para> + + &SCons; provides a number of functions + that provide ready-made behaviors + for various types of command-line build variables. + + </para> + + <section> + <title>True/False Values: the &BoolVariable; Build Variable Function</title> + + <para> + + It's often handy to be able to specify a + variable that controls a simple Boolean variable + with a &true; or &false; value. + It would be even more handy to accomodate + users who have different preferences for how to represent + &true; or &false; values. + The &BoolVariable; function + makes it easy to accomodate these + common representations of + &true; or &false;. + + </para> + + <para> + + The &BoolVariable; function takes three arguments: + the name of the build variable, + the default value of the build variable, + and the help string for the variable. + It then returns appropriate information for + passing to the &Add; method of a &Variables; object, like so: + + </para> + + <scons_example name="BoolVariable"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(BoolVariable('RELEASE', 'Set to build for release', 0)) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + With this build variable, + the &RELEASE; variable can now be enabled by + setting it to the value <literal>yes</literal> + or <literal>t</literal>: + + </para> + + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=yes foo.o</scons_output_command> + </scons_output> + + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=t foo.o</scons_output_command> + </scons_output> + + <para> + + Other values that equate to &true; include + <literal>y</literal>, + <literal>1</literal>, + <literal>on</literal> + and + <literal>all</literal>. + + </para> + + <para> + + Conversely, &RELEASE; may now be given a &false; + value by setting it to + <literal>no</literal> + or + <literal>f</literal>: + + </para> + + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=no foo.o</scons_output_command> + </scons_output> + + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=f foo.o</scons_output_command> + </scons_output> + + <para> + + Other values that equate to &false; include + <literal>n</literal>, + <literal>0</literal>, + <literal>off</literal> + and + <literal>none</literal>. + + </para> + + <para> + + Lastly, if a user tries to specify + any other value, + &SCons; supplies an appropriate error message: + + </para> + + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=bad_value foo.o</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Single Value From a List: the &EnumVariable; Build Variable Function</title> + + <para> + + Suppose that we want a user to be able to + set a &COLOR; variable + that selects a background color to be + displayed by an application, + but that we want to restrict the + choices to a specific set of allowed colors. + This can be set up quite easily + using the &EnumVariable;, + which takes a list of &allowed_values + in addition to the variable name, + default value, + and help text arguments: + + </para> + + <scons_example name="EnumVariable"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'))) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + The user can now explicity set the &COLOR; build variable + to any of the specified allowed values: + + </para> + + <scons_output example="EnumVariable"> + <scons_output_command>scons -Q COLOR=red foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=blue foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=green foo.o</scons_output_command> + </scons_output> + + <para> + + But, almost more importantly, + an attempt to set &COLOR; + to a value that's not in the list + generates an error message: + + </para> + + <scons_output example="EnumVariable"> + <scons_output_command>scons -Q COLOR=magenta foo.o</scons_output_command> + </scons_output> + + <para> + + The &EnumVariable; function also supports a way + to map alternate names to allowed values. + Suppose, for example, + that we want to allow the user + to use the word <literal>navy</literal> as a synonym for + <literal>blue</literal>. + We do this by adding a ↦ dictionary + that will map its key values + to the desired legal value: + + </para> + + <scons_example name="EnumVariable_map"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'})) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + As desired, the user can then use + <literal>navy</literal> on the command line, + and &SCons; will translate it into <literal>blue</literal> + when it comes time to use the &COLOR; + variable to build a target: + + </para> + + <scons_output example="EnumVariable_map"> + <scons_output_command>scons -Q COLOR=navy foo.o</scons_output_command> + </scons_output> + + <para> + + By default, when using the &EnumVariable; function, + arguments that differ + from the legal values + only in case + are treated as illegal values: + + </para> + + <scons_output example="EnumVariable"> + <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=BLUE foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> + </scons_output> + + <para> + + The &EnumVariable; function can take an additional + &ignorecase; keyword argument that, + when set to <literal>1</literal>, + tells &SCons; to allow case differences + when the values are specified: + + </para> + + <scons_example name="EnumVariable_ic1"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=1)) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + Which yields the output: + + </para> + + <scons_output example="EnumVariable_ic1"> + <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=BLUE foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=green foo.o</scons_output_command> + </scons_output> + + <para> + + Notice that an &ignorecase; value of <literal>1</literal> + preserves the case-spelling that the user supplied. + If you want &SCons; to translate the names + into lower-case, + regardless of the case used by the user, + specify an &ignorecase; value of <literal>2</literal>: + + </para> + + <scons_example name="EnumVariable_ic2"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=2)) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + Now &SCons; will use values of + <literal>red</literal>, + <literal>green</literal> or + <literal>blue</literal> + regardless of how the user spells + those values on the command line: + + </para> + + <scons_output example="EnumVariable_ic2"> + <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=GREEN foo.o</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Multiple Values From a List: the &ListVariable; Build Variable Function</title> + + <para> + + Another way in which you might want to allow users + to control a build variable is to + specify a list of one or more legal values. + &SCons; supports this through the &ListVariable; function. + If, for example, we want a user to be able to set a + &COLORS; variable to one or more of the legal list of values: + + </para> + + <scons_example name="ListVariable"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(ListVariable('COLORS', 'List of colors', 0, + ['red', 'green', 'blue'])) + env = Environment(variables = vars, + CPPDEFINES={'COLORS' : '"${COLORS}"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + A user can now specify a comma-separated list + of legal values, + which will get translated into a space-separated + list for passing to the any build commands: + + </para> + + <scons_output example="ListVariable"> + <scons_output_command>scons -Q COLORS=red,blue foo.o</scons_output_command> + <scons_output_command>scons -Q COLORS=blue,green,red foo.o</scons_output_command> + </scons_output> + + <para> + + In addition, the &ListVariable; function + allows the user to specify explicit keywords of + &all; or &none; + to select all of the legal values, + or none of them, respectively: + + </para> + + <scons_output example="ListVariable"> + <scons_output_command>scons -Q COLORS=all foo.o</scons_output_command> + <scons_output_command>scons -Q COLORS=none foo.o</scons_output_command> + </scons_output> + + <para> + + And, of course, an illegal value + still generates an error message: + + </para> + + <scons_output example="ListVariable"> + <scons_output_command>scons -Q COLORS=magenta foo.o</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Path Names: the &PathVariable; Build Variable Function</title> + + <para> + + &SCons; supports a &PathVariable; function + to make it easy to create a build variable + to control an expected path name. + If, for example, you need to + define a variable in the preprocessor + that controls the location of a + configuration file: + + </para> + + <scons_example name="PathVariable"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(PathVariable('CONFIG', + 'Path to configuration file', + '__ROOT__/etc/my_config')) + env = Environment(variables = vars, + CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/etc/my_config"> + /opt/location + </file> + <file name="__ROOT__/usr/local/etc/other_config"> + /opt/location + </file> + </scons_example> + + <para> + + This then allows the user to + override the &CONFIG; build variable + on the command line as necessary: + + </para> + + <scons_output example="PathVariable"> + <scons_output_command>scons -Q foo.o</scons_output_command> + <scons_output_command>scons -Q CONFIG=__ROOT__/usr/local/etc/other_config foo.o</scons_output_command> + </scons_output> + + <para> + + By default, &PathVariable; checks to make sure + that the specified path exists and generates an error if it + doesn't: + + </para> + + <scons_output example="PathVariable"> + <scons_output_command>scons -Q CONFIG=__ROOT__/does/not/exist foo.o</scons_output_command> + </scons_output> + + <para> + + &PathVariable; provides a number of methods + that you can use to change this behavior. + If you want to ensure that any specified paths are, + in fact, files and not directories, + use the &PathVariable_PathIsFile; method: + + </para> + + <scons_example name="PathIsFile"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(PathVariable('CONFIG', + 'Path to configuration file', + '__ROOT__/etc/my_config', + PathVariable.PathIsFile)) + env = Environment(variables = vars, + CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/etc/my_config"> + /opt/location + </file> + </scons_example> + + <para> + + Conversely, to ensure that any specified paths are + directories and not files, + use the &PathVariable_PathIsDir; method: + + </para> + + <scons_example name="PathIsDir"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(PathVariable('DBDIR', + 'Path to database directory', + '__ROOT__/var/my_dbdir', + PathVariable.PathIsDir)) + env = Environment(variables = vars, + CPPDEFINES={'DBDIR' : '"$DBDIR"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/var/my_dbdir"> + /opt/location + </file> + </scons_example> + + <para> + + If you want to make sure that any specified paths + are directories, + and you would like the directory created + if it doesn't already exist, + use the &PathVariable_PathIsDirCreate; method: + + </para> + + <scons_example name="PathIsDirCreate"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(PathVariable('DBDIR', + 'Path to database directory', + '__ROOT__/var/my_dbdir', + PathVariable.PathIsDirCreate)) + env = Environment(variables = vars, + CPPDEFINES={'DBDIR' : '"$DBDIR"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/var/my_dbdir"> + /opt/location + </file> + </scons_example> + + <para> + + Lastly, if you don't care whether the path exists, + is a file, or a directory, + use the &PathVariable_PathAccept; method + to accept any path that the user supplies: + + </para> + + <scons_example name="PathAccept"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(PathVariable('OUTPUT', + 'Path to output file or directory', + None, + PathVariable.PathAccept)) + env = Environment(variables = vars, + CPPDEFINES={'OUTPUT' : '"$OUTPUT"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + </section> + + <section> + <title>Enabled/Disabled Path Names: the &PackageVariable; Build Variable Function</title> + + <para> + + Sometimes you want to give users + even more control over a path name variable, + allowing them to explicitly enable or + disable the path name + by using <literal>yes</literal> or <literal>no</literal> keywords, + in addition to allow them + to supply an explicit path name. + &SCons; supports the &PackageVariable; + function to support this: + + </para> + + <scons_example name="PackageVariable"> + <file name="SConstruct" printme="1"> + vars = Variables('custom.py') + vars.Add(PackageVariable('PACKAGE', + 'Location package', + '__ROOT__/opt/location')) + env = Environment(variables = vars, + CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/opt/location"> + /opt/location + </file> + <file name="__ROOT__/usr/local/location"> + /opt/location + </file> + </scons_example> + + <para> + + When the &SConscript; file uses the &PackageVariable; funciton, + user can now still use the default + or supply an overriding path name, + but can now explicitly set the + specified variable to a value + that indicates the package should be enabled + (in which case the default should be used) + or disabled: + + </para> + + <scons_output example="PackageVariable"> + <scons_output_command>scons -Q foo.o</scons_output_command> + <scons_output_command>scons -Q PACKAGE=__ROOT__/usr/local/location foo.o</scons_output_command> + <scons_output_command>scons -Q PACKAGE=yes foo.o</scons_output_command> + <scons_output_command>scons -Q PACKAGE=no foo.o</scons_output_command> + </scons_output> + + </section> + + </section> + + <section> + <title>Adding Multiple Command-Line Build Variables at Once</title> + + <para> + + Lastly, &SCons; provides a way to add + multiple build variables to a &Variables; object at once. + Instead of having to call the &Add; method + multiple times, + you can call the &AddVariables; + method with a list of build variables + to be added to the object. + Each build variable is specified + as either a tuple of arguments, + just like you'd pass to the &Add; method itself, + or as a call to one of the pre-defined + functions for pre-packaged command-line build variables. + in any order: + + </para> + + <scons_example name="AddVariables_1"> + <file name="SConstruct" printme="1"> + vars = Variables() + vars.AddVariables( + ('RELEASE', 'Set to 1 to build for release', 0), + ('CONFIG', 'Configuration file', '/etc/my_config'), + BoolVariable('warnings', 'compilation with -Wall and similiar', 1), + EnumVariable('debug', 'debug output and symbols', 'no', + allowed_values=('yes', 'no', 'full'), + map={}, ignorecase=0), # case sensitive + ListVariable('shared', + 'libraries to build as shared libraries', + 'all', + names = list_of_libs), + PackageVariable('x11', + 'use X11 installed here (yes = search some places)', + 'yes'), + PathVariable('qtdir', 'where the root of Qt is installed', qtdir), + ) + </file> + </scons_example> + + <para> + </para> + + </section> + + <section> + <title>Handling Unknown Command-Line Build Variables: the &UnknownVariables; Function</title> + + <para> + + Users may, of course, + occasionally misspell variable names in their command-line settings. + &SCons; does not generate an error or warning + for any unknown variables the users specifies on the command line. + (This is in no small part because you may be + processing the arguments directly using the &ARGUMENTS; dictionary, + and therefore &SCons; can't know in the general case + whether a given "misspelled" variable is + really unknown and a potential problem, + or something that your &SConscript; file + will handle directly with some Python code.) + + </para> + + <para> + + If, however, you're using a &Variables; object to + define a specific set of command-line build variables + that you expect users to be able to set, + you may want to provide an error + message or warning of your own + if the user supplies a variable setting + that is <emphasis>not</emphasis> among + the defined list of variable names known to the &Variables; object. + You can do this by calling the &UnknownVariables; + method of the &Variables; object: + + </para> + + <scons_example name="UnknownVariables"> + <file name="SConstruct" printme="1"> + vars = Variables(None) + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + unknown = vars.UnknownVariables() + if unknown: + print "Unknown variables:", unknown.keys() + Exit(1) + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + The &UnknownVariables; method returns a dictionary + containing the keywords and values + of any variables the user specified on the command line + that are <emphasis>not</emphasis> + among the variables known to the &Variables; object + (from having been specified using + the &Variables; object's&Add; method). + In the examble above, + we check for whether the dictionary + returned by the &UnknownVariables; is non-empty, + and if so print the Python list + containing the names of the unknwown variables + and then call the &Exit; function + to terminate &SCons;: + + </para> + + <scons_output example="UnknownVariables"> + <scons_output_command>scons -Q NOT_KNOWN=foo</scons_output_command> + </scons_output> + + <para> + + Of course, you can process the items in the + dictionary returned by the &UnknownVariables; function + in any way appropriate to your build configuration, + including just printing a warning message + but not exiting, + logging an error somewhere, + etc. + + </para> + + <para> + + Note that you must delay the call of &UnknownVariables; + until after you have applied the &Variables; object + to a construction environment + with the <literal>variables=</literal> + keyword argument of an &Environment; call. + + </para> + + </section> + + </section> + + <section id="sect-command-line-targets"> + <title>Command-Line Targets</title> + + <section> + <title>Fetching Command-Line Targets: the &COMMAND_LINE_TARGETS; Variable</title> + + <para> + + &SCons; supports a &COMMAND_LINE_TARGETS; variable + that lets you fetch the list of targets that the + user specified on the command line. + You can use the targets to manipulate the + build in any way you wish. + As a simple example, + suppose that you want to print a reminder + to the user whenever a specific program is built. + You can do this by checking for the + target in the &COMMAND_LINE_TARGETS; list: + + </para> + + <scons_example name="COMMAND_LINE_TARGETS"> + <file name="SConstruct" printme="1"> + if 'bar' in COMMAND_LINE_TARGETS: + print "Don't forget to copy `bar' to the archive!" + Default(Program('foo.c')) + Program('bar.c') + </file> + <file name="foo.c"> + foo.c + </file> + <file name="bar.c"> + foo.c + </file> + </scons_example> + + <para> + + Then, running &SCons; with the default target + works as it always does, + but explicity specifying the &bar; target + on the command line generates the warning message: + + </para> + + <scons_output example="COMMAND_LINE_TARGETS"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q bar</scons_output_command> + </scons_output> + + <para> + + Another practical use for the &COMMAND_LINE_TARGETS; variable + might be to speed up a build + by only reading certain subsidiary &SConscript; + files if a specific target is requested. + + </para> + + </section> + + <section> + <title>Controlling the Default Targets: the &Default; Function</title> + + <para> + + One of the most basic things you can control + is which targets &SCons; will build by default--that is, + when there are no targets specified on the command line. + As mentioned previously, + &SCons; will normally build every target + in or below the current directory + by default--that is, when you don't + explicitly specify one or more targets + on the command line. + Sometimes, however, you may want + to specify explicitly that only + certain programs, or programs in certain directories, + should be built by default. + You do this with the &Default; function: + + </para> + + <scons_example name="Default1"> + <file name="SConstruct" printme="1"> + env = Environment() + hello = env.Program('hello.c') + env.Program('goodbye.c') + Default(hello) + </file> + <file name="hello.c"> + hello.c + </file> + <file name="goodbye.c"> + goodbye.c + </file> + </scons_example> + + <para> + + This &SConstruct; file knows how to build two programs, + &hello; and &goodbye;, + but only builds the + &hello; program by default: + + </para> + + <scons_output example="Default1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q goodbye</scons_output_command> + </scons_output> + + <para> + + Note that, even when you use the &Default; + function in your &SConstruct; file, + you can still explicitly specify the current directory + (<literal>.</literal>) on the command line + to tell &SCons; to build + everything in (or below) the current directory: + + </para> + + <scons_output example="Default1"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> + + <para> + + You can also call the &Default; + function more than once, + in which case each call + adds to the list of targets to be built by default: + + </para> + + <scons_example name="Default2"> + <file name="SConstruct" printme="1"> + env = Environment() + prog1 = env.Program('prog1.c') + Default(prog1) + prog2 = env.Program('prog2.c') + prog3 = env.Program('prog3.c') + Default(prog3) + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + <file name="prog3.c"> + prog3.c + </file> + </scons_example> + + <para> + + Or you can specify more than one target + in a single call to the &Default; function: + + </para> + + <programlisting> + env = Environment() + prog1 = env.Program('prog1.c') + prog2 = env.Program('prog2.c') + prog3 = env.Program('prog3.c') + Default(prog1, prog3) + </programlisting> + + <para> + + Either of these last two examples + will build only the + <application>prog1</application> + and + <application>prog3</application> + programs by default: + + </para> + + <scons_output example="Default2"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> + + <para> + + You can list a directory as + an argument to &Default;: + + </para> + + <scons_example name="Default3"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Program(['prog1/main.c', 'prog1/foo.c']) + env.Program(['prog2/main.c', 'prog2/bar.c']) + Default('prog1') + </file> + <directory name="prog1"></directory> + <directory name="prog2"></directory> + <file name="prog1/main.c"> + int main() { printf("prog1/main.c\n"); } + </file> + <file name="prog1/foo.c"> + int foo() { printf("prog1/foo.c\n"); } + </file> + <file name="prog2/main.c"> + int main() { printf("prog2/main.c\n"); } + </file> + <file name="prog2/bar.c"> + int bar() { printf("prog2/bar.c\n"); } + </file> + </scons_example> + + <para> + + In which case only the target(s) in that + directory will be built by default: + + </para> + + <scons_output example="Default3"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> + + <para> + + Lastly, if for some reason you don't want + any targets built by default, + you can use the Python <literal>None</literal> + variable: + + </para> + + <scons_example name="Default4"> + <file name="SConstruct" printme="1"> + env = Environment() + prog1 = env.Program('prog1.c') + prog2 = env.Program('prog2.c') + Default(None) + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> + + <para> + + Which would produce build output like: + + </para> + + <scons_output example="Default4"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> + + <section> + <title>Fetching the List of Default Targets: the &DEFAULT_TARGETS; Variable</title> + + <para> + + &SCons; supports a &DEFAULT_TARGETS; variable + that lets you get at the current list of default targets. + The &DEFAULT_TARGETS variable has + two important differences from the &COMMAND_LINE_TARGETS; variable. + First, the &DEFAULT_TARGETS; variable is a list of + internal &SCons; nodes, + so you need to convert the list elements to strings + if you want to print them or look for a specific target name. + Fortunately, you can do this easily + by using the Python <function>map</function> function + to run the list through <function>str</function>: + + </para> + + <scons_example name="DEFAULT_TARGETS_1"> + <file name="SConstruct" printme="1"> + prog1 = Program('prog1.c') + Default(prog1) + print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS) + </file> + <file name="prog1.c"> + prog1.c + </file> + </scons_example> + + <para> + + (Keep in mind that all of the manipulation of the + &DEFAULT_TARGETS; list takes place during the + first phase when &SCons; is reading up the &SConscript; files, + which is obvious if + we leave off the <literal>-Q</literal> flag when we run &SCons;:) + + </para> + + <scons_output example="DEFAULT_TARGETS_1"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + Second, + the contents of the &DEFAULT_TARGETS; list change + in response to calls to the &Default: function, + as you can see from the following &SConstruct; file: + + </para> + + <scons_example name="DEFAULT_TARGETS_2"> + <file name="SConstruct" printme="1"> + prog1 = Program('prog1.c') + Default(prog1) + print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) + prog2 = Program('prog2.c') + Default(prog2) + print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> + + <para> + + Which yields the output: + + </para> + + <scons_output example="DEFAULT_TARGETS_2"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + In practice, this simply means that you + need to pay attention to the order in + which you call the &Default; function + and refer to the &DEFAULT_TARGETS; list, + to make sure that you don't examine the + list before you've added the default targets + you expect to find in it. + + </para> + + </section> + + </section> + + <section> + <title>Fetching the List of Build Targets, Regardless of Origin: the &BUILD_TARGETS; Variable</title> + + <para> + + We've already been introduced to the + &COMMAND_LINE_TARGETS; variable, + which contains a list of targets specified on the command line, + and the &DEFAULT_TARGETS; variable, + which contains a list of targets specified + via calls to the &Default; method or function. + Sometimes, however, + you want a list of whatever targets + &SCons; will try to build, + regardless of whether the targets came from the + command line or a &Default; call. + You could code this up by hand, as follows: + + </para> + + <sconstruct> + if COMMAND_LINE_TARGETS: + targets = COMMAND_LINE_TARGETS + else: + targets = DEFAULT_TARGETS + </sconstruct> + + <para> + + &SCons;, however, provides a convenient + &BUILD_TARGETS; variable + that eliminates the need for this by-hand manipulation. + Essentially, the &BUILD_TARGETS; variable + contains a list of the command-line targets, + if any were specified, + and if no command-line targets were specified, + it contains a list of the targets specified + via the &Default; method or function. + + </para> + + <para> + + Because &BUILD_TARGETS; may contain a list of &SCons; nodes, + you must convert the list elements to strings + if you want to print them or look for a specific target name, + just like the &DEFAULT_TARGETS; list: + + </para> + + <scons_example name="BUILD_TARGETS_1"> + <file name="SConstruct" printme="1"> + prog1 = Program('prog1.c') + Program('prog2.c') + Default(prog1) + print "BUILD_TARGETS is", map(str, BUILD_TARGETS) + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> + + <para> + + Notice how the value of &BUILD_TARGETS; + changes depending on whether a target is + specified on the command line: + + </para> + + <scons_output example="BUILD_TARGETS_1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q prog2</scons_output_command> + <scons_output_command>scons -Q -c .</scons_output_command> + </scons_output> + + </section> + + </section> diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml new file mode 100644 index 0000000..630a9b2 --- /dev/null +++ b/doc/user/command-line.xml @@ -0,0 +1,2243 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; provides a number of ways + for the writer of the &SConscript; files + to give the users who will run &SCons; + a great deal of control over the build execution. + The arguments that the user can specify on + the command line are broken down into three types: + + </para> + + <variablelist> + + <varlistentry> + <term>Options</term> + + <listitem> + <para> + + Command-line options always begin with + one or two <literal>-</literal> (hyphen) characters. + &SCons; provides ways for you to examine + and set options values from within your &SConscript; files, + as well as the ability to define your own + custom options. + See <xref linkend="sect-command-line-options"></xref>, below. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Variables</term> + + <listitem> + <para> + + Any command-line argument containing an <literal>=</literal> + (equal sign) is considered a variable setting with the form + <varname>variable</varname>=<varname>value</varname> + &SCons; provides direct access to + all of the command-line variable settings, + the ability to apply command-line variable settings + to construction environments, + and functions for configuring + specific types of variables + (Boolean values, path names, etc.) + with automatic validation of the user's specified values. + See <xref linkend="sect-command-line-variables"></xref>, below. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Targets</term> + + <listitem> + <para> + + Any command-line argument that is not an option + or a variable setting + (does not begin with a hyphen + and does not contain an equal sign) + is considered a target that the user + (presumably) wants &SCons; to build. + A list of Node objects representing + the target or targets to build. + &SCons; provides access to the list of specified targets, + as well as ways to set the default list of targets + from within the &SConscript; files. + See <xref linkend="sect-command-line-targets"></xref>, below. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <section id="sect-command-line-options"> + <title>Command-Line Options</title> + + <para> + + &SCons; has many <emphasis>command-line options</emphasis> + that control its behavior. + A &SCons; <emphasis>command-line option</emphasis> + always begins with one or two <literal>-</literal> (hyphen) + characters. + + </para> + + <section> + <title>Not Having to Specify Command-Line Options Each Time: the &SCONSFLAGS; Environment Variable</title> + + <para> + + Users may find themselves supplying + the same command-line options every time + they run &SCons;. + For example, you might find it saves time + to specify a value of <literal>-j 2</literal> + to have &SCons; run up to two build commands in parallel. + To avoid having to type <literal>-j 2</literal> by hand + every time, + you can set the external environment variable + &SCONSFLAGS; to a string containing + command-line options that you want &SCons; to use. + + </para> + + <para> + + If, for example, + you're using a POSIX shell that's + compatible with the Bourne shell, + and you always want &SCons; to use the + <literal>-Q</literal> option, + you can set the &SCONSFLAGS; + environment as follows: + + </para> + + + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + ... [build output] ... + scons: done building targets. + % <userinput>export SCONSFLAGS="-Q"</userinput> + % <userinput>scons</userinput> + ... [build output] ... + </screen> + + <para> + + Users of &csh;-style shells on POSIX systems + can set the &SCONSFLAGS; environment as follows: + + </para> + + <screen> + $ <userinput>setenv SCONSFLAGS "-Q"</userinput> + </screen> + + <para> + + Windows users may typically want to set the + &SCONSFLAGS; in the appropriate tab of the + <literal>System Properties</literal> window. + + </para> + + </section> + + <section> + <title>Getting Values Set by Command-Line Options: the &GetOption; Function</title> + + <para> + + &SCons; provides the &GetOption; function + to get the values set by the various command-line options. + One common use of this is to check whether or not + the <literal>-h</literal> or <literal>--help</literal> option + has been specified. + Normally, &SCons; does not print its help text + until after it has read all of the &SConscript; files, + because it's possible that help text has been added + by some subsidiary &SConscript; file deep in the + source tree hierarchy. + Of course, reading all of the &SConscript; files + takes extra time. + + </para> + + <para> + + If you know that your configuration does not define + any additional help text in subsidiary &SConscript; files, + you can speed up the command-line help available to users + by using the &GetOption; function to load the + subsidiary &SConscript; files only if the + the user has <emphasis>not</emphasis> specified + the <literal>-h</literal> or <literal>--help</literal> option, + like so: + + </para> + + <programlisting></programlisting> + + <para> + + In general, the string that you pass to the + &GetOption; function to fetch the value of a command-line + option setting is the same as the "most common" long option name + (beginning with two hyphen characters), + although there are some exceptions. + The list of &SCons; command-line options + and the &GetOption; strings for fetching them, + are available in the + <xref linkend="sect-command-line-option-strings"></xref> section, + below. + + </para> + + </section> + + <section> + <title>Setting Values of Command-Line Options: the &SetOption; Function</title> + + <para> + + You can also set the values of &SCons; + command-line options from within the &SConscript; files + by using the &SetOption; function. + The strings that you use to set the values of &SCons; + command-line options are available in the + <xref linkend="sect-command-line-option-strings"></xref> section, + below. + + </para> + + <para> + + One use of the &SetOption; function is to + specify a value for the <literal>-j</literal> + or <literal>--jobs</literal> option, + so that users get the improved performance + of a parallel build without having to specify the option by hand. + A complicating factor is that a good value + for the <literal>-j</literal> option is + somewhat system-dependent. + One rough guideline is that the more processors + your system has, + the higher you want to set the + <literal>-j</literal> value, + in order to take advantage of the number of CPUs. + + </para> + + <para> + + For example, suppose the administrators + of your development systems + have standardized on setting a + <varname>NUM_CPU</varname> environment variable + to the number of processors on each system. + A little bit of Python code + to access the environment variable + and the &SetOption; function + provide the right level of flexibility: + + </para> + + <programlisting> + import os + num_cpu = int(os.environ.get('NUM_CPU', 2)) + SetOption('num_jobs', num_cpu) + print "running with -j", GetOption('num_jobs') + </programlisting> + + <para> + + The above snippet of code + sets the value of the <literal>--jobs</literal> option + to the value specified in the + <varname>$NUM_CPU</varname> environment variable. + (This is one of the exception cases + where the string is spelled differently from + the from command-line option. + The string for fetching or setting the <literal>--jobs</literal> + value is <literal>num_jobs</literal> + for historical reasons.) + The code in this example prints the <literal>num_jobs</literal> + value for illustrative purposes. + It uses a default value of <literal>2</literal> + to provide some minimal parallelism even on + single-processor systems: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + running with -j 2 + scons: `.' is up to date. + </screen> + + <para> + + But if the <varname>$NUM_CPU</varname> + environment variable is set, + then we use that for the default number of jobs: + + </para> + + <screen> + % <userinput>export NUM_CPU="4"</userinput> + % <userinput>scons -Q</userinput> + running with -j 4 + scons: `.' is up to date. + </screen> + + <para> + + But any explicit + <literal>-j</literal> or <literal>--jobs</literal> + value the user specifies an the command line is used first, + regardless of whether or not + the <varname>$NUM_CPU</varname> environment + variable is set: + + </para> + + <screen> + % <userinput>scons -Q -j 7</userinput> + running with -j 7 + scons: `.' is up to date. + % <userinput>export NUM_CPU="4"</userinput> + % <userinput>scons -Q -j 3</userinput> + running with -j 3 + scons: `.' is up to date. + </screen> + + </section> + + <section id="sect-command-line-option-strings"> + <title>Strings for Getting or Setting Values of &SCons; Command-Line Options</title> + + <para> + + The strings that you can pass to the &GetOption; + and &SetOption; functions usually correspond to the + first long-form option name + (beginning with two hyphen characters: <literal>--</literal>), + after replacing any remaining hyphen characters + with underscores. + + </para> + + <para> + + The full list of strings and the variables they + correspond to is as follows: + + </para> + + <informaltable> + <tgroup cols="2" align="left"> + + <thead> + + <row> + <entry>String for &GetOption; and &SetOption;</entry> + <entry>Command-Line Option(s)</entry> + </row> + + </thead> + + <tbody> + + <row> + <entry><literal>cache_debug</literal></entry> + <entry><option>--cache-debug</option></entry> + </row> + + <row> + <entry><literal>cache_disable</literal></entry> + <entry><option>--cache-disable</option></entry> + </row> + + <row> + <entry><literal>cache_force</literal></entry> + <entry><option>--cache-force</option></entry> + </row> + + <row> + <entry><literal>cache_show</literal></entry> + <entry><option>--cache-show</option></entry> + </row> + + <row> + <entry><literal>clean</literal></entry> + <entry><option>-c</option>, + <option>--clean</option>, + <option>--remove</option></entry> + </row> + + <row> + <entry><literal>config</literal></entry> + <entry><option>--config</option></entry> + </row> + + <row> + <entry><literal>directory</literal></entry> + <entry><option>-C</option>, + <option>--directory</option></entry> + </row> + + <row> + <entry><literal>diskcheck</literal></entry> + <entry><option>--diskcheck</option></entry> + </row> + + <row> + <entry><literal>duplicate</literal></entry> + <entry><option>--duplicate</option></entry> + </row> + + <row> + <entry><literal>file</literal></entry> + <entry><option>-f</option>, + <option>--file</option>, + <option>--makefile </option>, + <option>--sconstruct</option></entry> + </row> + + <row> + <entry><literal>help</literal></entry> + <entry><option>-h</option>, + <option>--help</option></entry> + </row> + + <row> + <entry><literal>ignore_errors</literal></entry> + <entry><option>--ignore-errors</option></entry> + </row> + + <row> + <entry><literal>implicit_cache</literal></entry> + <entry><option>--implicit-cache</option></entry> + </row> + + <row> + <entry><literal>implicit_deps_changed</literal></entry> + <entry><option>--implicit-deps-changed</option></entry> + </row> + + <row> + <entry><literal>implicit_deps_unchanged</literal></entry> + <entry><option>--implicit-deps-unchanged</option></entry> + </row> + + <row> + <entry><literal>interactive</literal></entry> + <entry><option>--interact</option>, + <option>--interactive</option></entry> + </row> + + <row> + <entry><literal>keep_going</literal></entry> + <entry><option>-k</option>, + <option>--keep-going</option></entry> + </row> + + <row> + <entry><literal>max_drift</literal></entry> + <entry><option>--max-drift</option></entry> + </row> + + <row> + <entry><literal>no_exec</literal></entry> + <entry><option>-n</option>, + <option>--no-exec</option>, + <option>--just-print</option>, + <option>--dry-run</option>, + <option>--recon</option></entry> + </row> + + <row> + <entry><literal>no_site_dir</literal></entry> + <entry><option>--no-site-dir</option></entry> + </row> + + <row> + <entry><literal>num_jobs</literal></entry> + <entry><option>-j</option>, + <option>--jobs</option></entry> + </row> + + <row> + <entry><literal>profile_file</literal></entry> + <entry><option>--profile</option></entry> + </row> + + <row> + <entry><literal>question</literal></entry> + <entry><option>-q</option>, + <option>--question</option></entry> + </row> + + <row> + <entry><literal>random</literal></entry> + <entry><option>--random</option></entry> + </row> + + <row> + <entry><literal>repository</literal></entry> + <entry><option>-Y</option>, + <option>--repository</option>, + <option>--srcdir</option></entry> + </row> + + <row> + <entry><literal>silent</literal></entry> + <entry><option>-s</option>, + <option>--silent</option>, + <option>--quiet</option></entry> + </row> + + <row> + <entry><literal>site_dir</literal></entry> + <entry><option>--site-dir</option></entry> + </row> + + <row> + <entry><literal>stack_size</literal></entry> + <entry><option>--stack-size</option></entry> + </row> + + <row> + <entry><literal>taskmastertrace_file</literal></entry> + <entry><option>--taskmastertrace</option></entry> + </row> + + <row> + <entry><literal>warn</literal></entry> + <entry><option>--warn</option> <option>--warning</option></entry> + </row> + + </tbody> + + </tgroup> + </informaltable> + + </section> + + <section> + <title>Adding Custom Command-Line Options: the &AddOption; Function</title> + + <para> + + &SCons; also allows you to define your own + command-line options with the &AddOption; function. + The &AddOption; function takes the same arguments + as the <function>optparse.add_option</function> function + from the standard Python library. + <footnote> + <para> + The &AddOption; function is, + in fact, implemented using a subclass + of the <classname>optparse.OptionParser</classname>. + </para> + </footnote> + Once you have added a custom command-line option + with the &AddOption; function, + the value of the option (if any) is immediately available + using the standard &GetOption; function. + (The value can also be set using &SetOption;, + although that's not very useful in practice + because a default value can be specified in + directly in the &AddOption; call.) + + </para> + + <para> + + One useful example of using this functionality + is to provide a <option>--prefix</option> for users: + + </para> + + <programlisting> + AddOption('--prefix', + dest='prefix', + type='string', + nargs=1, + action='store', + metavar='DIR', + help='installation prefix') + + env = Environment(PREFIX = GetOption('prefix')) + + installed_foo = env.Install('$PREFIX/usr/bin', 'foo.in') + Default(installed_foo) + </programlisting> + + <para> + + The above code uses the &GetOption; function + to set the <varname>$PREFIX</varname> + construction variable to any + value that the user specifies with a command-line + option of <literal>--prefix</literal>. + Because <varname>$PREFIX</varname> + will expand to a null string if it's not initialized, + running &SCons; without the + option of <literal>--prefix</literal> + will install the file in the + <filename>/usr/bin/</filename> directory: + + </para> + + <screen> + % <userinput>scons -Q -n</userinput> + Install file: "foo.in" as "/usr/bin/foo.in" + </screen> + + <para> + + But specifying <literal>--prefix=/tmp/install</literal> + on the command line causes the file to be installed in the + <filename>/tmp/install/usr/bin/</filename> directory: + + </para> + + <screen> + % <userinput>scons -Q -n --prefix=/tmp/install</userinput> + Install file: "foo.in" as "/tmp/install/usr/bin/foo.in" + </screen> + + </section> + + </section> + + <section id="sect-command-line-variables"> + <title>Command-Line <varname>variable</varname>=<varname>value</varname> Build Variables</title> + + <para> + + You may want to control various aspects + of your build by allowing the user + to specify <varname>variable</varname>=<varname>value</varname> + values on the command line. + For example, suppose you + want users to be able to + build a debug version of a program + by running &SCons; as follows: + + </para> + + <screen> + % <userinput>scons -Q debug=1</userinput> + </screen> + + <para> + + &SCons; provides an &ARGUMENTS; dictionary + that stores all of the + <varname>variable</varname>=<varname>value</varname> + assignments from the command line. + This allows you to modify + aspects of your build in response + to specifications on the command line. + (Note that unless you want to require + that users <emphasis>always</emphasis> + specify a variable, + you probably want to use + the Python + <literal>ARGUMENTS.get()</literal> function, + which allows you to specify a default value + to be used if there is no specification + on the command line.) + + </para> + + <para> + + The following code sets the &cv-link-CCFLAGS; construction + variable in response to the <varname>debug</varname> + flag being set in the &ARGUMENTS; dictionary: + + </para> + + <programlisting> + env = Environment() + debug = ARGUMENTS.get('debug', 0) + if int(debug): + env.Append(CCFLAGS = '-g') + env.Program('prog.c') + </programlisting> + + <para> + + This results in the <varname>-g</varname> + compiler option being used when + <literal>debug=1</literal> + is used on the command line: + + </para> + + <screen> + % <userinput>scons -Q debug=0</userinput> + cc -o prog.o -c prog.c + cc -o prog prog.o + % <userinput>scons -Q debug=0</userinput> + scons: `.' is up to date. + % <userinput>scons -Q debug=1</userinput> + scons: `.' is up to date. + % <userinput>scons -Q debug=1</userinput> + scons: `.' is up to date. + </screen> + + <para> + + Notice that &SCons; keeps track of + the last values used to build the object files, + and as a result correctly rebuilds + the object and executable files + only when the value of the <literal>debug</literal> + argument has changed. + + </para> + + <para> + + The &ARGUMENTS; dictionary has two minor drawbacks. + First, because it is a dictionary, + it can only store one value for each specified keyword, + and thus only "remembers" the last setting + for each keyword on the command line. + This makes the &ARGUMENTS; dictionary + inappropriate if users should be able to + specify multiple values + on the command line for a given keyword. + Second, it does not preserve + the order in which the variable settings + were specified, + which is a problem if + you want the configuration to + behave differently in response + to the order in which the build + variable settings were specified on the command line. + + </para> + + <para> + + To accomodate these requirements, + &SCons; provides an &ARGLIST; variable + that gives you direct access to + <varname>variable</varname>=<varname>value</varname> + settings on the command line, + in the exact order they were specified, + and without removing any duplicate settings. + Each element in the &ARGLIST; variable + is itself a two-element list + containing the keyword and the value + of the setting, + and you must loop through, + or otherwise select from, + the elements of &ARGLIST; to + process the specific settings you want + in whatever way is appropriate for your configuration. + For example, + the following code to let the user + add to the &CPPDEFINES; construction variable + by specifying multiple + <varname>define=</varname> + settings on the command line: + + </para> + + <programlisting> + cppdefines = [] + for key, value in ARGLIST: + if key == 'define': + cppdefines.append(value) + env = Environment(CPPDEFINES = cppdefines) + env.Object('prog.c') + </programlisting> + + <para> + + Yields the following output: + + </para> + + <screen> + % <userinput>scons -Q define=FOO</userinput> + cc -o prog.o -c -DFOO prog.c + % <userinput>scons -Q define=FOO define=BAR</userinput> + scons: `.' is up to date. + </screen> + + <para> + + Note that the &ARGLIST; and &ARGUMENTS; + variables do not interfere with each other, + but merely provide slightly different views + into how the user specified + <varname>variable</varname>=<varname>value</varname> + settings on the command line. + You can use both variables in the same + &SCons; configuration. + In general, the &ARGUMENTS; dictionary + is more convenient to use, + (since you can just fetch variable + settings through a dictionary access), + and the &ARGLIST; list + is more flexible + (since you can examine the + specific order in which + the user's command-line variabe settings). + + </para> + + <section> + <title>Controlling Command-Line Build Variables</title> + + <para> + + Being able to use a command-line build variable like + <literal>debug=1</literal> is handy, + but it can be a chore to write specific Python code + to recognize each such variable, + check for errors and provide appropriate messages, + and apply the values to a construction variable. + To help with this, + &SCons; supports a class to + define such build variables easily, + and a mechanism to apply the + build variables to a construction environment. + This allows you to control how the build variables affect + construction environments. + + </para> + + <para> + + For example, suppose that you want users to set + a &RELEASE; construction variable on the + command line whenever the time comes to build + a program for release, + and that the value of this variable + should be added to the command line + with the appropriate <literal>-D</literal> option + (or other command line option) + to pass the value to the C compiler. + Here's how you might do that by setting + the appropriate value in a dictionary for the + &cv-link-CPPDEFINES; construction variable: + + </para> + + <programlisting> + vars = Variables() + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + </programlisting> + + <para> + + This &SConstruct; file first creates a &Variables; object + (the <literal>vars = Variables()</literal> call), + and then uses the object's &Add; + method to indicate that the &RELEASE; + variable can be set on the command line, + and that its default value will be <literal>0</literal> + (the third argument to the &Add; method). + The second argument is a line of help text; + we'll learn how to use it in the next section. + + </para> + + <para> + + We then pass the created &Variables; + object as a &variables; keyword argument + to the &Environment; call + used to create the construction environment. + This then allows a user to set the + &RELEASE; build variable on the command line + and have the variable show up in + the command line used to build each object from + a C source file: + + </para> + + <screen> + % <userinput>scons -Q RELEASE=1</userinput> + cc -o bar.o -c -DRELEASE_BUILD=1 bar.c + cc -o foo.o -c -DRELEASE_BUILD=1 foo.c + cc -o foo foo.o bar.o + </screen> + + <para> + + NOTE: Before &SCons; release 0.98.1, these build variables + were known as "command-line build options." + The class was actually named the &Options; class, + and in the sections below, + the various functions were named + &BoolOption;, &EnumOption;, &ListOption;, + &PathOption;, &PackageOption; and &AddOptions;. + These older names still work, + and you may encounter them in older + &SConscript; fles, + but their use is discouraged + and will be officially deprecated some day. + + </para> + + </section> + + <section> + <title>Providing Help for Command-Line Build Variables</title> + + <para> + + To make command-line build variables most useful, + you ideally want to provide + some help text that will describe + the available variables + when the user runs <literal>scons -h</literal>. + You could write this text by hand, + but &SCons; provides an easier way. + &Variables; objects support a + &GenerateHelpText; method + that will, as its name suggests, + generate text that describes + the various variables that + have been added to it. + You then pass the output from this method to + the &Help; function: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars) + Help(vars.GenerateHelpText(env)) + </programlisting> + + <para> + + &SCons; will now display some useful text + when the <literal>-h</literal> option is used: + + </para> + + <screen> + % <userinput>scons -Q -h</userinput> + + RELEASE: Set to 1 to build for release + default: 0 + actual: 0 + + Use scons -H for help about command-line options. + </screen> + + <para> + + Notice that the help output shows the default value, + and the current actual value of the build variable. + + </para> + + </section> + + <section> + <title>Reading Build Variables From a File</title> + + <para> + + Giving the user a way to specify the + value of a build variable on the command line + is useful, + but can still be tedious + if users must specify the variable + every time they run &SCons;. + We can let users provide customized build variable settings + in a local file by providing a + file name when we create the + &Variables; object: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + Help(vars.GenerateHelpText(env)) + </programlisting> + + <para> + + This then allows the user to control the &RELEASE; + variable by setting it in the &custom_py; file: + + </para> + + <programlisting> + RELEASE = 1 + </programlisting> + + <para> + + Note that this file is actually executed + like a Python script. + Now when we run &SCons;: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o bar.o -c -DRELEASE_BUILD=1 bar.c + cc -o foo.o -c -DRELEASE_BUILD=1 foo.c + cc -o foo foo.o bar.o + </screen> + + <para> + + And if we change the contents of &custom_py; to: + + </para> + + <programlisting> + RELEASE = 0 + </programlisting> + + <para> + + The object files are rebuilt appropriately + with the new variable: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o bar.o -c -DRELEASE_BUILD=0 bar.c + cc -o foo.o -c -DRELEASE_BUILD=0 foo.c + cc -o foo foo.o bar.o + </screen> + + </section> + + <section> + <title>Pre-Defined Build Variable Functions</title> + + <para> + + &SCons; provides a number of functions + that provide ready-made behaviors + for various types of command-line build variables. + + </para> + + <section> + <title>True/False Values: the &BoolVariable; Build Variable Function</title> + + <para> + + It's often handy to be able to specify a + variable that controls a simple Boolean variable + with a &true; or &false; value. + It would be even more handy to accomodate + users who have different preferences for how to represent + &true; or &false; values. + The &BoolVariable; function + makes it easy to accomodate these + common representations of + &true; or &false;. + + </para> + + <para> + + The &BoolVariable; function takes three arguments: + the name of the build variable, + the default value of the build variable, + and the help string for the variable. + It then returns appropriate information for + passing to the &Add; method of a &Variables; object, like so: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(BoolVariable('RELEASE', 'Set to build for release', 0)) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program('foo.c') + </programlisting> + + <para> + + With this build variable, + the &RELEASE; variable can now be enabled by + setting it to the value <literal>yes</literal> + or <literal>t</literal>: + + </para> + + <screen> + % <userinput>scons -Q RELEASE=yes foo.o</userinput> + cc -o foo.o -c -DRELEASE_BUILD=True foo.c + </screen> + + <screen> + % <userinput>scons -Q RELEASE=t foo.o</userinput> + cc -o foo.o -c -DRELEASE_BUILD=True foo.c + </screen> + + <para> + + Other values that equate to &true; include + <literal>y</literal>, + <literal>1</literal>, + <literal>on</literal> + and + <literal>all</literal>. + + </para> + + <para> + + Conversely, &RELEASE; may now be given a &false; + value by setting it to + <literal>no</literal> + or + <literal>f</literal>: + + </para> + + <screen> + % <userinput>scons -Q RELEASE=no foo.o</userinput> + cc -o foo.o -c -DRELEASE_BUILD=False foo.c + </screen> + + <screen> + % <userinput>scons -Q RELEASE=f foo.o</userinput> + cc -o foo.o -c -DRELEASE_BUILD=False foo.c + </screen> + + <para> + + Other values that equate to &false; include + <literal>n</literal>, + <literal>0</literal>, + <literal>off</literal> + and + <literal>none</literal>. + + </para> + + <para> + + Lastly, if a user tries to specify + any other value, + &SCons; supplies an appropriate error message: + + </para> + + <screen> + % <userinput>scons -Q RELEASE=bad_value foo.o</userinput> + + scons: *** Error converting option: RELEASE + Invalid value for boolean option: bad_value + File "/home/my/project/SConstruct", line 4, in ? + </screen> + + </section> + + <section> + <title>Single Value From a List: the &EnumVariable; Build Variable Function</title> + + <para> + + Suppose that we want a user to be able to + set a &COLOR; variable + that selects a background color to be + displayed by an application, + but that we want to restrict the + choices to a specific set of allowed colors. + This can be set up quite easily + using the &EnumVariable;, + which takes a list of &allowed_values + in addition to the variable name, + default value, + and help text arguments: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'))) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + The user can now explicity set the &COLOR; build variable + to any of the specified allowed values: + + </para> + + <screen> + % <userinput>scons -Q COLOR=red foo.o</userinput> + cc -o foo.o -c -DCOLOR="red" foo.c + % <userinput>scons -Q COLOR=blue foo.o</userinput> + scons: `foo.o' is up to date. + % <userinput>scons -Q COLOR=green foo.o</userinput> + scons: `foo.o' is up to date. + </screen> + + <para> + + But, almost more importantly, + an attempt to set &COLOR; + to a value that's not in the list + generates an error message: + + </para> + + <screen> + % <userinput>scons -Q COLOR=magenta foo.o</userinput> + + scons: *** Invalid value for option COLOR: magenta + File "/home/my/project/SConstruct", line 5, in ? + </screen> + + <para> + + The &EnumVariable; function also supports a way + to map alternate names to allowed values. + Suppose, for example, + that we want to allow the user + to use the word <literal>navy</literal> as a synonym for + <literal>blue</literal>. + We do this by adding a ↦ dictionary + that will map its key values + to the desired legal value: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'})) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + As desired, the user can then use + <literal>navy</literal> on the command line, + and &SCons; will translate it into <literal>blue</literal> + when it comes time to use the &COLOR; + variable to build a target: + + </para> + + <screen> + % <userinput>scons -Q COLOR=navy foo.o</userinput> + cc -o foo.o -c -DCOLOR="blue" foo.c + </screen> + + <para> + + By default, when using the &EnumVariable; function, + arguments that differ + from the legal values + only in case + are treated as illegal values: + + </para> + + <screen> + % <userinput>scons -Q COLOR=Red foo.o</userinput> + + scons: *** Invalid value for option COLOR: Red + File "/home/my/project/SConstruct", line 5, in ? + % <userinput>scons -Q COLOR=BLUE foo.o</userinput> + + scons: *** Invalid value for option COLOR: BLUE + File "/home/my/project/SConstruct", line 5, in ? + % <userinput>scons -Q COLOR=nAvY foo.o</userinput> + + scons: *** Invalid value for option COLOR: nAvY + File "/home/my/project/SConstruct", line 5, in ? + </screen> + + <para> + + The &EnumVariable; function can take an additional + &ignorecase; keyword argument that, + when set to <literal>1</literal>, + tells &SCons; to allow case differences + when the values are specified: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=1)) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + Which yields the output: + + </para> + + <screen> + % <userinput>scons -Q COLOR=Red foo.o</userinput> + cc -o foo.o -c -DCOLOR="Red" foo.c + % <userinput>scons -Q COLOR=BLUE foo.o</userinput> + scons: `foo.o' is up to date. + % <userinput>scons -Q COLOR=nAvY foo.o</userinput> + scons: `foo.o' is up to date. + % <userinput>scons -Q COLOR=green foo.o</userinput> + scons: `foo.o' is up to date. + </screen> + + <para> + + Notice that an &ignorecase; value of <literal>1</literal> + preserves the case-spelling that the user supplied. + If you want &SCons; to translate the names + into lower-case, + regardless of the case used by the user, + specify an &ignorecase; value of <literal>2</literal>: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=2)) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + Now &SCons; will use values of + <literal>red</literal>, + <literal>green</literal> or + <literal>blue</literal> + regardless of how the user spells + those values on the command line: + + </para> + + <screen> + % <userinput>scons -Q COLOR=Red foo.o</userinput> + cc -o foo.o -c -DCOLOR="red" foo.c + % <userinput>scons -Q COLOR=nAvY foo.o</userinput> + scons: `foo.o' is up to date. + % <userinput>scons -Q COLOR=GREEN foo.o</userinput> + scons: `foo.o' is up to date. + </screen> + + </section> + + <section> + <title>Multiple Values From a List: the &ListVariable; Build Variable Function</title> + + <para> + + Another way in which you might want to allow users + to control a build variable is to + specify a list of one or more legal values. + &SCons; supports this through the &ListVariable; function. + If, for example, we want a user to be able to set a + &COLORS; variable to one or more of the legal list of values: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(ListVariable('COLORS', 'List of colors', 0, + ['red', 'green', 'blue'])) + env = Environment(variables = vars, + CPPDEFINES={'COLORS' : '"${COLORS}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + A user can now specify a comma-separated list + of legal values, + which will get translated into a space-separated + list for passing to the any build commands: + + </para> + + <screen> + % <userinput>scons -Q COLORS=red,blue foo.o</userinput> + cc -o foo.o -c -DCOLORS="red blue" foo.c + % <userinput>scons -Q COLORS=blue,green,red foo.o</userinput> + scons: `foo.o' is up to date. + </screen> + + <para> + + In addition, the &ListVariable; function + allows the user to specify explicit keywords of + &all; or &none; + to select all of the legal values, + or none of them, respectively: + + </para> + + <screen> + % <userinput>scons -Q COLORS=all foo.o</userinput> + cc -o foo.o -c -DCOLORS="red green blue" foo.c + % <userinput>scons -Q COLORS=none foo.o</userinput> + scons: `foo.o' is up to date. + </screen> + + <para> + + And, of course, an illegal value + still generates an error message: + + </para> + + <screen> + % <userinput>scons -Q COLORS=magenta foo.o</userinput> + + scons: *** Error converting option: COLORS + Invalid value(s) for option: magenta + File "/home/my/project/SConstruct", line 5, in ? + </screen> + + </section> + + <section> + <title>Path Names: the &PathVariable; Build Variable Function</title> + + <para> + + &SCons; supports a &PathVariable; function + to make it easy to create a build variable + to control an expected path name. + If, for example, you need to + define a variable in the preprocessor + that controls the location of a + configuration file: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(PathVariable('CONFIG', + 'Path to configuration file', + '/etc/my_config')) + env = Environment(variables = vars, + CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) + env.Program('foo.c') + </programlisting> + + <para> + + This then allows the user to + override the &CONFIG; build variable + on the command line as necessary: + + </para> + + <screen> + % <userinput>scons -Q foo.o</userinput> + cc -o foo.o -c -DCONFIG_FILE="/etc/my_config" foo.c + % <userinput>scons -Q CONFIG=/usr/local/etc/other_config foo.o</userinput> + scons: `foo.o' is up to date. + </screen> + + <para> + + By default, &PathVariable; checks to make sure + that the specified path exists and generates an error if it + doesn't: + + </para> + + <screen> + % <userinput>scons -Q CONFIG=/does/not/exist foo.o</userinput> + + scons: *** Path for option CONFIG does not exist: /does/not/exist + File "/home/my/project/SConstruct", line 6, in ? + </screen> + + <para> + + &PathVariable; provides a number of methods + that you can use to change this behavior. + If you want to ensure that any specified paths are, + in fact, files and not directories, + use the &PathVariable_PathIsFile; method: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(PathVariable('CONFIG', + 'Path to configuration file', + '/etc/my_config', + PathVariable.PathIsFile)) + env = Environment(variables = vars, + CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) + env.Program('foo.c') + </programlisting> + + <para> + + Conversely, to ensure that any specified paths are + directories and not files, + use the &PathVariable_PathIsDir; method: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(PathVariable('DBDIR', + 'Path to database directory', + '/var/my_dbdir', + PathVariable.PathIsDir)) + env = Environment(variables = vars, + CPPDEFINES={'DBDIR' : '"$DBDIR"'}) + env.Program('foo.c') + </programlisting> + + <para> + + If you want to make sure that any specified paths + are directories, + and you would like the directory created + if it doesn't already exist, + use the &PathVariable_PathIsDirCreate; method: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(PathVariable('DBDIR', + 'Path to database directory', + '/var/my_dbdir', + PathVariable.PathIsDirCreate)) + env = Environment(variables = vars, + CPPDEFINES={'DBDIR' : '"$DBDIR"'}) + env.Program('foo.c') + </programlisting> + + <para> + + Lastly, if you don't care whether the path exists, + is a file, or a directory, + use the &PathVariable_PathAccept; method + to accept any path that the user supplies: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(PathVariable('OUTPUT', + 'Path to output file or directory', + None, + PathVariable.PathAccept)) + env = Environment(variables = vars, + CPPDEFINES={'OUTPUT' : '"$OUTPUT"'}) + env.Program('foo.c') + </programlisting> + + </section> + + <section> + <title>Enabled/Disabled Path Names: the &PackageVariable; Build Variable Function</title> + + <para> + + Sometimes you want to give users + even more control over a path name variable, + allowing them to explicitly enable or + disable the path name + by using <literal>yes</literal> or <literal>no</literal> keywords, + in addition to allow them + to supply an explicit path name. + &SCons; supports the &PackageVariable; + function to support this: + + </para> + + <programlisting> + vars = Variables('custom.py') + vars.Add(PackageVariable('PACKAGE', + 'Location package', + '/opt/location')) + env = Environment(variables = vars, + CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) + env.Program('foo.c') + </programlisting> + + <para> + + When the &SConscript; file uses the &PackageVariable; funciton, + user can now still use the default + or supply an overriding path name, + but can now explicitly set the + specified variable to a value + that indicates the package should be enabled + (in which case the default should be used) + or disabled: + + </para> + + <screen> + % <userinput>scons -Q foo.o</userinput> + cc -o foo.o -c -DPACKAGE="/opt/location" foo.c + % <userinput>scons -Q PACKAGE=/usr/local/location foo.o</userinput> + scons: `foo.o' is up to date. + % <userinput>scons -Q PACKAGE=yes foo.o</userinput> + scons: `foo.o' is up to date. + % <userinput>scons -Q PACKAGE=no foo.o</userinput> + scons: `foo.o' is up to date. + </screen> + + </section> + + </section> + + <section> + <title>Adding Multiple Command-Line Build Variables at Once</title> + + <para> + + Lastly, &SCons; provides a way to add + multiple build variables to a &Variables; object at once. + Instead of having to call the &Add; method + multiple times, + you can call the &AddVariables; + method with a list of build variables + to be added to the object. + Each build variable is specified + as either a tuple of arguments, + just like you'd pass to the &Add; method itself, + or as a call to one of the pre-defined + functions for pre-packaged command-line build variables. + in any order: + + </para> + + <programlisting> + vars = Variables() + vars.AddVariables( + ('RELEASE', 'Set to 1 to build for release', 0), + ('CONFIG', 'Configuration file', '/etc/my_config'), + BoolVariable('warnings', 'compilation with -Wall and similiar', 1), + EnumVariable('debug', 'debug output and symbols', 'no', + allowed_values=('yes', 'no', 'full'), + map={}, ignorecase=0), # case sensitive + ListVariable('shared', + 'libraries to build as shared libraries', + 'all', + names = list_of_libs), + PackageVariable('x11', + 'use X11 installed here (yes = search some places)', + 'yes'), + PathVariable('qtdir', 'where the root of Qt is installed', qtdir), + ) + </programlisting> + + <para> + </para> + + </section> + + <section> + <title>Handling Unknown Command-Line Build Variables: the &UnknownVariables; Function</title> + + <para> + + Users may, of course, + occasionally misspell variable names in their command-line settings. + &SCons; does not generate an error or warning + for any unknown variables the users specifies on the command line. + (This is in no small part because you may be + processing the arguments directly using the &ARGUMENTS; dictionary, + and therefore &SCons; can't know in the general case + whether a given "misspelled" variable is + really unknown and a potential problem, + or something that your &SConscript; file + will handle directly with some Python code.) + + </para> + + <para> + + If, however, you're using a &Variables; object to + define a specific set of command-line build variables + that you expect users to be able to set, + you may want to provide an error + message or warning of your own + if the user supplies a variable setting + that is <emphasis>not</emphasis> among + the defined list of variable names known to the &Variables; object. + You can do this by calling the &UnknownVariables; + method of the &Variables; object: + + </para> + + <programlisting> + vars = Variables(None) + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + unknown = vars.UnknownVariables() + if unknown: + print "Unknown variables:", unknown.keys() + Exit(1) + env.Program('foo.c') + </programlisting> + + <para> + + The &UnknownVariables; method returns a dictionary + containing the keywords and values + of any variables the user specified on the command line + that are <emphasis>not</emphasis> + among the variables known to the &Variables; object + (from having been specified using + the &Variables; object's&Add; method). + In the examble above, + we check for whether the dictionary + returned by the &UnknownVariables; is non-empty, + and if so print the Python list + containing the names of the unknwown variables + and then call the &Exit; function + to terminate &SCons;: + + </para> + + <screen> + % <userinput>scons -Q NOT_KNOWN=foo</userinput> + Unknown variables: ['NOT_KNOWN'] + </screen> + + <para> + + Of course, you can process the items in the + dictionary returned by the &UnknownVariables; function + in any way appropriate to your build configuration, + including just printing a warning message + but not exiting, + logging an error somewhere, + etc. + + </para> + + <para> + + Note that you must delay the call of &UnknownVariables; + until after you have applied the &Variables; object + to a construction environment + with the <literal>variables=</literal> + keyword argument of an &Environment; call. + + </para> + + </section> + + </section> + + <section id="sect-command-line-targets"> + <title>Command-Line Targets</title> + + <section> + <title>Fetching Command-Line Targets: the &COMMAND_LINE_TARGETS; Variable</title> + + <para> + + &SCons; supports a &COMMAND_LINE_TARGETS; variable + that lets you fetch the list of targets that the + user specified on the command line. + You can use the targets to manipulate the + build in any way you wish. + As a simple example, + suppose that you want to print a reminder + to the user whenever a specific program is built. + You can do this by checking for the + target in the &COMMAND_LINE_TARGETS; list: + + </para> + + <programlisting> + if 'bar' in COMMAND_LINE_TARGETS: + print "Don't forget to copy `bar' to the archive!" + Default(Program('foo.c')) + Program('bar.c') + </programlisting> + + <para> + + Then, running &SCons; with the default target + works as it always does, + but explicity specifying the &bar; target + on the command line generates the warning message: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o foo.o -c foo.c + cc -o foo foo.o + % <userinput>scons -Q bar</userinput> + Don't forget to copy `bar' to the archive! + cc -o bar.o -c bar.c + cc -o bar bar.o + </screen> + + <para> + + Another practical use for the &COMMAND_LINE_TARGETS; variable + might be to speed up a build + by only reading certain subsidiary &SConscript; + files if a specific target is requested. + + </para> + + </section> + + <section> + <title>Controlling the Default Targets: the &Default; Function</title> + + <para> + + One of the most basic things you can control + is which targets &SCons; will build by default--that is, + when there are no targets specified on the command line. + As mentioned previously, + &SCons; will normally build every target + in or below the current directory + by default--that is, when you don't + explicitly specify one or more targets + on the command line. + Sometimes, however, you may want + to specify explicitly that only + certain programs, or programs in certain directories, + should be built by default. + You do this with the &Default; function: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + env.Program('goodbye.c') + Default(hello) + </programlisting> + + <para> + + This &SConstruct; file knows how to build two programs, + &hello; and &goodbye;, + but only builds the + &hello; program by default: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q</userinput> + scons: `hello' is up to date. + % <userinput>scons -Q goodbye</userinput> + cc -o goodbye.o -c goodbye.c + cc -o goodbye goodbye.o + </screen> + + <para> + + Note that, even when you use the &Default; + function in your &SConstruct; file, + you can still explicitly specify the current directory + (<literal>.</literal>) on the command line + to tell &SCons; to build + everything in (or below) the current directory: + + </para> + + <screen> + % <userinput>scons -Q .</userinput> + cc -o goodbye.o -c goodbye.c + cc -o goodbye goodbye.o + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + You can also call the &Default; + function more than once, + in which case each call + adds to the list of targets to be built by default: + + </para> + + <programlisting> + env = Environment() + prog1 = env.Program('prog1.c') + Default(prog1) + prog2 = env.Program('prog2.c') + prog3 = env.Program('prog3.c') + Default(prog3) + </programlisting> + + <para> + + Or you can specify more than one target + in a single call to the &Default; function: + + </para> + + <programlisting> + env = Environment() + prog1 = env.Program('prog1.c') + prog2 = env.Program('prog2.c') + prog3 = env.Program('prog3.c') + Default(prog1, prog3) + </programlisting> + + <para> + + Either of these last two examples + will build only the + <application>prog1</application> + and + <application>prog3</application> + programs by default: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + cc -o prog3.o -c prog3.c + cc -o prog3 prog3.o + % <userinput>scons -Q .</userinput> + cc -o prog2.o -c prog2.c + cc -o prog2 prog2.o + </screen> + + <para> + + You can list a directory as + an argument to &Default;: + + </para> + + <programlisting> + env = Environment() + env.Program(['prog1/main.c', 'prog1/foo.c']) + env.Program(['prog2/main.c', 'prog2/bar.c']) + Default('prog1') + </programlisting> + + <para> + + In which case only the target(s) in that + directory will be built by default: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o prog1/foo.o -c prog1/foo.c + cc -o prog1/main.o -c prog1/main.c + cc -o prog1/main prog1/main.o prog1/foo.o + % <userinput>scons -Q</userinput> + scons: `prog1' is up to date. + % <userinput>scons -Q .</userinput> + cc -o prog2/bar.o -c prog2/bar.c + cc -o prog2/main.o -c prog2/main.c + cc -o prog2/main prog2/main.o prog2/bar.o + </screen> + + <para> + + Lastly, if for some reason you don't want + any targets built by default, + you can use the Python <literal>None</literal> + variable: + + </para> + + <programlisting> + env = Environment() + prog1 = env.Program('prog1.c') + prog2 = env.Program('prog2.c') + Default(None) + </programlisting> + + <para> + + Which would produce build output like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + scons: *** No targets specified and no Default() targets found. Stop. + % <userinput>scons -Q .</userinput> + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + cc -o prog2.o -c prog2.c + cc -o prog2 prog2.o + </screen> + + <section> + <title>Fetching the List of Default Targets: the &DEFAULT_TARGETS; Variable</title> + + <para> + + &SCons; supports a &DEFAULT_TARGETS; variable + that lets you get at the current list of default targets. + The &DEFAULT_TARGETS variable has + two important differences from the &COMMAND_LINE_TARGETS; variable. + First, the &DEFAULT_TARGETS; variable is a list of + internal &SCons; nodes, + so you need to convert the list elements to strings + if you want to print them or look for a specific target name. + Fortunately, you can do this easily + by using the Python <function>map</function> function + to run the list through <function>str</function>: + + </para> + + <programlisting> + prog1 = Program('prog1.c') + Default(prog1) + print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS) + </programlisting> + + <para> + + (Keep in mind that all of the manipulation of the + &DEFAULT_TARGETS; list takes place during the + first phase when &SCons; is reading up the &SConscript; files, + which is obvious if + we leave off the <literal>-Q</literal> flag when we run &SCons;:) + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + DEFAULT_TARGETS is ['prog1'] + scons: done reading SConscript files. + scons: Building targets ... + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + scons: done building targets. + </screen> + + <para> + + Second, + the contents of the &DEFAULT_TARGETS; list change + in response to calls to the &Default;: function, + as you can see from the following &SConstruct; file: + + </para> + + <programlisting> + prog1 = Program('prog1.c') + Default(prog1) + print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) + prog2 = Program('prog2.c') + Default(prog2) + print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) + </programlisting> + + <para> + + Which yields the output: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + DEFAULT_TARGETS is now ['prog1'] + DEFAULT_TARGETS is now ['prog1', 'prog2'] + scons: done reading SConscript files. + scons: Building targets ... + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + cc -o prog2.o -c prog2.c + cc -o prog2 prog2.o + scons: done building targets. + </screen> + + <para> + + In practice, this simply means that you + need to pay attention to the order in + which you call the &Default; function + and refer to the &DEFAULT_TARGETS; list, + to make sure that you don't examine the + list before you've added the default targets + you expect to find in it. + + </para> + + </section> + + </section> + + <section> + <title>Fetching the List of Build Targets, Regardless of Origin: the &BUILD_TARGETS; Variable</title> + + <para> + + We've already been introduced to the + &COMMAND_LINE_TARGETS; variable, + which contains a list of targets specified on the command line, + and the &DEFAULT_TARGETS; variable, + which contains a list of targets specified + via calls to the &Default; method or function. + Sometimes, however, + you want a list of whatever targets + &SCons; will try to build, + regardless of whether the targets came from the + command line or a &Default; call. + You could code this up by hand, as follows: + + </para> + + <programlisting> + if COMMAND_LINE_TARGETS: + targets = COMMAND_LINE_TARGETS + else: + targets = DEFAULT_TARGETS + </programlisting> + + <para> + + &SCons;, however, provides a convenient + &BUILD_TARGETS; variable + that eliminates the need for this by-hand manipulation. + Essentially, the &BUILD_TARGETS; variable + contains a list of the command-line targets, + if any were specified, + and if no command-line targets were specified, + it contains a list of the targets specified + via the &Default; method or function. + + </para> + + <para> + + Because &BUILD_TARGETS; may contain a list of &SCons; nodes, + you must convert the list elements to strings + if you want to print them or look for a specific target name, + just like the &DEFAULT_TARGETS; list: + + </para> + + <programlisting> + prog1 = Program('prog1.c') + Program('prog2.c') + Default(prog1) + print "BUILD_TARGETS is", map(str, BUILD_TARGETS) + </programlisting> + + <para> + + Notice how the value of &BUILD_TARGETS; + changes depending on whether a target is + specified on the command line: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + BUILD_TARGETS is ['prog1'] + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + % <userinput>scons -Q prog2</userinput> + BUILD_TARGETS is ['prog2'] + cc -o prog2.o -c prog2.c + cc -o prog2 prog2.o + % <userinput>scons -Q -c .</userinput> + BUILD_TARGETS is ['.'] + Removed prog1.o + Removed prog1 + Removed prog2.o + Removed prog2 + </screen> + + </section> + + </section> diff --git a/doc/user/cons.pl b/doc/user/cons.pl new file mode 100644 index 0000000..8afbfec --- /dev/null +++ b/doc/user/cons.pl @@ -0,0 +1,720 @@ +=head1 Introduction + +B<Cons> is a system for constructing, primarily, software, but is quite +different from previous software construction systems. Cons was designed +from the ground up to deal easily with the construction of software spread +over multiple source directories. Cons makes it easy to create build scripts +that are simple, understandable and maintainable. Cons ensures that complex +software is easily and accurately reproducible. + +Cons uses a number of techniques to accomplish all of this. Construction +scripts are just Perl scripts, making them both easy to comprehend and very +flexible. Global scoping of variables is replaced with an import/export +mechanism for sharing information between scripts, significantly improving +the readability and maintainability of each script. B<Construction +environments> are introduced: these are Perl objects that capture the +information required for controlling the build process. Multiple +environments are used when different semantics are required for generating +products in the build tree. Cons implements automatic dependency analysis +and uses this to globally sequence the entire build. Variant builds are +easily produced from a single source tree. Intelligent build subsetting is +possible, when working on localized changes. Overrides can be setup to +easily override build instructions without modifying any scripts. MD5 +cryptographic B<signatures> are associated with derived files, and are used +to accurately determine whether a given file needs to be rebuilt. + +While offering all of the above, and more, Cons remains simple and easy to +use. This will, hopefully, become clear as you read the remainder of this +document. + + + +=head2 Automatic global build sequencing + +Because Cons does full and accurate dependency analysis, and does this +globally, for the entire build, Cons is able to use this information to take +full control of the B<sequencing> of the build. This sequencing is evident +in the above examples, and is equivalent to what you would expect for make, +given a full set of dependencies. With Cons, this extends trivially to +larger, multi-directory builds. As a result, all of the complexity involved +in making sure that a build is organized correctly--including multi-pass +hierarchical builds--is eliminated. We'll discuss this further in the next +sections. + + + +=head1 A Model for sharing files + + +=head2 Some simple conventions + +In any complex software system, a method for sharing build products needs to +be established. We propose a simple set of conventions which are trivial to +implement with Cons, but very effective. + +The basic rule is to require that all build products which need to be shared +between directories are shared via an intermediate directory. We have +typically called this F<export>, and, in a C environment, provided +conventional sub-directories of this directory, such as F<include>, F<lib>, +F<bin>, etc. + +These directories are defined by the top-level F<Construct> file. A simple +F<Construct> file for a B<Hello, World!> application, organized using +multiple directories, might look like this: + + # Construct file for Hello, World! + + # Where to put all our shared products. + $EXPORT = '#export'; + + Export qw( CONS INCLUDE LIB BIN ); + + # Standard directories for sharing products. + $INCLUDE = "$EXPORT/include"; + $LIB = "$EXPORT/lib"; + $BIN = "$EXPORT/bin"; + + # A standard construction environment. + $CONS = new cons ( + CPPPATH => $INCLUDE, # Include path for C Compilations + LIBPATH => $LIB, # Library path for linking programs + LIBS => '-lworld', # List of standard libraries + ); + + Build qw( + hello/Conscript + world/Conscript + ); + +The F<world> directory's F<Conscript> file looks like this: + + # Conscript file for directory world + Import qw( CONS INCLUDE LIB ); + + # Install the products of this directory + Install $CONS $LIB, 'libworld.a'; + Install $CONS $INCLUDE, 'world.h'; + + # Internal products + Library $CONS 'libworld.a', 'world.c'; + +and the F<hello> directory's F<Conscript> file looks like this: + + # Conscript file for directory hello + Import qw( CONS BIN ); + + # Exported products + Install $CONS $BIN, 'hello'; + + # Internal products + Program $CONS 'hello', 'hello.c'; + +To construct a B<Hello, World!> program with this directory structure, go to +the top-level directory, and invoke C<cons> with the appropriate +arguments. In the following example, we tell Cons to build the directory +F<export>. To build a directory, Cons recursively builds all known products +within that directory (only if they need rebuilding, of course). If any of +those products depend upon other products in other directories, then those +will be built, too. + + % cons export + Install world/world.h as export/include/world.h + cc -Iexport/include -c hello/hello.c -o hello/hello.o + cc -Iexport/include -c world/world.c -o world/world.o + ar r world/libworld.a world/world.o + ar: creating world/libworld.a + ranlib world/libworld.a + Install world/libworld.a as export/lib/libworld.a + cc -o hello/hello hello/hello.o -Lexport/lib -lworld + Install hello/hello as export/bin/hello + + +=head2 Clean, understandable, location-independent scripts + +You'll note that the two F<Conscript> files are very clean and +to-the-point. They simply specify products of the directory and how to build +those products. The build instructions are minimal: they specify which +construction environment to use, the name of the product, and the name of +the inputs. Note also that the scripts are location-independent: if you wish +to reorganize your source tree, you are free to do so: you only have to +change the F<Construct> file (in this example), to specify the new locations +of the F<Conscript> files. The use of an export tree makes this goal easy. + +Note, too, how Cons takes care of little details for you. All the F<export> +directories, for example, were made automatically. And the installed files +were really hard-linked into the respective export directories, to save +space and time. This attention to detail saves considerable work, and makes +it even easier to produce simple, maintainable scripts. + + + +=head1 Signatures + +Cons uses file B<signatures> to decide if a derived file is out-of-date +and needs rebuilding. In essence, if the contents of a file change, +or the manner in which the file is built changes, the file's signature +changes as well. This allows Cons to decide with certainty when a file +needs rebuilding, because Cons can detect, quickly and reliably, whether +any of its dependency files have been changed. + + +=head2 MD5 content and build signatures + +Cons uses the B<MD5> (B<Message Digest 5>) algorithm to compute file +signatures. The MD5 algorithm computes a strong cryptographic checksum +for any given input string. Cons can, based on configuration, use two +different MD5 signatures for a given file: + +The B<content signature> of a file is an MD5 checksum of the file's +contents. Consequently, when the contents of a file change, its content +signature changes as well. + +The B<build signature> of a file is a combined MD5 checksum of: + +=over 4 + +the signatures of all the input files used to build the file + +the signatures of all dependency files discovered by source scanners +(for example, C<.h> files) + +the signatures of all dependency files specified explicitly via the +C<Depends> method) + +the command-line string used to build the file + +=back + +The build signature is, in effect, a digest of all the dependency +information for the specified file. Consequently, a file's build +signature changes whenever any part of its dependency information +changes: a new file is added, the contents of a file on which it depends +change, there's a change to the command line used to build the file (or +any of its dependency files), etc. + +For example, in the previous section, the build signature of the +F<world.o> file will include: + +=over 4 + +the signature of the F<world.c> file + +the signatures of any header files that Cons detects are included, +directly or indirectly, by F<world.c> + +the text of the actual command line was used to generate F<world.o> + +=back + +Similarly, the build signature of the F<libworld.a> file will include +all the signatures of its constituents (and hence, transitively, the +signatures of B<their> constituents), as well as the command line that +created the file. + +Note that there is no need for a derived file to depend upon any +particular F<Construct> or F<Conscript> file. If changes to these files +affect a file, then this will be automatically reflected in its build +signature, since relevant parts of the command line are included in the +signature. Unrelated F<Construct> or F<Conscript> changes will have no +effect. + + +=head2 Storing signatures in .consign files + +Before Cons exits, it stores the calculated signatures for all of the +files it built or examined in F<.consign> files, one per directory. +Cons uses this stored information on later invocations to decide if +derived files need to be rebuilt. + +After the previous example was compiled, the F<.consign> file in the +F<build/peach/world> directory looked like this: + + world.h:985533370 - d181712f2fdc07c1f05d97b16bfad904 + world.o:985533372 2a0f71e0766927c0532977b0d2158981 + world.c:985533370 - c712f77189307907f4189b5a7ab62ff3 + libworld.a:985533374 69e568fc5241d7d25be86d581e1fb6aa + +After the file name and colon, the first number is a timestamp of the +file's modification time (on UNIX systems, this is typically the number +of seconds since January 1st, 1970). The second value is the build +signature of the file (or ``-'' in the case of files with no build +signature--that is, source files). The third value, if any, is the +content signature of the file. + + +=head2 Using build signatures to decide when to rebuild files + +When Cons is deciding whether to build or rebuild a derived file, it +first computes the file's current build signature. If the file doesn't +exist, it must obviously be built. + +If, however, the file already exists, Cons next compares the +modification timestamp of the file against the timestamp value in +the F<.consign> file. If the timestamps match, Cons compares the +newly-computed build signature against the build signature in the +F<.consign> file. If the timestamps do not match or the build +signatures do not match, the derived file is rebuilt. + +After the file is built or rebuilt, Cons arranges to store the +newly-computed build signature in the F<.consign> file when it exits. + + +=head2 Signature example + +The use of these signatures is an extremely simple, efficient, and +effective method of improving--dramatically--the reproducibility of a +system. + +We'll demonstrate this with a simple example: + + # Simple "Hello, World!" Construct file + $CFLAGS = '-g' if $ARG{DEBUG} eq 'on'; + $CONS = new cons(CFLAGS => $CFLAGS); + Program $CONS 'hello', 'hello.c'; + +Notice how Cons recompiles at the appropriate times: + + % cons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % cons hello + cons: "hello" is up-to-date. + % cons DEBUG=on hello + cc -g -c hello.c -o hello.o + cc -o hello hello.o + % cons DEBUG=on hello + cons: "hello" is up-to-date. + % cons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + + +=head2 Source-file signature configuration + +Cons provides a C<SourceSignature> method that allows you to configure +how the signature should be calculated for any source file when its +signature is being used to decide if a dependent file is up-to-date. +The arguments to the C<SourceSignature> method consist of one or more +pairs of strings: + + SourceSignature 'auto/*.c' => 'content', + '*' => 'stored-content'; + +The first string in each pair is a pattern to match against derived file +path names. The pattern is a file-globbing pattern, not a Perl regular +expression; the pattern <*.l> will match all Lex source files. The C<*> +wildcard will match across directory separators; the pattern C<foo/*.c> +would match all C source files in any subdirectory underneath the C<foo> +subdirectory. + +The second string in each pair contains one of the following keywords to +specify how signatures should be calculated for source files that match +the pattern. The available keywords are: + +=over 4 + +=item content + +Use the content signature of the source file when calculating signatures +of files that depend on it. This guarantees correct calculation of the +file's signature for all builds, by telling Cons to read the contents of +a source file to calculate its content signature each time it is run. + +=item stored-content + +Use the source file's content signature as stored in the F<.consign> +file, provided the file's timestamp matches the cached timestamp value +in the F<.consign> file. This optimizes performance, with the slight +risk of an incorrect build if a source file's contents have been changed +so quickly after its previous update that the timestamp still matches +the stored timestamp in the F<.consign> file even though the contents +have changed. + +=back + +The Cons default behavior of always calculating a source file's +signature from the file's contents is equivalent to specifying: + + SourceSignature '*' => 'content'; + +The C<*> will match all source files. The C<content> keyword +specifies that Cons will read the contents of a source file to calculate +its signature each time it is run. + +A useful global performance optimization is: + + SourceSignature '*' => 'stored-content'; + +This specifies that Cons will use pre-computed content signatures +from F<.consign> files, when available, rather than re-calculating a +signature from the the source file's contents each time Cons is run. In +practice, this is safe for most build situations, and only a problem +when source files are changed automatically (by scripts, for example). +The Cons default, however, errs on the side of guaranteeing a correct +build in all situations. + +Cons tries to match source file path names against the patterns in the +order they are specified in the C<SourceSignature> arguments: + + SourceSignature '/usr/repository/objects/*' => 'stored-content', + '/usr/repository/*' => 'content', + '*.y' => 'content', + '*' => 'stored-content'; + +In this example, all source files under the F</usr/repository/objects> +directory will use F<.consign> file content signatures, source files +anywhere else underneath F</usr/repository> will not use F<.consign> +signature values, all Yacc source files (C<*.y>) anywhere else will not +use F<.consign> signature values, and any other source file will use +F<.consign> signature values. + + +=head2 Derived-file signature configuration + +Cons provides a C<SIGNATURE> construction variable that allows you to +configure how signatures are calculated for any derived file when its +signature is being used to decide if a dependent file is up-to-date. +The value of the C<SIGNATURE> construction variable is a Perl array +reference that holds one or more pairs of strings, like the arguments to +the C<SourceSignature> method. + +The first string in each pair is a pattern to match against derived file +path names. The pattern is a file-globbing pattern, not a Perl regular +expression; the pattern `*.obj' will match all (Win32) object files. +The C<*> wildcard will match across directory separators; the pattern +`foo/*.a' would match all (UNIX) library archives in any subdirectory +underneath the foo subdirectory. + +The second string in each pair contains one of the following keywords +to specify how signatures should be calculated for derived files that +match the pattern. The available keywords are the same as for the +C<SourceSignature> method, with an additional keyword: + +=over 4 + +=item build + +Use the build signature of the derived file when calculating signatures +of files that depend on it. This guarantees correct builds by forcing +Cons to rebuild any and all files that depend on the derived file. + +=item content + +Use the content signature of the derived file when calculating signatures +of files that depend on it. This guarantees correct calculation of the +file's signature for all builds, by telling Cons to read the contents of +a derived file to calculate its content signature each time it is run. + +=item stored-content + +Use the derived file's content signature as stored in the F<.consign> +file, provided the file's timestamp matches the cached timestamp value +in the F<.consign> file. This optimizes performance, with the slight +risk of an incorrect build if a derived file's contents have been +changed so quickly after a Cons build that the file's timestamp still +matches the stored timestamp in the F<.consign> file. + +=back + +The Cons default behavior (as previously described) for using +derived-file signatures is equivalent to: + + $env = new cons(SIGNATURE => ['*' => 'build']); + +The C<*> will match all derived files. The C<build> keyword specifies +that all derived files' build signatures will be used when calculating +whether a dependent file is up-to-date. + +A useful alternative default C<SIGNATURE> configuration for many sites: + + $env = new cons(SIGNATURE => ['*' => 'content']); + +In this configuration, derived files have their signatures calculated +from the file contents. This adds slightly to Cons' workload, but has +the useful effect of "stopping" further rebuilds if a derived file is +rebuilt to exactly the same file contents as before, which usually +outweighs the additional computation Cons must perform. + +For example, changing a comment in a C file and recompiling should +generate the exact same object file (assuming the compiler doesn't +insert a timestamp in the object file's header). In that case, +specifying C<content> or C<stored-content> for the signature calculation +will cause Cons to recognize that the object file did not actually +change as a result of being rebuilt, and libraries or programs that +include the object file will not be rebuilt. When C<build> is +specified, however, Cons will only "know" that the object file was +rebuilt, and proceed to rebuild any additional files that include the +object file. + +Note that Cons tries to match derived file path names against the +patterns in the order they are specified in the C<SIGNATURE> array +reference: + + $env = new cons(SIGNATURE => ['foo/*.o' => 'build', + '*.o' => 'content', + '*.a' => 'stored-content', + '*' => 'content']); + +In this example, all object files underneath the F<foo> subdirectory +will use build signatures, all other object files (including object +files underneath other subdirectories!) will use F<.consign> file +content signatures, libraries will use F<.consign> file build +signatures, and all other derived files will use content signatures. + + +=head2 Debugging signature calculation + +Cons provides a C<-S> option that can be used to specify what internal +Perl package Cons should use to calculate signatures. The default Cons +behavior is equivalent to specifying C<-S md5> on the command line. + +The only other package (currently) available is an C<md5::debug> +package that prints out detailed information about the MD5 signature +calculations performed by Cons: + + % cons -S md5::debug hello + sig::md5::srcsig(hello.c) + => |52d891204c62fe93ecb95281e1571938| + sig::md5::collect(52d891204c62fe93ecb95281e1571938) + => |fb0660af4002c40461a2f01fbb5ffd03| + sig::md5::collect(52d891204c62fe93ecb95281e1571938, + fb0660af4002c40461a2f01fbb5ffd03, + cc -c %< -o %>) + => |f7128da6c3fe3c377dc22ade70647b39| + sig::md5::current(|| + eq |f7128da6c3fe3c377dc22ade70647b39|) + cc -c hello.c -o hello.o + sig::md5::collect() + => |d41d8cd98f00b204e9800998ecf8427e| + sig::md5::collect(f7128da6c3fe3c377dc22ade70647b39, + d41d8cd98f00b204e9800998ecf8427e, + cc -o %> %< ) + => |a0bdce7fd09e0350e7efbbdb043a00b0| + sig::md5::current(|| + eq |a0bdce7fd09e0350e7efbbdb043a00b0|) + cc -o hello, hello.o + + + + + + + +=head1 Temporary overrides + +Cons provides a very simple mechanism for overriding aspects of a build. The +essence is that you write an override file containing one or more +C<Override> commands, and you specify this on the command line, when you run +C<cons>: + + % cons -o over export + +will build the F<export> directory, with all derived files subject to the +overrides present in the F<over> file. If you leave out the C<-o> option, +then everything necessary to remove all overrides will be rebuilt. + + +=head2 Overriding environment variables + +The override file can contain two types of overrides. The first is incoming +environment variables. These are normally accessible by the F<Construct> +file from the C<%ENV> hash variable. These can trivially be overridden in +the override file by setting the appropriate elements of C<%ENV> (these +could also be overridden in the user's environment, of course). + + +=head2 The Override command + +The second type of override is accomplished with the C<Override> command, +which looks like this: + + Override <regexp>, <var1> => <value1>, <var2> => <value2>, ...; + +The regular expression I<regexp> is matched against every derived file that +is a candidate for the build. If the derived file matches, then the +variable/value pairs are used to override the values in the construction +environment associated with the derived file. + +Let's suppose that we have a construction environment like this: + + $CONS = new cons( + COPT => '', + CDBG => '-g', + CFLAGS => '%COPT %CDBG', + ); + +Then if we have an override file F<over> containing this command: + + Override '\.o$', COPT => '-O', CDBG => ''; + +then any C<cons> invocation with C<-o over> that creates F<.o> files via +this environment will cause them to be compiled with C<-O >and no C<-g>. The +override could, of course, be restricted to a single directory by the +appropriate selection of a regular expression. + +Here's the original version of the Hello, World! program, built with this +environment. Note that Cons rebuilds the appropriate pieces when the +override is applied or removed: + + % cons hello + cc -g -c hello.c -o hello.o + cc -o hello hello.o + % cons -o over hello + cc -O -c hello.c -o hello.o + cc -o hello hello.o + % cons -o over hello + cons: "hello" is up-to-date. + % cons hello + cc -g -c hello.c -o hello.o + cc -o hello hello.o + +It's important that the C<Override> command only be used for temporary, +on-the-fly overrides necessary for development because the overrides are not +platform independent and because they rely too much on intimate knowledge of +the workings of the scripts. For temporary use, however, they are exactly +what you want. + +Note that it is still useful to provide, say, the ability to create a fully +optimized version of a system for production use--from the F<Construct> and +F<Conscript> files. This way you can tailor the optimized system to the +platform. Where optimizer trade-offs need to be made (particular files may +not be compiled with full optimization, for example), then these can be +recorded for posterity (and reproducibility) directly in the scripts. + + + +=head2 The C<Module> method + +The C<Module> method is a combination of the C<Program> and C<Command> +methods. Rather than generating an executable program directly, this command +allows you to specify your own command to actually generate a module. The +method is invoked as follows: + + Module $env <module name>, <source or object files>, <construction command>; + +This command is useful in instances where you wish to create, for example, +dynamically loaded modules, or statically linked code libraries. + + + + +=head2 The C<RuleSet> method + +The C<RuleSet> method returns the construction variables for building +various components with one of the rule sets supported by Cons. The +currently supported rule sets are: + +=over 4 + +=item msvc + +Rules for the Microsoft Visual C++ compiler suite. + +=item unix + +Generic rules for most UNIX-like compiler suites. + +=back + +On systems with more than one available compiler suite, this allows you +to easily create side-by-side environments for building software with +multiple tools: + + $msvcenv = new cons(RuleSet("msvc")); + $cygnusenv = new cons(RuleSet("unix")); + +In the future, this could also be extended to other platforms that +have different default rule sets. + + +=head2 The C<DefaultRules> method + +The C<DefaultRules> method sets the default construction variables that +will be returned by the C<new> method to the specified arguments: + + DefaultRules(CC => 'gcc', + CFLAGS => '', + CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>'); + $env = new cons(); + # $env now contains *only* the CC, CFLAGS, + # and CCCOM construction variables + +Combined with the C<RuleSet> method, this also provides an easy way +to set explicitly the default build environment to use some supported +toolset other than the Cons defaults: + + # use a UNIX-like tool suite (like cygwin) on Win32 + DefaultRules(RuleSet('unix')); + $env = new cons(); + +Note that the C<DefaultRules> method completely replaces the default +construction environment with the specified arguments, it does not +simply override the existing defaults. To override one or more +variables in a supported C<RuleSet>, append the variables and values: + + DefaultRules(RuleSet('unix'), CFLAGS => '-O3'); + $env1 = new cons(); + $env2 = new cons(); + # both $env1 and $env2 have 'unix' defaults + # with CFLAGS set to '-O3' + + + + + + + + +=head2 The C<SourcePath> method + +The C<SourcePath> mathod returns the real source path name of a file, +as opposed to the path name within a build directory. It is invoked +as follows: + + $path = SourcePath <buildpath>; + + +=head2 The C<ConsPath> method + +The C<ConsPath> method returns true if the supplied path is a derivable +file, and returns undef (false) otherwise. +It is invoked as follows: + + $result = ConsPath <path>; + + +=head2 The C<SplitPath> method + +The C<SplitPath> method looks up multiple path names in a string separated +by the default path separator for the operating system (':' on UNIX +systems, ';' on Windows NT), and returns the fully-qualified names. +It is invoked as follows: + + @paths = SplitPath <pathlist>; + +The C<SplitPath> method will convert names prefixed '#' to the +appropriate top-level build name (without the '#') and will convert +relative names to top-level names. + + +=head2 The C<DirPath> method + +The C<DirPath> method returns the build path name(s) of a directory or +list of directories. It is invoked as follows: + + $cwd = DirPath <paths>; + +The most common use for the C<DirPath> method is: + + $cwd = DirPath '.'; + +to fetch the path to the current directory of a subsidiary F<Conscript> +file. + + +=head2 The C<FilePath> method + +The C<FilePath> method returns the build path name(s) of a file or +list of files. It is invoked as follows: + + $file = FilePath <path>; diff --git a/doc/user/copyright.in b/doc/user/copyright.in new file mode 100644 index 0000000..341698d --- /dev/null +++ b/doc/user/copyright.in @@ -0,0 +1,32 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<blockquote> + <para> + + SCons User's Guide Copyright (c) 2004, 2005, 2006, 2007 Steven Knight + + </para> +</blockquote> diff --git a/doc/user/copyright.xml b/doc/user/copyright.xml new file mode 100644 index 0000000..341698d --- /dev/null +++ b/doc/user/copyright.xml @@ -0,0 +1,32 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<blockquote> + <para> + + SCons User's Guide Copyright (c) 2004, 2005, 2006, 2007 Steven Knight + + </para> +</blockquote> diff --git a/doc/user/depends.in b/doc/user/depends.in new file mode 100644 index 0000000..dfd52e3 --- /dev/null +++ b/doc/user/depends.in @@ -0,0 +1,1816 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + So far we've seen how &SCons; handles one-time builds. + But one of the main functions of a build tool like &SCons; + is to rebuild only what is necessary + when source files change--or, put another way, + &SCons; should <emphasis>not</emphasis> + waste time rebuilding things that don't need to be rebuilt. + You can see this at work simply by re-invoking &SCons; + after building our simple &hello; example: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct"> + Program('hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + The second time it is executed, + &SCons; realizes that the &hello; program + is up-to-date with respect to the current &hello_c; source file, + and avoids rebuilding it. + You can see this more clearly by naming + the &hello; program explicitly on the command line: + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + Note that &SCons; reports <literal>"...is up to date"</literal> + only for target files named explicitly on the command line, + to avoid cluttering the output. + + </para> + + <section> + <title>Deciding When an Input File Has Changed: the &Decider; Function</title> + + <para> + + Another aspect of avoiding unnecessary rebuilds + is the fundamental build tool behavior + of <emphasis>rebuilding</emphasis> + things when an input file changes, + so that the built software is up to date. + By default, + &SCons; keeps track of this through an + MD5 &signature;, or checksum, of the contents of each file, + although you can easily configure + &SCons; to use the + modification times (or time stamps) + instead. + You can even specify your own Python function + for deciding if an input file has changed. + + </para> + + <section> + <title>Using MD5 Signatures to Decide if a File Has Changed</title> + + <para> + + By default, + &SCons; keeps track of whether a file has changed + based on an MD5 checksum of the file's contents, + not the file's modification time. + This means that you may be surprised by the + default &SCons; behavior if you are used to the + &Make; convention of forcing + a rebuild by updating the file's modification time + (using the &touch; command, for example): + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>touch hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + Even though the file's modification time has changed, + &SCons; realizes that the contents of the + &hello_c; file have <emphasis>not</emphasis> changed, + and therefore that the &hello; program + need not be rebuilt. + This avoids unnecessary rebuilds when, + for example, someone rewrites the + contents of a file without making a change. + But if the contents of the file really do change, + then &SCons; detects the change + and rebuilds the program as required: + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + Note that you can, if you wish, + specify this default behavior + (MD5 signatures) explicitly + using the &Decider; function as follows: + + </para> + + <sconstruct> + Program('hello.c') + Decider('MD5') + </sconstruct> + + <para> + + You can also use the string <literal>'content'</literal> + as a synonym for <literal>'MD5'</literal> + when calling the &Decider; function. + + </para> + + <section> + <title>Ramifications of Using MD5 Signatures</title> + + <para> + + Using MD5 signatures to decide if an input file has changed + has one surprising benefit: + if a source file has been changed + in such a way that the contents of the + rebuilt target file(s) + will be exactly the same as the last time + the file was built, + then any "downstream" target files + that depend on the rebuilt-but-not-changed target + file actually need not be rebuilt. + + </para> + + <para> + + So if, for example, + a user were to only change a comment in a &hello_c; file, + then the rebuilt &hello_o; file + would be exactly the same as the one previously built + (assuming the compiler doesn't put any build-specific + information in the object file). + &SCons; would then realize that it would not + need to rebuild the &hello; program as follows: + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + In essence, &SCons; + "short-circuits" any dependent builds + when it realizes that a target file + has been rebuilt to exactly the same file as the last build. + This does take some extra processing time + to read the contents of the target (&hello_o;) file, + but often saves time when the rebuild that was avoided + would have been time-consuming and expensive. + + </para> + + </section> + + </section> + + <section> + <title>Using Time Stamps to Decide If a File Has Changed</title> + + <para> + + If you prefer, you can + configure &SCons; to use the modification time + of a file, not the file contents, + when deciding if a target needs to be rebuilt. + &SCons; gives you two ways to use time stamps + to decide if an input file has changed + since the last time a target has been built. + + </para> + + <para> + + The most familiar way to use time stamps + is the way &Make; does: + that is, have &SCons; decide + that a target must be rebuilt + if a source file's modification time is + <emphasis>newer</emphasis> + than the target file. + To do this, call the &Decider; + function as follows: + + </para> + + <scons_example name="newer"> + <file name="SConstruct" printme="1"> + Program('hello.c') + Decider('timestamp-newer') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + This makes &SCons; act like &Make; + when a file's modification time is updated + (using the &touch; command, for example): + + </para> + + <scons_output example="newer" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>touch hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + And, in fact, because this behavior is the same + as the behavior of &Make;, + you can also use the string <literal>'make'</literal> + as a synonym for <literal>'timestamp-newer'</literal> + when calling the &Decider; function: + + </para> + + <sconstruct> + Program('hello.c') + Decider('make') + </sconstruct> + + <para> + + One drawback to using times stamps exactly like &Make; + is that if an input file's modification time suddenly + becomes <emphasis>older</emphasis> than a target file, + the target file will not be rebuilt. + This can happen if an old copy of a source file is restored + from a backup archive, for example. + The contents of the restored file will likely be different + than they were the last time a dependent target was built, + but the target won't be rebuilt + because the modification time of the source file + is not newer than the target. + + </para> + + <para> + + Because &SCons; actually stores information + about the source files' time stamps whenever a target is built, + it can handle this situation by checking for + an exact match of the source file time stamp, + instead of just whether or not the source file + is newer than the target file. + To do this, specify the argument + <literal>'timestamp-match'</literal> + when calling the &Decider; function: + + </para> + + <scons_example name="match"> + <file name="SConstruct" printme="1"> + Program('hello.c') + Decider('timestamp-match') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + When configured this way, + &SCons; will rebuild a target whenever + a source file's modification time has changed. + So if we use the <literal>touch -t</literal> + option to change the modification time of + &hello_c; to an old date (January 1, 1989), + &SCons; will still rebuild the target file: + + </para> + + <scons_output example="match" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>touch -t 198901010000 hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + In general, the only reason to prefer + <literal>timestamp-newer</literal> + instead of + <literal>timestamp-match</literal>, + would be if you have some specific reason + to require this &Make;-like behavior of + not rebuilding a target when an otherwise-modified + source file is older. + + </para> + + </section> + + <section> + <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title> + + <para> + + As a performance enhancement, + &SCons; provides a way to use + MD5 checksums of file contents + but to read those contents + only when the file's timestamp has changed. + To do this, call the &Decider; + function with <literal>'MD5-timestamp'</literal> + argument as follows: + + </para> + + <scons_example name="MD5-timestamp"> + <file name="SConstruct" printme="1"> + Program('hello.c') + Decider('MD5-timestamp') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + So configured, &SCons will still behave like + it does when using <literal>Decider('MD5')</literal>: + + </para> + + <!-- + + We want to generate the output as follows, + but our "surrogate" system for generating the + output seems to get this wrong. + Just in-line the output for now. + + <scons_output example="MD5-timestamp" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>touch hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>touch hello.c</userinput> + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit hello.c</userinput> + [CHANGE THE CONTENTS OF hello.c] + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + However, the second call to &SCons; in the above output, + when the build is up-to-date, + will have been performed by simply looking at the + modification time of the &hello_c; file, + not by opening it and performing + an MD5 checksum calcuation on its contents. + This can significantly speed up many up-to-date builds. + + </para> + + <para> + + The only drawback to using + <literal>Decider('MD5-timestamp')</literal> + is that &SCons; will <emphasis>not</emphasis> + rebuild a target file if a source file was modified + within one second of the last time &SCons; built the file. + While most developers are programming, + this isn't a problem in practice, + since it's unlikely that someone will have built + and then thought quickly enough to make a substantive + change to a source file within one second. + Certain build scripts or + continuous integration tools may, however, + rely on the ability to apply changes to files + automatically and then rebuild as quickly as possible, + in which case use of + <literal>Decider('MD5-timestamp')</literal> + may not be appropriate. + + </para> + + </section> + + <section> + <title>Writing Your Own Custom &Decider; Function</title> + + <para> + + The different string values that we've passed to + the &Decider; function are essentially used by &SCons; + to pick one of several specific internal functions + that implement various ways of deciding if a dependency + (usually a source file) + has changed since a target file has been built. + As it turns out, + you can also supply your own function + to decide if a dependency has changed. + + </para> + + <para> + + For example, suppose we have an input file + that contains a lot of data, + in some specific regular format, + that is used to rebuild a lot of different target files, + but each target file really only depends on + one particular section of the input file. + We'd like to have each target file depend on + only its section of the input file. + However, since the input file may contain a lot of data, + we want to open the input file only if its timestamp has changed. + This could done with a custom + &Decider; function that might look something like this: + + </para> + + <scons_example name="function"> + <file name="SConstruct" printme="1"> + Program('hello.c') + def decide_if_changed(dependency, target, prev_ni): + if self.get_timestamp() != prev_ni.timestamp: + dep = str(dependency) + tgt = str(target) + if specific_part_of_file_has_changed(dep, tgt): + return True + return False + Decider(decide_if_changed) + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Note that in the function definition, + the <varname>dependency</varname> + (input file) is the first argument, + and then the ⌖. + Both of these are passed to the functions as + SCons &Node; objects, + which we convert to strings using the Python + <function>str()</function>. + + </para> + + <para> + + The third argument, <varname>prev_ni</varname>, + is an object that holds the + signature or timestamp information + that was recorded about the dependency + the last time the target was built. + A <varname>prev_ni</varname> object can hold + different information, + depending on the type of thing that the + <varname>dependency</varname> argument represents. + For normal files, + the <varname>prev_ni</varname> object + has the following attributes: + + </para> + + <variablelist> + + <varlistentry> + <term>.csig</term> + + <listitem> + <para> + The <emphasis>content signature</emphasis>, + or MD5 checksum, of the contents of the + <varname>dependency</varname> + file the list time the ⌖ was built. + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>.size</term> + + <listitem> + <para> + The size in bytes of the <varname>dependency</varname> + file the list time the target was built. + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>.timestamp</term> + + <listitem> + <para> + The modification time of the <varname>dependency</varname> + file the list time the ⌖ was built. + </para> + </listitem> + + </varlistentry> + + </variablelist> + + <para> + + Note that ignoring some of the arguments + in your custom &Decider; function + is a perfectly normal thing to do, + if they don't impact the way you want to + decide if the dependency file has changed. + + </para> + + </section> + + <section> + <title>Mixing Different Ways of Deciding If a File Has Changed</title> + + <para> + + The previous examples have all demonstrated calling + the global &Decider; function + to configure all dependency decisions that &SCons; makes. + Sometimes, however, you want to be able to configure + different decision-making for different targets. + When that's necessary, you can use the + <function>env.Decider</function> + method to affect only the configuration + decisions for targets built with a + specific construction environment. + + </para> + + <para> + + For example, if we arbitrarily want to build + one program using MD5 checkums + and another using file modification times + from the same source + we might configure it this way: + + </para> + + <scons_example name="mixing"> + <file name="SConstruct" printme="1"> + env1 = Environment(CPPPATH = ['.']) + env2 = env1.Clone() + env2.Decider('timestamp-match') + env1.Program('prog-MD5', 'program1.c') + env2.Program('prog-timestamp', 'program2.c') + </file> + <file name="program1.c"> + #include "inc.h" + int main() { printf("Hello, world!\n"); } + </file> + <file name="program2.c"> + #include "inc.h" + int main() { printf("Hello, world!\n"); } + </file> + <file name="inc.h"> + #define INC 1 + </file> + </scons_example> + + <para> + + If both of the programs include the same + <filename>inc.h</filename> file, + then updating the modification time of + <filename>inc.h</filename> + (using the &touch; command) + will cause only <filename>prog-timestamp</filename> + to be rebuilt: + + </para> + + <scons_output example="mixing" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>touch inc.h</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + </section> + + <section> + <title>Older Functions for Deciding When an Input File Has Changed</title> + + <para> + + &SCons; still supports two functions that used to be the + primary methods for configuring the + decision about whether or not an input file has changed. + Although they're not officially deprecated yet, + their use is discouraged, + mainly because they rely on a somewhat + confusing distinction between how + source files and target files are handled. + These functions are documented here mainly in case you + encounter them in existing &SConscript; files. + + </para> + + <section> + <title>The &SourceSignatures; Function</title> + + <para> + + The &SourceSignatures; function is fairly straightforward, + and supports two different argument values + to configure whether source file changes should be decided + using MD5 signatures: + + </para> + + <sconstruct> + Program('hello.c') + SourceSignatures('MD5') + </sconstruct> + + <para> + + Or using time stamps: + + </para> + + <sconstruct> + Program('hello.c') + SourceSignatures('timestamp') + </sconstruct> + + <para> + + These are roughly equivalent to specifying + <function>Decider('MD5')</function> + or + <function>Decider('timestamp-match')</function>, + respectively, + although it only affects how SCons makes + decisions about dependencies on + <emphasis>source</emphasis> files--that is, + files that are not built from any other files. + + </para> + + </section> + + <section> + <title>The &TargetSignatures; Function</title> + + <para> + + The &TargetSignatures; function + specifies how &SCons; decides + when a target file has changed + <emphasis>when it is used as a + dependency of (input to) another target</emphasis>--that is, + the &TargetSignatures; function configures + how the signatures of "intermediate" target files + are used when deciding if a "downstream" target file + must be rebuilt. + <footnote><para> + This easily-overlooked distinction between + how &SCons; decides if the target itself must be rebuilt + and how the target is then used to decide if a different + target must be rebuilt is one of the confusing + things that has led to the &TargetSignatures; + and &SourceSignatures; functions being + replaced by the simpler &Decider; function. + </para></footnote> + + </para> + + <para> + + The &TargetSignatures; function supports the same + <literal>'MD5'</literal> and <literal>'timestamp'</literal> + argument values that are supported by the &SourceSignatures;, + with the same meanings, but applied to target files. + That is, in the example: + + </para> + + <sconstruct> + Program('hello.c') + TargetSignatures('MD5') + </sconstruct> + + <para> + + The MD5 checksum of the &hello_o; target file + will be used to decide if it has changed since the last + time the "downstream" &hello; target file was built. + And in the example: + + </para> + + <sconstruct> + Program('hello.c') + TargetSignatures('timestamp') + </sconstruct> + + <para> + + The modification time of the &hello_o; target file + will be used to decide if it has changed since the last + time the "downstream" &hello; target file was built. + + </para> + + <para> + + The &TargetSignatures; function supports + two additional argument values: + <literal>'source'</literal> and <literal>'build'</literal>. + The <literal>'source'</literal> argument + specifies that decisions involving + whether target files have changed + since a previous build + should use the same behavior + for the decisions configured for source files + (using the &SourceSignatures; function). + So in the example: + + </para> + + <sconstruct> + Program('hello.c') + TargetSignatures('source') + SourceSignatures('timestamp') + </sconstruct> + + <para> + + All files, both targets and sources, + will use modification times + when deciding if an input file + has changed since the last + time a target was built. + + </para> + + <para> + + Lastly, the <literal>'build'</literal> argument + specifies that &SCons; should examine + the build status of a target file + and always rebuild a "downstream" target + if the target file was itself rebuilt, + without re-examining the contents or timestamp + of the newly-built target file. + If the target file was not rebuilt during + this &scons; invocation, + then the target file will be examined + the same way as configured by + the &SourceSignature; call + to decide if it has changed. + + </para> + + <para> + + This mimics the behavior of + <literal>build signatures</literal> + in earlier versions of &SCons;. + A &buildsignature; re-combined + signatures of all the input files + that went into making the target file, + so that the target file itself + did not need to have its contents read + to compute an MD5 signature. + This can improve performance for some configurations, + but is generally not as effective as using + <literal>Decider('MD5-timestamp')</literal>. + + </para> + + </section> + + </section> + + <section> + <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title> + + <para> + + Now suppose that our "Hello, World!" program + actually has an <literal>#include</literal> line + to include the &hello_h; file in the compilation: + + </para> + + <scons_example name="include"> + <file name="SConstruct"> + Program('hello.c', CPPPATH = '.') + </file> + <file name="hello.c" printme="1"> + #include <hello.h> + int + main() + { + printf("Hello, %s!\n", string); + } + </file> + <file name="hello.h"> + #define string "world" + </file> + </scons_example> + + <para> + + And, for completeness, the &hello_h; file looks like this: + + </para> + + <scons_example_file example="include" name="hello.h"> + </scons_example_file> + + <para> + + In this case, we want &SCons; to recognize that, + if the contents of the &hello_h; file change, + the &hello; program must be recompiled. + To do this, we need to modify the + &SConstruct; file like so: + + </para> + + <scons_example_file example="include" name="SConstruct"> + </scons_example_file> + + <para> + + The &cv-link-CPPPATH; value + tells &SCons; to look in the current directory + (<literal>'.'</literal>) + for any files included by C source files + (<filename>.c</filename> or <filename>.h</filename> files). + With this assignment in the &SConstruct; file: + + </para> + + <scons_output example="include" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + First, notice that &SCons; + added the <literal>-I.</literal> argument + from the &cv-CPPPATH; variable + so that the compilation would find the + &hello_h; file in the local directory. + + </para> + + <para> + + Second, realize that &SCons; knows that the &hello; + program must be rebuilt + because it scans the contents of + the &hello_c; file + for the <literal>#include</literal> lines that indicate + another file is being included in the compilation. + &SCons; records these as + <emphasis>implicit dependencies</emphasis> + of the target file, + Consequently, + when the &hello_h; file changes, + &SCons; realizes that the &hello_c; file includes it, + and rebuilds the resulting &hello; program + that depends on both the &hello_c; and &hello_h; files. + + </para> + + <para> + + Like the &cv-link-LIBPATH; variable, + the &cv-CPPPATH; variable + may be a list of directories, + or a string separated by + the system-specific path separation character + (':' on POSIX/Linux, ';' on Windows). + Either way, &SCons; creates the + right command-line options + so that the following example: + + </para> + + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> + Program('hello.c', CPPPATH = ['include', '/home/project/inc']) + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Will look like this on POSIX or Linux: + + </para> + + <scons_output example="ex5" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + And like this on Windows: + + </para> + + <scons_output example="ex5" os="win32"> + <scons_output_command>scons -Q hello.exe</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Caching Implicit Dependencies</title> + + <para> + + Scanning each file for <literal>#include</literal> lines + does take some extra processing time. + When you're doing a full build of a large system, + the scanning time is usually a very small percentage + of the overall time spent on the build. + You're most likely to notice the scanning time, + however, when you <emphasis>rebuild</emphasis> + all or part of a large system: + &SCons; will likely take some extra time to "think about" + what must be built before it issues the + first build command + (or decides that everything is up to date + and nothing must be rebuilt). + + <!-- + Isn't this expensive? The answer is, it depends. If you do a full build of a + large system, the scanning time is insignificant. If you do a rebuild of a + large system, then Cons will spend a fair amount of time thinking about it + before it decides that nothing has to be done (although not necessarily more + time than make!). The good news is that Cons makes it very easy to + intelligently subset your build, when you are working on localized changes. + --> + + </para> + + <para> + + In practice, having &SCons; scan files saves time + relative to the amount of potential time + lost to tracking down subtle problems + introduced by incorrect dependencies. + Nevertheless, the "waiting time" + while &SCons; scans files can annoy + individual developers waiting for their builds to finish. + Consequently, &SCons; lets you cache + the implicit dependencies + that its scanners find, + for use by later builds. + You can do this by specifying the + &implicit-cache; option on the command line: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q --implicit-cache hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + If you don't want to specify &implicit-cache; + on the command line each time, + you can make it the default behavior for your build + by setting the &implicit_cache; option + in an &SConscript; file: + + </para> + + <sconstruct> + SetOption('implicit_cache', 1) + </sconstruct> + + <para> + + &SCons; does not cache implicit dependencies like this by default + because the &implicit-cache; causes &SCons; to simply use the implicit + dependencies stored during the last run, without any checking + for whether or not those dependencies are still correct. + Specifically, this means &implicit-cache; instructs &SCons; + to <emphasis>not</emphasis> rebuild "correctly" in the + following cases: + + + </para> + + <itemizedlist> + + <listitem> + <para> + + When &implicit-cache; is used, &SCons; will ignore any changes that + may have been made to search paths + (like &cv-CPPPATH; or &cv-LIBPATH;,). + This can lead to &SCons; not rebuilding a file if a change to + &cv-CPPPATH; would normally cause a different, same-named file from + a different directory to be used. + + </para> + </listitem> + + <listitem> + <para> + + When &implicit-cache; is used, &SCons; will not detect if a + same-named file has been added to a directory that is earlier in + the search path than the directory in which the file was found + last time. + + </para> + </listitem> + + </itemizedlist> + + <section> + <title>The &implicit-deps-changed; Option</title> + + <para> + + When using cached implicit dependencies, + sometimes you want to "start fresh" + and have &SCons; re-scan the files + for which it previously cached the dependencies. + For example, + if you have recently installed a new version of + external code that you use for compilation, + the external header files will have changed + and the previously-cached implicit dependencies + will be out of date. + You can update them by + running &SCons; with the &implicit-deps-changed; option: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q --implicit-deps-changed hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + In this case, &SCons; will re-scan all of the implicit dependencies + and cache updated copies of the information. + + </para> + + </section> + + <section> + <title>The &implicit-deps-unchanged; Option</title> + + <para> + + By default when caching dependencies, + &SCons; notices when a file has been modified + and re-scans the file for any updated + implicit dependency information. + Sometimes, however, you may want + to force &SCons; to use the cached implicit dependencies, + even if the source files changed. + This can speed up a build for example, + when you have changed your source files + but know that you haven't changed + any <literal>#include</literal> lines. + In this case, + you can use the &implicit-deps-unchanged; option: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q --implicit-deps-unchanged hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + <para> + + In this case, + &SCons; will assume that the cached implicit + dependencies are correct and + will not bother to re-scan changed files. + For typical builds after small, + incremental changes to source files, + the savings may not be very big, + but sometimes every bit of + improved performance counts. + + </para> + + </section> + + <!-- + + <section> + <title>XXX max drift</title> + + XXX SetOption('max_drift') + + </section> + + --> + + </section> + + <section> + <title>Explicit Dependencies: the &Depends; Function</title> + + <para> + + Sometimes a file depends on another file + that is not detected by an &SCons; scanner. + For this situation, + &SCons; allows you to specific explicitly that one file + depends on another file, + and must be rebuilt whenever that file changes. + This is specified using the &Depends; method: + + </para> + + <programlisting> + hello = Program('hello.c') + Depends(hello, 'other_file') + </programlisting> + + <!-- XXX mention that you can use arrays for target and source? --> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit other_file</userinput> + [CHANGE THE CONTENTS OF other_file] + % <userinput>scons -Q hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + </screen> + + <para> + + Note that the dependency + (the second argument to &Depends;) + may also be a list of Node objects + (for example, as returned by a call to a Builder): + + </para> + + <programlisting> + hello = Program('hello.c') + goodbye = Program('goodbye.c') + Depends(hello, goodbye) + </programlisting> + + <para> + + in which case the dependency or dependencies + will be built before the target(s): + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -c goodbye.c -o goodbye.o + cc -o goodbye goodbye.o + cc -c hello.c -o hello.o + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Dependencies From External Files: the &ParseDepends; + Function</title> + + <para> + + &SCons; has built-in scanners for a number of languages. Sometimes + these scanners fail to extract certain implicit dependencies due + to limitations of the scanner implementation. + + </para> + + <para> + + The following example illustrates a case where the built-in C + scanner is unable to extract the implicit dependency on a header + file. + + </para> + + <scons_example name="macroinc"> + <file name="hello.c" printme="1"> + #define FOO_HEADER <foo.h> + #include FOO_HEADER + + int main() { + return FOO; + } + </file> + <file name="SConstruct"> + Program('hello', 'hello.c', CPPPATH='.') + </file> + <file name="foo.h"> + #define FOO 42 + </file> + </scons_example> + + <scons_output example="macroinc" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE CONTENTS OF foo.h]" + >edit foo.h</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Apparently, the scanner does not know about the header dependency. + Being not a full-fledged C preprocessor, the scanner does not + expand the macro. + + </para> + + <para> + + In these cases, you may also use the compiler to extract the + implicit dependencies. &ParseDepends; can parse the contents of + the compiler output in the style of &Make;, and explicitly + establish all of the listed dependencies. + + </para> + + <para> + + The following example uses &ParseDepends; to process a compiler + generated dependency file which is generated as a side effect + during compilation of the object file: + + </para> + + <!-- XXX The ParseDepends example below fakes proper working by a + priori specification of the dependency file. The produced hello.d + file is not found (or used) for unknown reasons. --> + + <scons_example name="parsedep"> + <file name="hello.c"> + #define FOO_HEADER <foo.h> + #include FOO_HEADER + + int main() { + return FOO; + } + </file> + <file name="SConstruct" printme="1"> + obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') + SideEffect('hello.d', obj) + ParseDepends('hello.d') + Program('hello', obj) + </file> + <file name="foo.h"> + #define FOO 42 + </file> + <file name="hello.d"> + hello.o: hello.c foo.h + </file> + </scons_example> + + <scons_output example="parsedep" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE CONTENTS OF foo.h]" + >edit foo.h</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Parsing dependencies from a compiler-generated + <filename>.d</filename> file has a chicken-and-egg problem, that + causes unnecessary rebuilds: + + </para> + + <scons_example name="parsedeprebuild"> + <file name="hello.c"> + #define FOO_HEADER <foo.h> + #include FOO_HEADER + + int main() { + return FOO; + } + </file> + <file name="SConstruct"> + obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') + SideEffect('hello.d', obj) + ParseDepends('hello.d') + Program('hello', obj) + </file> + <file name="foo.h"> + #define FOO 42 + </file> + </scons_example> + + <!-- + <scons_output example="parsedeprebuild" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + --> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -MD -MF hello.d -I. hello.c + cc -o hello hello.o + % <userinput>scons -Q --debug=explain</userinput> + scons: rebuilding `hello.o' because `foo.h' is a new dependency + cc -o hello.o -c -MD -MF hello.d -I. hello.c + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + </screen> + + <para> + + In the first pass, the dependency file is generated while the + object file is compiled. At that time, &SCons; does not know about + the dependency on <filename>foo.h</filename>. In the second pass, + the object file is regenerated because <filename>foo.h</filename> + is detected as a new dependency. + + </para> + + <para> + + &ParseDepends; immediately reads the specified file at invocation + time and just returns if the file does not exist. A dependency + file generated during the build process is not automatically + parsed again. Hence, the compiler-extracted dependencies are not + stored in the signature database during the same build pass. This + limitation of &ParseDepends; leads to unnecessary recompilations. + Therefore, &ParseDepends; should only be used if scanners are not + available for the employed language or not powerful enough for the + specific task. + + </para> + + </section> + + <section> + <title>Ignoring Dependencies: the &Ignore; Function</title> + + <para> + + Sometimes it makes sense + to not rebuild a program, + even if a dependency file changes. + In this case, + you would tell &SCons; specifically + to ignore a dependency as follows: + + </para> + + <scons_example name="ignore"> + <file name="SConstruct" printme="1"> + hello = Program('hello.c') + Ignore(hello, 'hello.h') + </file> + <file name="hello.c"> + #include "hello.h" + int main() { printf("Hello, %s!\n", string); } + </file> + <file name="hello.h"> + #define string "world" + </file> + </scons_example> + + <!-- XXX mention that you can use lists for target and source? --> + + <!-- + <scons_output example="ignore"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX + </scons_output> + --> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -c -o hello.o hello.c + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit hello.h</userinput> + [CHANGE THE CONTENTS OF hello.h] + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + </screen> + + <para> + + Now, the above example is a little contrived, + because it's hard to imagine a real-world situation + where you wouldn't want to rebuild &hello; + if the &hello_h; file changed. + A more realistic example + might be if the &hello; + program is being built in a + directory that is shared between multiple systems + that have different copies of the + &stdio_h; include file. + In that case, + &SCons; would notice the differences between + the different systems' copies of &stdio_h; + and would rebuild &hello; + each time you change systems. + You could avoid these rebuilds as follows: + + </para> + + <programlisting> + hello = Program('hello.c', CPPPATH=['/usr/include']) + Ignore(hello, '/usr/include/stdio.h') + </programlisting> + + <para> + &Ignore; can also be used to prevent a generated file from being built + by default. This is due to the fact that directories depend on + their contents. So to ignore a generated file from the default build, + you specify that the directory should ignore the generated file. + Note that the file will still be built if the user specifically + requests the target on scons command line, or if the file is + a dependency of another file which is requested and/or is built + by default. + </para> + + <scons_example name="ignore_explicit"> + <file name="SConstruct" printme="1"> + hello_obj=Object('hello.c') + hello = Program(hello_obj) + Ignore('.',[hello,hello_obj]) + </file> + <file name="hello.c"> + #include "stdio.h" + int main() { printf("Hello!\n"); } + </file> + </scons_example> + + <scons_output example="ignore_explicit" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + </section> + + <section> + <title>Order-Only Dependencies: the &Requires; Function</title> + + <para> + + Occasionally, + it may be useful to specify that a certain + file or directory must, if necessary, + be built or created before some other target is built, + but that changes to that file or directory + do <emphasis>not</emphasis> + require that the target itself be rebuilt. + Such a relationship is called an + <emphasis>order-only dependency</emphasis> + because it only affects the order in which + things must be built--the dependency before the target--but + it is not a strict dependency relationship + because the target should not + change in response to changes in the dependent file. + + </para> + + <para> + + For example, suppose that you want to create a file + every time you run a build + that identifies the time the build was performed, + the version number, etc., + and which is included in every program that you build. + The version file's contents will change every build. + If you specify a normal dependency relationship, + then every program that depends on + that file would be rebuilt every time you ran &SCons;. + For example, we could use some Python code in + a &SConstruct; file to create a new <filename>version.c</filename> file + with a string containing the current date every time + we run &SCons;, + and then link a program with the resulting object file + by listing <filename>version.c</filename> in the sources: + + </para> + + <scons_example name="no-Requires"> + <file name="SConstruct" printme="1"> + import time + + version_c_text = """ + char *date = "%s"; + """ % time.ctime(time.time()) + open('version.c', 'w').write(version_c_text) + + hello = Program(['hello.c', 'version.c']) + </file> + <file name="hello.c"> + extern char *date; + int main() { printf("Hello, %s! I was built: %s\n", date); } + </file> + </scons_example> + + <para> + + If we list <filename>version.c</filename> as an actual source file, + though, then <filename>version.o</filename> + will get rebuilt every time we run &SCons; + (because the &SConstruct; file itself changes + the contents of <filename>version.c</filename>) + and the <filename>hello</filename> executable + will get re-linked every time + (because the <filename>version.o</filename> file changes): + + </para> + + <!-- + + <scons_output example="no-Requires"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + gcc -o hello.o -c hello.c + gcc -o version.o -c version.c + gcc -o hello hello.o version.o + % <userinput>scons -Q</userinput> + gcc -o version.o -c version.c + gcc -o hello hello.o version.o + % <userinput>scons -Q</userinput> + gcc -o version.o -c version.c + gcc -o hello hello.o version.o + </screen> + + <para> + + One solution is to use the &Requires; function + to specify that the <filename>version.o</filename> + must be rebuilt before it is used by the link step, + but that changes to <filename>version.o</filename> + should not actually cause the <filename>hello</filename> + executable to be re-linked: + + </para> + + <scons_example name="Requires"> + <file name="SConstruct" printme="1"> + import time + + version_c_text = """ + char *date = "%s"; + """ % time.ctime(time.time()) + open('version.c', 'w').write(version_c_text) + + version_obj = Object('version.c') + + hello = Program('hello.c', + LINKFLAGS = str(version_obj[0])) + + Requires(hello, version_obj) + </file> + <file name="hello.c"> + extern char *date; + int main() { printf("Hello, %s! I was built: %s\n", date); } + </file> + </scons_example> + + <para> + + Notice that because we can no longer list <filename>version.c</filename> + as one of the sources for the <filename>hello</filename> program, + we have to find some other way to get it into the link command line. + For this example, we're cheating a bit and stuffing the + object file name (extracted from <literal>version_obj</literal> + list returned by the &b-Object; call) + into the &cv-link-LINKFLAGS; variable, + because &cv-LINKFLAGS; is already included + in the &cv-link-LINKCOM; command line. + + </para> + + <para> + + With these changes, + we get the desired behavior of + re-building the <filename>version.o</filename> file, + and therefore re-linking the <filename>hello</filename> executable, + only when the <filename>hello.c</filename> has changed: + + </para> + + <scons_output example="Requires"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>The &AlwaysBuild; Function</title> + + <para> + + How &SCons; handles dependencies can also be affected + by the &AlwaysBuild; method. + When a file is passed to the &AlwaysBuild; method, + like so: + + </para> + + <scons_example name="AlwaysBuild"> + <file name="SConstruct" printme="1"> + hello = Program('hello.c') + AlwaysBuild(hello) + </file> + <file name="hello.c"> + int main() { printf("Hello, %s!\n", string); } + </file> + </scons_example> + + <para> + + Then the specified target file (&hello; in our example) + will always be considered out-of-date and + rebuilt whenever that target file is evaluated + while walking the dependency graph: + + </para> + + <scons_output example="AlwaysBuild"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + The &AlwaysBuild; function has a somewhat misleading name, + because it does not actually mean the target file will + be rebuilt every single time &SCons; is invoked. + Instead, it means that the target will, in fact, + be rebuilt whenever the target file is encountered + while evaluating the targets specified on + the command line (and their dependencies). + So specifying some other target on the command line, + a target that does <emphasis>not</emphasis> + itself depend on the &AlwaysBuild; target, + will still be rebuilt only if it's out-of-date + with respect to its dependencies: + + </para> + + <scons_output example="AlwaysBuild"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q hello.o</scons_output_command> + </scons_output> + + <!-- + + XXX AlwaysBuild() and Alias Nodes + + XXX AlwaysBuild() and Dir Nodes + + XXX AlwaysBuild() with no sources + + --> + + </section> + + <!-- + + <section> + <title>The &Salt; Method</title> + + <para> + + XXX Salt() (are we going to implement this ?) + + original Cons classic POD documentation: + +=head2 The C<Salt> method + +The C<Salt> method adds a constant value to the signature calculation +for every derived file. It is invoked as follows: + + Salt $string; + +Changing the Salt value will force a complete rebuild of every derived +file. This can be used to force rebuilds in certain desired +circumstances. For example, + + Salt `uname -s`; + +Would force a complete rebuild of every derived file whenever the +operating system on which the build is performed (as reported by C<uname +-s>) changes. + + </para> + + </section> + + --> diff --git a/doc/user/depends.xml b/doc/user/depends.xml new file mode 100644 index 0000000..b72f41f --- /dev/null +++ b/doc/user/depends.xml @@ -0,0 +1,1776 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + So far we've seen how &SCons; handles one-time builds. + But one of the main functions of a build tool like &SCons; + is to rebuild only what is necessary + when source files change--or, put another way, + &SCons; should <emphasis>not</emphasis> + waste time rebuilding things that don't need to be rebuilt. + You can see this at work simply by re-invoking &SCons; + after building our simple &hello; example: + + </para> + + + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + </screen> + + <para> + + The second time it is executed, + &SCons; realizes that the &hello; program + is up-to-date with respect to the current &hello_c; source file, + and avoids rebuilding it. + You can see this more clearly by naming + the &hello; program explicitly on the command line: + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + </screen> + + <para> + + Note that &SCons; reports <literal>"...is up to date"</literal> + only for target files named explicitly on the command line, + to avoid cluttering the output. + + </para> + + <section> + <title>Deciding When an Input File Has Changed: the &Decider; Function</title> + + <para> + + Another aspect of avoiding unnecessary rebuilds + is the fundamental build tool behavior + of <emphasis>rebuilding</emphasis> + things when an input file changes, + so that the built software is up to date. + By default, + &SCons; keeps track of this through an + MD5 &signature;, or checksum, of the contents of each file, + although you can easily configure + &SCons; to use the + modification times (or time stamps) + instead. + You can even specify your own Python function + for deciding if an input file has changed. + + </para> + + <section> + <title>Using MD5 Signatures to Decide if a File Has Changed</title> + + <para> + + By default, + &SCons; keeps track of whether a file has changed + based on an MD5 checksum of the file's contents, + not the file's modification time. + This means that you may be surprised by the + default &SCons; behavior if you are used to the + &Make; convention of forcing + a rebuild by updating the file's modification time + (using the &touch; command, for example): + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>touch hello.c</userinput> + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + </screen> + + <para> + + Even though the file's modification time has changed, + &SCons; realizes that the contents of the + &hello_c; file have <emphasis>not</emphasis> changed, + and therefore that the &hello; program + need not be rebuilt. + This avoids unnecessary rebuilds when, + for example, someone rewrites the + contents of a file without making a change. + But if the contents of the file really do change, + then &SCons; detects the change + and rebuilds the program as required: + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>edit hello.c</userinput> + [CHANGE THE CONTENTS OF hello.c] + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + Note that you can, if you wish, + specify this default behavior + (MD5 signatures) explicitly + using the &Decider; function as follows: + + </para> + + <programlisting> + Program('hello.c') + Decider('MD5') + </programlisting> + + <para> + + You can also use the string <literal>'content'</literal> + as a synonym for <literal>'MD5'</literal> + when calling the &Decider; function. + + </para> + + <section> + <title>Ramifications of Using MD5 Signatures</title> + + <para> + + Using MD5 signatures to decide if an input file has changed + has one surprising benefit: + if a source file has been changed + in such a way that the contents of the + rebuilt target file(s) + will be exactly the same as the last time + the file was built, + then any "downstream" target files + that depend on the rebuilt-but-not-changed target + file actually need not be rebuilt. + + </para> + + <para> + + So if, for example, + a user were to only change a comment in a &hello_c; file, + then the rebuilt &hello_o; file + would be exactly the same as the one previously built + (assuming the compiler doesn't put any build-specific + information in the object file). + &SCons; would then realize that it would not + need to rebuild the &hello; program as follows: + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>edit hello.c</userinput> + [CHANGE A COMMENT IN hello.c] + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + scons: `hello' is up to date. + </screen> + + <para> + + In essence, &SCons; + "short-circuits" any dependent builds + when it realizes that a target file + has been rebuilt to exactly the same file as the last build. + This does take some extra processing time + to read the contents of the target (&hello_o;) file, + but often saves time when the rebuild that was avoided + would have been time-consuming and expensive. + + </para> + + </section> + + </section> + + <section> + <title>Using Time Stamps to Decide If a File Has Changed</title> + + <para> + + If you prefer, you can + configure &SCons; to use the modification time + of a file, not the file contents, + when deciding if a target needs to be rebuilt. + &SCons; gives you two ways to use time stamps + to decide if an input file has changed + since the last time a target has been built. + + </para> + + <para> + + The most familiar way to use time stamps + is the way &Make; does: + that is, have &SCons; decide + that a target must be rebuilt + if a source file's modification time is + <emphasis>newer</emphasis> + than the target file. + To do this, call the &Decider; + function as follows: + + </para> + + <programlisting> + Program('hello.c') + Decider('timestamp-newer') + </programlisting> + + <para> + + This makes &SCons; act like &Make; + when a file's modification time is updated + (using the &touch; command, for example): + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>touch hello.c</userinput> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + And, in fact, because this behavior is the same + as the behavior of &Make;, + you can also use the string <literal>'make'</literal> + as a synonym for <literal>'timestamp-newer'</literal> + when calling the &Decider; function: + + </para> + + <programlisting> + Program('hello.c') + Decider('make') + </programlisting> + + <para> + + One drawback to using times stamps exactly like &Make; + is that if an input file's modification time suddenly + becomes <emphasis>older</emphasis> than a target file, + the target file will not be rebuilt. + This can happen if an old copy of a source file is restored + from a backup archive, for example. + The contents of the restored file will likely be different + than they were the last time a dependent target was built, + but the target won't be rebuilt + because the modification time of the source file + is not newer than the target. + + </para> + + <para> + + Because &SCons; actually stores information + about the source files' time stamps whenever a target is built, + it can handle this situation by checking for + an exact match of the source file time stamp, + instead of just whether or not the source file + is newer than the target file. + To do this, specify the argument + <literal>'timestamp-match'</literal> + when calling the &Decider; function: + + </para> + + <programlisting> + Program('hello.c') + Decider('timestamp-match') + </programlisting> + + <para> + + When configured this way, + &SCons; will rebuild a target whenever + a source file's modification time has changed. + So if we use the <literal>touch -t</literal> + option to change the modification time of + &hello_c; to an old date (January 1, 1989), + &SCons; will still rebuild the target file: + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>touch -t 198901010000 hello.c</userinput> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + In general, the only reason to prefer + <literal>timestamp-newer</literal> + instead of + <literal>timestamp-match</literal>, + would be if you have some specific reason + to require this &Make;-like behavior of + not rebuilding a target when an otherwise-modified + source file is older. + + </para> + + </section> + + <section> + <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title> + + <para> + + As a performance enhancement, + &SCons; provides a way to use + MD5 checksums of file contents + but to read those contents + only when the file's timestamp has changed. + To do this, call the &Decider; + function with <literal>'MD5-timestamp'</literal> + argument as follows: + + </para> + + <programlisting> + Program('hello.c') + Decider('MD5-timestamp') + </programlisting> + + <para> + + So configured, &SCons; will still behave like + it does when using <literal>Decider('MD5')</literal>: + + </para> + + <!-- + + We want to generate the output as follows, + but our "surrogate" system for generating the + output seems to get this wrong. + Just in-line the output for now. + + <scons_output example="MD5-timestamp" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>touch hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>touch hello.c</userinput> + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit hello.c</userinput> + [CHANGE THE CONTENTS OF hello.c] + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + However, the second call to &SCons; in the above output, + when the build is up-to-date, + will have been performed by simply looking at the + modification time of the &hello_c; file, + not by opening it and performing + an MD5 checksum calcuation on its contents. + This can significantly speed up many up-to-date builds. + + </para> + + <para> + + The only drawback to using + <literal>Decider('MD5-timestamp')</literal> + is that &SCons; will <emphasis>not</emphasis> + rebuild a target file if a source file was modified + within one second of the last time &SCons; built the file. + While most developers are programming, + this isn't a problem in practice, + since it's unlikely that someone will have built + and then thought quickly enough to make a substantive + change to a source file within one second. + Certain build scripts or + continuous integration tools may, however, + rely on the ability to apply changes to files + automatically and then rebuild as quickly as possible, + in which case use of + <literal>Decider('MD5-timestamp')</literal> + may not be appropriate. + + </para> + + </section> + + <section> + <title>Writing Your Own Custom &Decider; Function</title> + + <para> + + The different string values that we've passed to + the &Decider; function are essentially used by &SCons; + to pick one of several specific internal functions + that implement various ways of deciding if a dependency + (usually a source file) + has changed since a target file has been built. + As it turns out, + you can also supply your own function + to decide if a dependency has changed. + + </para> + + <para> + + For example, suppose we have an input file + that contains a lot of data, + in some specific regular format, + that is used to rebuild a lot of different target files, + but each target file really only depends on + one particular section of the input file. + We'd like to have each target file depend on + only its section of the input file. + However, since the input file may contain a lot of data, + we want to open the input file only if its timestamp has changed. + This could done with a custom + &Decider; function that might look something like this: + + </para> + + <programlisting> + Program('hello.c') + def decide_if_changed(dependency, target, prev_ni): + if self.get_timestamp() != prev_ni.timestamp: + dep = str(dependency) + tgt = str(target) + if specific_part_of_file_has_changed(dep, tgt): + return True + return False + Decider(decide_if_changed) + </programlisting> + + <para> + + Note that in the function definition, + the <varname>dependency</varname> + (input file) is the first argument, + and then the ⌖. + Both of these are passed to the functions as + SCons &Node; objects, + which we convert to strings using the Python + <function>str()</function>. + + </para> + + <para> + + The third argument, <varname>prev_ni</varname>, + is an object that holds the + signature or timestamp information + that was recorded about the dependency + the last time the target was built. + A <varname>prev_ni</varname> object can hold + different information, + depending on the type of thing that the + <varname>dependency</varname> argument represents. + For normal files, + the <varname>prev_ni</varname> object + has the following attributes: + + </para> + + <variablelist> + + <varlistentry> + <term>.csig</term> + + <listitem> + <para> + The <emphasis>content signature</emphasis>, + or MD5 checksum, of the contents of the + <varname>dependency</varname> + file the list time the ⌖ was built. + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>.size</term> + + <listitem> + <para> + The size in bytes of the <varname>dependency</varname> + file the list time the target was built. + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>.timestamp</term> + + <listitem> + <para> + The modification time of the <varname>dependency</varname> + file the list time the ⌖ was built. + </para> + </listitem> + + </varlistentry> + + </variablelist> + + <para> + + Note that ignoring some of the arguments + in your custom &Decider; function + is a perfectly normal thing to do, + if they don't impact the way you want to + decide if the dependency file has changed. + + </para> + + </section> + + <section> + <title>Mixing Different Ways of Deciding If a File Has Changed</title> + + <para> + + The previous examples have all demonstrated calling + the global &Decider; function + to configure all dependency decisions that &SCons; makes. + Sometimes, however, you want to be able to configure + different decision-making for different targets. + When that's necessary, you can use the + <function>env.Decider</function> + method to affect only the configuration + decisions for targets built with a + specific construction environment. + + </para> + + <para> + + For example, if we arbitrarily want to build + one program using MD5 checkums + and another using file modification times + from the same source + we might configure it this way: + + </para> + + <programlisting> + env1 = Environment(CPPPATH = ['.']) + env2 = env1.Clone() + env2.Decider('timestamp-match') + env1.Program('prog-MD5', 'program1.c') + env2.Program('prog-timestamp', 'program2.c') + </programlisting> + + <para> + + If both of the programs include the same + <filename>inc.h</filename> file, + then updating the modification time of + <filename>inc.h</filename> + (using the &touch; command) + will cause only <filename>prog-timestamp</filename> + to be rebuilt: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o program1.o -c -I. program1.c + cc -o prog-MD5 program1.o + cc -o program2.o -c -I. program2.c + cc -o prog-timestamp program2.o + % <userinput>touch inc.h</userinput> + % <userinput>scons -Q</userinput> + cc -o program2.o -c -I. program2.c + cc -o prog-timestamp program2.o + </screen> + + </section> + + </section> + + <section> + <title>Older Functions for Deciding When an Input File Has Changed</title> + + <para> + + &SCons; still supports two functions that used to be the + primary methods for configuring the + decision about whether or not an input file has changed. + Although they're not officially deprecated yet, + their use is discouraged, + mainly because they rely on a somewhat + confusing distinction between how + source files and target files are handled. + These functions are documented here mainly in case you + encounter them in existing &SConscript; files. + + </para> + + <section> + <title>The &SourceSignatures; Function</title> + + <para> + + The &SourceSignatures; function is fairly straightforward, + and supports two different argument values + to configure whether source file changes should be decided + using MD5 signatures: + + </para> + + <programlisting> + Program('hello.c') + SourceSignatures('MD5') + </programlisting> + + <para> + + Or using time stamps: + + </para> + + <programlisting> + Program('hello.c') + SourceSignatures('timestamp') + </programlisting> + + <para> + + These are roughly equivalent to specifying + <function>Decider('MD5')</function> + or + <function>Decider('timestamp-match')</function>, + respectively, + although it only affects how SCons makes + decisions about dependencies on + <emphasis>source</emphasis> files--that is, + files that are not built from any other files. + + </para> + + </section> + + <section> + <title>The &TargetSignatures; Function</title> + + <para> + + The &TargetSignatures; function + specifies how &SCons; decides + when a target file has changed + <emphasis>when it is used as a + dependency of (input to) another target</emphasis>--that is, + the &TargetSignatures; function configures + how the signatures of "intermediate" target files + are used when deciding if a "downstream" target file + must be rebuilt. + <footnote><para> + This easily-overlooked distinction between + how &SCons; decides if the target itself must be rebuilt + and how the target is then used to decide if a different + target must be rebuilt is one of the confusing + things that has led to the &TargetSignatures; + and &SourceSignatures; functions being + replaced by the simpler &Decider; function. + </para></footnote> + + </para> + + <para> + + The &TargetSignatures; function supports the same + <literal>'MD5'</literal> and <literal>'timestamp'</literal> + argument values that are supported by the &SourceSignatures;, + with the same meanings, but applied to target files. + That is, in the example: + + </para> + + <programlisting> + Program('hello.c') + TargetSignatures('MD5') + </programlisting> + + <para> + + The MD5 checksum of the &hello_o; target file + will be used to decide if it has changed since the last + time the "downstream" &hello; target file was built. + And in the example: + + </para> + + <programlisting> + Program('hello.c') + TargetSignatures('timestamp') + </programlisting> + + <para> + + The modification time of the &hello_o; target file + will be used to decide if it has changed since the last + time the "downstream" &hello; target file was built. + + </para> + + <para> + + The &TargetSignatures; function supports + two additional argument values: + <literal>'source'</literal> and <literal>'build'</literal>. + The <literal>'source'</literal> argument + specifies that decisions involving + whether target files have changed + since a previous build + should use the same behavior + for the decisions configured for source files + (using the &SourceSignatures; function). + So in the example: + + </para> + + <programlisting> + Program('hello.c') + TargetSignatures('source') + SourceSignatures('timestamp') + </programlisting> + + <para> + + All files, both targets and sources, + will use modification times + when deciding if an input file + has changed since the last + time a target was built. + + </para> + + <para> + + Lastly, the <literal>'build'</literal> argument + specifies that &SCons; should examine + the build status of a target file + and always rebuild a "downstream" target + if the target file was itself rebuilt, + without re-examining the contents or timestamp + of the newly-built target file. + If the target file was not rebuilt during + this &scons; invocation, + then the target file will be examined + the same way as configured by + the &SourceSignature; call + to decide if it has changed. + + </para> + + <para> + + This mimics the behavior of + <literal>build signatures</literal> + in earlier versions of &SCons;. + A &buildsignature; re-combined + signatures of all the input files + that went into making the target file, + so that the target file itself + did not need to have its contents read + to compute an MD5 signature. + This can improve performance for some configurations, + but is generally not as effective as using + <literal>Decider('MD5-timestamp')</literal>. + + </para> + + </section> + + </section> + + <section> + <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title> + + <para> + + Now suppose that our "Hello, World!" program + actually has an <literal>#include</literal> line + to include the &hello_h; file in the compilation: + + </para> + + <programlisting> + #include <hello.h> + int + main() + { + printf("Hello, %s!\n", string); + } + </programlisting> + + <para> + + And, for completeness, the &hello_h; file looks like this: + + </para> + + + <programlisting> + #define string "world" + </programlisting> + + <para> + + In this case, we want &SCons; to recognize that, + if the contents of the &hello_h; file change, + the &hello; program must be recompiled. + To do this, we need to modify the + &SConstruct; file like so: + + </para> + + + <programlisting> + Program('hello.c', CPPPATH = '.') + </programlisting> + + <para> + + The &cv-link-CPPPATH; value + tells &SCons; to look in the current directory + (<literal>'.'</literal>) + for any files included by C source files + (<filename>.c</filename> or <filename>.h</filename> files). + With this assignment in the &SConstruct; file: + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c -I. hello.c + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit hello.h</userinput> + [CHANGE THE CONTENTS OF hello.h] + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c -I. hello.c + cc -o hello hello.o + </screen> + + <para> + + First, notice that &SCons; + added the <literal>-I.</literal> argument + from the &cv-CPPPATH; variable + so that the compilation would find the + &hello_h; file in the local directory. + + </para> + + <para> + + Second, realize that &SCons; knows that the &hello; + program must be rebuilt + because it scans the contents of + the &hello_c; file + for the <literal>#include</literal> lines that indicate + another file is being included in the compilation. + &SCons; records these as + <emphasis>implicit dependencies</emphasis> + of the target file, + Consequently, + when the &hello_h; file changes, + &SCons; realizes that the &hello_c; file includes it, + and rebuilds the resulting &hello; program + that depends on both the &hello_c; and &hello_h; files. + + </para> + + <para> + + Like the &cv-link-LIBPATH; variable, + the &cv-CPPPATH; variable + may be a list of directories, + or a string separated by + the system-specific path separation character + (':' on POSIX/Linux, ';' on Windows). + Either way, &SCons; creates the + right command-line options + so that the following example: + + </para> + + <programlisting> + Program('hello.c', CPPPATH = ['include', '/home/project/inc']) + </programlisting> + + <para> + + Will look like this on POSIX or Linux: + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c -Iinclude -I/home/project/inc hello.c + cc -o hello hello.o + </screen> + + <para> + + And like this on Windows: + + </para> + + <screen> + C:\><userinput>scons -Q hello.exe</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fohello.obj /c hello.c /nologo /Iinclude /I\home\project\inc + link /nologo /OUT:hello.exe hello.obj + </screen> + + </section> + + <section> + <title>Caching Implicit Dependencies</title> + + <para> + + Scanning each file for <literal>#include</literal> lines + does take some extra processing time. + When you're doing a full build of a large system, + the scanning time is usually a very small percentage + of the overall time spent on the build. + You're most likely to notice the scanning time, + however, when you <emphasis>rebuild</emphasis> + all or part of a large system: + &SCons; will likely take some extra time to "think about" + what must be built before it issues the + first build command + (or decides that everything is up to date + and nothing must be rebuilt). + + <!-- + Isn't this expensive? The answer is, it depends. If you do a full build of a + large system, the scanning time is insignificant. If you do a rebuild of a + large system, then Cons will spend a fair amount of time thinking about it + before it decides that nothing has to be done (although not necessarily more + time than make!). The good news is that Cons makes it very easy to + intelligently subset your build, when you are working on localized changes. + --> + + </para> + + <para> + + In practice, having &SCons; scan files saves time + relative to the amount of potential time + lost to tracking down subtle problems + introduced by incorrect dependencies. + Nevertheless, the "waiting time" + while &SCons; scans files can annoy + individual developers waiting for their builds to finish. + Consequently, &SCons; lets you cache + the implicit dependencies + that its scanners find, + for use by later builds. + You can do this by specifying the + &implicit-cache; option on the command line: + + </para> + + <screen> + % <userinput>scons -Q --implicit-cache hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + </screen> + + <para> + + If you don't want to specify &implicit-cache; + on the command line each time, + you can make it the default behavior for your build + by setting the &implicit_cache; option + in an &SConscript; file: + + </para> + + <programlisting> + SetOption('implicit_cache', 1) + </programlisting> + + <para> + + &SCons; does not cache implicit dependencies like this by default + because the &implicit-cache; causes &SCons; to simply use the implicit + dependencies stored during the last run, without any checking + for whether or not those dependencies are still correct. + Specifically, this means &implicit-cache; instructs &SCons; + to <emphasis>not</emphasis> rebuild "correctly" in the + following cases: + + + </para> + + <itemizedlist> + + <listitem> + <para> + + When &implicit-cache; is used, &SCons; will ignore any changes that + may have been made to search paths + (like &cv-CPPPATH; or &cv-LIBPATH;,). + This can lead to &SCons; not rebuilding a file if a change to + &cv-CPPPATH; would normally cause a different, same-named file from + a different directory to be used. + + </para> + </listitem> + + <listitem> + <para> + + When &implicit-cache; is used, &SCons; will not detect if a + same-named file has been added to a directory that is earlier in + the search path than the directory in which the file was found + last time. + + </para> + </listitem> + + </itemizedlist> + + <section> + <title>The &implicit-deps-changed; Option</title> + + <para> + + When using cached implicit dependencies, + sometimes you want to "start fresh" + and have &SCons; re-scan the files + for which it previously cached the dependencies. + For example, + if you have recently installed a new version of + external code that you use for compilation, + the external header files will have changed + and the previously-cached implicit dependencies + will be out of date. + You can update them by + running &SCons; with the &implicit-deps-changed; option: + + </para> + + <screen> + % <userinput>scons -Q --implicit-deps-changed hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + </screen> + + <para> + + In this case, &SCons; will re-scan all of the implicit dependencies + and cache updated copies of the information. + + </para> + + </section> + + <section> + <title>The &implicit-deps-unchanged; Option</title> + + <para> + + By default when caching dependencies, + &SCons; notices when a file has been modified + and re-scans the file for any updated + implicit dependency information. + Sometimes, however, you may want + to force &SCons; to use the cached implicit dependencies, + even if the source files changed. + This can speed up a build for example, + when you have changed your source files + but know that you haven't changed + any <literal>#include</literal> lines. + In this case, + you can use the &implicit-deps-unchanged; option: + + </para> + + <screen> + % <userinput>scons -Q --implicit-deps-unchanged hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + </screen> + + <para> + + In this case, + &SCons; will assume that the cached implicit + dependencies are correct and + will not bother to re-scan changed files. + For typical builds after small, + incremental changes to source files, + the savings may not be very big, + but sometimes every bit of + improved performance counts. + + </para> + + </section> + + <!-- + + <section> + <title>XXX max drift</title> + + XXX SetOption('max_drift') + + </section> + + --> + + </section> + + <section> + <title>Explicit Dependencies: the &Depends; Function</title> + + <para> + + Sometimes a file depends on another file + that is not detected by an &SCons; scanner. + For this situation, + &SCons; allows you to specific explicitly that one file + depends on another file, + and must be rebuilt whenever that file changes. + This is specified using the &Depends; method: + + </para> + + <programlisting> + hello = Program('hello.c') + Depends(hello, 'other_file') + </programlisting> + + <!-- XXX mention that you can use arrays for target and source? --> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit other_file</userinput> + [CHANGE THE CONTENTS OF other_file] + % <userinput>scons -Q hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + </screen> + + <para> + + Note that the dependency + (the second argument to &Depends;) + may also be a list of Node objects + (for example, as returned by a call to a Builder): + + </para> + + <programlisting> + hello = Program('hello.c') + goodbye = Program('goodbye.c') + Depends(hello, goodbye) + </programlisting> + + <para> + + in which case the dependency or dependencies + will be built before the target(s): + + </para> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -c goodbye.c -o goodbye.o + cc -o goodbye goodbye.o + cc -c hello.c -o hello.o + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Dependencies From External Files: the &ParseDepends; + Function</title> + + <para> + + &SCons; has built-in scanners for a number of languages. Sometimes + these scanners fail to extract certain implicit dependencies due + to limitations of the scanner implementation. + + </para> + + <para> + + The following example illustrates a case where the built-in C + scanner is unable to extract the implicit dependency on a header + file. + + </para> + + <programlisting> + #define FOO_HEADER <foo.h> + #include FOO_HEADER + + int main() { + return FOO; + } + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -I. hello.c + cc -o hello hello.o + % <userinput>edit foo.h</userinput> + [CHANGE CONTENTS OF foo.h] + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + </screen> + + <para> + + Apparently, the scanner does not know about the header dependency. + Being not a full-fledged C preprocessor, the scanner does not + expand the macro. + + </para> + + <para> + + In these cases, you may also use the compiler to extract the + implicit dependencies. &ParseDepends; can parse the contents of + the compiler output in the style of &Make;, and explicitly + establish all of the listed dependencies. + + </para> + + <para> + + The following example uses &ParseDepends; to process a compiler + generated dependency file which is generated as a side effect + during compilation of the object file: + + </para> + + <!-- XXX The ParseDepends example below fakes proper working by a + priori specification of the dependency file. The produced hello.d + file is not found (or used) for unknown reasons. --> + + <programlisting> + obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') + SideEffect('hello.d', obj) + ParseDepends('hello.d') + Program('hello', obj) + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -MD -MF hello.d -I. hello.c + cc -o hello hello.o + % <userinput>edit foo.h</userinput> + [CHANGE CONTENTS OF foo.h] + % <userinput>scons -Q</userinput> + cc -o hello.o -c -MD -MF hello.d -I. hello.c + </screen> + + <para> + + Parsing dependencies from a compiler-generated + <filename>.d</filename> file has a chicken-and-egg problem, that + causes unnecessary rebuilds: + + </para> + + + + <!-- + <scons_output example="parsedeprebuild" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + --> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -MD -MF hello.d -I. hello.c + cc -o hello hello.o + % <userinput>scons -Q --debug=explain</userinput> + scons: rebuilding `hello.o' because `foo.h' is a new dependency + cc -o hello.o -c -MD -MF hello.d -I. hello.c + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + </screen> + + <para> + + In the first pass, the dependency file is generated while the + object file is compiled. At that time, &SCons; does not know about + the dependency on <filename>foo.h</filename>. In the second pass, + the object file is regenerated because <filename>foo.h</filename> + is detected as a new dependency. + + </para> + + <para> + + &ParseDepends; immediately reads the specified file at invocation + time and just returns if the file does not exist. A dependency + file generated during the build process is not automatically + parsed again. Hence, the compiler-extracted dependencies are not + stored in the signature database during the same build pass. This + limitation of &ParseDepends; leads to unnecessary recompilations. + Therefore, &ParseDepends; should only be used if scanners are not + available for the employed language or not powerful enough for the + specific task. + + </para> + + </section> + + <section> + <title>Ignoring Dependencies: the &Ignore; Function</title> + + <para> + + Sometimes it makes sense + to not rebuild a program, + even if a dependency file changes. + In this case, + you would tell &SCons; specifically + to ignore a dependency as follows: + + </para> + + <programlisting> + hello = Program('hello.c') + Ignore(hello, 'hello.h') + </programlisting> + + <!-- XXX mention that you can use lists for target and source? --> + + <!-- + <scons_output example="ignore"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX + </scons_output> + --> + + <screen> + % <userinput>scons -Q hello</userinput> + cc -c -o hello.o hello.c + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + % <userinput>edit hello.h</userinput> + [CHANGE THE CONTENTS OF hello.h] + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + </screen> + + <para> + + Now, the above example is a little contrived, + because it's hard to imagine a real-world situation + where you wouldn't want to rebuild &hello; + if the &hello_h; file changed. + A more realistic example + might be if the &hello; + program is being built in a + directory that is shared between multiple systems + that have different copies of the + &stdio_h; include file. + In that case, + &SCons; would notice the differences between + the different systems' copies of &stdio_h; + and would rebuild &hello; + each time you change systems. + You could avoid these rebuilds as follows: + + </para> + + <programlisting> + hello = Program('hello.c', CPPPATH=['/usr/include']) + Ignore(hello, '/usr/include/stdio.h') + </programlisting> + + <para> + &Ignore; can also be used to prevent a generated file from being built + by default. This is due to the fact that directories depend on + their contents. So to ignore a generated file from the default build, + you specify that the directory should ignore the generated file. + Note that the file will still be built if the user specifically + requests the target on scons command line, or if the file is + a dependency of another file which is requested and/or is built + by default. + </para> + + <programlisting> + hello_obj=Object('hello.c') + hello = Program(hello_obj) + Ignore('.',[hello,hello_obj]) + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + % <userinput>scons -Q hello</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q hello</userinput> + scons: `hello' is up to date. + </screen> + </section> + + <section> + <title>Order-Only Dependencies: the &Requires; Function</title> + + <para> + + Occasionally, + it may be useful to specify that a certain + file or directory must, if necessary, + be built or created before some other target is built, + but that changes to that file or directory + do <emphasis>not</emphasis> + require that the target itself be rebuilt. + Such a relationship is called an + <emphasis>order-only dependency</emphasis> + because it only affects the order in which + things must be built--the dependency before the target--but + it is not a strict dependency relationship + because the target should not + change in response to changes in the dependent file. + + </para> + + <para> + + For example, suppose that you want to create a file + every time you run a build + that identifies the time the build was performed, + the version number, etc., + and which is included in every program that you build. + The version file's contents will change every build. + If you specify a normal dependency relationship, + then every program that depends on + that file would be rebuilt every time you ran &SCons;. + For example, we could use some Python code in + a &SConstruct; file to create a new <filename>version.c</filename> file + with a string containing the current date every time + we run &SCons;, + and then link a program with the resulting object file + by listing <filename>version.c</filename> in the sources: + + </para> + + <programlisting> + import time + + version_c_text = """ + char *date = "%s"; + """ % time.ctime(time.time()) + open('version.c', 'w').write(version_c_text) + + hello = Program(['hello.c', 'version.c']) + </programlisting> + + <para> + + If we list <filename>version.c</filename> as an actual source file, + though, then <filename>version.o</filename> + will get rebuilt every time we run &SCons; + (because the &SConstruct; file itself changes + the contents of <filename>version.c</filename>) + and the <filename>hello</filename> executable + will get re-linked every time + (because the <filename>version.o</filename> file changes): + + </para> + + <!-- + + <scons_output example="no-Requires"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + gcc -o hello.o -c hello.c + gcc -o version.o -c version.c + gcc -o hello hello.o version.o + % <userinput>scons -Q</userinput> + gcc -o version.o -c version.c + gcc -o hello hello.o version.o + % <userinput>scons -Q</userinput> + gcc -o version.o -c version.c + gcc -o hello hello.o version.o + </screen> + + <para> + + One solution is to use the &Requires; function + to specify that the <filename>version.o</filename> + must be rebuilt before it is used by the link step, + but that changes to <filename>version.o</filename> + should not actually cause the <filename>hello</filename> + executable to be re-linked: + + </para> + + <programlisting> + import time + + version_c_text = """ + char *date = "%s"; + """ % time.ctime(time.time()) + open('version.c', 'w').write(version_c_text) + + version_obj = Object('version.c') + + hello = Program('hello.c', + LINKFLAGS = str(version_obj[0])) + + Requires(hello, version_obj) + </programlisting> + + <para> + + Notice that because we can no longer list <filename>version.c</filename> + as one of the sources for the <filename>hello</filename> program, + we have to find some other way to get it into the link command line. + For this example, we're cheating a bit and stuffing the + object file name (extracted from <literal>version_obj</literal> + list returned by the &b-Object; call) + into the &cv-link-LINKFLAGS; variable, + because &cv-LINKFLAGS; is already included + in the &cv-link-LINKCOM; command line. + + </para> + + <para> + + With these changes, + we get the desired behavior of + re-building the <filename>version.o</filename> file, + and therefore re-linking the <filename>hello</filename> executable, + only when the <filename>hello.c</filename> has changed: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o version.o -c version.c + cc -o hello.o -c hello.c + cc -o hello version.o hello.o + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + % <userinput>edit hello.c</userinput> + [CHANGE THE CONTENTS OF hello.c] + % <userinput>scons -Q</userinput> + cc -o version.o -c version.c + cc -o hello.o -c hello.c + cc -o hello version.o hello.o + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + </screen> + + </section> + + <section> + <title>The &AlwaysBuild; Function</title> + + <para> + + How &SCons; handles dependencies can also be affected + by the &AlwaysBuild; method. + When a file is passed to the &AlwaysBuild; method, + like so: + + </para> + + <programlisting> + hello = Program('hello.c') + AlwaysBuild(hello) + </programlisting> + + <para> + + Then the specified target file (&hello; in our example) + will always be considered out-of-date and + rebuilt whenever that target file is evaluated + while walking the dependency graph: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q</userinput> + cc -o hello hello.o + </screen> + + <para> + + The &AlwaysBuild; function has a somewhat misleading name, + because it does not actually mean the target file will + be rebuilt every single time &SCons; is invoked. + Instead, it means that the target will, in fact, + be rebuilt whenever the target file is encountered + while evaluating the targets specified on + the command line (and their dependencies). + So specifying some other target on the command line, + a target that does <emphasis>not</emphasis> + itself depend on the &AlwaysBuild; target, + will still be rebuilt only if it's out-of-date + with respect to its dependencies: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q hello.o</userinput> + scons: `hello.o' is up to date. + </screen> + + <!-- + + XXX AlwaysBuild() and Alias Nodes + + XXX AlwaysBuild() and Dir Nodes + + XXX AlwaysBuild() with no sources + + --> + + </section> + + <!-- + + <section> + <title>The &Salt; Method</title> + + <para> + + XXX Salt() (are we going to implement this ?) + + original Cons classic POD documentation: + +=head2 The C<Salt> method + +The C<Salt> method adds a constant value to the signature calculation +for every derived file. It is invoked as follows: + + Salt $string; + +Changing the Salt value will force a complete rebuild of every derived +file. This can be used to force rebuilds in certain desired +circumstances. For example, + + Salt `uname -s`; + +Would force a complete rebuild of every derived file whenever the +operating system on which the build is performed (as reported by C<uname +-s>) changes. + + </para> + + </section> + + --> diff --git a/doc/user/environments.in b/doc/user/environments.in new file mode 100644 index 0000000..124aaaa --- /dev/null +++ b/doc/user/environments.in @@ -0,0 +1,1678 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 More on construction environments + +As previously mentioned, a B<construction environment> is an object that +has a set of keyword/value pairs and a set of methods, and which is used +to tell Cons how target files should be built. This section describes +how Cons uses and expands construction environment values to control its +build behavior. + +=head2 Construction variable expansion + +Construction variables from a construction environment are expanded +by preceding the keyword with a C<%> (percent sign): + + Construction variables: + XYZZY => 'abracadabra', + + The string: "The magic word is: %XYZZY!" + expands to: "The magic word is: abracadabra!" + +A construction variable name may be surrounded by C<{> and C<}> (curly +braces), which are stripped as part of the expansion. This can +sometimes be necessary to separate a variable expansion from trailing +alphanumeric characters: + + Construction variables: + OPT => 'value1', + OPTION => 'value2', + + The string: "%OPT %{OPT}ION %OPTION %{OPTION}" + expands to: "value1 value1ION value2 value2" + +Construction variable expansion is recursive, that is, a string +containing C<%->expansions after substitution will be re-expanded until +no further substitutions can be made: + + Construction variables: + STRING => 'The result is: %FOO', + FOO => '%BAR', + BAR => 'final value', + + The string: "The string says: %STRING" + expands to: "The string says: The result is: final value" + +If a construction variable is not defined in an environment, then the +null string is substituted: + + Construction variables: + FOO => 'value1', + BAR => 'value2', + + The string: "%FOO <%NO_VARIABLE> %BAR" + expands to: "value1 <> value2" + +A doubled C<%%> will be replaced by a single C<%>: + + The string: "Here is a percent sign: %%" + expands to: "Here is a percent sign: %" + +=head2 Default construction variables + +When you specify no arguments when creating a new construction +environment: + + $env = new cons(); + +Cons creates a reference to a new, default construction +environment. This contains a number of construction variables and some +methods. At the present writing, the default construction variables on a +UNIX system are: + + CC => 'cc', + CFLAGS => '', + CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>', + CXX => '%CC', + CXXFLAGS => '%CFLAGS', + CXXCOM => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>', + INCDIRPREFIX => '-I', + INCDIRSUFFIX => '', + LINK => '%CXX', + LINKCOM => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS', + LINKMODULECOM => '%LD -r -o %> %<', + LIBDIRPREFIX => '-L', + LIBDIRSUFFIX => '', + AR => 'ar', + ARFLAGS => 'r', + ARCOM => ['%AR %ARFLAGS %> %<', '%RANLIB %>'], + RANLIB => 'ranlib', + AS => 'as', + ASFLAGS => '', + ASCOM => '%AS %ASFLAGS %< -o %>', + LD => 'ld', + LDFLAGS => '', + PREFLIB => 'lib', + SUFLIB => '.a', + SUFLIBS => '.so:.a', + SUFOBJ => '.o', + SIGNATURE => [ '*' => 'build' ], + ENV => { 'PATH' => '/bin:/usr/bin' }, + + +And on a Windows system (Windows NT), the default construction variables +are (unless the default rule style is set using the B<DefaultRules> +method): + + CC => 'cl', + CFLAGS => '/nologo', + CCCOM => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>', + CXXCOM => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>', + INCDIRPREFIX => '/I', + INCDIRSUFFIX => '', + LINK => 'link', + LINKCOM => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS', + LINKMODULECOM => '%LD /r /o %> %<', + LIBDIRPREFIX => '/LIBPATH:', + LIBDIRSUFFIX => '', + AR => 'lib', + ARFLAGS => '/nologo ', + ARCOM => "%AR %ARFLAGS /out:%> %<", + RANLIB => '', + LD => 'link', + LDFLAGS => '/nologo ', + PREFLIB => '', + SUFEXE => '.exe', + SUFLIB => '.lib', + SUFLIBS => '.dll:.lib', + SUFOBJ => '.obj', + SIGNATURE => [ '*' => 'build' ], + +These variables are used by the various methods associated with the +environment. In particular, any method that ultimately invokes an external +command will substitute these variables into the final command, as +appropriate. For example, the C<Objects> method takes a number of source +files and arranges to derive, if necessary, the corresponding object +files: + + Objects $env 'foo.c', 'bar.c'; + +This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The +command invoked is simply C<%CCCOM>, which expands, through substitution, +to the appropriate external command required to build each object. The +substitution rules will be discussed in detail in the next section. + +The construction variables are also used for other purposes. For example, +C<CPPPATH> is used to specify a colon-separated path of include +directories. These are intended to be passed to the C preprocessor and are +also used by the C-file scanning machinery to determine the dependencies +involved in a C Compilation. + +Variables beginning with underscore are created by various methods, +and should normally be considered ``internal'' variables. For example, +when a method is called which calls for the creation of an object from +a C source, the variable C<_IFLAGS> is created: this corresponds to the +C<-I> switches required by the C compiler to represent the directories +specified by C<CPPPATH>. + +Note that, for any particular environment, the value of a variable is set +once, and then never reset (to change a variable, you must create a new +environment. Methods are provided for copying existing environments for this +purpose). Some internal variables, such as C<_IFLAGS> are created on demand, +but once set, they remain fixed for the life of the environment. + +The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place +for passing options to the compiler, loader, and archiver, respectively. + +The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option +strings to be appended to the beginning and end, respectively, of each +include directory so that the compiler knows where to find F<.h> files. +Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the +option string to be appended to the beginning of and end, respectively, +of each directory that the linker should search for libraries. + +Another variable, C<ENV>, is used to determine the system environment during +the execution of an external command. By default, the only environment +variable that is set is C<PATH>, which is the execution path for a UNIX +command. For the utmost reproducibility, you should really arrange to set +your own execution path, in your top-level F<Construct> file (or perhaps by +importing an appropriate construction package with the Perl C<use> +command). The default variables are intended to get you off the ground. + +=head2 Expanding variables in construction commands + +Within a construction command, construction variables will be expanded +according to the rules described above. In addition to normal variable +expansion from the construction environment, construction commands also +expand the following pseudo-variables to insert the specific input and +output files in the command line that will be executed: + +=over 10 + +=item %> + +The target file name. In a multi-target command, this expands to the +first target mentioned.) + +=item %0 + +Same as C<%E<gt>>. + +=item %1, %2, ..., %9 + +These refer to the first through ninth input file, respectively. + +=item %E<lt> + +The full set of input file names. If any of these have been used +anywhere else in the current command line (via C<%1>, C<%2>, etc.), then +those will be deleted from the list provided by C<%E<lt>>. Consider the +following command found in a F<Conscript> file in the F<test> directory: + + Command $env 'tgt', qw(foo bar baz), qq( + echo %< -i %1 > %> + echo %< -i %2 >> %> + echo %< -i %3 >> %> + ); + +If F<tgt> needed to be updated, then this would result in the execution of +the following commands, assuming that no remapping has been established for +the F<test> directory: + + echo test/bar test/baz -i test/foo > test/tgt + echo test/foo test/baz -i test/bar >> test/tgt + echo test/foo test/bar -i test/baz >> test/tgt + +=back + +Any of the above pseudo-variables may be followed immediately by one of +the following suffixes to select a portion of the expanded path name: + + :a the absolute path to the file name + :b the directory plus the file name stripped of any suffix + :d the directory + :f the file name + :s the file name suffix + :F the file name stripped of any suffix + :S the absolute path path to a Linked source file + +Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>, +and C<%E<gt>:d> would expand to C<test>. + +There are additional C<%> elements which affect the command line(s): + +=over 10 + +=item %[ %] + +It is possible to programmatically rewrite part of the command by +enclosing part of it between C<%[> and C<%]>. This will call the +construction variable named as the first word enclosed in the brackets +as a Perl code reference; the results of this call will be used to +replace the contents of the brackets in the command line. For example, +given an existing input file named F<tgt.in>: + + @keywords = qw(foo bar baz); + $env = new cons(X_COMMA => sub { join(",", @_) }); + Command $env 'tgt', 'tgt.in', qq( + echo '# Keywords: %[X_COMMA @keywords %]' > %> + cat %< >> %> + ); + +This will execute: + + echo '# Keywords: foo,bar,baz' > tgt + cat tgt.in >> tgt + +=item %( %) + +Cons includes the text of the command line in the MD5 signature for a +build, so that targets get rebuilt if you change the command line (to +add or remove an option, for example). Command-line text in between +C<%(> and C<%)>, however, will be ignored for MD5 signature calculation. + +Internally, Cons uses C<%(> and C<%)> around include and library +directory options (C<-I> and C<-L> on UNIX systems, C</I> and +C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory +list changes. Rebuilds occur only if the changed directory list causes +any included I<files> to change, and a changed include file is detected +by the MD5 signature calculation on the actual file contents. + +=back + +XXX DESCRIBE THE Literal() FUNCTION, TOO XXX + +=head2 Expanding construction variables in file names + +Cons expands construction variables in the source and target file names +passed to the various construction methods according to the expansion +rules described above: + + $env = new cons( + DESTDIR => 'programs', + SRCDIR => 'src', + ); + Program $env '%DESTDIR/hello', '%SRCDIR/hello.c'; + +This allows for flexible configuration, through the construction +environment, of directory names, suffixes, etc. + +--> + + <para> + + An <literal>environment</literal> + is a collection of values that + can affect how a program executes. + &SCons; distinguishes between three + different types of environments + that can affect the behavior of &SCons; itself + (subject to the configuration in the &SConscript; files), + as well as the compilers and other tools it executes: + + </para> + + <variablelist> + + <varlistentry> + <term>External Environment</term> + + <listitem> + <para> + + The <literal>external environment</literal> + is the set of variables in the user's environment + at the time the user runs &SCons. + These variables are available within the &SConscript; files + through the Python <literal>os.environ</literal> dictionary. + See <xref linkend="sect-external-environments"></xref>, below. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>&ConsEnv;</term> + + <listitem> + <para> + + A &consenv; + is a distinct object creating within + a &SConscript; file and + and which contains values that + affect how &SCons; decides + what action to use to build a target, + and even to define which targets + should be built from which sources. + One of the most powerful features of &SCons; + is the ability to create multiple &consenvs;, + including the ability to clone a new, customized + &consenv; from an existing &consenv;. + See <xref linkend="sect-construction-environments"></xref>, below. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Execution Environment</term> + + <listitem> + <para> + + An <literal>execution environment</literal> + is the values that &SCons; sets + when executing an external + command (such as a compiler or linker) + to build one or more targets. + Note that this is not the same as + the <literal>external environment</literal> + (see above). + See <xref linkend="sect-execution-environments"></xref>, below. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + Unlike &Make;, &SCons; does not automatically + copy or import values between different environments + (with the exception of explicit clones of &consenvs, + which inherit values from their parent). + This is a deliberate design choice + to make sure that builds are, + by default, repeatable regardless of + the values in the user's external environment. + This avoids a whole class of problems with builds + where a developer's local build works + because a custom variable setting + causes a different compiler or build option to be used, + but the checked-in change breaks the official build + because it uses different environment variable settings. + + </para> + + <para> + + Note that the &SConscript; writer can + easily arrange for variables to be + copied or imported between environments, + and this is often very useful + (or even downright necessary) + to make it easy for developers + to customize the build in appropriate ways. + The point is <emphasis>not</emphasis> + that copying variables between different environments + is evil and must always be avoided. + Instead, it should be up to the + implementer of the build system + to make conscious choices + about how and when to import + a variable from one environment to another, + making informed decisions about + striking the right balance + between making the build + repeatable on the one hand + and convenient to use on the other. + + </para> + + <section id="sect-external-environments"> + <title>Using Values From the External Environment</title> + + <para> + + The <literal>external environment</literal> + variable settings that + the user has in force + when executing &SCons; + are available through the normal Python + <envar>os.environ</envar> + dictionary. + This means that you must add an + <literal>import os</literal> statement + to any &SConscript; file + in which you want to use + values from the user's external environment. + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + import os + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + More usefully, you can use the + <envar>os.environ</envar> + dictionary in your &SConscript; + files to initialize &consenvs; + with values from the user's external environment. + See the next section, + <xref linkend="sect-construction-environments"></xref>, + for information on how to do this. + + </para> + + </section> + + <section id="sect-construction-environments"> + <title>Construction Environments</title> + + <para> + + It is rare that all of the software in a large, + complicated system needs to be built the same way. + For example, different source files may need different options + enabled on the command line, + or different executable programs need to be linked + with different libraries. + &SCons; accommodates these different build + requirements by allowing you to create and + configure multiple &consenvs; + that control how the software is built. + A &consenv; is an object + that has a number of associated + &consvars;, each with a name and a value. + (A construction environment also has an attached + set of &Builder; methods, + about which we'll learn more later.) + + </para> + + <section> + <title>Creating a &ConsEnv;: the &Environment; Function</title> + + <para> + + A &consenv; is created by the &Environment; method: + + </para> + + <sconstruct> + env = Environment() + </sconstruct> + + <para> + + By default, &SCons; initializes every + new construction environment + with a set of &consvars; + based on the tools that it finds on your system, + plus the default set of builder methods + necessary for using those tools. + The construction variables + are initialized with values describing + the C compiler, + the Fortran compiler, + the linker, + etc., + as well as the command lines to invoke them. + + </para> + + <para> + + When you initialize a construction environment + you can set the values of the + environment's &consvars; + to control how a program is built. + For example: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment(CC = 'gcc', + CCFLAGS = '-O2') + + env.Program('foo.c') + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + The construction environment in this example + is still initialized with the same default + construction variable values, + except that the user has explicitly specified use of the + GNU C compiler &gcc;, + and further specifies that the <literal>-O2</literal> + (optimization level two) + flag should be used when compiling the object file. + In other words, the explicit initializations of + &cv-link-CC; and &cv-link-CCFLAGS; + override the default values in the newly-created + construction environment. + So a run from this example would look like: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Fetching Values From a &ConsEnv;</title> + + <para> + + You can fetch individual construction variables + using the normal syntax + for accessing individual named items in a Python dictionary: + + </para> + + <scons_example name="ex6"> + <file name="SConstruct" printme="1"> + env = Environment() + print "CC is:", env['CC'] + </file> + </scons_example> + + <para> + + This example &SConstruct; file doesn't build anything, + but because it's actually a Python script, + it will print the value of &cv-link-CC; for us: + + </para> + + <scons_output example="ex6"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + A construction environment, however, + is actually an object with associated methods, etc. + If you want to have direct access to only the + dictionary of construction variables, + you can fetch this using the &Dictionary; method: + + </para> + + <scons_example name="ex6b"> + <file name="SConstruct" printme="1"> + env = Environment(FOO = 'foo', BAR = 'bar') + dict = env.Dictionary() + for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']: + print "key = %s, value = %s" % (key, dict[key]) + </file> + </scons_Example> + + <para> + + This &SConstruct; file + will print the specified dictionary items for us on POSIX + systems as follows: + + </para> + + <scons_output example="ex6b" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And on Windows: + + </para> + + <scons_output example="ex6b" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + If you want to loop and print the values of + all of the construction variables in a construction environment, + the Python code to do that in sorted order might look something like: + + </para> + + <sconstruct> + env = Environment() + dict = env.Dictionary() + keys = dict.keys() + keys.sort() + for key in keys: + print "construction variable = '%s', value = '%s'" % (key, dict[key]) + </sconstruct> + + </section> + + <section> + <title>Expanding Values From a &ConsEnv;: the &subst; Method</title> + + <para> + + Another way to get information from + a construction environment. + is to use the &subst; method + on a string containing <literal>$</literal> expansions + of construction variable names. + As a simple example, + the example from the previous + section that used + <literal>env['CC']</literal> + to fetch the value of &cv-link-CC; + could also be written as: + + </para> + + <sconstruct> + env = Environment() + print "CC is:", env.subst('$CC') + </sconstruct> + + <para> + + One advantage of using + &subst; to expand strings is + that construction variables + in the result get re-expanded until + there are no expansions left in the string. + So a simple fetch of a value like + &cv-link-CCCOM;: + + </para> + + <sconstruct> + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env['CCCOM'] + </sconstruct> + + <para> + + Will print the unexpanded value of &cv-CCCOM;, + showing us the construction + variables that still need to be expanded: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES + scons: `.' is up to date. + </screen> + + <para> + + Calling the &subst; method on <varname>$CCOM</varname>, + however: + + </para> + + <sconstruct> + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env.subst('$CCCOM') + </sconstruct> + + <para> + + Will recursively expand all of + the construction variables prefixed + with <literal>$</literal> (dollar signs), + showing us the final output: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CCCOM is: gcc -DFOO -c -o + scons: `.' is up to date. + </screen> + + <para> + + Note that because we're not expanding this + in the context of building something + there are no target or source files + for &cv-link-TARGET; and &cv-link-SOURCES; to expand. + + </para> + + </section> + + <section> + <title>Controlling the Default &ConsEnv;: the &DefaultEnvironment; Function</title> + + <para> + + All of the &Builder; functions that we've introduced so far, + like &Program; and &Library;, + actually use a default &consenv; + that contains settings + for the various compilers + and other tools that + &SCons; configures by default, + or otherwise knows about + and has discovered on your system. + The goal of the default construction environment + is to make many configurations to "just work" + to build software using + readily available tools + with a minimum of configuration changes. + + </para> + + <para> + + You can, however, control the settings + in the default contstruction environment + by using the &DefaultEnvironment; function + to initialize various settings: + + </para> + + <sconstruct> + + DefaultEnvironment(CC = '/usr/local/bin/gcc') + + </sconstruct> + + <para> + + When configured as above, + all calls to the &Program; + or &Object; Builder + will build object files with the + <filename>/usr/local/bin/gcc</filename> + compiler. + + </para> + + <para> + + Note that the &DefaultEnvironment; function + returns the initialized + default construction environment object, + which can then be manipulated like any + other construction environment. + So the following + would be equivalent to the + previous example, + setting the &cv-CC; + variable to <filename>/usr/local/bin/gcc</filename> + but as a separate step after + the default construction environment has been initialized: + + </para> + + <sconstruct> + + env = DefaultEnvironment() + env['CC'] = '/usr/local/bin/gcc' + + </sconstruct> + + <para> + + One very common use of the &DefaultEnvironment; function + is to speed up &SCons; initialization. + As part of trying to make most default + configurations "just work," + &SCons; will actually + search the local system for installed + compilers and other utilities. + This search can take time, + especially on systems with + slow or networked file systems. + If you know which compiler(s) and/or + other utilities you want to configure, + you can control the search + that &SCons; performs + by specifying some specific + tool modules with which to + initialize the default construction environment: + + </para> + + <sconstruct> + + env = DefaultEnvironment(tools = ['gcc', 'gnulink'], + CC = '/usr/local/bin/gcc') + + </sconstruct> + + <para> + + So the above example would tell &SCons; + to explicitly configure the default environment + to use its normal GNU Compiler and GNU Linker settings + (without having to search for them, + or any other utilities for that matter), + and specifically to use the compiler found at + <filename>/usr/local/bin/gcc</filename>. + + </para> + + </section> + + <section> + <title>Multiple &ConsEnvs;</title> + + <para> + + The real advantage of construction environments + is that you can create as many different construction + environments as you need, + each tailored to a different way to build + some piece of software or other file. + If, for example, we need to build + one program with the <literal>-O2</literal> flag + and another with the <literal>-g</literal> (debug) flag, + we would do this like so: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + opt.Program('foo', 'foo.c') + + dbg.Program('bar', 'bar.c') + </file> + <file name="foo.c"> + int main() { } + </file> + <file name="bar.c"> + int main() { } + </file> + </scons_example> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + We can even use multiple construction environments to build + multiple versions of a single program. + If you do this by simply trying to use the + &b-link-Program; builder with both environments, though, + like this: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + opt.Program('foo', 'foo.c') + + dbg.Program('foo', 'foo.c') + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + Then &SCons; generates the following error: + + </para> + + <scons_output example="ex3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + This is because the two &b-Program; calls have + each implicitly told &SCons; to generate an object file named + <filename>foo.o</filename>, + one with a &cv-link-CCFLAGS; value of + <literal>-O2</literal> + and one with a &cv-link-CCFLAGS; value of + <literal>-g</literal>. + &SCons; can't just decide that one of them + should take precedence over the other, + so it generates the error. + To avoid this problem, + we must explicitly specify + that each environment compile + <filename>foo.c</filename> + to a separately-named object file + using the &b-link-Object; builder, like so: + + </para> + + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + o = opt.Object('foo-opt', 'foo.c') + opt.Program(o) + + d = dbg.Object('foo-dbg', 'foo.c') + dbg.Program(d) + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + Notice that each call to the &b-Object; builder + returns a value, + an internal &SCons; object that + represents the object file that will be built. + We then use that object + as input to the &b-Program; builder. + This avoids having to specify explicitly + the object file name in multiple places, + and makes for a compact, readable + &SConstruct; file. + Our &SCons; output then looks like: + + </para> + + <scons_output example="ex4"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Making Copies of &ConsEnvs;: the &Clone; Method</title> + + <para> + + Sometimes you want more than one construction environment + to share the same values for one or more variables. + Rather than always having to repeat all of the common + variables when you create each construction environment, + you can use the &Clone; method + to create a copy of a construction environment. + + </para> + + <para> + + Like the &Environment; call that creates a construction environment, + the &Clone; method takes &consvar; assignments, + which will override the values in the copied construction environment. + For example, suppose we want to use &gcc; + to create three versions of a program, + one optimized, one debug, and one with neither. + We could do this by creating a "base" construction environment + that sets &cv-link-CC; to &gcc;, + and then creating two copies, + one which sets &cv-link-CCFLAGS; for optimization + and the other which sets &cv-CCFLAGS; for debugging: + + </para> + + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> + env = Environment(CC = 'gcc') + opt = env.Clone(CCFLAGS = '-O2') + dbg = env.Clone(CCFLAGS = '-g') + + env.Program('foo', 'foo.c') + + o = opt.Object('foo-opt', 'foo.c') + opt.Program(o) + + d = dbg.Object('foo-dbg', 'foo.c') + dbg.Program(d) + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + Then our output would look like: + + </para> + + <scons_output example="ex5"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Replacing Values: the &Replace; Method</title> + + <para> + + You can replace existing construction variable values + using the &Replace; method: + + </para> + + <scons_example name="Replace1"> + <file name="SConstruct" printme="1"> + env = Environment(CCFLAGS = '-DDEFINE1') + env.Replace(CCFLAGS = '-DDEFINE2') + env.Program('foo.c') + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + The replacing value + (<literal>-DDEFINE2</literal> in the above example) + completely replaces the value in the + construction environment: + + </para> + + <scons_output example="Replace1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + You can safely call &Replace; + for construction variables that + don't exist in the construction environment: + + </para> + + <scons_example name="Replace-nonexistent"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Replace(NEW_VARIABLE = 'xyzzy') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </file> + </scons_example> + + <para> + + In this case, + the construction variable simply + gets added to the construction environment: + + </para> + + <scons_output example="Replace-nonexistent"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Because the variables + aren't expanded until the construction environment + is actually used to build the targets, + and because &SCons; function and method calls + are order-independent, + the last replacement "wins" + and is used to build all targets, + regardless of the order in which + the calls to Replace() are + interspersed with calls to + builder methods: + + </para> + + <scons_example name="Replace2"> + <file name="SConstruct" printme="1"> + env = Environment(CCFLAGS = '-DDEFINE1') + print "CCFLAGS =", env['CCFLAGS'] + env.Program('foo.c') + + env.Replace(CCFLAGS = '-DDEFINE2') + print "CCFLAGS =", env['CCFLAGS'] + env.Program('bar.c') + </file> + <file name="foo.c"> + int main() { } + </file> + <file name="bar.c"> + int main() { } + </file> + </scons_example> + + <para> + + The timing of when the replacement + actually occurs relative + to when the targets get built + becomes apparent + if we run &scons; without the <literal>-Q</literal> + option: + + </para> + + <scons_output example="Replace2"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + Because the replacement occurs while + the &SConscript; files are being read, + the &cv-link-CCFLAGS; + variable has already been set to + <literal>-DDEFINE2</literal> + by the time the &foo_o; target is built, + even though the call to the &Replace; + method does not occur until later in + the &SConscript; file. + + </para> + + </section> + + <section> + <title>Setting Values Only If They're Not Already Defined: the &SetDefault; Method</title> + + <para> + + Sometimes it's useful to be able to specify + that a construction variable should be + set to a value only if the construction environment + does not already have that variable defined + You can do this with the &SetDefault; method, + which behaves similarly to the <function>set_default</function> + method of Python dictionary objects: + + </para> + + <sconstruct> + env.SetDefault(SPECIAL_FLAG = '-extra-option') + </sconstruct> + + <para> + + This is especially useful + when writing your own <literal>Tool</literal> modules + to apply variables to construction environments. + <!-- + See <xref linkend="chap-tool-modules"></xref> + for more information about writing + Tool modules. + --> + + </para> + + </section> + + <section> + <title>Appending to the End of Values: the &Append; Method</title> + + <para> + + You can append a value to + an existing construction variable + using the &Append; method: + + </para> + + <scons_example name="ex8"> + <file name="SConstruct" printme="1"> + env = Environment(CCFLAGS = ['-DMY_VALUE']) + env.Append(CCFLAGS = ['-DLAST']) + env.Program('foo.c') + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + &SCons; then supplies both the <literal>-DMY_VALUE</literal> and + <literal>-DLAST</literal> flags when compiling the object file: + + </para> + + <scons_output example="ex8"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + If the construction variable doesn't already exist, + the &Append; method will create it: + + </para> + + <scons_example name="Append-nonexistent"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Append(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </file> + </scons_example> + + <para> + + Which yields: + + </para> + + <scons_output example="Append-nonexistent"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that the &Append; function tries to be "smart" + about how the new value is appended to the old value. + If both are strings, the previous and new strings + are simply concatenated. + Similarly, if both are lists, + the lists are concatenated. + If, however, one is a string and the other is a list, + the string is added as a new element to the list. + + </para> + + </section> + + <section> + <title>Appending Unique Values: the &AppendUnique; Method</title> + + <para> + + Some times it's useful to add a new value + only if the existing construction variable + doesn't already contain the value. + This can be done using the &AppendUnique; method: + + </para> + + <sconstruct> + env.AppendUnique(CCFLAGS=['-g']) + </sconstruct> + + <para> + + In the above example, + the <literal>-g</literal> would be added + only if the &cv-CCFLAGS; variable + does not already contain a <literal>-g</literal> value. + + </para> + + </section> + + <section> + <title>Appending to the Beginning of Values: the &Prepend; Method</title> + + <para> + + You can append a value to the beginning of + an existing construction variable + using the &Prepend; method: + + </para> + + <scons_example name="ex9"> + <file name="SConstruct" printme="1"> + env = Environment(CCFLAGS = ['-DMY_VALUE']) + env.Prepend(CCFLAGS = ['-DFIRST']) + env.Program('foo.c') + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + &SCons; then supplies both the <literal>-DFIRST</literal> and + <literal>-DMY_VALUE</literal> flags when compiling the object file: + + </para> + + <scons_output example="ex9"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + If the construction variable doesn't already exist, + the &Prepend; method will create it: + + </para> + + <scons_example name="Prepend-nonexistent"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Prepend(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </file> + </scons_example> + + <para> + + Which yields: + + </para> + + <scons_output example="Prepend-nonexistent"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Like the &Append; function, + the &Prepend; function tries to be "smart" + about how the new value is appended to the old value. + If both are strings, the previous and new strings + are simply concatenated. + Similarly, if both are lists, + the lists are concatenated. + If, however, one is a string and the other is a list, + the string is added as a new element to the list. + + </para> + + </section> + + <section> + <title>Prepending Unique Values: the &PrependUnique; Method</title> + + <para> + + Some times it's useful to add a new value + to the beginning of a construction variable + only if the existing value + doesn't already contain the to-be-added value. + This can be done using the &PrependUnique; method: + + </para> + + <sconstruct> + env.PrependUnique(CCFLAGS=['-g']) + </sconstruct> + + <para> + + In the above example, + the <literal>-g</literal> would be added + only if the &cv-CCFLAGS; variable + does not already contain a <literal>-g</literal> value. + + </para> + + </section> + + </section> + + <section id="sect-execution-environments"> + <title>Controlling the Execution Environment for Issued Commands</title> + + <para> + + When &SCons; builds a target file, + it does not execute the commands with + the same external environment + that you used to execute &SCons;. + Instead, it uses the dictionary + stored in the &cv-link-ENV; construction variable + as the external environment + for executing commands. + + </para> + + <para> + + The most important ramification of this behavior + is that the &PATH; environment variable, + which controls where the operating system + will look for commands and utilities, + is not the same as in the external environment + from which you called &SCons;. + This means that &SCons; will not, by default, + necessarily find all of the tools + that you can execute from the command line. + + </para> + + <para> + + The default value of the &PATH; environment variable + on a POSIX system + is <literal>/usr/local/bin:/bin:/usr/bin</literal>. + The default value of the &PATH; environment variable + on a Windows system comes from the Windows registry + value for the command interpreter. + If you want to execute any commands--compilers, linkers, etc.--that + are not in these default locations, + you need to set the &PATH; value + in the &cv-ENV; dictionary + in your construction environment. + + </para> + + <para> + + The simplest way to do this is to initialize explicitly + the value when you create the construction environment; + this is one way to do that: + + </para> + + <sconstruct> + path = ['/usr/local/bin', '/bin', '/usr/bin'] + env = Environment(ENV = {'PATH' : path}) + </sconstruct> + + <para> + + Assign a dictionary to the &cv-ENV; + construction variable in this way + completely resets the external environment + so that the only variable that will be + set when external commands are executed + will be the &PATH; value. + If you want to use the rest of + the values in &cv-ENV; and only + set the value of &PATH;, + the most straightforward way is probably: + + </para> + + <sconstruct> + env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin'] + </sconstruct> + + <para> + + Note that &SCons; does allow you to define + the directories in the &PATH; in a string, + separated by the pathname-separator character + for your system (':' on POSIX systems, ';' on Windows): + + </para> + + <sconstruct> + env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' + </sconstruct> + + <para> + + But doing so makes your &SConscript; file less portable, + (although in this case that may not be a huge concern + since the directories you list are likley system-specific, anyway). + + </para> + + <!-- + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Command('foo', [], '__ROOT__/usr/bin/printenv.py') + </file> + <file name="__ROOT__/usr/bin/printenv.py" chmod="0755"> + #!/usr/bin/env python + import os + import sys + if len(sys.argv) > 1: + keys = sys.argv[1:] + else: + keys = os.environ.keys() + keys.sort() + for key in keys: + print " " + key + "=" + os.environ[key] + </file> + </scons_example> + + <para> + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <section> + <title>Propagating &PATH; From the External Environment</title> + + <para> + + You may want to propagate the external &PATH; + to the execution environment for commands. + You do this by initializing the &PATH; + variable with the &PATH; value from + the <literal>os.environ</literal> + dictionary, + which is Python's way of letting you + get at the external environment: + + </para> + + <sconstruct> + import os + env = Environment(ENV = {'PATH' : os.environ['PATH']}) + </sconstruct> + + <para> + + Alternatively, you may find it easier + to just propagate the entire external + environment to the execution environment + for commands. + This is simpler to code than explicity + selecting the &PATH; value: + + </para> + + <sconstruct> + import os + env = Environment(ENV = os.environ) + </sconstruct> + + <para> + + Either of these will guarantee that + &SCons; will be able to execute + any command that you can execute from the command line. + The drawback is that the build can behave + differently if it's run by people with + different &PATH; values in their environment--for example, + if both the <literal>/bin</literal> and + <literal>/usr/local/bin</literal> directories + have different &cc; commands, + then which one will be used to compile programs + will depend on which directory is listed + first in the user's &PATH; variable. + + </para> + + </section> + + <section> + <title>Adding to <varname>PATH</varname> Values in the Execution Environment</title> + + <para> + + One of the most common requirements + for manipulating a variable in the execution environment + is to add one or more custom directories to a search + like the <envar>$PATH</envar> variable on Linux or POSIX systems, + or the <envar>%PATH%</envar> variable on Windows, + so that a locally-installed compiler or other utility + can be found when &SCons; tries to execute it to update a target. + &SCons; provides &PrependENVPath; and &AppendENVPath; functions + to make adding things to execution variables convenient. + You call these functions by specifying the variable + to which you want the value added, + and then value itself. + So to add some <filename>/usr/local</filename> directories + to the <envar>$PATH</envar> and <envar>$LIB</envar> variables, + you might: + + </para> + + <sconstruct> + env = Environment(ENV = os.environ) + env.PrependENVPath('PATH', '/usr/local/bin') + env.AppendENVPath('LIB', '/usr/local/lib') + </sconstruct> + + <para> + + Note that the added values are strings, + and if you want to add multiple directories to + a variable like <envar>$PATH</envar>, + you must include the path separate character + (<literal>:</literal> on Linux or POSIX, + <literal>;</literal> on Windows) + in the string. + + </para> + + </section> + + </section> diff --git a/doc/user/environments.xml b/doc/user/environments.xml new file mode 100644 index 0000000..b9a60b9 --- /dev/null +++ b/doc/user/environments.xml @@ -0,0 +1,1684 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 More on construction environments + +As previously mentioned, a B<construction environment> is an object that +has a set of keyword/value pairs and a set of methods, and which is used +to tell Cons how target files should be built. This section describes +how Cons uses and expands construction environment values to control its +build behavior. + +=head2 Construction variable expansion + +Construction variables from a construction environment are expanded +by preceding the keyword with a C<%> (percent sign): + + Construction variables: + XYZZY => 'abracadabra', + + The string: "The magic word is: %XYZZY!" + expands to: "The magic word is: abracadabra!" + +A construction variable name may be surrounded by C<{> and C<}> (curly +braces), which are stripped as part of the expansion. This can +sometimes be necessary to separate a variable expansion from trailing +alphanumeric characters: + + Construction variables: + OPT => 'value1', + OPTION => 'value2', + + The string: "%OPT %{OPT}ION %OPTION %{OPTION}" + expands to: "value1 value1ION value2 value2" + +Construction variable expansion is recursive, that is, a string +containing C<%->expansions after substitution will be re-expanded until +no further substitutions can be made: + + Construction variables: + STRING => 'The result is: %FOO', + FOO => '%BAR', + BAR => 'final value', + + The string: "The string says: %STRING" + expands to: "The string says: The result is: final value" + +If a construction variable is not defined in an environment, then the +null string is substituted: + + Construction variables: + FOO => 'value1', + BAR => 'value2', + + The string: "%FOO <%NO_VARIABLE> %BAR" + expands to: "value1 <> value2" + +A doubled C<%%> will be replaced by a single C<%>: + + The string: "Here is a percent sign: %%" + expands to: "Here is a percent sign: %" + +=head2 Default construction variables + +When you specify no arguments when creating a new construction +environment: + + $env = new cons(); + +Cons creates a reference to a new, default construction +environment. This contains a number of construction variables and some +methods. At the present writing, the default construction variables on a +UNIX system are: + + CC => 'cc', + CFLAGS => '', + CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>', + CXX => '%CC', + CXXFLAGS => '%CFLAGS', + CXXCOM => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>', + INCDIRPREFIX => '-I', + INCDIRSUFFIX => '', + LINK => '%CXX', + LINKCOM => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS', + LINKMODULECOM => '%LD -r -o %> %<', + LIBDIRPREFIX => '-L', + LIBDIRSUFFIX => '', + AR => 'ar', + ARFLAGS => 'r', + ARCOM => ['%AR %ARFLAGS %> %<', '%RANLIB %>'], + RANLIB => 'ranlib', + AS => 'as', + ASFLAGS => '', + ASCOM => '%AS %ASFLAGS %< -o %>', + LD => 'ld', + LDFLAGS => '', + PREFLIB => 'lib', + SUFLIB => '.a', + SUFLIBS => '.so:.a', + SUFOBJ => '.o', + SIGNATURE => [ '*' => 'build' ], + ENV => { 'PATH' => '/bin:/usr/bin' }, + + +And on a Windows system (Windows NT), the default construction variables +are (unless the default rule style is set using the B<DefaultRules> +method): + + CC => 'cl', + CFLAGS => '/nologo', + CCCOM => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>', + CXXCOM => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>', + INCDIRPREFIX => '/I', + INCDIRSUFFIX => '', + LINK => 'link', + LINKCOM => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS', + LINKMODULECOM => '%LD /r /o %> %<', + LIBDIRPREFIX => '/LIBPATH:', + LIBDIRSUFFIX => '', + AR => 'lib', + ARFLAGS => '/nologo ', + ARCOM => "%AR %ARFLAGS /out:%> %<", + RANLIB => '', + LD => 'link', + LDFLAGS => '/nologo ', + PREFLIB => '', + SUFEXE => '.exe', + SUFLIB => '.lib', + SUFLIBS => '.dll:.lib', + SUFOBJ => '.obj', + SIGNATURE => [ '*' => 'build' ], + +These variables are used by the various methods associated with the +environment. In particular, any method that ultimately invokes an external +command will substitute these variables into the final command, as +appropriate. For example, the C<Objects> method takes a number of source +files and arranges to derive, if necessary, the corresponding object +files: + + Objects $env 'foo.c', 'bar.c'; + +This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The +command invoked is simply C<%CCCOM>, which expands, through substitution, +to the appropriate external command required to build each object. The +substitution rules will be discussed in detail in the next section. + +The construction variables are also used for other purposes. For example, +C<CPPPATH> is used to specify a colon-separated path of include +directories. These are intended to be passed to the C preprocessor and are +also used by the C-file scanning machinery to determine the dependencies +involved in a C Compilation. + +Variables beginning with underscore are created by various methods, +and should normally be considered ``internal'' variables. For example, +when a method is called which calls for the creation of an object from +a C source, the variable C<_IFLAGS> is created: this corresponds to the +C<-I> switches required by the C compiler to represent the directories +specified by C<CPPPATH>. + +Note that, for any particular environment, the value of a variable is set +once, and then never reset (to change a variable, you must create a new +environment. Methods are provided for copying existing environments for this +purpose). Some internal variables, such as C<_IFLAGS> are created on demand, +but once set, they remain fixed for the life of the environment. + +The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place +for passing options to the compiler, loader, and archiver, respectively. + +The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option +strings to be appended to the beginning and end, respectively, of each +include directory so that the compiler knows where to find F<.h> files. +Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the +option string to be appended to the beginning of and end, respectively, +of each directory that the linker should search for libraries. + +Another variable, C<ENV>, is used to determine the system environment during +the execution of an external command. By default, the only environment +variable that is set is C<PATH>, which is the execution path for a UNIX +command. For the utmost reproducibility, you should really arrange to set +your own execution path, in your top-level F<Construct> file (or perhaps by +importing an appropriate construction package with the Perl C<use> +command). The default variables are intended to get you off the ground. + +=head2 Expanding variables in construction commands + +Within a construction command, construction variables will be expanded +according to the rules described above. In addition to normal variable +expansion from the construction environment, construction commands also +expand the following pseudo-variables to insert the specific input and +output files in the command line that will be executed: + +=over 10 + +=item %> + +The target file name. In a multi-target command, this expands to the +first target mentioned.) + +=item %0 + +Same as C<%E<gt>>. + +=item %1, %2, ..., %9 + +These refer to the first through ninth input file, respectively. + +=item %E<lt> + +The full set of input file names. If any of these have been used +anywhere else in the current command line (via C<%1>, C<%2>, etc.), then +those will be deleted from the list provided by C<%E<lt>>. Consider the +following command found in a F<Conscript> file in the F<test> directory: + + Command $env 'tgt', qw(foo bar baz), qq( + echo %< -i %1 > %> + echo %< -i %2 >> %> + echo %< -i %3 >> %> + ); + +If F<tgt> needed to be updated, then this would result in the execution of +the following commands, assuming that no remapping has been established for +the F<test> directory: + + echo test/bar test/baz -i test/foo > test/tgt + echo test/foo test/baz -i test/bar >> test/tgt + echo test/foo test/bar -i test/baz >> test/tgt + +=back + +Any of the above pseudo-variables may be followed immediately by one of +the following suffixes to select a portion of the expanded path name: + + :a the absolute path to the file name + :b the directory plus the file name stripped of any suffix + :d the directory + :f the file name + :s the file name suffix + :F the file name stripped of any suffix + :S the absolute path path to a Linked source file + +Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>, +and C<%E<gt>:d> would expand to C<test>. + +There are additional C<%> elements which affect the command line(s): + +=over 10 + +=item %[ %] + +It is possible to programmatically rewrite part of the command by +enclosing part of it between C<%[> and C<%]>. This will call the +construction variable named as the first word enclosed in the brackets +as a Perl code reference; the results of this call will be used to +replace the contents of the brackets in the command line. For example, +given an existing input file named F<tgt.in>: + + @keywords = qw(foo bar baz); + $env = new cons(X_COMMA => sub { join(",", @_) }); + Command $env 'tgt', 'tgt.in', qq( + echo '# Keywords: %[X_COMMA @keywords %]' > %> + cat %< >> %> + ); + +This will execute: + + echo '# Keywords: foo,bar,baz' > tgt + cat tgt.in >> tgt + +=item %( %) + +Cons includes the text of the command line in the MD5 signature for a +build, so that targets get rebuilt if you change the command line (to +add or remove an option, for example). Command-line text in between +C<%(> and C<%)>, however, will be ignored for MD5 signature calculation. + +Internally, Cons uses C<%(> and C<%)> around include and library +directory options (C<-I> and C<-L> on UNIX systems, C</I> and +C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory +list changes. Rebuilds occur only if the changed directory list causes +any included I<files> to change, and a changed include file is detected +by the MD5 signature calculation on the actual file contents. + +=back + +XXX DESCRIBE THE Literal() FUNCTION, TOO XXX + +=head2 Expanding construction variables in file names + +Cons expands construction variables in the source and target file names +passed to the various construction methods according to the expansion +rules described above: + + $env = new cons( + DESTDIR => 'programs', + SRCDIR => 'src', + ); + Program $env '%DESTDIR/hello', '%SRCDIR/hello.c'; + +This allows for flexible configuration, through the construction +environment, of directory names, suffixes, etc. + +--> + + <para> + + An <literal>environment</literal> + is a collection of values that + can affect how a program executes. + &SCons; distinguishes between three + different types of environments + that can affect the behavior of &SCons; itself + (subject to the configuration in the &SConscript; files), + as well as the compilers and other tools it executes: + + </para> + + <variablelist> + + <varlistentry> + <term>External Environment</term> + + <listitem> + <para> + + The <literal>external environment</literal> + is the set of variables in the user's environment + at the time the user runs &SCons;. + These variables are available within the &SConscript; files + through the Python <literal>os.environ</literal> dictionary. + See <xref linkend="sect-external-environments"></xref>, below. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>&ConsEnv;</term> + + <listitem> + <para> + + A &consenv; + is a distinct object creating within + a &SConscript; file and + and which contains values that + affect how &SCons; decides + what action to use to build a target, + and even to define which targets + should be built from which sources. + One of the most powerful features of &SCons; + is the ability to create multiple &consenvs;, + including the ability to clone a new, customized + &consenv; from an existing &consenv;. + See <xref linkend="sect-construction-environments"></xref>, below. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Execution Environment</term> + + <listitem> + <para> + + An <literal>execution environment</literal> + is the values that &SCons; sets + when executing an external + command (such as a compiler or linker) + to build one or more targets. + Note that this is not the same as + the <literal>external environment</literal> + (see above). + See <xref linkend="sect-execution-environments"></xref>, below. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + Unlike &Make;, &SCons; does not automatically + copy or import values between different environments + (with the exception of explicit clones of &consenvs;, + which inherit values from their parent). + This is a deliberate design choice + to make sure that builds are, + by default, repeatable regardless of + the values in the user's external environment. + This avoids a whole class of problems with builds + where a developer's local build works + because a custom variable setting + causes a different compiler or build option to be used, + but the checked-in change breaks the official build + because it uses different environment variable settings. + + </para> + + <para> + + Note that the &SConscript; writer can + easily arrange for variables to be + copied or imported between environments, + and this is often very useful + (or even downright necessary) + to make it easy for developers + to customize the build in appropriate ways. + The point is <emphasis>not</emphasis> + that copying variables between different environments + is evil and must always be avoided. + Instead, it should be up to the + implementer of the build system + to make conscious choices + about how and when to import + a variable from one environment to another, + making informed decisions about + striking the right balance + between making the build + repeatable on the one hand + and convenient to use on the other. + + </para> + + <section id="sect-external-environments"> + <title>Using Values From the External Environment</title> + + <para> + + The <literal>external environment</literal> + variable settings that + the user has in force + when executing &SCons; + are available through the normal Python + <envar>os.environ</envar> + dictionary. + This means that you must add an + <literal>import os</literal> statement + to any &SConscript; file + in which you want to use + values from the user's external environment. + + </para> + + <programlisting> + import os + </programlisting> + + <para> + + More usefully, you can use the + <envar>os.environ</envar> + dictionary in your &SConscript; + files to initialize &consenvs; + with values from the user's external environment. + See the next section, + <xref linkend="sect-construction-environments"></xref>, + for information on how to do this. + + </para> + + </section> + + <section id="sect-construction-environments"> + <title>Construction Environments</title> + + <para> + + It is rare that all of the software in a large, + complicated system needs to be built the same way. + For example, different source files may need different options + enabled on the command line, + or different executable programs need to be linked + with different libraries. + &SCons; accommodates these different build + requirements by allowing you to create and + configure multiple &consenvs; + that control how the software is built. + A &consenv; is an object + that has a number of associated + &consvars;, each with a name and a value. + (A construction environment also has an attached + set of &Builder; methods, + about which we'll learn more later.) + + </para> + + <section> + <title>Creating a &ConsEnv;: the &Environment; Function</title> + + <para> + + A &consenv; is created by the &Environment; method: + + </para> + + <programlisting> + env = Environment() + </programlisting> + + <para> + + By default, &SCons; initializes every + new construction environment + with a set of &consvars; + based on the tools that it finds on your system, + plus the default set of builder methods + necessary for using those tools. + The construction variables + are initialized with values describing + the C compiler, + the Fortran compiler, + the linker, + etc., + as well as the command lines to invoke them. + + </para> + + <para> + + When you initialize a construction environment + you can set the values of the + environment's &consvars; + to control how a program is built. + For example: + + </para> + + <programlisting> + import os + + env = Environment(CC = 'gcc', + CCFLAGS = '-O2') + + env.Program('foo.c') + </programlisting> + + <para> + + The construction environment in this example + is still initialized with the same default + construction variable values, + except that the user has explicitly specified use of the + GNU C compiler &gcc;, + and further specifies that the <literal>-O2</literal> + (optimization level two) + flag should be used when compiling the object file. + In other words, the explicit initializations of + &cv-link-CC; and &cv-link-CCFLAGS; + override the default values in the newly-created + construction environment. + So a run from this example would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + gcc -o foo.o -c -O2 foo.c + gcc -o foo foo.o + </screen> + + </section> + + <section> + <title>Fetching Values From a &ConsEnv;</title> + + <para> + + You can fetch individual construction variables + using the normal syntax + for accessing individual named items in a Python dictionary: + + </para> + + <programlisting> + env = Environment() + print "CC is:", env['CC'] + </programlisting> + + <para> + + This example &SConstruct; file doesn't build anything, + but because it's actually a Python script, + it will print the value of &cv-link-CC; for us: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CC is: cc + scons: `.' is up to date. + </screen> + + <para> + + A construction environment, however, + is actually an object with associated methods, etc. + If you want to have direct access to only the + dictionary of construction variables, + you can fetch this using the &Dictionary; method: + + </para> + + <programlisting> + env = Environment(FOO = 'foo', BAR = 'bar') + dict = env.Dictionary() + for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']: + print "key = %s, value = %s" % (key, dict[key]) + </programlisting> + + <para> + + This &SConstruct; file + will print the specified dictionary items for us on POSIX + systems as follows: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + key = OBJSUFFIX, value = .o + key = LIBSUFFIX, value = .a + key = PROGSUFFIX, value = + scons: `.' is up to date. + </screen> + + <para> + + And on Windows: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + key = OBJSUFFIX, value = .obj + key = LIBSUFFIX, value = .lib + key = PROGSUFFIX, value = .exe + scons: `.' is up to date. + </screen> + + <para> + + If you want to loop and print the values of + all of the construction variables in a construction environment, + the Python code to do that in sorted order might look something like: + + </para> + + <programlisting> + env = Environment() + dict = env.Dictionary() + keys = dict.keys() + keys.sort() + for key in keys: + print "construction variable = '%s', value = '%s'" % (key, dict[key]) + </programlisting> + + </section> + + <section> + <title>Expanding Values From a &ConsEnv;: the &subst; Method</title> + + <para> + + Another way to get information from + a construction environment. + is to use the &subst; method + on a string containing <literal>$</literal> expansions + of construction variable names. + As a simple example, + the example from the previous + section that used + <literal>env['CC']</literal> + to fetch the value of &cv-link-CC; + could also be written as: + + </para> + + <programlisting> + env = Environment() + print "CC is:", env.subst('$CC') + </programlisting> + + <para> + + One advantage of using + &subst; to expand strings is + that construction variables + in the result get re-expanded until + there are no expansions left in the string. + So a simple fetch of a value like + &cv-link-CCCOM;: + + </para> + + <programlisting> + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env['CCCOM'] + </programlisting> + + <para> + + Will print the unexpanded value of &cv-CCCOM;, + showing us the construction + variables that still need to be expanded: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES + scons: `.' is up to date. + </screen> + + <para> + + Calling the &subst; method on <varname>$CCOM</varname>, + however: + + </para> + + <programlisting> + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env.subst('$CCCOM') + </programlisting> + + <para> + + Will recursively expand all of + the construction variables prefixed + with <literal>$</literal> (dollar signs), + showing us the final output: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CCCOM is: gcc -DFOO -c -o + scons: `.' is up to date. + </screen> + + <para> + + Note that because we're not expanding this + in the context of building something + there are no target or source files + for &cv-link-TARGET; and &cv-link-SOURCES; to expand. + + </para> + + </section> + + <section> + <title>Controlling the Default &ConsEnv;: the &DefaultEnvironment; Function</title> + + <para> + + All of the &Builder; functions that we've introduced so far, + like &Program; and &Library;, + actually use a default &consenv; + that contains settings + for the various compilers + and other tools that + &SCons; configures by default, + or otherwise knows about + and has discovered on your system. + The goal of the default construction environment + is to make many configurations to "just work" + to build software using + readily available tools + with a minimum of configuration changes. + + </para> + + <para> + + You can, however, control the settings + in the default contstruction environment + by using the &DefaultEnvironment; function + to initialize various settings: + + </para> + + <programlisting> + + DefaultEnvironment(CC = '/usr/local/bin/gcc') + + </programlisting> + + <para> + + When configured as above, + all calls to the &Program; + or &Object; Builder + will build object files with the + <filename>/usr/local/bin/gcc</filename> + compiler. + + </para> + + <para> + + Note that the &DefaultEnvironment; function + returns the initialized + default construction environment object, + which can then be manipulated like any + other construction environment. + So the following + would be equivalent to the + previous example, + setting the &cv-CC; + variable to <filename>/usr/local/bin/gcc</filename> + but as a separate step after + the default construction environment has been initialized: + + </para> + + <programlisting> + + env = DefaultEnvironment() + env['CC'] = '/usr/local/bin/gcc' + + </programlisting> + + <para> + + One very common use of the &DefaultEnvironment; function + is to speed up &SCons; initialization. + As part of trying to make most default + configurations "just work," + &SCons; will actually + search the local system for installed + compilers and other utilities. + This search can take time, + especially on systems with + slow or networked file systems. + If you know which compiler(s) and/or + other utilities you want to configure, + you can control the search + that &SCons; performs + by specifying some specific + tool modules with which to + initialize the default construction environment: + + </para> + + <programlisting> + + env = DefaultEnvironment(tools = ['gcc', 'gnulink'], + CC = '/usr/local/bin/gcc') + + </programlisting> + + <para> + + So the above example would tell &SCons; + to explicitly configure the default environment + to use its normal GNU Compiler and GNU Linker settings + (without having to search for them, + or any other utilities for that matter), + and specifically to use the compiler found at + <filename>/usr/local/bin/gcc</filename>. + + </para> + + </section> + + <section> + <title>Multiple &ConsEnvs;</title> + + <para> + + The real advantage of construction environments + is that you can create as many different construction + environments as you need, + each tailored to a different way to build + some piece of software or other file. + If, for example, we need to build + one program with the <literal>-O2</literal> flag + and another with the <literal>-g</literal> (debug) flag, + we would do this like so: + + </para> + + <programlisting> + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + opt.Program('foo', 'foo.c') + + dbg.Program('bar', 'bar.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + cc -o bar.o -c -g bar.c + cc -o bar bar.o + cc -o foo.o -c -O2 foo.c + cc -o foo foo.o + </screen> + + <para> + + We can even use multiple construction environments to build + multiple versions of a single program. + If you do this by simply trying to use the + &b-link-Program; builder with both environments, though, + like this: + + </para> + + <programlisting> + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + opt.Program('foo', 'foo.c') + + dbg.Program('foo', 'foo.c') + </programlisting> + + <para> + + Then &SCons; generates the following error: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + + scons: warning: Two different environments were specified for target foo.o, + but they appear to have the same action: CCCom(target, source, env) + File "/home/my/project/SConstruct", line 6, in ? + + scons: warning: Two different environments were specified for target foo, + but they appear to have the same action: Cat(target, source, env) + File "/home/my/project/SConstruct", line 6, in ? + cc -o foo.o -c -g foo.c + cc -o foo foo.o + </screen> + + <para> + + This is because the two &b-Program; calls have + each implicitly told &SCons; to generate an object file named + <filename>foo.o</filename>, + one with a &cv-link-CCFLAGS; value of + <literal>-O2</literal> + and one with a &cv-link-CCFLAGS; value of + <literal>-g</literal>. + &SCons; can't just decide that one of them + should take precedence over the other, + so it generates the error. + To avoid this problem, + we must explicitly specify + that each environment compile + <filename>foo.c</filename> + to a separately-named object file + using the &b-link-Object; builder, like so: + + </para> + + <programlisting> + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + o = opt.Object('foo-opt', 'foo.c') + opt.Program(o) + + d = dbg.Object('foo-dbg', 'foo.c') + dbg.Program(d) + </programlisting> + + <para> + + Notice that each call to the &b-Object; builder + returns a value, + an internal &SCons; object that + represents the object file that will be built. + We then use that object + as input to the &b-Program; builder. + This avoids having to specify explicitly + the object file name in multiple places, + and makes for a compact, readable + &SConstruct; file. + Our &SCons; output then looks like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o foo-dbg.o -c -g foo.c + cc -o foo-dbg foo-dbg.o + cc -o foo-opt.o -c -O2 foo.c + cc -o foo-opt foo-opt.o + </screen> + + </section> + + <section> + <title>Making Copies of &ConsEnvs;: the &Clone; Method</title> + + <para> + + Sometimes you want more than one construction environment + to share the same values for one or more variables. + Rather than always having to repeat all of the common + variables when you create each construction environment, + you can use the &Clone; method + to create a copy of a construction environment. + + </para> + + <para> + + Like the &Environment; call that creates a construction environment, + the &Clone; method takes &consvar; assignments, + which will override the values in the copied construction environment. + For example, suppose we want to use &gcc; + to create three versions of a program, + one optimized, one debug, and one with neither. + We could do this by creating a "base" construction environment + that sets &cv-link-CC; to &gcc;, + and then creating two copies, + one which sets &cv-link-CCFLAGS; for optimization + and the other which sets &cv-CCFLAGS; for debugging: + + </para> + + <programlisting> + env = Environment(CC = 'gcc') + opt = env.Clone(CCFLAGS = '-O2') + dbg = env.Clone(CCFLAGS = '-g') + + env.Program('foo', 'foo.c') + + o = opt.Object('foo-opt', 'foo.c') + opt.Program(o) + + d = dbg.Object('foo-dbg', 'foo.c') + dbg.Program(d) + </programlisting> + + <para> + + Then our output would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + gcc -o foo.o -c foo.c + gcc -o foo foo.o + gcc -o foo-dbg.o -c -g foo.c + gcc -o foo-dbg foo-dbg.o + gcc -o foo-opt.o -c -O2 foo.c + gcc -o foo-opt foo-opt.o + </screen> + + </section> + + <section> + <title>Replacing Values: the &Replace; Method</title> + + <para> + + You can replace existing construction variable values + using the &Replace; method: + + </para> + + <programlisting> + env = Environment(CCFLAGS = '-DDEFINE1') + env.Replace(CCFLAGS = '-DDEFINE2') + env.Program('foo.c') + </programlisting> + + <para> + + The replacing value + (<literal>-DDEFINE2</literal> in the above example) + completely replaces the value in the + construction environment: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o foo.o -c -DDEFINE2 foo.c + cc -o foo foo.o + </screen> + + <para> + + You can safely call &Replace; + for construction variables that + don't exist in the construction environment: + + </para> + + <programlisting> + env = Environment() + env.Replace(NEW_VARIABLE = 'xyzzy') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </programlisting> + + <para> + + In this case, + the construction variable simply + gets added to the construction environment: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + NEW_VARIABLE = xyzzy + scons: `.' is up to date. + </screen> + + <para> + + Because the variables + aren't expanded until the construction environment + is actually used to build the targets, + and because &SCons; function and method calls + are order-independent, + the last replacement "wins" + and is used to build all targets, + regardless of the order in which + the calls to Replace() are + interspersed with calls to + builder methods: + + </para> + + <programlisting> + env = Environment(CCFLAGS = '-DDEFINE1') + print "CCFLAGS =", env['CCFLAGS'] + env.Program('foo.c') + + env.Replace(CCFLAGS = '-DDEFINE2') + print "CCFLAGS =", env['CCFLAGS'] + env.Program('bar.c') + </programlisting> + + <para> + + The timing of when the replacement + actually occurs relative + to when the targets get built + becomes apparent + if we run &scons; without the <literal>-Q</literal> + option: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + CCFLAGS = -DDEFINE1 + CCFLAGS = -DDEFINE2 + scons: done reading SConscript files. + scons: Building targets ... + cc -o bar.o -c -DDEFINE2 bar.c + cc -o bar bar.o + cc -o foo.o -c -DDEFINE2 foo.c + cc -o foo foo.o + scons: done building targets. + </screen> + + <para> + + Because the replacement occurs while + the &SConscript; files are being read, + the &cv-link-CCFLAGS; + variable has already been set to + <literal>-DDEFINE2</literal> + by the time the &foo_o; target is built, + even though the call to the &Replace; + method does not occur until later in + the &SConscript; file. + + </para> + + </section> + + <section> + <title>Setting Values Only If They're Not Already Defined: the &SetDefault; Method</title> + + <para> + + Sometimes it's useful to be able to specify + that a construction variable should be + set to a value only if the construction environment + does not already have that variable defined + You can do this with the &SetDefault; method, + which behaves similarly to the <function>set_default</function> + method of Python dictionary objects: + + </para> + + <programlisting> + env.SetDefault(SPECIAL_FLAG = '-extra-option') + </programlisting> + + <para> + + This is especially useful + when writing your own <literal>Tool</literal> modules + to apply variables to construction environments. + <!-- + See <xref linkend="chap-tool-modules"></xref> + for more information about writing + Tool modules. + --> + + </para> + + </section> + + <section> + <title>Appending to the End of Values: the &Append; Method</title> + + <para> + + You can append a value to + an existing construction variable + using the &Append; method: + + </para> + + <programlisting> + env = Environment(CCFLAGS = ['-DMY_VALUE']) + env.Append(CCFLAGS = ['-DLAST']) + env.Program('foo.c') + </programlisting> + + <para> + + &SCons; then supplies both the <literal>-DMY_VALUE</literal> and + <literal>-DLAST</literal> flags when compiling the object file: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o foo.o -c -DMY_VALUE -DLAST foo.c + cc -o foo foo.o + </screen> + + <para> + + If the construction variable doesn't already exist, + the &Append; method will create it: + + </para> + + <programlisting> + env = Environment() + env.Append(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </programlisting> + + <para> + + Which yields: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + NEW_VARIABLE = added + scons: `.' is up to date. + </screen> + + <para> + + Note that the &Append; function tries to be "smart" + about how the new value is appended to the old value. + If both are strings, the previous and new strings + are simply concatenated. + Similarly, if both are lists, + the lists are concatenated. + If, however, one is a string and the other is a list, + the string is added as a new element to the list. + + </para> + + </section> + + <section> + <title>Appending Unique Values: the &AppendUnique; Method</title> + + <para> + + Some times it's useful to add a new value + only if the existing construction variable + doesn't already contain the value. + This can be done using the &AppendUnique; method: + + </para> + + <programlisting> + env.AppendUnique(CCFLAGS=['-g']) + </programlisting> + + <para> + + In the above example, + the <literal>-g</literal> would be added + only if the &cv-CCFLAGS; variable + does not already contain a <literal>-g</literal> value. + + </para> + + </section> + + <section> + <title>Appending to the Beginning of Values: the &Prepend; Method</title> + + <para> + + You can append a value to the beginning of + an existing construction variable + using the &Prepend; method: + + </para> + + <programlisting> + env = Environment(CCFLAGS = ['-DMY_VALUE']) + env.Prepend(CCFLAGS = ['-DFIRST']) + env.Program('foo.c') + </programlisting> + + <para> + + &SCons; then supplies both the <literal>-DFIRST</literal> and + <literal>-DMY_VALUE</literal> flags when compiling the object file: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o foo.o -c -DFIRST -DMY_VALUE foo.c + cc -o foo foo.o + </screen> + + <para> + + If the construction variable doesn't already exist, + the &Prepend; method will create it: + + </para> + + <programlisting> + env = Environment() + env.Prepend(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </programlisting> + + <para> + + Which yields: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + NEW_VARIABLE = added + scons: `.' is up to date. + </screen> + + <para> + + Like the &Append; function, + the &Prepend; function tries to be "smart" + about how the new value is appended to the old value. + If both are strings, the previous and new strings + are simply concatenated. + Similarly, if both are lists, + the lists are concatenated. + If, however, one is a string and the other is a list, + the string is added as a new element to the list. + + </para> + + </section> + + <section> + <title>Prepending Unique Values: the &PrependUnique; Method</title> + + <para> + + Some times it's useful to add a new value + to the beginning of a construction variable + only if the existing value + doesn't already contain the to-be-added value. + This can be done using the &PrependUnique; method: + + </para> + + <programlisting> + env.PrependUnique(CCFLAGS=['-g']) + </programlisting> + + <para> + + In the above example, + the <literal>-g</literal> would be added + only if the &cv-CCFLAGS; variable + does not already contain a <literal>-g</literal> value. + + </para> + + </section> + + </section> + + <section id="sect-execution-environments"> + <title>Controlling the Execution Environment for Issued Commands</title> + + <para> + + When &SCons; builds a target file, + it does not execute the commands with + the same external environment + that you used to execute &SCons;. + Instead, it uses the dictionary + stored in the &cv-link-ENV; construction variable + as the external environment + for executing commands. + + </para> + + <para> + + The most important ramification of this behavior + is that the &PATH; environment variable, + which controls where the operating system + will look for commands and utilities, + is not the same as in the external environment + from which you called &SCons;. + This means that &SCons; will not, by default, + necessarily find all of the tools + that you can execute from the command line. + + </para> + + <para> + + The default value of the &PATH; environment variable + on a POSIX system + is <literal>/usr/local/bin:/bin:/usr/bin</literal>. + The default value of the &PATH; environment variable + on a Windows system comes from the Windows registry + value for the command interpreter. + If you want to execute any commands--compilers, linkers, etc.--that + are not in these default locations, + you need to set the &PATH; value + in the &cv-ENV; dictionary + in your construction environment. + + </para> + + <para> + + The simplest way to do this is to initialize explicitly + the value when you create the construction environment; + this is one way to do that: + + </para> + + <programlisting> + path = ['/usr/local/bin', '/bin', '/usr/bin'] + env = Environment(ENV = {'PATH' : path}) + </programlisting> + + <para> + + Assign a dictionary to the &cv-ENV; + construction variable in this way + completely resets the external environment + so that the only variable that will be + set when external commands are executed + will be the &PATH; value. + If you want to use the rest of + the values in &cv-ENV; and only + set the value of &PATH;, + the most straightforward way is probably: + + </para> + + <programlisting> + env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin'] + </programlisting> + + <para> + + Note that &SCons; does allow you to define + the directories in the &PATH; in a string, + separated by the pathname-separator character + for your system (':' on POSIX systems, ';' on Windows): + + </para> + + <programlisting> + env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' + </programlisting> + + <para> + + But doing so makes your &SConscript; file less portable, + (although in this case that may not be a huge concern + since the directories you list are likley system-specific, anyway). + + </para> + + <!-- + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Command('foo', [], '__ROOT__/usr/bin/printenv.py') + </file> + <file name="__ROOT__/usr/bin/printenv.py" chmod="0755"> + #!/usr/bin/env python + import os + import sys + if len(sys.argv) > 1: + keys = sys.argv[1:] + else: + keys = os.environ.keys() + keys.sort() + for key in keys: + print " " + key + "=" + os.environ[key] + </file> + </scons_example> + + <para> + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <section> + <title>Propagating &PATH; From the External Environment</title> + + <para> + + You may want to propagate the external &PATH; + to the execution environment for commands. + You do this by initializing the &PATH; + variable with the &PATH; value from + the <literal>os.environ</literal> + dictionary, + which is Python's way of letting you + get at the external environment: + + </para> + + <programlisting> + import os + env = Environment(ENV = {'PATH' : os.environ['PATH']}) + </programlisting> + + <para> + + Alternatively, you may find it easier + to just propagate the entire external + environment to the execution environment + for commands. + This is simpler to code than explicity + selecting the &PATH; value: + + </para> + + <programlisting> + import os + env = Environment(ENV = os.environ) + </programlisting> + + <para> + + Either of these will guarantee that + &SCons; will be able to execute + any command that you can execute from the command line. + The drawback is that the build can behave + differently if it's run by people with + different &PATH; values in their environment--for example, + if both the <literal>/bin</literal> and + <literal>/usr/local/bin</literal> directories + have different &cc; commands, + then which one will be used to compile programs + will depend on which directory is listed + first in the user's &PATH; variable. + + </para> + + </section> + + <section> + <title>Adding to <varname>PATH</varname> Values in the Execution Environment</title> + + <para> + + One of the most common requirements + for manipulating a variable in the execution environment + is to add one or more custom directories to a search + like the <envar>$PATH</envar> variable on Linux or POSIX systems, + or the <envar>%PATH%</envar> variable on Windows, + so that a locally-installed compiler or other utility + can be found when &SCons; tries to execute it to update a target. + &SCons; provides &PrependENVPath; and &AppendENVPath; functions + to make adding things to execution variables convenient. + You call these functions by specifying the variable + to which you want the value added, + and then value itself. + So to add some <filename>/usr/local</filename> directories + to the <envar>$PATH</envar> and <envar>$LIB</envar> variables, + you might: + + </para> + + <programlisting> + env = Environment(ENV = os.environ) + env.PrependENVPath('PATH', '/usr/local/bin') + env.AppendENVPath('LIB', '/usr/local/lib') + </programlisting> + + <para> + + Note that the added values are strings, + and if you want to add multiple directories to + a variable like <envar>$PATH</envar>, + you must include the path separate character + (<literal>:</literal> on Linux or POSIX, + <literal>;</literal> on Windows) + in the string. + + </para> + + </section> + + </section> diff --git a/doc/user/errors.in b/doc/user/errors.in new file mode 100644 index 0000000..0051953 --- /dev/null +++ b/doc/user/errors.in @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>XXX</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/errors.xml b/doc/user/errors.xml new file mode 100644 index 0000000..0051953 --- /dev/null +++ b/doc/user/errors.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>XXX</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/example.in b/doc/user/example.in new file mode 100644 index 0000000..0051953 --- /dev/null +++ b/doc/user/example.in @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>XXX</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/example.xml b/doc/user/example.xml new file mode 100644 index 0000000..0051953 --- /dev/null +++ b/doc/user/example.xml @@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + XXX + + </para> + + <section> + <title>XXX</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/factories.in b/doc/user/factories.in new file mode 100644 index 0000000..0cea6c4 --- /dev/null +++ b/doc/user/factories.in @@ -0,0 +1,507 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; provides a number of platform-independent functions, + called <literal>factories</literal>, + that perform common file system manipulations + like copying, moving or deleting files and directories, + or making directories. + These functions are <literal>factories</literal> + because they don't perform the action + at the time they're called, + they each return an &Action; object + that can be executed at the appropriate time. + + </para> + + <section> + <title>Copying Files or Directories: The &Copy; Factory</title> + + <para> + + Suppose you want to arrange to make a copy of a file, + and don't have a suitable pre-existing builder. + <footnote> + <para> + Unfortunately, in the early days of SCons design, + we used the name &Copy; for the function that + returns a copy of the environment, + otherwise that would be the logical choice for + a Builder that copies a file or directory tree + to a target location. + </para> + </footnote> + One way would be to use the &Copy; action factory + in conjunction with the &Command; builder: + + </para> + + <scons_example name="Copy1"> + <file name="SConstruct" printme="1"> + Command("file.out", "file.in", Copy("$TARGET", "$SOURCE")) + </file> + <file name="file.in">file.in</file> + </scons_example> + + <para> + + Notice that the action returned by the &Copy; factory + will expand the &cv-link-TARGET; and &cv-link-SOURCE; strings + at the time &file_out; is built, + and that the order of the arguments + is the same as that of a builder itself--that is, + target first, followed by source: + + </para> + + <scons_output example="Copy1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + You can, of course, name a file explicitly + instead of using &cv-TARGET; or &cv-SOURCE;: + + </para> + + <scons_example name="Copy2"> + <file name="SConstruct" printme="1"> + Command("file.out", [], Copy("$TARGET", "file.in")) + </file> + <file name="file.in">file.in</file> + </scons_example> + + <para> + + Which executes as: + + </para> + + <scons_output example="Copy2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + The usefulness of the &Copy; factory + becomes more apparent when + you use it in a list of actions + passed to the &Command; builder. + For example, suppose you needed to run a + file through a utility that only modifies files in-place, + and can't "pipe" input to output. + One solution is to copy the source file + to a temporary file name, + run the utility, + and then copy the modified temporary file to the target, + which the &Copy; factory makes extremely easy: + + </para> + + <scons_example name="Copy3"> + <file name="S" printme="1"> + Command("file.out", "file.in", + [ + Copy("tempfile", "$SOURCE"), + "modify tempfile", + Copy("$TARGET", "tempfile"), + ]) + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + <file name="modify" chmod="0755"> + touch $* + </file> + </scons_example> + + <para> + + The output then looks like: + + </para> + + <scons_output example="Copy3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Deleting Files or Directories: The &Delete; Factory</title> + + <para> + + If you need to delete a file, + then the &Delete; factory + can be used in much the same way as + the &Copy; factory. + For example, if we want to make sure that + the temporary file + in our last example doesn't exist before + we copy to it, + we could add &Delete; to the beginning + of the command list: + + </para> + + <scons_example name="Delete1"> + <file name="S" printme="1"> + Command("file.out", "file.in", + [ + Delete("tempfile"), + Copy("tempfile", "$SOURCE"), + "modify tempfile", + Copy("$TARGET", "tempfile"), + ]) + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + <file name="modify" chmod="0755"> + touch $* + </file> + </scons_example> + + <para> + + Which then executes as follows: + + </para> + + <scons_output example="Delete1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Of course, like all of these &Action; factories, + the &Delete factory also expands + &cv-link-TARGET; and &cv-link-SOURCE; variables appropriately. + For example: + + </para> + + <scons_example name="Delete2"> + <file name="SConstruct" printme="1"> + Command("file.out", "file.in", + [ + Delete("$TARGET"), + Copy("$TARGET", "$SOURCE") + ]) + </file> + <file name="file.in">file.in</file> + </scons_example> + + <para> + + Executes as: + + </para> + + <scons_output example="Delete2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note, however, that you typically don't need to + call the &Delete; factory explicitly in this way; + by default, &SCons; deletes its target(s) + for you before executing any action. + + </para> + + <para> + + One word of caution about using the &Delete; factory: + it has the same variable expansions available + as any other factory, including the &cv-SOURCE; variable. + Specifying <literal>Delete("$SOURCE")</literal> + is not something you usually want to do! + + </para> + + </section> + + <section> + <title>Moving (Renaming) Files or Directories: The &Move; Factory</title> + + <para> + + The &Move; factory + allows you to rename a file or directory. + For example, if we don't want to copy the temporary file, + we could use: + + </para> + + <scons_example name="Move"> + <file name="S" printme="1"> + Command("file.out", "file.in", + [ + Copy("tempfile", "$SOURCE"), + "modify tempfile", + Move("$TARGET", "tempfile"), + ]) + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + <file name="modify" chmod="0755"> + touch $* + </file> + </scons_example> + + <para> + + Which would execute as: + + </para> + + <scons_output example="Move"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Updating the Modification Time of a File: The &Touch; Factory</title> + + <para> + + If you just need to update the + recorded modification time for a file, + use the &Touch; factory: + + </para> + + <scons_example name="Touch"> + <file name="S" printme="1"> + Command("file.out", "file.in", + [ + Copy("$TARGET", "$SOURCE"), + Touch("$TARGET"), + ]) + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + </scons_example> + + <para> + + Which executes as: + + </para> + + <scons_output example="Touch"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Creating a Directory: The &Mkdir; Factory</title> + + <para> + + If you need to create a directory, + use the &Mkdir; factory. + For example, if we need to process + a file in a temporary directory + in which the processing tool + will create other files that we don't care about, + you could use: + + </para> + + <scons_example name="Mkdir"> + <file name="S" printme="1"> + Command("file.out", "file.in", + [ + Delete("tempdir"), + Mkdir("tempdir"), + Copy("tempdir/${SOURCE.file}", "$SOURCE"), + "process tempdir", + Move("$TARGET", "tempdir/output_file"), + Delete("tempdir"), + ]) + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + <file name="process" chmod="0755"> + touch $* + </file> + </scons_example> + + <para> + + Which executes as: + + </para> + + <scons_output example="Mkdir"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Changing File or Directory Permissions: The &Chmod; Factory</title> + + <para> + + To change permissions on a file or directory, + use the &Chmod; factory. + The permission argument uses POSIX-style + permission bits and should typically + be expressed as an octal, + not decimal, number: + + </para> + + <scons_example name="Chmod"> + <file name="SConstruct" printme="1"> + Command("file.out", "file.in", + [ + Copy("$TARGET", "$SOURCE"), + Chmod("$TARGET", 0755), + ]) + </file> + <file name="file.in">file.in</file> + </scons_example> + + <para> + + Which executes: + + </para> + + <scons_output example="Chmod"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Executing an action immediately: the &Execute; Function</title> + + <para> + + We've been showing you how to use &Action; factories + in the &Command; function. + You can also execute an &Action; returned by a factory + (or actually, any &Action;) + at the time the &SConscript; file is read + by using the &Execute; function. + For example, if we need to make sure that + a directory exists before we build any targets, + + </para> + + <scons_example name="Execute"> + <file name="SConstruct" printme="1"> + Execute(Mkdir('__ROOT__/tmp/my_temp_directory')) + </file> + </scons_example> + + <para> + + Notice that this will + create the directory while + the &SConscript; file is being read: + + </para> + + <scons_output example="Execute"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + If you're familiar with Python, + you may wonder why you would want to use this + instead of just calling the native Python + <function>os.mkdir()</function> function. + The advantage here is that the &Mkdir; + action will behave appropriately if the user + specifies the &SCons; <option>-n</option> or + <option>-q</option> options--that is, + it will print the action but not actually + make the directory when <option>-n</option> is specified, + or make the directory but not print the action + when <option>-q</option> is specified. + + </para> + + <para> + + The &Execute; function returns the exit status + or return value of the underlying action being executed. + It will also print an error message if the action + fails and returns a non-zero value. + &SCons; will <emphasis>not</emphasis>, however, + actually stop the build if the action fails. + If you want the build to stop + in response to a failure in an action called by &Execute;, + you must do so by explicitly + checking the return value + and calling the &Exit; function + (or a Python equivalent): + + </para> + + <sconstruct> + if Execute(Mkdir('__ROOT__/tmp/my_temp_directory')): + # A problem occurred while making the temp directory. + Exit(1) + </sconstruct> + + </section> diff --git a/doc/user/factories.xml b/doc/user/factories.xml new file mode 100644 index 0000000..17e52bd --- /dev/null +++ b/doc/user/factories.xml @@ -0,0 +1,466 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; provides a number of platform-independent functions, + called <literal>factories</literal>, + that perform common file system manipulations + like copying, moving or deleting files and directories, + or making directories. + These functions are <literal>factories</literal> + because they don't perform the action + at the time they're called, + they each return an &Action; object + that can be executed at the appropriate time. + + </para> + + <section> + <title>Copying Files or Directories: The &Copy; Factory</title> + + <para> + + Suppose you want to arrange to make a copy of a file, + and don't have a suitable pre-existing builder. + <footnote> + <para> + Unfortunately, in the early days of SCons design, + we used the name &Copy; for the function that + returns a copy of the environment, + otherwise that would be the logical choice for + a Builder that copies a file or directory tree + to a target location. + </para> + </footnote> + One way would be to use the &Copy; action factory + in conjunction with the &Command; builder: + + </para> + + <programlisting> + Command("file.out", "file.in", Copy("$TARGET", "$SOURCE")) + </programlisting> + + <para> + + Notice that the action returned by the &Copy; factory + will expand the &cv-link-TARGET; and &cv-link-SOURCE; strings + at the time &file_out; is built, + and that the order of the arguments + is the same as that of a builder itself--that is, + target first, followed by source: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Copy("file.out", "file.in") + </screen> + + <para> + + You can, of course, name a file explicitly + instead of using &cv-TARGET; or &cv-SOURCE;: + + </para> + + <programlisting> + Command("file.out", [], Copy("$TARGET", "file.in")) + </programlisting> + + <para> + + Which executes as: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Copy("file.out", "file.in") + </screen> + + <para> + + The usefulness of the &Copy; factory + becomes more apparent when + you use it in a list of actions + passed to the &Command; builder. + For example, suppose you needed to run a + file through a utility that only modifies files in-place, + and can't "pipe" input to output. + One solution is to copy the source file + to a temporary file name, + run the utility, + and then copy the modified temporary file to the target, + which the &Copy; factory makes extremely easy: + + </para> + + <programlisting> + Command("file.out", "file.in", + [ + Copy("tempfile", "$SOURCE"), + "modify tempfile", + Copy("$TARGET", "tempfile"), + ]) + </programlisting> + + <para> + + The output then looks like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Copy("tempfile", "file.in") + modify tempfile + Copy("file.out", "tempfile") + </screen> + + </section> + + <section> + <title>Deleting Files or Directories: The &Delete; Factory</title> + + <para> + + If you need to delete a file, + then the &Delete; factory + can be used in much the same way as + the &Copy; factory. + For example, if we want to make sure that + the temporary file + in our last example doesn't exist before + we copy to it, + we could add &Delete; to the beginning + of the command list: + + </para> + + <programlisting> + Command("file.out", "file.in", + [ + Delete("tempfile"), + Copy("tempfile", "$SOURCE"), + "modify tempfile", + Copy("$TARGET", "tempfile"), + ]) + </programlisting> + + <para> + + Which then executes as follows: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Delete("tempfile") + Copy("tempfile", "file.in") + modify tempfile + Copy("file.out", "tempfile") + </screen> + + <para> + + Of course, like all of these &Action; factories, + the &Delete; factory also expands + &cv-link-TARGET; and &cv-link-SOURCE; variables appropriately. + For example: + + </para> + + <programlisting> + Command("file.out", "file.in", + [ + Delete("$TARGET"), + Copy("$TARGET", "$SOURCE") + ]) + </programlisting> + + <para> + + Executes as: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Delete("file.out") + Copy("file.out", "file.in") + </screen> + + <para> + + Note, however, that you typically don't need to + call the &Delete; factory explicitly in this way; + by default, &SCons; deletes its target(s) + for you before executing any action. + + </para> + + <para> + + One word of caution about using the &Delete; factory: + it has the same variable expansions available + as any other factory, including the &cv-SOURCE; variable. + Specifying <literal>Delete("$SOURCE")</literal> + is not something you usually want to do! + + </para> + + </section> + + <section> + <title>Moving (Renaming) Files or Directories: The &Move; Factory</title> + + <para> + + The &Move; factory + allows you to rename a file or directory. + For example, if we don't want to copy the temporary file, + we could use: + + </para> + + <programlisting> + Command("file.out", "file.in", + [ + Copy("tempfile", "$SOURCE"), + "modify tempfile", + Move("$TARGET", "tempfile"), + ]) + </programlisting> + + <para> + + Which would execute as: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Copy("tempfile", "file.in") + modify tempfile + Move("file.out", "tempfile") + </screen> + + </section> + + <section> + <title>Updating the Modification Time of a File: The &Touch; Factory</title> + + <para> + + If you just need to update the + recorded modification time for a file, + use the &Touch; factory: + + </para> + + <programlisting> + Command("file.out", "file.in", + [ + Copy("$TARGET", "$SOURCE"), + Touch("$TARGET"), + ]) + </programlisting> + + <para> + + Which executes as: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Copy("file.out", "file.in") + Touch("file.out") + </screen> + + </section> + + <section> + <title>Creating a Directory: The &Mkdir; Factory</title> + + <para> + + If you need to create a directory, + use the &Mkdir; factory. + For example, if we need to process + a file in a temporary directory + in which the processing tool + will create other files that we don't care about, + you could use: + + </para> + + <programlisting> + Command("file.out", "file.in", + [ + Delete("tempdir"), + Mkdir("tempdir"), + Copy("tempdir/${SOURCE.file}", "$SOURCE"), + "process tempdir", + Move("$TARGET", "tempdir/output_file"), + Delete("tempdir"), + ]) + </programlisting> + + <para> + + Which executes as: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Delete("tempdir") + Mkdir("tempdir") + Copy("tempdir/file.in", "file.in") + process tempdir + Move("file.out", "tempdir/output_file") + scons: *** [file.out] tempdir/output_file: No such file or directory + </screen> + + </section> + + <section> + <title>Changing File or Directory Permissions: The &Chmod; Factory</title> + + <para> + + To change permissions on a file or directory, + use the &Chmod; factory. + The permission argument uses POSIX-style + permission bits and should typically + be expressed as an octal, + not decimal, number: + + </para> + + <programlisting> + Command("file.out", "file.in", + [ + Copy("$TARGET", "$SOURCE"), + Chmod("$TARGET", 0755), + ]) + </programlisting> + + <para> + + Which executes: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Copy("file.out", "file.in") + Chmod("file.out", 0755) + </screen> + + </section> + + <section> + <title>Executing an action immediately: the &Execute; Function</title> + + <para> + + We've been showing you how to use &Action; factories + in the &Command; function. + You can also execute an &Action; returned by a factory + (or actually, any &Action;) + at the time the &SConscript; file is read + by using the &Execute; function. + For example, if we need to make sure that + a directory exists before we build any targets, + + </para> + + <programlisting> + Execute(Mkdir('/tmp/my_temp_directory')) + </programlisting> + + <para> + + Notice that this will + create the directory while + the &SConscript; file is being read: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + Mkdir("/tmp/my_temp_directory") + scons: done reading SConscript files. + scons: Building targets ... + scons: `.' is up to date. + scons: done building targets. + </screen> + + <para> + + If you're familiar with Python, + you may wonder why you would want to use this + instead of just calling the native Python + <function>os.mkdir()</function> function. + The advantage here is that the &Mkdir; + action will behave appropriately if the user + specifies the &SCons; <option>-n</option> or + <option>-q</option> options--that is, + it will print the action but not actually + make the directory when <option>-n</option> is specified, + or make the directory but not print the action + when <option>-q</option> is specified. + + </para> + + <para> + + The &Execute; function returns the exit status + or return value of the underlying action being executed. + It will also print an error message if the action + fails and returns a non-zero value. + &SCons; will <emphasis>not</emphasis>, however, + actually stop the build if the action fails. + If you want the build to stop + in response to a failure in an action called by &Execute;, + you must do so by explicitly + checking the return value + and calling the &Exit; function + (or a Python equivalent): + + </para> + + <programlisting> + if Execute(Mkdir('/tmp/my_temp_directory')): + # A problem occurred while making the temp directory. + Exit(1) + </programlisting> + + </section> diff --git a/doc/user/file-removal.in b/doc/user/file-removal.in new file mode 100644 index 0000000..c26f020 --- /dev/null +++ b/doc/user/file-removal.in @@ -0,0 +1,223 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + There are two occasions when &SCons; will, + by default, remove target files. + The first is when &SCons; determines that + an target file needs to be rebuilt + and removes the existing version of the target + before executing + The second is when &SCons; is invoked with the + <literal>-c</literal> option to "clean" + a tree of its built targets. + + These behaviours can be suppressed with the + &Precious; and &NoClean; functions, respectively. + + </para> + + <section> + <title>Preventing target removal during build: the &Precious; Function</title> + + <para> + + By default, &SCons; removes targets before building them. + Sometimes, however, this is not what you want. + For example, you may want to update a library incrementally, + not by having it deleted and then rebuilt from all + of the constituent object files. + In such cases, you can use the + &Precious; method to prevent + &SCons; from removing the target before it is built: + + </para> + + <scons_example name="precious-ex1"> + <file name="SConstruct" printme="1"> + env = Environment(RANLIBCOM='') + lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.Precious(lib) + </file> + <file name="f1.c"> + int f1() { } + </file> + <file name="f2.c"> + int f2() { } + </file> + <file name="f3.c"> + int f3() { } + </file> + </scons_example> + + <para> + + Although the output doesn't look any different, + &SCons; does not, in fact, + delete the target library before rebuilding it: + + </para> + + <scons_output example="precious-ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + &SCons; will, however, still delete files marked as &Precious; + when the <literal>-c</literal> option is used. + + </para> + + </section> + + <section> + <title>Preventing target removal during clean: the &NoClean; Function</title> + + <para> + + By default, &SCons; removes all built targets when invoked + with the <literal>-c</literal> option to clean a source tree + of built targets. + Sometimes, however, this is not what you want. + For example, you may want to remove only intermediate generated files + (such as object files), + but leave the final targets + (the libraries) + untouched. + + In such cases, you can use the &NoClean; method to prevent &SCons; + from removing a target during a clean: + + </para> + + <scons_example name="noclean-ex1"> + <file name="SConstruct" printme="1"> + env = Environment(RANLIBCOM='') + lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.NoClean(lib) + </file> + <file name="f1.c"> + int f1() { } + </file> + <file name="f2.c"> + int f2() { } + </file> + <file name="f3.c"> + int f3() { } + </file> + </scons_example> + + <para> + + Notice that the <filename>libfoo.a</filename> + is not listed as a removed file: + + </para> + + <scons_output example="noclean-ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -c</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Removing additional files during clean: the &Clean; Function</title> + + <para> + + There may be additional files that you want removed + when the <literal>-c</literal> option is used, + but which &SCons; doesn't know about + because they're not normal target files. + For example, perhaps a command you invoke + creates a log file as + part of building the target file you want. + You would like the log file cleaned, + but you don't want to have to teach + SCons that the command + "builds" two files. + + </para> + + <para> + + You can use the &Clean; function to arrange for additional files + to be removed when the <literal>-c</literal> option is used. + Notice, however, that the &Clean; function takes two arguments, + and the <emphasis>second</emphasis> argument + is the name of the additional file you want cleaned + (<filename>foo.log</filename> in this example): + + </para> + + <scons_example name="clean-ex1"> + <file name="S" printme="1"> + t = Command('foo.out', 'foo.in', 'build -o $TARGET $SOURCE') + Clean(t, 'foo.log') + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="foo.in"> + foo.in + </file> + <file name="foo.log"> + foo.log + </file> + <file name="build" chmod="0755"> + cat $3 > $2 + </file> + </scons_example> + + <para> + + The first argument is the target with which you want + the cleaning of this additional file associated. + In the above example, + we've used the return value from the + &Command; function, + which represents the + <filename>foo.out</filename> + target. + Now whenever the + <filename>foo.out</filename> target is cleaned + by the <literal>-c</literal> option, + the <filename>foo.log</filename> file + will be removed as well: + + </para> + + <scons_output example="clean-ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + </scons_output> + + </section> diff --git a/doc/user/file-removal.xml b/doc/user/file-removal.xml new file mode 100644 index 0000000..542fd38 --- /dev/null +++ b/doc/user/file-removal.xml @@ -0,0 +1,202 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + There are two occasions when &SCons; will, + by default, remove target files. + The first is when &SCons; determines that + an target file needs to be rebuilt + and removes the existing version of the target + before executing + The second is when &SCons; is invoked with the + <literal>-c</literal> option to "clean" + a tree of its built targets. + + These behaviours can be suppressed with the + &Precious; and &NoClean; functions, respectively. + + </para> + + <section> + <title>Preventing target removal during build: the &Precious; Function</title> + + <para> + + By default, &SCons; removes targets before building them. + Sometimes, however, this is not what you want. + For example, you may want to update a library incrementally, + not by having it deleted and then rebuilt from all + of the constituent object files. + In such cases, you can use the + &Precious; method to prevent + &SCons; from removing the target before it is built: + + </para> + + <programlisting> + env = Environment(RANLIBCOM='') + lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.Precious(lib) + </programlisting> + + <para> + + Although the output doesn't look any different, + &SCons; does not, in fact, + delete the target library before rebuilding it: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o f1.o -c f1.c + cc -o f2.o -c f2.c + cc -o f3.o -c f3.c + ar rc libfoo.a f1.o f2.o f3.o + </screen> + + <para> + + &SCons; will, however, still delete files marked as &Precious; + when the <literal>-c</literal> option is used. + + </para> + + </section> + + <section> + <title>Preventing target removal during clean: the &NoClean; Function</title> + + <para> + + By default, &SCons; removes all built targets when invoked + with the <literal>-c</literal> option to clean a source tree + of built targets. + Sometimes, however, this is not what you want. + For example, you may want to remove only intermediate generated files + (such as object files), + but leave the final targets + (the libraries) + untouched. + + In such cases, you can use the &NoClean; method to prevent &SCons; + from removing a target during a clean: + + </para> + + <programlisting> + env = Environment(RANLIBCOM='') + lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.NoClean(lib) + </programlisting> + + <para> + + Notice that the <filename>libfoo.a</filename> + is not listed as a removed file: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o f1.o -c f1.c + cc -o f2.o -c f2.c + cc -o f3.o -c f3.c + ar rc libfoo.a f1.o f2.o f3.o + % <userinput>scons -c</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Cleaning targets ... + Removed f1.o + Removed f2.o + Removed f3.o + scons: done cleaning targets. + </screen> + + </section> + + <section> + <title>Removing additional files during clean: the &Clean; Function</title> + + <para> + + There may be additional files that you want removed + when the <literal>-c</literal> option is used, + but which &SCons; doesn't know about + because they're not normal target files. + For example, perhaps a command you invoke + creates a log file as + part of building the target file you want. + You would like the log file cleaned, + but you don't want to have to teach + SCons that the command + "builds" two files. + + </para> + + <para> + + You can use the &Clean; function to arrange for additional files + to be removed when the <literal>-c</literal> option is used. + Notice, however, that the &Clean; function takes two arguments, + and the <emphasis>second</emphasis> argument + is the name of the additional file you want cleaned + (<filename>foo.log</filename> in this example): + + </para> + + <programlisting> + t = Command('foo.out', 'foo.in', 'build -o $TARGET $SOURCE') + Clean(t, 'foo.log') + </programlisting> + + <para> + + The first argument is the target with which you want + the cleaning of this additional file associated. + In the above example, + we've used the return value from the + &Command; function, + which represents the + <filename>foo.out</filename> + target. + Now whenever the + <filename>foo.out</filename> target is cleaned + by the <literal>-c</literal> option, + the <filename>foo.log</filename> file + will be removed as well: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + build -o foo.out foo.in + % <userinput>scons -Q -c</userinput> + Removed foo.out + Removed foo.log + </screen> + + </section> diff --git a/doc/user/hierarchy.in b/doc/user/hierarchy.in new file mode 100644 index 0000000..a917d10 --- /dev/null +++ b/doc/user/hierarchy.in @@ -0,0 +1,794 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + + +=head2 The Build command + +By default, Cons does not change its working directory to the directory +containing a subsidiary F<Conscript> file it is including. This behavior +can be enabled for a build by specifying, in the top-level F<Construct> +file: + + Conscript_chdir 1; + +When enabled, Cons will change to the subsidiary F<Conscript> file's +containing directory while reading in that file, and then change back +to the top-level directory once the file has been processed. + +It is expected that this behavior will become the default in some future +version of Cons. To prepare for this transition, builds that expect +Cons to remain at the top of the build while it reads in a subsidiary +F<Conscript> file should explicitly disable this feature as follows: + + Conscript_chdir 0; + +=head2 Relative, top-relative, and absolute file names + +(There is another file prefix, ``!'', that is interpreted specially by +Cons. See discussion of the C<Link> command, below, for details.) + + +=head2 Using modules in build scripts + +You may pull modules into each F<Conscript> file using the normal Perl +C<use> or C<require> statements: + + use English; + require My::Module; + +Each C<use> or C<require> only affects the one F<Conscript> file in which +it appears. To use a module in multiple F<Conscript> files, you must +put a C<use> or C<require> statement in each one that needs the module. + + +=head2 Scope of variables + +The top-level F<Construct> file and all F<Conscript> files begin life in +a common, separate Perl package. B<Cons> controls the symbol table for +the package so that, the symbol table for each script is empty, except +for the F<Construct> file, which gets some of the command line arguments. +All of the variables that are set or used, therefore, are set by the +script itself, not by some external script. + +Variables can be explicitly B<imported> by a script from its parent +script. To import a variable, it must have been B<exported> by the parent +and initialized (otherwise an error will occur). + + +=head2 The Export command + +The C<Export> command is used as in the following example: + + $env = new cons(); + $INCLUDE = "#export/include"; + $LIB = "#export/lib"; + Export qw( env INCLUDE LIB ); + Build qw( util/Conscript ); + +The values of the simple variables mentioned in the C<Export> list will be +squirreled away by any subsequent C<Build> commands. The C<Export> command +will only export Perl B<scalar> variables, that is, variables whose name +begins with C<$>. Other variables, objects, etc. can be exported by +reference, but all scripts will refer to the same object, and this object +should be considered to be read-only by the subsidiary scripts and by the +original exporting script. It's acceptable, however, to assign a new value +to the exported scalar variable, that won't change the underlying variable +referenced. This sequence, for example, is OK: + + $env = new cons(); + Export qw( env INCLUDE LIB ); + Build qw( util/Conscript ); + $env = new cons(CFLAGS => '-O'); + Build qw( other/Conscript ); + +It doesn't matter whether the variable is set before or after the C<Export> +command. The important thing is the value of the variable at the time the +C<Build> command is executed. This is what gets squirreled away. Any +subsequent C<Export> commands, by the way, invalidate the first: you must +mention all the variables you wish to export on each C<Export> command. + + +=head2 The Import command + +Variables exported by the C<Export> command can be imported into subsidiary +scripts by the C<Import> command. The subsidiary script always imports +variables directly from the superior script. Consider this example: + + Import qw( env INCLUDE ); + +This is only legal if the parent script exported both C<$env> and +C<$INCLUDE>. It also must have given each of these variables values. It is +OK for the subsidiary script to only import a subset of the exported +variables (in this example, C<$LIB>, which was exported by the previous +example, is not imported). + +All the imported variables are automatically re-exported, so the sequence: + + Import qw ( env INCLUDE ); + Build qw ( beneath-me/Conscript ); + +will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only +C<$env> is to be exported, then the following will suffice: + + Import qw ( env INCLUDE ); + Export qw ( env ); + Build qw ( beneath-me/Conscript ); + +Needless to say, the variables may be modified locally before invoking +C<Build> on the subsidiary script. + +=head2 Build script evaluation order + +The only constraint on the ordering of build scripts is that superior +scripts are evaluated before their inferior scripts. The top-level +F<Construct> file, for instance, is evaluated first, followed by any +inferior scripts. This is all you really need to know about the evaluation +order, since order is generally irrelevant. Consider the following C<Build> +command: + + Build qw( + drivers/display/Conscript + drivers/mouse/Conscript + parser/Conscript + utilities/Conscript + ); + +We've chosen to put the script names in alphabetical order, simply because +that's the most convenient for maintenance purposes. Changing the order will +make no difference to the build. + +--> + + <para> + + The source code for large software projects + rarely stays in a single directory, + but is nearly always divided into a + hierarchy of directories. + Organizing a large software build using &SCons; + involves creating a hierarchy of build scripts + using the &SConscript; function. + + </para> + + <section> + <title>&SConscript; Files</title> + + <para> + + As we've already seen, + the build script at the top of the tree is called &SConstruct;. + The top-level &SConstruct; file can + use the &SConscript; function to + include other subsidiary scripts in the build. + These subsidiary scripts can, in turn, + use the &SConscript; function + to include still other scripts in the build. + By convention, these subsidiary scripts are usually + named &SConscript;. + For example, a top-level &SConstruct; file might + arrange for four subsidiary scripts to be included + in the build as follows: + + </para> + + <sconstruct> + SConscript(['drivers/display/SConscript', + 'drivers/mouse/SConscript', + 'parser/SConscript', + 'utilities/SConscript']) + </sconstruct> + + <para> + + In this case, the &SConstruct; file + lists all of the &SConscript; files in the build explicitly. + (Note, however, that not every directory in the tree + necessarily has an &SConscript; file.) + Alternatively, the <literal>drivers</literal> + subdirectory might contain an intermediate + &SConscript; file, + in which case the &SConscript; call in + the top-level &SConstruct; file + would look like: + + </para> + + <sconstruct> + SConscript(['drivers/SConscript', + 'parser/SConscript', + 'utilities/SConscript']) + </sconstruct> + + <para> + + And the subsidiary &SConscript; file in the + <literal>drivers</literal> subdirectory + would look like: + + </para> + + <sconstruct> + SConscript(['display/SConscript', + 'mouse/SConscript']) + </sconstruct> + + <para> + + Whether you list all of the &SConscript; files in the + top-level &SConstruct; file, + or place a subsidiary &SConscript; file in + intervening directories, + or use some mix of the two schemes, + is up to you and the needs of your software. + + </para> + + </section> + + <section> + <title>Path Names Are Relative to the &SConscript; Directory</title> + + <para> + + Subsidiary &SConscript; files make it easy to create a build + hierarchy because all of the file and directory names + in a subsidiary &SConscript; files are interpreted + relative to the directory in which the &SConscript; file lives. + Typically, this allows the &SConscript; file containing the + instructions to build a target file + to live in the same directory as the source files + from which the target will be built, + making it easy to update how the software is built + whenever files are added or deleted + (or other changes are made). + + </para> + + <para> + + For example, suppose we want to build two programs + &prog1; and &prog2; in two separate directories + with the same names as the programs. + One typical way to do this would be + with a top-level &SConstruct; file like this: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + SConscript(['prog1/SConscript', + 'prog2/SConscript']) + </file> + <file name="prog1/SConscript"> + env = Environment() + env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c']) + </file> + <file name="prog2/SConscript"> + env = Environment() + env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c']) + </file> + <directory name="prog1"></directory> + <file name="prog1/main.c"> + x + </file> + <file name="prog1/foo1.c"> + x + </file> + <file name="prog1/foo2.c"> + x + </file> + <directory name="prog2"></directory> + <file name="prog2/main.c"> + x + </file> + <file name="prog2/bar1.c"> + x + </file> + <file name="prog2/bar2.c"> + x + </file> + </scons_example> + + <para> + + And subsidiary &SConscript; files that look like this: + + </para> + + <scons_example_file example="ex1" name="prog1/SConscript"> + </scons_example_file> + + <para> + + And this: + + </para> + + <scons_example_file example="ex1" name="prog2/SConscript"> + </scons_example_file> + + <para> + + Then, when we run &SCons; in the top-level directory, + our build looks like: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Notice the following: + + First, you can have files with the same names + in multiple directories, like main.c in the above example. + + Second, unlike standard recursive use of &Make;, + &SCons; stays in the top-level directory + (where the &SConstruct; file lives) + and issues commands that use the path names + from the top-level directory to the + target and source files within the hierarchy. + + </para> + + </section> + + <section> + <title>Top-Level Path Names in Subsidiary &SConscript; Files</title> + + <para> + + If you need to use a file from another directory, + it's sometimes more convenient to specify + the path to a file in another directory + from the top-level &SConstruct; directory, + even when you're using that file in + a subsidiary &SConscript; file in a subdirectory. + You can tell &SCons; to interpret a path name + as relative to the top-level &SConstruct; directory, + not the local directory of the &SConscript; file, + by appending a &hash; (hash mark) + to the beginning of the path name: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct"> + SConscript('src/prog/SConscript') + </file> + <file name="src/prog/SConscript" printme="1"> + env = Environment() + env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c']) + </file> + <file name="src/prog/main.c"> + x + </file> + <file name="lib/foo1.c"> + x + </file> + <file name="src/prog/foo2.c"> + x + </file> + </scons_example> + + <para> + + In this example, + the <literal>lib</literal> directory is + directly underneath the top-level &SConstruct; directory. + If the above &SConscript; file is in a subdirectory + named <literal>src/prog</literal>, + the output would look like: + + </para> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + (Notice that the <literal>lib/foo1.o</literal> object file + is built in the same directory as its source file. + See <xref linkend="chap-separate"></xref>, below, + for information about + how to build the object file in a different subdirectory.) + + </para> + + </section> + + <section> + <title>Absolute Path Names</title> + + <para> + + Of course, you can always specify + an absolute path name for a file--for example: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct"> + SConscript('src/prog/SConscript') + </file> + <file name="src/prog/SConscript" printme="1"> + env = Environment() + env.Program('prog', ['main.c', '__ROOT__/usr/joe/lib/foo1.c', 'foo2.c']) + </file> + <file name="src/prog/main.c"> + x + </file> + <file name="__ROOT__/usr/joe/lib/foo1.c"> + x + </file> + <file name="src/prog/foo2.c"> + x + </file> + </scons_example> + + <para> + + Which, when executed, would yield: + + </para> + + <scons_output example="ex3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + (As was the case with top-relative path names, + notice that the <literal>/usr/joe/lib/foo1.o</literal> object file + is built in the same directory as its source file. + See <xref linkend="chap-separate"></xref>, below, + for information about + how to build the object file in a different subdirectory.) + + </para> + + </section> + + <section> + <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title> + + <para> + + In the previous example, + each of the subsidiary &SConscript; files + created its own construction environment + by calling &Environment; separately. + This obviously works fine, + but if each program must be built + with the same construction variables, + it's cumbersome and error-prone to initialize + separate construction environments + in the same way over and over in each subsidiary + &SConscript; file. + + </para> + + <para> + + &SCons; supports the ability to <emphasis>export</emphasis> variables + from a parent &SConscript; file + to its subsidiary &SConscript; files, + which allows you to share common initialized + values throughout your build hierarchy. + + </para> + + <section> + <title>Exporting Variables</title> + + <para> + + There are two ways to export a variable, + such as a construction environment, + from an &SConscript; file, + so that it may be used by other &SConscript; files. + First, you can call the &Export; + function with a list of variables, + or a string of white-space separated variable names. + Each call to &Export; adds one + or more variables to a global list + of variables that are available for import + by other &SConscript; files. + + </para> + + <sconstruct> + env = Environment() + Export('env') + </sconstruct> + + <para> + + You may export more than one variable name at a time: + + </para> + + <sconstruct> + env = Environment() + debug = ARGUMENTS['debug'] + Export('env', 'debug') + </sconstruct> + + <para> + + Because white space is not legal in Python variable names, + the &Export; function will even automatically split + a string into separate names for you: + + </para> + + <sconstruct> + Export('env debug') + </sconstruct> + + <para> + + Second, you can specify a list of + variables to export as a second argument + to the &SConscript; function call: + + </para> + + <sconstruct> + SConscript('src/SConscript', 'env') + </sconstruct> + + <para> + + Or as the &exports; keyword argument: + + </para> + + <sconstruct> + SConscript('src/SConscript', exports='env') + </sconstruct> + + <para> + + These calls export the specified variables + to only the listed &SConscript; files. + You may, however, specify more than one + &SConscript; file in a list: + + </para> + + <sconstruct> + SConscript(['src1/SConscript', + 'src2/SConscript'], exports='env') + </sconstruct> + + <para> + + This is functionally equivalent to + calling the &SConscript; function + multiple times with the same &exports; argument, + one per &SConscript; file. + + </para> + + </section> + + <section> + <title>Importing Variables</title> + + <para> + + Once a variable has been exported from a calling + &SConscript; file, + it may be used in other &SConscript; files + by calling the &Import; function: + + </para> + + <sconstruct> + Import('env') + env.Program('prog', ['prog.c']) + </sconstruct> + + <para> + + The &Import; call makes the <literal>env</literal> construction + environment available to the &SConscript; file, + after which the variable can be used to build + programs, libraries, etc. + + </para> + + <para> + + Like the &Export; function, + the &Import; function can be used + with multiple variable names: + + </para> + + <sconstruct> + Import('env', 'debug') + env = env.Clone(DEBUG = debug) + env.Program('prog', ['prog.c']) + </sconstruct> + + <para> + + And the &Import; function will similarly + split a string along white-space + into separate variable names: + + </para> + + <sconstruct> + Import('env debug') + env = env.Clone(DEBUG = debug) + env.Program('prog', ['prog.c']) + </sconstruct> + + <para> + + Lastly, as a special case, + you may import all of the variables that + have been exported by supplying an asterisk + to the &Import; function: + + </para> + + <sconstruct> + Import('*') + env = env.Clone(DEBUG = debug) + env.Program('prog', ['prog.c']) + </sconstruct> + + <para> + + If you're dealing with a lot of &SConscript; files, + this can be a lot simpler than keeping + arbitrary lists of imported variables in each file. + + </para> + + </section> + + <section> + <title>Returning Values From an &SConscript; File</title> + + <para> + + Sometimes, you would like to be able to + use information from a subsidiary + &SConscript file in some way. + For example, + suppose that you want to create one + library from source files + scattered throughout a number + of subsidiary &SConscript; files. + You can do this by using the &Return; + function to return values + from the subsidiary &SConscript; files + to the calling file. + + </para> + + <para> + + If, for example, we have two subdirectories + &foo; and &bar; + that should each contribute a source + file to a Library, + what we'd like to be able to do is + collect the object files + from the subsidiary &SConscript; calls + like this: + + </para> + + <scons_example name="Return"> + <file name="SConstruct" printme="1"> + env = Environment() + Export('env') + objs = [] + for subdir in ['foo', 'bar']: + o = SConscript('%s/SConscript' % subdir) + objs.append(o) + env.Library('prog', objs) + </file> + <directory name="foo"></directory> + <directory name="bar"></directory> + <file name="foo/SConscript"> + Import('env') + obj = env.Object('foo.c') + Return('obj') + </file> + <file name="bar/SConscript"> + Import('env') + obj = env.Object('bar.c') + Return('obj') + </file> + <file name="foo/foo.c"> + void foo(void) { printf("foo/foo.c\n"); } + </file> + <file name="bar/bar.c"> + void bar(void) { printf("bar/bar.c\n"); } + </file> + </scons_example> + + <para> + + We can do this by using the &Return; + function in the + <literal>foo/SConscript</literal> file like this: + + </para> + + <scons_example_file example="Return" name="foo/SConscript"> + </scons_example_file> + + <para> + + (The corresponding + <literal>bar/SConscript</literal> + file should be pretty obvious.) + Then when we run &SCons;, + the object files from the subsidiary subdirectories + are all correctly archived in the desired library: + + </para> + + <scons_output example="Return"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <!-- + XXX Return(stop=False) + --> + + </section> + + </section> + + <!-- + + <section> + <title>Executing From a Subdirectory: the -D, -u and -U Options</title> + + <para> + + XXX -D, -u and -U + + </para> + + </section> + + --> diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml new file mode 100644 index 0000000..3495c5f --- /dev/null +++ b/doc/user/hierarchy.xml @@ -0,0 +1,746 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + + +=head2 The Build command + +By default, Cons does not change its working directory to the directory +containing a subsidiary F<Conscript> file it is including. This behavior +can be enabled for a build by specifying, in the top-level F<Construct> +file: + + Conscript_chdir 1; + +When enabled, Cons will change to the subsidiary F<Conscript> file's +containing directory while reading in that file, and then change back +to the top-level directory once the file has been processed. + +It is expected that this behavior will become the default in some future +version of Cons. To prepare for this transition, builds that expect +Cons to remain at the top of the build while it reads in a subsidiary +F<Conscript> file should explicitly disable this feature as follows: + + Conscript_chdir 0; + +=head2 Relative, top-relative, and absolute file names + +(There is another file prefix, ``!'', that is interpreted specially by +Cons. See discussion of the C<Link> command, below, for details.) + + +=head2 Using modules in build scripts + +You may pull modules into each F<Conscript> file using the normal Perl +C<use> or C<require> statements: + + use English; + require My::Module; + +Each C<use> or C<require> only affects the one F<Conscript> file in which +it appears. To use a module in multiple F<Conscript> files, you must +put a C<use> or C<require> statement in each one that needs the module. + + +=head2 Scope of variables + +The top-level F<Construct> file and all F<Conscript> files begin life in +a common, separate Perl package. B<Cons> controls the symbol table for +the package so that, the symbol table for each script is empty, except +for the F<Construct> file, which gets some of the command line arguments. +All of the variables that are set or used, therefore, are set by the +script itself, not by some external script. + +Variables can be explicitly B<imported> by a script from its parent +script. To import a variable, it must have been B<exported> by the parent +and initialized (otherwise an error will occur). + + +=head2 The Export command + +The C<Export> command is used as in the following example: + + $env = new cons(); + $INCLUDE = "#export/include"; + $LIB = "#export/lib"; + Export qw( env INCLUDE LIB ); + Build qw( util/Conscript ); + +The values of the simple variables mentioned in the C<Export> list will be +squirreled away by any subsequent C<Build> commands. The C<Export> command +will only export Perl B<scalar> variables, that is, variables whose name +begins with C<$>. Other variables, objects, etc. can be exported by +reference, but all scripts will refer to the same object, and this object +should be considered to be read-only by the subsidiary scripts and by the +original exporting script. It's acceptable, however, to assign a new value +to the exported scalar variable, that won't change the underlying variable +referenced. This sequence, for example, is OK: + + $env = new cons(); + Export qw( env INCLUDE LIB ); + Build qw( util/Conscript ); + $env = new cons(CFLAGS => '-O'); + Build qw( other/Conscript ); + +It doesn't matter whether the variable is set before or after the C<Export> +command. The important thing is the value of the variable at the time the +C<Build> command is executed. This is what gets squirreled away. Any +subsequent C<Export> commands, by the way, invalidate the first: you must +mention all the variables you wish to export on each C<Export> command. + + +=head2 The Import command + +Variables exported by the C<Export> command can be imported into subsidiary +scripts by the C<Import> command. The subsidiary script always imports +variables directly from the superior script. Consider this example: + + Import qw( env INCLUDE ); + +This is only legal if the parent script exported both C<$env> and +C<$INCLUDE>. It also must have given each of these variables values. It is +OK for the subsidiary script to only import a subset of the exported +variables (in this example, C<$LIB>, which was exported by the previous +example, is not imported). + +All the imported variables are automatically re-exported, so the sequence: + + Import qw ( env INCLUDE ); + Build qw ( beneath-me/Conscript ); + +will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only +C<$env> is to be exported, then the following will suffice: + + Import qw ( env INCLUDE ); + Export qw ( env ); + Build qw ( beneath-me/Conscript ); + +Needless to say, the variables may be modified locally before invoking +C<Build> on the subsidiary script. + +=head2 Build script evaluation order + +The only constraint on the ordering of build scripts is that superior +scripts are evaluated before their inferior scripts. The top-level +F<Construct> file, for instance, is evaluated first, followed by any +inferior scripts. This is all you really need to know about the evaluation +order, since order is generally irrelevant. Consider the following C<Build> +command: + + Build qw( + drivers/display/Conscript + drivers/mouse/Conscript + parser/Conscript + utilities/Conscript + ); + +We've chosen to put the script names in alphabetical order, simply because +that's the most convenient for maintenance purposes. Changing the order will +make no difference to the build. + +--> + + <para> + + The source code for large software projects + rarely stays in a single directory, + but is nearly always divided into a + hierarchy of directories. + Organizing a large software build using &SCons; + involves creating a hierarchy of build scripts + using the &SConscript; function. + + </para> + + <section> + <title>&SConscript; Files</title> + + <para> + + As we've already seen, + the build script at the top of the tree is called &SConstruct;. + The top-level &SConstruct; file can + use the &SConscript; function to + include other subsidiary scripts in the build. + These subsidiary scripts can, in turn, + use the &SConscript; function + to include still other scripts in the build. + By convention, these subsidiary scripts are usually + named &SConscript;. + For example, a top-level &SConstruct; file might + arrange for four subsidiary scripts to be included + in the build as follows: + + </para> + + <programlisting> + SConscript(['drivers/display/SConscript', + 'drivers/mouse/SConscript', + 'parser/SConscript', + 'utilities/SConscript']) + </programlisting> + + <para> + + In this case, the &SConstruct; file + lists all of the &SConscript; files in the build explicitly. + (Note, however, that not every directory in the tree + necessarily has an &SConscript; file.) + Alternatively, the <literal>drivers</literal> + subdirectory might contain an intermediate + &SConscript; file, + in which case the &SConscript; call in + the top-level &SConstruct; file + would look like: + + </para> + + <programlisting> + SConscript(['drivers/SConscript', + 'parser/SConscript', + 'utilities/SConscript']) + </programlisting> + + <para> + + And the subsidiary &SConscript; file in the + <literal>drivers</literal> subdirectory + would look like: + + </para> + + <programlisting> + SConscript(['display/SConscript', + 'mouse/SConscript']) + </programlisting> + + <para> + + Whether you list all of the &SConscript; files in the + top-level &SConstruct; file, + or place a subsidiary &SConscript; file in + intervening directories, + or use some mix of the two schemes, + is up to you and the needs of your software. + + </para> + + </section> + + <section> + <title>Path Names Are Relative to the &SConscript; Directory</title> + + <para> + + Subsidiary &SConscript; files make it easy to create a build + hierarchy because all of the file and directory names + in a subsidiary &SConscript; files are interpreted + relative to the directory in which the &SConscript; file lives. + Typically, this allows the &SConscript; file containing the + instructions to build a target file + to live in the same directory as the source files + from which the target will be built, + making it easy to update how the software is built + whenever files are added or deleted + (or other changes are made). + + </para> + + <para> + + For example, suppose we want to build two programs + &prog1; and &prog2; in two separate directories + with the same names as the programs. + One typical way to do this would be + with a top-level &SConstruct; file like this: + + </para> + + <programlisting> + SConscript(['prog1/SConscript', + 'prog2/SConscript']) + </programlisting> + + <para> + + And subsidiary &SConscript; files that look like this: + + </para> + + + <programlisting> + env = Environment() + env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c']) + </programlisting> + + <para> + + And this: + + </para> + + + <programlisting> + env = Environment() + env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c']) + </programlisting> + + <para> + + Then, when we run &SCons; in the top-level directory, + our build looks like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o prog1/foo1.o -c prog1/foo1.c + cc -o prog1/foo2.o -c prog1/foo2.c + cc -o prog1/main.o -c prog1/main.c + cc -o prog1/prog1 prog1/main.o prog1/foo1.o prog1/foo2.o + cc -o prog2/bar1.o -c prog2/bar1.c + cc -o prog2/bar2.o -c prog2/bar2.c + cc -o prog2/main.o -c prog2/main.c + cc -o prog2/prog2 prog2/main.o prog2/bar1.o prog2/bar2.o + </screen> + + <para> + + Notice the following: + + First, you can have files with the same names + in multiple directories, like main.c in the above example. + + Second, unlike standard recursive use of &Make;, + &SCons; stays in the top-level directory + (where the &SConstruct; file lives) + and issues commands that use the path names + from the top-level directory to the + target and source files within the hierarchy. + + </para> + + </section> + + <section> + <title>Top-Level Path Names in Subsidiary &SConscript; Files</title> + + <para> + + If you need to use a file from another directory, + it's sometimes more convenient to specify + the path to a file in another directory + from the top-level &SConstruct; directory, + even when you're using that file in + a subsidiary &SConscript; file in a subdirectory. + You can tell &SCons; to interpret a path name + as relative to the top-level &SConstruct; directory, + not the local directory of the &SConscript; file, + by appending a &hash; (hash mark) + to the beginning of the path name: + + </para> + + <programlisting> + env = Environment() + env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c']) + </programlisting> + + <para> + + In this example, + the <literal>lib</literal> directory is + directly underneath the top-level &SConstruct; directory. + If the above &SConscript; file is in a subdirectory + named <literal>src/prog</literal>, + the output would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o lib/foo1.o -c lib/foo1.c + cc -o src/prog/foo2.o -c src/prog/foo2.c + cc -o src/prog/main.o -c src/prog/main.c + cc -o src/prog/prog src/prog/main.o lib/foo1.o src/prog/foo2.o + </screen> + + <para> + + (Notice that the <literal>lib/foo1.o</literal> object file + is built in the same directory as its source file. + See <xref linkend="chap-separate"></xref>, below, + for information about + how to build the object file in a different subdirectory.) + + </para> + + </section> + + <section> + <title>Absolute Path Names</title> + + <para> + + Of course, you can always specify + an absolute path name for a file--for example: + + </para> + + <programlisting> + env = Environment() + env.Program('prog', ['main.c', '/usr/joe/lib/foo1.c', 'foo2.c']) + </programlisting> + + <para> + + Which, when executed, would yield: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o src/prog/foo2.o -c src/prog/foo2.c + cc -o src/prog/main.o -c src/prog/main.c + cc -o /usr/joe/lib/foo1.o -c /usr/joe/lib/foo1.c + cc -o src/prog/prog src/prog/main.o /usr/joe/lib/foo1.o src/prog/foo2.o + </screen> + + <para> + + (As was the case with top-relative path names, + notice that the <literal>/usr/joe/lib/foo1.o</literal> object file + is built in the same directory as its source file. + See <xref linkend="chap-separate"></xref>, below, + for information about + how to build the object file in a different subdirectory.) + + </para> + + </section> + + <section> + <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title> + + <para> + + In the previous example, + each of the subsidiary &SConscript; files + created its own construction environment + by calling &Environment; separately. + This obviously works fine, + but if each program must be built + with the same construction variables, + it's cumbersome and error-prone to initialize + separate construction environments + in the same way over and over in each subsidiary + &SConscript; file. + + </para> + + <para> + + &SCons; supports the ability to <emphasis>export</emphasis> variables + from a parent &SConscript; file + to its subsidiary &SConscript; files, + which allows you to share common initialized + values throughout your build hierarchy. + + </para> + + <section> + <title>Exporting Variables</title> + + <para> + + There are two ways to export a variable, + such as a construction environment, + from an &SConscript; file, + so that it may be used by other &SConscript; files. + First, you can call the &Export; + function with a list of variables, + or a string of white-space separated variable names. + Each call to &Export; adds one + or more variables to a global list + of variables that are available for import + by other &SConscript; files. + + </para> + + <programlisting> + env = Environment() + Export('env') + </programlisting> + + <para> + + You may export more than one variable name at a time: + + </para> + + <programlisting> + env = Environment() + debug = ARGUMENTS['debug'] + Export('env', 'debug') + </programlisting> + + <para> + + Because white space is not legal in Python variable names, + the &Export; function will even automatically split + a string into separate names for you: + + </para> + + <programlisting> + Export('env debug') + </programlisting> + + <para> + + Second, you can specify a list of + variables to export as a second argument + to the &SConscript; function call: + + </para> + + <programlisting> + SConscript('src/SConscript', 'env') + </programlisting> + + <para> + + Or as the &exports; keyword argument: + + </para> + + <programlisting> + SConscript('src/SConscript', exports='env') + </programlisting> + + <para> + + These calls export the specified variables + to only the listed &SConscript; files. + You may, however, specify more than one + &SConscript; file in a list: + + </para> + + <programlisting> + SConscript(['src1/SConscript', + 'src2/SConscript'], exports='env') + </programlisting> + + <para> + + This is functionally equivalent to + calling the &SConscript; function + multiple times with the same &exports; argument, + one per &SConscript; file. + + </para> + + </section> + + <section> + <title>Importing Variables</title> + + <para> + + Once a variable has been exported from a calling + &SConscript; file, + it may be used in other &SConscript; files + by calling the &Import; function: + + </para> + + <programlisting> + Import('env') + env.Program('prog', ['prog.c']) + </programlisting> + + <para> + + The &Import; call makes the <literal>env</literal> construction + environment available to the &SConscript; file, + after which the variable can be used to build + programs, libraries, etc. + + </para> + + <para> + + Like the &Export; function, + the &Import; function can be used + with multiple variable names: + + </para> + + <programlisting> + Import('env', 'debug') + env = env.Clone(DEBUG = debug) + env.Program('prog', ['prog.c']) + </programlisting> + + <para> + + And the &Import; function will similarly + split a string along white-space + into separate variable names: + + </para> + + <programlisting> + Import('env debug') + env = env.Clone(DEBUG = debug) + env.Program('prog', ['prog.c']) + </programlisting> + + <para> + + Lastly, as a special case, + you may import all of the variables that + have been exported by supplying an asterisk + to the &Import; function: + + </para> + + <programlisting> + Import('*') + env = env.Clone(DEBUG = debug) + env.Program('prog', ['prog.c']) + </programlisting> + + <para> + + If you're dealing with a lot of &SConscript; files, + this can be a lot simpler than keeping + arbitrary lists of imported variables in each file. + + </para> + + </section> + + <section> + <title>Returning Values From an &SConscript; File</title> + + <para> + + Sometimes, you would like to be able to + use information from a subsidiary + &SConscript; file in some way. + For example, + suppose that you want to create one + library from source files + scattered throughout a number + of subsidiary &SConscript; files. + You can do this by using the &Return; + function to return values + from the subsidiary &SConscript; files + to the calling file. + + </para> + + <para> + + If, for example, we have two subdirectories + &foo; and &bar; + that should each contribute a source + file to a Library, + what we'd like to be able to do is + collect the object files + from the subsidiary &SConscript; calls + like this: + + </para> + + <programlisting> + env = Environment() + Export('env') + objs = [] + for subdir in ['foo', 'bar']: + o = SConscript('%s/SConscript' % subdir) + objs.append(o) + env.Library('prog', objs) + </programlisting> + + <para> + + We can do this by using the &Return; + function in the + <literal>foo/SConscript</literal> file like this: + + </para> + + + <programlisting> + Import('env') + obj = env.Object('foo.c') + Return('obj') + </programlisting> + + <para> + + (The corresponding + <literal>bar/SConscript</literal> + file should be pretty obvious.) + Then when we run &SCons;, + the object files from the subsidiary subdirectories + are all correctly archived in the desired library: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o bar/bar.o -c bar/bar.c + cc -o foo/foo.o -c foo/foo.c + ar rc libprog.a foo/foo.o bar/bar.o + ranlib libprog.a + </screen> + + <!-- + XXX Return(stop=False) + --> + + </section> + + </section> + + <!-- + + <section> + <title>Executing From a Subdirectory: the -D, -u and -U Options</title> + + <para> + + XXX -D, -u and -U + + </para> + + </section> + + --> diff --git a/doc/user/install.in b/doc/user/install.in new file mode 100644 index 0000000..cce2de3 --- /dev/null +++ b/doc/user/install.in @@ -0,0 +1,247 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Once a program is built, + it is often appropriate to install it in another + directory for public use. + You use the &Install; method + to arrange for a program, or any other file, + to be copied into a destination directory: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment() + hello = env.Program('hello.c') + env.Install('__ROOT__/usr/bin', hello) + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Note, however, that installing a file is + still considered a type of file "build." + This is important when you remember that + the default behavior of &SCons; is + to build files in or below the current directory. + If, as in the example above, + you are installing files in a directory + outside of the top-level &SConstruct; file's directory tree, + you must specify that directory + (or a higher directory, such as <literal>/</literal>) + for it to install anything there: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q __ROOT__/usr/bin</scons_output_command> + </scons_output> + + <para> + + It can, however, be cumbersome to remember + (and type) the specific destination directory + in which the program (or any other file) + should be installed. + This is an area where the &Alias; + function comes in handy, + allowing you, for example, + to create a pseudo-target named <literal>install</literal> + that can expand to the specified destination directory: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + env = Environment() + hello = env.Program('hello.c') + env.Install('__ROOT__/usr/bin', hello) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + This then yields the more natural + ability to install the program + in its destination as follows: + + </para> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> + + <section> + <title>Installing Multiple Files in a Directory</title> + + <para> + + You can install multiple files into a directory + simply by calling the &Install; function multiple times: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> + env = Environment() + hello = env.Program('hello.c') + goodbye = env.Program('goodbye.c') + env.Install('__ROOT__/usr/bin', hello) + env.Install('__ROOT__/usr/bin', goodbye) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> + + <para> + + Or, more succinctly, listing the multiple input + files in a list + (just like you can do with any other builder): + + </para> + + <sconstruct> + env = Environment() + hello = env.Program('hello.c') + goodbye = env.Program('goodbye.c') + env.Install('__ROOT__/usr/bin', [hello, goodbye]) + env.Alias('install', '__ROOT__/usr/bin') + </sconstruct> + + <para> + + Either of these two examples yields: + + </para> + + <scons_output example="ex3"> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Installing a File Under a Different Name</title> + + <para> + + The &Install; method preserves the name + of the file when it is copied into the + destination directory. + If you need to change the name of the file + when you copy it, use the &InstallAs; function: + + </para> + + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> + env = Environment() + hello = env.Program('hello.c') + env.InstallAs('__ROOT__/usr/bin/hello-new', hello) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + This installs the <literal>hello</literal> + program with the name <literal>hello-new</literal> + as follows: + + </para> + + <scons_output example="ex4"> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Installing Multiple Files Under Different Names</title> + + <para> + + Lastly, if you have multiple files that all + need to be installed with different file names, + you can either call the &InstallAs; function + multiple times, or as a shorthand, + you can supply same-length lists + for both the target and source arguments: + + </para> + + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> + env = Environment() + hello = env.Program('hello.c') + goodbye = env.Program('goodbye.c') + env.InstallAs(['__ROOT__/usr/bin/hello-new', + '__ROOT__/usr/bin/goodbye-new'], + [hello, goodbye]) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> + + <para> + + In this case, the &InstallAs; function + loops through both lists simultaneously, + and copies each source file into its corresponding + target file name: + + </para> + + <scons_output example="ex5"> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> + + </section> diff --git a/doc/user/install.xml b/doc/user/install.xml new file mode 100644 index 0000000..e011986 --- /dev/null +++ b/doc/user/install.xml @@ -0,0 +1,237 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Once a program is built, + it is often appropriate to install it in another + directory for public use. + You use the &Install; method + to arrange for a program, or any other file, + to be copied into a destination directory: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + env.Install('/usr/bin', hello) + </programlisting> + + <para> + + Note, however, that installing a file is + still considered a type of file "build." + This is important when you remember that + the default behavior of &SCons; is + to build files in or below the current directory. + If, as in the example above, + you are installing files in a directory + outside of the top-level &SConstruct; file's directory tree, + you must specify that directory + (or a higher directory, such as <literal>/</literal>) + for it to install anything there: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q /usr/bin</userinput> + Install file: "hello" as "/usr/bin/hello" + </screen> + + <para> + + It can, however, be cumbersome to remember + (and type) the specific destination directory + in which the program (or any other file) + should be installed. + This is an area where the &Alias; + function comes in handy, + allowing you, for example, + to create a pseudo-target named <literal>install</literal> + that can expand to the specified destination directory: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + env.Install('/usr/bin', hello) + env.Alias('install', '/usr/bin') + </programlisting> + + <para> + + This then yields the more natural + ability to install the program + in its destination as follows: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + % <userinput>scons -Q install</userinput> + Install file: "hello" as "/usr/bin/hello" + </screen> + + <section> + <title>Installing Multiple Files in a Directory</title> + + <para> + + You can install multiple files into a directory + simply by calling the &Install; function multiple times: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + goodbye = env.Program('goodbye.c') + env.Install('/usr/bin', hello) + env.Install('/usr/bin', goodbye) + env.Alias('install', '/usr/bin') + </programlisting> + + <para> + + Or, more succinctly, listing the multiple input + files in a list + (just like you can do with any other builder): + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + goodbye = env.Program('goodbye.c') + env.Install('/usr/bin', [hello, goodbye]) + env.Alias('install', '/usr/bin') + </programlisting> + + <para> + + Either of these two examples yields: + + </para> + + <screen> + % <userinput>scons -Q install</userinput> + cc -o goodbye.o -c goodbye.c + cc -o goodbye goodbye.o + Install file: "goodbye" as "/usr/bin/goodbye" + cc -o hello.o -c hello.c + cc -o hello hello.o + Install file: "hello" as "/usr/bin/hello" + </screen> + + </section> + + <section> + <title>Installing a File Under a Different Name</title> + + <para> + + The &Install; method preserves the name + of the file when it is copied into the + destination directory. + If you need to change the name of the file + when you copy it, use the &InstallAs; function: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + env.InstallAs('/usr/bin/hello-new', hello) + env.Alias('install', '/usr/bin') + </programlisting> + + <para> + + This installs the <literal>hello</literal> + program with the name <literal>hello-new</literal> + as follows: + + </para> + + <screen> + % <userinput>scons -Q install</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + Install file: "hello" as "/usr/bin/hello-new" + </screen> + + </section> + + <section> + <title>Installing Multiple Files Under Different Names</title> + + <para> + + Lastly, if you have multiple files that all + need to be installed with different file names, + you can either call the &InstallAs; function + multiple times, or as a shorthand, + you can supply same-length lists + for both the target and source arguments: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + goodbye = env.Program('goodbye.c') + env.InstallAs(['/usr/bin/hello-new', + '/usr/bin/goodbye-new'], + [hello, goodbye]) + env.Alias('install', '/usr/bin') + </programlisting> + + <para> + + In this case, the &InstallAs; function + loops through both lists simultaneously, + and copies each source file into its corresponding + target file name: + + </para> + + <screen> + % <userinput>scons -Q install</userinput> + cc -o goodbye.o -c goodbye.c + cc -o goodbye goodbye.o + Install file: "goodbye" as "/usr/bin/goodbye-new" + cc -o hello.o -c hello.c + cc -o hello hello.o + Install file: "hello" as "/usr/bin/hello-new" + </screen> + + </section> diff --git a/doc/user/java.in b/doc/user/java.in new file mode 100644 index 0000000..358d79b --- /dev/null +++ b/doc/user/java.in @@ -0,0 +1,657 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + So far, we've been using examples of + building C and C++ programs + to demonstrate the features of &SCons;. + &SCons; also supports building Java programs, + but Java builds are handled slightly differently, + which reflects the ways in which + the Java compiler and tools + build programs differently than + other languages' tool chains. + + </para> + + <section> + <title>Building Java Class Files: the &b-Java; Builder</title> + + <para> + + The basic activity when programming in Java, + of course, is to take one or more <filename>.java</filename> files + containing Java source code + and to call the Java compiler + to turn them into one or more + <filename>.class</filename> files. + In &SCons;, you do this + by giving the &b-link-Java; Builder + a target directory in which + to put the <filename>.class</filename> files, + and a source directory that contains + the <filename>.java</filename> files: + + </para> + + <scons_example name="java"> + <file name="SConstruct" printme="1"> + Java('classes', 'src') + </file> + <file name="src/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> + + <para> + + If the <filename>src</filename> directory contains + three <filename>.java</filename> source files, + then running &SCons; might look like this: + + </para> + + <scons_output example="java"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + &SCons; will actually search the <filename>src</filename> + directory tree for all of the <filename>.java</filename> files. + The Java compiler will then create the + necessary class files in the <filename>classes</filename> subdirectory, + based on the class names found in the <filename>.java</filename> files. + + </para> + + </section> + + <section> + <title>How &SCons; Handles Java Dependencies</title> + + <para> + + In addition to searching the source directory for + <filename>.java</filename> files, + &SCons; actually runs the <filename>.java</filename> files + through a stripped-down Java parser that figures out + what classes are defined. + In other words, &SCons; knows, + without you having to tell it, + what <filename>.class</filename> files + will be produced by the &javac; call. + So our one-liner example from the preceding section: + + </para> + + <scons_example name="java-classes"> + <file name="SConstruct" printme="1"> + Java('classes', 'src') + </file> + <file name="src/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + public class AdditionalClass1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example2.java"> + public class Example2 + { + class Inner2 { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + } + </file> + <file name="src/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + public class AdditionalClass3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> + + <para> + + Will not only tell you reliably + that the <filename>.class</filename> files + in the <filename>classes</filename> subdirectory + are up-to-date: + + </para> + + <scons_output example="java-classes"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q classes</scons_output_command> + </scons_output> + + <para> + + But it will also remove all of the generated + <filename>.class</filename> files, + even for inner classes, + without you having to specify them manually. + For example, if our + <filename>Example1.java</filename> + and + <filename>Example3.java</filename> + files both define additional classes, + and the class defined in <filename>Example2.java</filename> + has an inner class, + running <userinput>scons -c</userinput> + will clean up all of those <filename>.class</filename> files + as well: + + </para> + + <scons_output example="java-classes"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c classes</scons_output_command> + </scons_output> + + <para> + + To ensure correct handling of <filename>.class</filename> + dependencies in all cases, you need to tell &SCons; which Java + version is being used. This is needed because Java 1.5 changed + the <filename>.class</filename> file names for nested anonymous + inner classes. Use the <varname>JAVAVERSION</varname> construction + variable to specify the version in use. With Java 1.6, the + one-liner example can then be defined like this: + + </para> + + <sconstruct> + Java('classes', 'src', JAVAVERSION='1.6') + </sconstruct> + + <para> + See <varname>JAVAVERSION</varname> in the man page for more information. + </para> + + </section> + + <section> + <title>Building Java Archive (<filename>.jar</filename>) Files: the &b-Jar; Builder</title> + + <para> + + After building the class files, + it's common to collect them into + a Java archive (<filename>.jar</filename>) file, + which you do by calling the &b-link-Jar; Builder method. + If you want to just collect all of the + class files within a subdirectory, + you can just specify that subdirectory + as the &b-Jar; source: + + </para> + + <scons_example name="jar1"> + <file name="SConstruct" printme="1"> + Java(target = 'classes', source = 'src') + Jar(target = 'test.jar', source = 'classes') + </file> + <file name="src/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> + + <para> + + &SCons; will then pass that directory + to the &jar; command, + which will collect all of the underlying + <filename>.class</filename> files: + + </para> + + <scons_output example="jar1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + If you want to keep all of the + <filename>.class</filename> files + for multiple programs in one location, + and only archive some of them in + each <filename>.jar</filename> file, + you can pass the &b-Jar; builder a + list of files as its source. + It's extremely simple to create multiple + <filename>.jar</filename> files this way, + using the lists of target class files created + by calls to the &b-link-Java; builder + as sources to the various &b-Jar; calls: + + </para> + + <scons_example name="jar2"> + <file name="SConstruct" printme="1"> + prog1_class_files = Java(target = 'classes', source = 'prog1') + prog2_class_files = Java(target = 'classes', source = 'prog2') + Jar(target = 'prog1.jar', source = prog1_class_files) + Jar(target = 'prog2.jar', source = prog2_class_files) + </file> + <file name="prog1/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog1/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog2/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog2/Example4.java"> + public class Example4 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> + + <para> + + This will then create + <filename>prog1.jar</filename> + and <filename>prog2.jar</filename> + next to the subdirectories + that contain their <filename>.java</filename> files: + + </para> + + <scons_output example="jar2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Building C Header and Stub Files: the &b-JavaH; Builder</title> + + <para> + + You can generate C header and source files + for implementing native methods, + by using the &b-link-JavaH; Builder. + There are several ways of using the &JavaH Builder. + One typical invocation might look like: + + </para> + + <scons_example name="javah"> + <file name="SConstruct" printme="1"> + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = 'native', source = classes) + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> + + <para> + + The source is a list of class files generated by the + call to the &b-link-Java; Builder, + and the target is the output directory in + which we want the C header files placed. + The target + gets converted into the <option>-d</option> + when &SCons; runs &javah;: + + </para> + + <scons_output example="javah"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + In this case, + the call to &javah; + will generate the header files + <filename>native/pkg_sub_Example1.h</filename>, + <filename>native/pkg_sub_Example2.h</filename> + and + <filename>native/pkg_sub_Example3.h</filename>. + Notice that &SCons; remembered that the class + files were generated with a target directory of + <filename>classes</filename>, + and that it then specified that target directory + as the <option>-classpath</option> option + to the call to &javah;. + + </para> + + <para> + + Although it's more convenient to use + the list of class files returned by + the &b-Java; Builder + as the source of a call to the &b-JavaH; Builder, + you <emphasis>can</emphasis> + specify the list of class files + by hand, if you prefer. + If you do, + you need to set the + &cv-link-JAVACLASSDIR; construction variable + when calling &b-JavaH;: + + </para> + + <scons_example name="JAVACLASSDIR"> + <file name="SConstruct" printme="1"> + Java(target = 'classes', source = 'src/pkg/sub') + class_file_list = ['classes/pkg/sub/Example1.class', + 'classes/pkg/sub/Example2.class', + 'classes/pkg/sub/Example3.class'] + JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes') + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> + + <para> + + The &cv-JAVACLASSDIR; value then + gets converted into the <option>-classpath</option> + when &SCons; runs &javah;: + + </para> + + <scons_output example="JAVACLASSDIR"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Lastly, if you don't want a separate header file + generated for each source file, + you can specify an explicit File Node + as the target of the &b-JavaH; Builder: + + </para> + + <scons_example name="javah_file"> + <file name="SConstruct" printme="1"> + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = File('native.h'), source = classes) + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> + + <para> + + Because &SCons; assumes by default + that the target of the &b-JavaH; builder is a directory, + you need to use the &File; function + to make sure that &SCons; doesn't + create a directory named <filename>native.h</filename>. + When a file is used, though, + &SCons; correctly converts the file name + into the &javah; <option>-o</option> option: + + </para> + + <scons_output example="javah_file"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Building RMI Stub and Skeleton Class Files: the &b-RMIC; Builder</title> + + <para> + + You can generate Remote Method Invocation stubs + by using the &b-link-RMIC; Builder. + The source is a list of directories, + typically returned by a call to the &b-link-Java; Builder, + and the target is an output directory + where the <filename>_Stub.class</filename> + and <filename>_Skel.class</filename> files will + be placed: + + </para> + + <scons_example name="RMIC"> + <file name="SConstruct" printme="1"> + classes = Java(target = 'classes', source = 'src/pkg/sub') + RMIC(target = 'outdir', source = classes) + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> + + <para> + + As it did with the &b-link-JavaH; Builder, + &SCons; remembers the class directory + and passes it as the <option>-classpath</option> option + to &rmic: + + </para> + + <scons_output example="RMIC"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + This example would generate the files + <filename>outdir/pkg/sub/Example1_Skel.class</filename>, + <filename>outdir/pkg/sub/Example1_Stub.class</filename>, + <filename>outdir/pkg/sub/Example2_Skel.class</filename> and + <filename>outdir/pkg/sub/Example2_Stub.class</filename>. + + </para> + + </section> diff --git a/doc/user/java.xml b/doc/user/java.xml new file mode 100644 index 0000000..8198b65 --- /dev/null +++ b/doc/user/java.xml @@ -0,0 +1,433 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + So far, we've been using examples of + building C and C++ programs + to demonstrate the features of &SCons;. + &SCons; also supports building Java programs, + but Java builds are handled slightly differently, + which reflects the ways in which + the Java compiler and tools + build programs differently than + other languages' tool chains. + + </para> + + <section> + <title>Building Java Class Files: the &b-Java; Builder</title> + + <para> + + The basic activity when programming in Java, + of course, is to take one or more <filename>.java</filename> files + containing Java source code + and to call the Java compiler + to turn them into one or more + <filename>.class</filename> files. + In &SCons;, you do this + by giving the &b-link-Java; Builder + a target directory in which + to put the <filename>.class</filename> files, + and a source directory that contains + the <filename>.java</filename> files: + + </para> + + <programlisting> + Java('classes', 'src') + </programlisting> + + <para> + + If the <filename>src</filename> directory contains + three <filename>.java</filename> source files, + then running &SCons; might look like this: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + </screen> + + <para> + + &SCons; will actually search the <filename>src</filename> + directory tree for all of the <filename>.java</filename> files. + The Java compiler will then create the + necessary class files in the <filename>classes</filename> subdirectory, + based on the class names found in the <filename>.java</filename> files. + + </para> + + </section> + + <section> + <title>How &SCons; Handles Java Dependencies</title> + + <para> + + In addition to searching the source directory for + <filename>.java</filename> files, + &SCons; actually runs the <filename>.java</filename> files + through a stripped-down Java parser that figures out + what classes are defined. + In other words, &SCons; knows, + without you having to tell it, + what <filename>.class</filename> files + will be produced by the &javac; call. + So our one-liner example from the preceding section: + + </para> + + <programlisting> + Java('classes', 'src') + </programlisting> + + <para> + + Will not only tell you reliably + that the <filename>.class</filename> files + in the <filename>classes</filename> subdirectory + are up-to-date: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + % <userinput>scons -Q classes</userinput> + scons: `classes' is up to date. + </screen> + + <para> + + But it will also remove all of the generated + <filename>.class</filename> files, + even for inner classes, + without you having to specify them manually. + For example, if our + <filename>Example1.java</filename> + and + <filename>Example3.java</filename> + files both define additional classes, + and the class defined in <filename>Example2.java</filename> + has an inner class, + running <userinput>scons -c</userinput> + will clean up all of those <filename>.class</filename> files + as well: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + % <userinput>scons -Q -c classes</userinput> + Removed classes/Example1.class + Removed classes/AdditionalClass1.class + Removed classes/Example2$Inner2.class + Removed classes/Example2.class + Removed classes/Example3.class + Removed classes/AdditionalClass3.class + </screen> + + <para> + + To ensure correct handling of <filename>.class</filename> + dependencies in all cases, you need to tell &SCons; which Java + version is being used. This is needed because Java 1.5 changed + the <filename>.class</filename> file names for nested anonymous + inner classes. Use the <varname>JAVAVERSION</varname> construction + variable to specify the version in use. With Java 1.6, the + one-liner example can then be defined like this: + + </para> + + <programlisting> + Java('classes', 'src', JAVAVERSION='1.6') + </programlisting> + + <para> + See <varname>JAVAVERSION</varname> in the man page for more information. + </para> + + </section> + + <section> + <title>Building Java Archive (<filename>.jar</filename>) Files: the &b-Jar; Builder</title> + + <para> + + After building the class files, + it's common to collect them into + a Java archive (<filename>.jar</filename>) file, + which you do by calling the &b-link-Jar; Builder method. + If you want to just collect all of the + class files within a subdirectory, + you can just specify that subdirectory + as the &b-Jar; source: + + </para> + + <programlisting> + Java(target = 'classes', source = 'src') + Jar(target = 'test.jar', source = 'classes') + </programlisting> + + <para> + + &SCons; will then pass that directory + to the &jar; command, + which will collect all of the underlying + <filename>.class</filename> files: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + jar cf test.jar classes + </screen> + + <para> + + If you want to keep all of the + <filename>.class</filename> files + for multiple programs in one location, + and only archive some of them in + each <filename>.jar</filename> file, + you can pass the &b-Jar; builder a + list of files as its source. + It's extremely simple to create multiple + <filename>.jar</filename> files this way, + using the lists of target class files created + by calls to the &b-link-Java; builder + as sources to the various &b-Jar; calls: + + </para> + + <programlisting> + prog1_class_files = Java(target = 'classes', source = 'prog1') + prog2_class_files = Java(target = 'classes', source = 'prog2') + Jar(target = 'prog1.jar', source = prog1_class_files) + Jar(target = 'prog2.jar', source = prog2_class_files) + </programlisting> + + <para> + + This will then create + <filename>prog1.jar</filename> + and <filename>prog2.jar</filename> + next to the subdirectories + that contain their <filename>.java</filename> files: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath prog1 prog1/Example1.java prog1/Example2.java + javac -d classes -sourcepath prog2 prog2/Example3.java prog2/Example4.java + jar cf prog1.jar -C classes Example1.class -C classes Example2.class + jar cf prog2.jar -C classes Example3.class -C classes Example4.class + </screen> + + </section> + + <section> + <title>Building C Header and Stub Files: the &b-JavaH; Builder</title> + + <para> + + You can generate C header and source files + for implementing native methods, + by using the &b-link-JavaH; Builder. + There are several ways of using the &JavaH; Builder. + One typical invocation might look like: + + </para> + + <programlisting> + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = 'native', source = classes) + </programlisting> + + <para> + + The source is a list of class files generated by the + call to the &b-link-Java; Builder, + and the target is the output directory in + which we want the C header files placed. + The target + gets converted into the <option>-d</option> + when &SCons; runs &javah;: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java + javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 + </screen> + + <para> + + In this case, + the call to &javah; + will generate the header files + <filename>native/pkg_sub_Example1.h</filename>, + <filename>native/pkg_sub_Example2.h</filename> + and + <filename>native/pkg_sub_Example3.h</filename>. + Notice that &SCons; remembered that the class + files were generated with a target directory of + <filename>classes</filename>, + and that it then specified that target directory + as the <option>-classpath</option> option + to the call to &javah;. + + </para> + + <para> + + Although it's more convenient to use + the list of class files returned by + the &b-Java; Builder + as the source of a call to the &b-JavaH; Builder, + you <emphasis>can</emphasis> + specify the list of class files + by hand, if you prefer. + If you do, + you need to set the + &cv-link-JAVACLASSDIR; construction variable + when calling &b-JavaH;: + + </para> + + <programlisting> + Java(target = 'classes', source = 'src/pkg/sub') + class_file_list = ['classes/pkg/sub/Example1.class', + 'classes/pkg/sub/Example2.class', + 'classes/pkg/sub/Example3.class'] + JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes') + </programlisting> + + <para> + + The &cv-JAVACLASSDIR; value then + gets converted into the <option>-classpath</option> + when &SCons; runs &javah;: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java + javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 + </screen> + + <para> + + Lastly, if you don't want a separate header file + generated for each source file, + you can specify an explicit File Node + as the target of the &b-JavaH; Builder: + + </para> + + <programlisting> + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = File('native.h'), source = classes) + </programlisting> + + <para> + + Because &SCons; assumes by default + that the target of the &b-JavaH; builder is a directory, + you need to use the &File; function + to make sure that &SCons; doesn't + create a directory named <filename>native.h</filename>. + When a file is used, though, + &SCons; correctly converts the file name + into the &javah; <option>-o</option> option: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java + javah -o native.h -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 + </screen> + + </section> + + <section> + <title>Building RMI Stub and Skeleton Class Files: the &b-RMIC; Builder</title> + + <para> + + You can generate Remote Method Invocation stubs + by using the &b-link-RMIC; Builder. + The source is a list of directories, + typically returned by a call to the &b-link-Java; Builder, + and the target is an output directory + where the <filename>_Stub.class</filename> + and <filename>_Skel.class</filename> files will + be placed: + + </para> + + <programlisting> + classes = Java(target = 'classes', source = 'src/pkg/sub') + RMIC(target = 'outdir', source = classes) + </programlisting> + + <para> + + As it did with the &b-link-JavaH; Builder, + &SCons; remembers the class directory + and passes it as the <option>-classpath</option> option + to &rmic;: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java + rmic -d outdir -classpath classes pkg.sub.Example1 pkg.sub.Example2 + </screen> + + <para> + + This example would generate the files + <filename>outdir/pkg/sub/Example1_Skel.class</filename>, + <filename>outdir/pkg/sub/Example1_Stub.class</filename>, + <filename>outdir/pkg/sub/Example2_Skel.class</filename> and + <filename>outdir/pkg/sub/Example2_Stub.class</filename>. + + </para> + + </section> diff --git a/doc/user/less-simple.in b/doc/user/less-simple.in new file mode 100644 index 0000000..e19ba13 --- /dev/null +++ b/doc/user/less-simple.in @@ -0,0 +1,623 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + In this chapter, + you will see several examples of + very simple build configurations using &SCons;, + which will demonstrate how easy + it is to use &SCons; to + build programs from several different programming languages + on different types of systems. + + </para> + + <section> + <title>Specifying the Name of the Target (Output) File</title> + + <para> + + You've seen that when you call the &b-link-Program; builder method, + it builds the resulting program with the same + base name as the source file. + That is, the following call to build an + executable program from the &hello_c; source file + will build an executable program named &hello; on POSIX systems, + and an executable program named &hello_exe; on Windows systems: + + </para> + + <programlisting> + Program('hello.c') + </programlisting> + + <para> + + If you want to build a program with + a different name than the base of the source file name, + you simply put the target file name + to the left of the source file name: + + </para> + + <scons_example name="target"> + <file name="SConstruct" printme="1"> + Program('new_hello', 'hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + (&SCons; requires the target file name first, + followed by the source file name, + so that the order mimics that of an + assignment statement in most programming languages, + including Python: + <literal>"program = source files"</literal>.) + + </para> + + <para> + + Now &SCons; will build an executable program + named &new_hello; when run on a POSIX system: + + </para> + + <scons_output example="target" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And &SCons; will build an executable program + named &new_hello_exe; when run on a Windows system: + + </para> + + <scons_output example="target" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Compiling Multiple Source Files</title> + + <para> + + You've just seen how to configure &SCons; + to compile a program from a single source file. + It's more common, of course, + that you'll need to build a program from + many input source files, not just one. + To do this, you need to put the + source files in a Python list + (enclosed in square brackets), + like so: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + Program(['prog.c', 'file1.c', 'file2.c']) + </file> + <file name="prog.c"> + int main() { printf("prog.c\n"); } + </file> + <file name="file1.c"> + void file1() { printf("file1.c\n"); } + </file> + <file name="file2.c"> + void file2() { printf("file2.c\n"); } + </file> + </scons_example> + + <para> + + A build of the above example would look like: + + </para> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Notice that &SCons; + deduces the output program name + from the first source file specified + in the list--that is, + because the first source file was &prog_c;, + &SCons; will name the resulting program &prog; + (or &prog_exe; on a Windows system). + If you want to specify a different program name, + then (as we've seen in the previous section) + you slide the list of source files + over to the right + to make room for the output program file name. + (&SCons; puts the output file name to the left + of the source file names + so that the order mimics that of an + assignment statement: "program = source files".) + This makes our example: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> + Program('program', ['prog.c', 'file1.c', 'file2.c']) + </file> + <file name="prog.c"> + int main() { printf("prog.c\n"); } + </file> + <file name="file1.c"> + void file1() { printf("file1.c\n"); } + </file> + <file name="file2.c"> + void file2() { printf("file2.c\n"); } + </file> + </scons_example> + + <para> + + On Linux, a build of this example would look like: + + </para> + + <scons_output example="ex3" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Or on Windows: + + </para> + + <scons_output example="ex3" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Making a list of files with &Glob;</title> + + <para> + + You can also use the &Glob; function to find all files matching a + certain template, using the standard shell pattern matching + characters <literal>*</literal>, <literal>?</literal> + and <literal>[abc]</literal> to match any of + <literal>a</literal>, <literal>b</literal> or <literal>c</literal>. + <literal>[!abc]</literal> is also supported, + to match any character <emphasis>except</emphasis> + <literal>a</literal>, <literal>b</literal> or <literal>c</literal>. + This makes many multi-source-file builds quite easy: + + </para> + + <sconstruct> + Program('program', Glob('*.c')) + </sconstruct> + + <para> + + The SCons man page has more details on using &Glob; + with variant directories + (see <xref linkend="chap-variants"></xref>, below) + and repositories + (see <xref linkend="chap-repositories"></xref>, below), + and returning strings rather than Nodes. + + </para> + + </section> + + <section> + <title>Specifying Single Files Vs. Lists of Files</title> + + <para> + + We've now shown you two ways to specify + the source for a program, + one with a list of files: + + </para> + + <sconstruct> + Program('hello', ['file1.c', 'file2.c']) + </sconstruct> + + <para> + + And one with a single file: + + </para> + + <sconstruct> + Program('hello', 'hello.c') + </sconstruct> + + <para> + + You could actually put a single file name in a list, too, + which you might prefer just for the sake of consistency: + + </para> + + <sconstruct> + Program('hello', ['hello.c']) + </sconstruct> + + <para> + + &SCons; functions will accept a single file name in either form. + In fact, internally, &SCons; treats all input as lists of files, + but allows you to omit the square brackets + to cut down a little on the typing + when there's only a single file name. + + </para> + + <important> + + <para> + + Although &SCons; functions + are forgiving about whether or not you + use a string vs. a list for a single file name, + Python itself is more strict about + treating lists and strings differently. + So where &SCons; allows either + a string or list: + + </para> + + <sconstruct> + # The following two calls both work correctly: + Program('program1', 'program1.c') + Program('program2', ['program2.c']) + </sconstruct> + + <para> + + Trying to do "Python things" that mix strings and + lists will cause errors or lead to incorrect results: + + </para> + + <sconstruct> + common_sources = ['file1.c', 'file2.c'] + + # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR + # BECAUSE IT TRIES TO ADD A STRING TO A LIST: + Program('program1', common_sources + 'program1.c') + + # The following works correctly, because it's adding two + # lists together to make another list. + Program('program2', common_sources + ['program2.c']) + </sconstruct> + + </important> + + </section> + + <section> + <title>Making Lists of Files Easier to Read</title> + + <para> + + One drawback to the use of a Python list + for source files is that + each file name must be enclosed in quotes + (either single quotes or double quotes). + This can get cumbersome and difficult to read + when the list of file names is long. + Fortunately, &SCons; and Python provide a number of ways + to make sure that + the &SConstruct; file stays easy to read. + + </para> + + <para> + + To make long lists of file names + easier to deal with, &SCons; provides a + &Split; function + that takes a quoted list of file names, + with the names separated by spaces or other white-space characters, + and turns it into a list of separate file names. + Using the &Split; function turns the + previous example into: + + </para> + + <programlisting> + Program('program', Split('main.c file1.c file2.c')) + </programlisting> + + <para> + + (If you're already familiar with Python, + you'll have realized that this is similar to the + <function>split()</function> method + in the Python standard <function>string</function> module. + Unlike the <function>string.split()</function> method, + however, the &Split; function + does not require a string as input + and will wrap up a single non-string object in a list, + or return its argument untouched if it's already a list. + This comes in handy as a way to make sure + arbitrary values can be passed to &SCons; functions + without having to check the type of the variable by hand.) + + </para> + + <para> + + Putting the call to the &Split; function + inside the &b-Program; call + can also be a little unwieldy. + A more readable alternative is to + assign the output from the &Split; call + to a variable name, + and then use the variable when calling the + &b-Program; function: + + </para> + + <programlisting> + src_files = Split('main.c file1.c file2.c') + Program('program', src_files) + </programlisting> + + <para> + + Lastly, the &Split; function + doesn't care how much white space separates + the file names in the quoted string. + This allows you to create lists of file + names that span multiple lines, + which often makes for easier editing: + + </para> + + <programlisting> + src_files = Split("""main.c + file1.c + file2.c""") + Program('program', src_files) + </programlisting> + + <para> + + (Note in this example that we used + the Python "triple-quote" syntax, + which allows a string to contain + multiple lines. + The three quotes can be either + single or double quotes.) + + </para> + + </section> + + <section> + <title>Keyword Arguments</title> + + <para> + + &SCons; also allows you to identify + the output file and input source files + using Python keyword arguments. + The output file is known as the + <emphasis>target</emphasis>, + and the source file(s) are known (logically enough) as the + <emphasis>source</emphasis>. + The Python syntax for this is: + + </para> + + <programlisting> + src_files = Split('main.c file1.c file2.c') + Program(target = 'program', source = src_files) + </programlisting> + + <para> + + Because the keywords explicitly identify + what each argument is, + you can actually reverse the order if you prefer: + + </para> + + <programlisting> + src_files = Split('main.c file1.c file2.c') + Program(source = src_files, target = 'program') + </programlisting> + + <para> + + Whether or not you choose to use keyword arguments + to identify the target and source files, + and the order in which you specify them + when using keywords, + are purely personal choices; + &SCons; functions the same regardless. + + </para> + + </section> + + <section> + <title>Compiling Multiple Programs</title> + + <para> + + In order to compile multiple programs + within the same &SConstruct; file, + simply call the &Program; method + multiple times, + once for each program you need to build: + + </para> + + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> + Program('foo.c') + Program('bar', ['bar1.c', 'bar2.c']) + </file> + <file name="foo.c"> + int main() { printf("foo.c\n"); } + </file> + <file name="bar1.c"> + int main() { printf("bar1.c\n"); } + </file> + <file name="bar2.c"> + void bar2() { printf("bar2.c\n"); } + </file> + </scons_example> + + <para> + + &SCons; would then build the programs as follows: + + </para> + + <scons_output example="ex4"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Notice that &SCons; does not necessarily build the + programs in the same order in which you specify + them in the &SConstruct; file. + &SCons; does, however, recognize that + the individual object files must be built + before the resulting program can be built. + We'll discuss this in greater detail in + the "Dependencies" section, below. + + </para> + + </section> + + <section> + <title>Sharing Source Files Between Multiple Programs</title> + + <para> + + It's common to re-use code by sharing source files + between multiple programs. + One way to do this is to create a library + from the common source files, + which can then be linked into resulting programs. + (Creating libraries is discussed in + <xref linkend="chap-libraries"></xref>, below.) + + </para> + + <para> + + A more straightforward, but perhaps less convenient, + way to share source files between multiple programs + is simply to include the common files + in the lists of source files for each program: + + </para> + + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> + Program(Split('foo.c common1.c common2.c')) + Program('bar', Split('bar1.c bar2.c common1.c common2.c')) + </file> + <file name="foo.c"> + int main() { printf("foo.c\n"); } + </file> + <file name="bar1.c"> + int main() { printf("bar1.c\n"); } + </file> + <file name="bar2.c"> + int bar2() { printf("bar2.c\n"); } + </file> + <file name="common1.c"> + void common1() { printf("common1.c\n"); } + </file> + <file name="common2.c"> + void common22() { printf("common2.c\n"); } + </file> + </scons_example> + + <para> + + &SCons; recognizes that the object files for + the &common1_c; and &common2_c; source files + each need to be built only once, + even though the resulting object files are + each linked in to both of the resulting executable programs: + + </para> + + <scons_output example="ex5"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + If two or more programs + share a lot of common source files, + repeating the common files in the list for each program + can be a maintenance problem when you need to change the + list of common files. + You can simplify this by creating a separate Python list + to hold the common file names, + and concatenating it with other lists + using the Python + operator: + + </para> + + <programlisting> + common = ['common1.c', 'common2.c'] + foo_files = ['foo.c'] + common + bar_files = ['bar1.c', 'bar2.c'] + common + Program('foo', foo_files) + Program('bar', bar_files) + </programlisting> + + <para> + + This is functionally equivalent to the previous example. + + </para> + + </section> diff --git a/doc/user/less-simple.xml b/doc/user/less-simple.xml new file mode 100644 index 0000000..57c61e2 --- /dev/null +++ b/doc/user/less-simple.xml @@ -0,0 +1,608 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + In this chapter, + you will see several examples of + very simple build configurations using &SCons;, + which will demonstrate how easy + it is to use &SCons; to + build programs from several different programming languages + on different types of systems. + + </para> + + <section> + <title>Specifying the Name of the Target (Output) File</title> + + <para> + + You've seen that when you call the &b-link-Program; builder method, + it builds the resulting program with the same + base name as the source file. + That is, the following call to build an + executable program from the &hello_c; source file + will build an executable program named &hello; on POSIX systems, + and an executable program named &hello_exe; on Windows systems: + + </para> + + <programlisting> + Program('hello.c') + </programlisting> + + <para> + + If you want to build a program with + a different name than the base of the source file name, + you simply put the target file name + to the left of the source file name: + + </para> + + <programlisting> + Program('new_hello', 'hello.c') + </programlisting> + + <para> + + (&SCons; requires the target file name first, + followed by the source file name, + so that the order mimics that of an + assignment statement in most programming languages, + including Python: + <literal>"program = source files"</literal>.) + + </para> + + <para> + + Now &SCons; will build an executable program + named &new_hello; when run on a POSIX system: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o new_hello hello.o + </screen> + + <para> + + And &SCons; will build an executable program + named &new_hello_exe; when run on a Windows system: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fohello.obj /c hello.c /nologo + link /nologo /OUT:new_hello.exe hello.obj + </screen> + + </section> + + <section> + <title>Compiling Multiple Source Files</title> + + <para> + + You've just seen how to configure &SCons; + to compile a program from a single source file. + It's more common, of course, + that you'll need to build a program from + many input source files, not just one. + To do this, you need to put the + source files in a Python list + (enclosed in square brackets), + like so: + + </para> + + <programlisting> + Program(['prog.c', 'file1.c', 'file2.c']) + </programlisting> + + <para> + + A build of the above example would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o file1.o -c file1.c + cc -o file2.o -c file2.c + cc -o prog.o -c prog.c + cc -o prog prog.o file1.o file2.o + </screen> + + <para> + + Notice that &SCons; + deduces the output program name + from the first source file specified + in the list--that is, + because the first source file was &prog_c;, + &SCons; will name the resulting program &prog; + (or &prog_exe; on a Windows system). + If you want to specify a different program name, + then (as we've seen in the previous section) + you slide the list of source files + over to the right + to make room for the output program file name. + (&SCons; puts the output file name to the left + of the source file names + so that the order mimics that of an + assignment statement: "program = source files".) + This makes our example: + + </para> + + <programlisting> + Program('program', ['prog.c', 'file1.c', 'file2.c']) + </programlisting> + + <para> + + On Linux, a build of this example would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o file1.o -c file1.c + cc -o file2.o -c file2.c + cc -o prog.o -c prog.c + cc -o program prog.o file1.o file2.o + </screen> + + <para> + + Or on Windows: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fofile1.obj /c file1.c /nologo + cl /Fofile2.obj /c file2.c /nologo + cl /Foprog.obj /c prog.c /nologo + link /nologo /OUT:program.exe prog.obj file1.obj file2.obj + </screen> + + </section> + + <section> + <title>Making a list of files with &Glob;</title> + + <para> + + You can also use the &Glob; function to find all files matching a + certain template, using the standard shell pattern matching + characters <literal>*</literal>, <literal>?</literal> + and <literal>[abc]</literal> to match any of + <literal>a</literal>, <literal>b</literal> or <literal>c</literal>. + <literal>[!abc]</literal> is also supported, + to match any character <emphasis>except</emphasis> + <literal>a</literal>, <literal>b</literal> or <literal>c</literal>. + This makes many multi-source-file builds quite easy: + + </para> + + <programlisting> + Program('program', Glob('*.c')) + </programlisting> + + <para> + + The SCons man page has more details on using &Glob; + with variant directories + (see <xref linkend="chap-variants"></xref>, below) + and repositories + (see <xref linkend="chap-repositories"></xref>, below), + and returning strings rather than Nodes. + + </para> + + </section> + + <section> + <title>Specifying Single Files Vs. Lists of Files</title> + + <para> + + We've now shown you two ways to specify + the source for a program, + one with a list of files: + + </para> + + <programlisting> + Program('hello', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + And one with a single file: + + </para> + + <programlisting> + Program('hello', 'hello.c') + </programlisting> + + <para> + + You could actually put a single file name in a list, too, + which you might prefer just for the sake of consistency: + + </para> + + <programlisting> + Program('hello', ['hello.c']) + </programlisting> + + <para> + + &SCons; functions will accept a single file name in either form. + In fact, internally, &SCons; treats all input as lists of files, + but allows you to omit the square brackets + to cut down a little on the typing + when there's only a single file name. + + </para> + + <important> + + <para> + + Although &SCons; functions + are forgiving about whether or not you + use a string vs. a list for a single file name, + Python itself is more strict about + treating lists and strings differently. + So where &SCons; allows either + a string or list: + + </para> + + <programlisting> + # The following two calls both work correctly: + Program('program1', 'program1.c') + Program('program2', ['program2.c']) + </programlisting> + + <para> + + Trying to do "Python things" that mix strings and + lists will cause errors or lead to incorrect results: + + </para> + + <programlisting> + common_sources = ['file1.c', 'file2.c'] + + # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR + # BECAUSE IT TRIES TO ADD A STRING TO A LIST: + Program('program1', common_sources + 'program1.c') + + # The following works correctly, because it's adding two + # lists together to make another list. + Program('program2', common_sources + ['program2.c']) + </programlisting> + + </important> + + </section> + + <section> + <title>Making Lists of Files Easier to Read</title> + + <para> + + One drawback to the use of a Python list + for source files is that + each file name must be enclosed in quotes + (either single quotes or double quotes). + This can get cumbersome and difficult to read + when the list of file names is long. + Fortunately, &SCons; and Python provide a number of ways + to make sure that + the &SConstruct; file stays easy to read. + + </para> + + <para> + + To make long lists of file names + easier to deal with, &SCons; provides a + &Split; function + that takes a quoted list of file names, + with the names separated by spaces or other white-space characters, + and turns it into a list of separate file names. + Using the &Split; function turns the + previous example into: + + </para> + + <programlisting> + Program('program', Split('main.c file1.c file2.c')) + </programlisting> + + <para> + + (If you're already familiar with Python, + you'll have realized that this is similar to the + <function>split()</function> method + in the Python standard <function>string</function> module. + Unlike the <function>string.split()</function> method, + however, the &Split; function + does not require a string as input + and will wrap up a single non-string object in a list, + or return its argument untouched if it's already a list. + This comes in handy as a way to make sure + arbitrary values can be passed to &SCons; functions + without having to check the type of the variable by hand.) + + </para> + + <para> + + Putting the call to the &Split; function + inside the &b-Program; call + can also be a little unwieldy. + A more readable alternative is to + assign the output from the &Split; call + to a variable name, + and then use the variable when calling the + &b-Program; function: + + </para> + + <programlisting> + src_files = Split('main.c file1.c file2.c') + Program('program', src_files) + </programlisting> + + <para> + + Lastly, the &Split; function + doesn't care how much white space separates + the file names in the quoted string. + This allows you to create lists of file + names that span multiple lines, + which often makes for easier editing: + + </para> + + <programlisting> + src_files = Split("""main.c + file1.c + file2.c""") + Program('program', src_files) + </programlisting> + + <para> + + (Note in this example that we used + the Python "triple-quote" syntax, + which allows a string to contain + multiple lines. + The three quotes can be either + single or double quotes.) + + </para> + + </section> + + <section> + <title>Keyword Arguments</title> + + <para> + + &SCons; also allows you to identify + the output file and input source files + using Python keyword arguments. + The output file is known as the + <emphasis>target</emphasis>, + and the source file(s) are known (logically enough) as the + <emphasis>source</emphasis>. + The Python syntax for this is: + + </para> + + <programlisting> + src_files = Split('main.c file1.c file2.c') + Program(target = 'program', source = src_files) + </programlisting> + + <para> + + Because the keywords explicitly identify + what each argument is, + you can actually reverse the order if you prefer: + + </para> + + <programlisting> + src_files = Split('main.c file1.c file2.c') + Program(source = src_files, target = 'program') + </programlisting> + + <para> + + Whether or not you choose to use keyword arguments + to identify the target and source files, + and the order in which you specify them + when using keywords, + are purely personal choices; + &SCons; functions the same regardless. + + </para> + + </section> + + <section> + <title>Compiling Multiple Programs</title> + + <para> + + In order to compile multiple programs + within the same &SConstruct; file, + simply call the &Program; method + multiple times, + once for each program you need to build: + + </para> + + <programlisting> + Program('foo.c') + Program('bar', ['bar1.c', 'bar2.c']) + </programlisting> + + <para> + + &SCons; would then build the programs as follows: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o bar1.o -c bar1.c + cc -o bar2.o -c bar2.c + cc -o bar bar1.o bar2.o + cc -o foo.o -c foo.c + cc -o foo foo.o + </screen> + + <para> + + Notice that &SCons; does not necessarily build the + programs in the same order in which you specify + them in the &SConstruct; file. + &SCons; does, however, recognize that + the individual object files must be built + before the resulting program can be built. + We'll discuss this in greater detail in + the "Dependencies" section, below. + + </para> + + </section> + + <section> + <title>Sharing Source Files Between Multiple Programs</title> + + <para> + + It's common to re-use code by sharing source files + between multiple programs. + One way to do this is to create a library + from the common source files, + which can then be linked into resulting programs. + (Creating libraries is discussed in + <xref linkend="chap-libraries"></xref>, below.) + + </para> + + <para> + + A more straightforward, but perhaps less convenient, + way to share source files between multiple programs + is simply to include the common files + in the lists of source files for each program: + + </para> + + <programlisting> + Program(Split('foo.c common1.c common2.c')) + Program('bar', Split('bar1.c bar2.c common1.c common2.c')) + </programlisting> + + <para> + + &SCons; recognizes that the object files for + the &common1_c; and &common2_c; source files + each need to be built only once, + even though the resulting object files are + each linked in to both of the resulting executable programs: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o bar1.o -c bar1.c + cc -o bar2.o -c bar2.c + cc -o common1.o -c common1.c + cc -o common2.o -c common2.c + cc -o bar bar1.o bar2.o common1.o common2.o + cc -o foo.o -c foo.c + cc -o foo foo.o common1.o common2.o + </screen> + + <para> + + If two or more programs + share a lot of common source files, + repeating the common files in the list for each program + can be a maintenance problem when you need to change the + list of common files. + You can simplify this by creating a separate Python list + to hold the common file names, + and concatenating it with other lists + using the Python + operator: + + </para> + + <programlisting> + common = ['common1.c', 'common2.c'] + foo_files = ['foo.c'] + common + bar_files = ['bar1.c', 'bar2.c'] + common + Program('foo', foo_files) + Program('bar', bar_files) + </programlisting> + + <para> + + This is functionally equivalent to the previous example. + + </para> + + </section> diff --git a/doc/user/libraries.in b/doc/user/libraries.in new file mode 100644 index 0000000..4cce091 --- /dev/null +++ b/doc/user/libraries.in @@ -0,0 +1,445 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + It's often useful to organize large software projects + by collecting parts of the software into one or more libraries. + &SCons; makes it easy to create libraries + and to use them in the programs. + + </para> + + <section> + <title>Building Libraries</title> + + <para> + + You build your own libraries by specifying &b-link-Library; + instead of &b-link-Program;: + + </para> + + <scons_example name="ex1" printme="1"> + <file name="SConstruct" printme="1"> + Library('foo', ['f1.c', 'f2.c', 'f3.c']) + </file> + <file name="f1.c"> + void f1() { printf("f1.c\n"); } + </file> + <file name="f2.c"> + void f2() { printf("f2.c\n"); } + </file> + <file name="f3.c"> + void f3() { printf("f3.c\n"); } + </file> + </scons_example> + + <para> + + &SCons; uses the appropriate library prefix and suffix for your system. + So on POSIX or Linux systems, + the above example would build as follows + (although &ranlib; may not be called on all systems): + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <scons_output example="ex1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + The rules for the target name of the library + are similar to those for programs: + if you don't explicitly specify a target library name, + &SCons; will deduce one from the + name of the first source file specified, + and &SCons; will add an appropriate + file prefix and suffix if you leave them off. + + </para> + + <section> + <title>Building Libraries From Source Code or Object Files</title> + + <para> + + The previous example shows building a library from a + list of source files. + You can, however, also give the &b-link-Library; call + object files, + and it will correctly realize + In fact, you can arbitrarily mix source code files + and object files in the source list: + + </para> + + <scons_example name="objects" printme="1"> + <file name="SConstruct" printme="1"> + Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o']) + </file> + <file name="f1.c"> + void f1() { printf("f1.c\n"); } + </file> + <file name="f2.o"> + object file + </file> + <file name="f3.c"> + void f3() { printf("f3.c\n"); } + </file> + <file name="f4.o"> + object file + </file> + </scons_example> + + <para> + + And SCons realizes that only the source code files + must be compiled into object files + before creating the final library: + + </para> + + <scons_output example="objects" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Of course, in this example, the object files + must already exist for the build to succeed. + See <xref linkend="chap-nodes"></xref>, below, + for information about how you can + build object files explicitly + and include the built files in a library. + + </para> + + </section> + + <section> + <title>Building Static Libraries Explicitly: the &b-StaticLibrary; Builder</title> + + <para> + + The &b-link-Library; function builds a traditional static library. + If you want to be explicit about the type of library being built, + you can use the synonym &b-link-StaticLibrary; function + instead of &b-Library;: + + </para> + + <scons_example name="StaticLibrary" printme="1"> + <file name="SConstruct" printme="1"> + StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) + </file> + </scons_example> + + <para> + + There is no functional difference between the + &b-link-StaticLibrary; and &b-Library; functions. + + </para> + + </section> + + <section> + <title>Building Shared (DLL) Libraries: the &b-SharedLibrary; Builder</title> + + <para> + + If you want to build a shared library (on POSIX systems) + or a DLL file (on Windows systems), + you use the &b-link-SharedLibrary; function: + + </para> + + <scons_example name="SharedLibrary" printme="1"> + <file name="SConstruct" printme="1"> + SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) + </file> + <file name="f1.c"> + void f1() { printf("f1.c\n"); } + </file> + <file name="f2.c"> + void f2() { printf("f2.c\n"); } + </file> + <file name="f3.c"> + void f3() { printf("f3.c\n"); } + </file> + </scons_example> + + <para> + + The output on POSIX: + + </para> + + <scons_output example="SharedLibrary" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And the output on Windows: + + </para> + + <scons_output example="SharedLibrary" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Notice again that &SCons; takes care of + building the output file correctly, + adding the <literal>-shared</literal> option + for a POSIX compilation, + and the <literal>/dll</literal> option on Windows. + + </para> + + </section> + + </section> + + <section> + <title>Linking with Libraries</title> + + <para> + + Usually, you build a library + because you want to link it with one or more programs. + You link libraries with a program by specifying + the libraries in the &cv-link-LIBS; construction variable, + and by specifying the directory in which + the library will be found in the + &cv-link-LIBPATH; construction variable: + + <!-- In the preceding paragraph, the "$" notation for + LIBS, LIBPATH etc. is used for the first time. + Maybe some words of explanation would be nice. --> + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + Library('foo', ['f1.c', 'f2.c', 'f3.c']) + Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.') + </file> + <file name="f1.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="f2.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="f3.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="prog.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Notice, of course, that you don't need to specify a library + prefix (like <literal>lib</literal>) + or suffix (like <literal>.a</literal> or <literal>.lib</literal>). + &SCons; uses the correct prefix or suffix for the current system. + + </para> + + <para> + + On a POSIX or Linux system, + a build of the above example would look like: + + </para> + + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <scons_output example="ex2" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + As usual, notice that &SCons; has taken care + of constructing the correct command lines + to link with the specified library on each system. + + </para> + + <para> + + Note also that, + if you only have a single library to link with, + you can specify the library name in single string, + instead of a Python list, + so that: + + </para> + + <sconstruct> + Program('prog.c', LIBS='foo', LIBPATH='.') + </sconstruct> + + <para> + + is equivalent to: + + </para> + + <sconstruct> + Program('prog.c', LIBS=['foo'], LIBPATH='.') + </sconstruct> + + <para> + + This is similar to the way that &SCons; + handles either a string or a list to + specify a single source file. + + </para> + + </section> + + <section> + <title>Finding Libraries: the &cv-LIBPATH; Construction Variable</title> + + <para> + + By default, the linker will only look in + certain system-defined directories for libraries. + &SCons; knows how to look for libraries + in directories that you specify with the + &cv-link-LIBPATH; construction variable. + &cv-LIBPATH; consists of a list of + directory names, like so: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> + Program('prog.c', LIBS = 'm', + LIBPATH = ['/usr/lib', '/usr/local/lib']) + </file> + <file name="prog.c"> + int main() { printf("prog.c\n"); } + </file> + </scons_example> + + <para> + + Using a Python list is preferred because it's portable + across systems. Alternatively, you could put all of + the directory names in a single string, separated by the + system-specific path separator character: + a colon on POSIX systems: + + </para> + + <sconstruct> + LIBPATH = '/usr/lib:/usr/local/lib' + </sconstruct> + + <para> + + or a semi-colon on Windows systems: + + </para> + + <sconstruct> + LIBPATH = 'C:\\lib;D:\\lib' + </sconstruct> + + <para> + + (Note that Python requires that the backslash + separators in a Windows path name + be escaped within strings.) + + </para> + + <para> + + When the linker is executed, + &SCons; will create appropriate flags + so that the linker will look for + libraries in the same directories as &SCons;. + So on a POSIX or Linux system, + a build of the above example would look like: + + </para> + + <scons_output example="ex3" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <scons_output example="ex3" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + <!-- The link command is too wide in the PDF version. + There are some other examples of this throughout the document. --> + + <para> + + Note again that &SCons; has taken care of + the system-specific details of creating + the right command-line options. + + </para> + + </section> diff --git a/doc/user/libraries.xml b/doc/user/libraries.xml new file mode 100644 index 0000000..e3821ce --- /dev/null +++ b/doc/user/libraries.xml @@ -0,0 +1,451 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + It's often useful to organize large software projects + by collecting parts of the software into one or more libraries. + &SCons; makes it easy to create libraries + and to use them in the programs. + + </para> + + <section> + <title>Building Libraries</title> + + <para> + + You build your own libraries by specifying &b-link-Library; + instead of &b-link-Program;: + + </para> + + <programlisting> + Library('foo', ['f1.c', 'f2.c', 'f3.c']) + </programlisting> + + <para> + + &SCons; uses the appropriate library prefix and suffix for your system. + So on POSIX or Linux systems, + the above example would build as follows + (although &ranlib; may not be called on all systems): + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o f1.o -c f1.c + cc -o f2.o -c f2.c + cc -o f3.o -c f3.c + ar rc libfoo.a f1.o f2.o f3.o + ranlib libfoo.a + </screen> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fof1.obj /c f1.c /nologo + cl /Fof2.obj /c f2.c /nologo + cl /Fof3.obj /c f3.c /nologo + lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj + </screen> + + <para> + + The rules for the target name of the library + are similar to those for programs: + if you don't explicitly specify a target library name, + &SCons; will deduce one from the + name of the first source file specified, + and &SCons; will add an appropriate + file prefix and suffix if you leave them off. + + </para> + + <section> + <title>Building Libraries From Source Code or Object Files</title> + + <para> + + The previous example shows building a library from a + list of source files. + You can, however, also give the &b-link-Library; call + object files, + and it will correctly realize + In fact, you can arbitrarily mix source code files + and object files in the source list: + + </para> + + <programlisting> + Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o']) + </programlisting> + + <para> + + And SCons realizes that only the source code files + must be compiled into object files + before creating the final library: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o f1.o -c f1.c + cc -o f3.o -c f3.c + ar rc libfoo.a f1.o f2.o f3.o f4.o + ranlib libfoo.a + </screen> + + <para> + + Of course, in this example, the object files + must already exist for the build to succeed. + See <xref linkend="chap-nodes"></xref>, below, + for information about how you can + build object files explicitly + and include the built files in a library. + + </para> + + </section> + + <section> + <title>Building Static Libraries Explicitly: the &b-StaticLibrary; Builder</title> + + <para> + + The &b-link-Library; function builds a traditional static library. + If you want to be explicit about the type of library being built, + you can use the synonym &b-link-StaticLibrary; function + instead of &b-Library;: + + </para> + + <programlisting> + StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) + </programlisting> + + <para> + + There is no functional difference between the + &b-link-StaticLibrary; and &b-Library; functions. + + </para> + + </section> + + <section> + <title>Building Shared (DLL) Libraries: the &b-SharedLibrary; Builder</title> + + <para> + + If you want to build a shared library (on POSIX systems) + or a DLL file (on Windows systems), + you use the &b-link-SharedLibrary; function: + + </para> + + <programlisting> + SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) + </programlisting> + + <para> + + The output on POSIX: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o f1.os -c f1.c + cc -o f2.os -c f2.c + cc -o f3.os -c f3.c + cc -o libfoo.so -shared f1.os f2.os f3.os + </screen> + + <para> + + And the output on Windows: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fof1.obj /c f1.c /nologo + cl /Fof2.obj /c f2.c /nologo + cl /Fof3.obj /c f3.c /nologo + link /nologo /dll /out:foo.dll /implib:foo.lib f1.obj f2.obj f3.obj + RegServerFunc(target, source, env) + </screen> + + <para> + + Notice again that &SCons; takes care of + building the output file correctly, + adding the <literal>-shared</literal> option + for a POSIX compilation, + and the <literal>/dll</literal> option on Windows. + + </para> + + </section> + + </section> + + <section> + <title>Linking with Libraries</title> + + <para> + + Usually, you build a library + because you want to link it with one or more programs. + You link libraries with a program by specifying + the libraries in the &cv-link-LIBS; construction variable, + and by specifying the directory in which + the library will be found in the + &cv-link-LIBPATH; construction variable: + + <!-- In the preceding paragraph, the "$" notation for + LIBS, LIBPATH etc. is used for the first time. + Maybe some words of explanation would be nice. --> + + </para> + + <programlisting> + Library('foo', ['f1.c', 'f2.c', 'f3.c']) + Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.') + </programlisting> + + <para> + + Notice, of course, that you don't need to specify a library + prefix (like <literal>lib</literal>) + or suffix (like <literal>.a</literal> or <literal>.lib</literal>). + &SCons; uses the correct prefix or suffix for the current system. + + </para> + + <para> + + On a POSIX or Linux system, + a build of the above example would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o f1.o -c f1.c + cc -o f2.o -c f2.c + cc -o f3.o -c f3.c + ar rc libfoo.a f1.o f2.o f3.o + ranlib libfoo.a + cc -o prog.o -c prog.c + cc -o prog prog.o -L. -lfoo -lbar + </screen> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fof1.obj /c f1.c /nologo + cl /Fof2.obj /c f2.c /nologo + cl /Fof3.obj /c f3.c /nologo + lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj + cl /Foprog.obj /c prog.c /nologo + link /nologo /OUT:prog.exe /LIBPATH:. foo.lib bar.lib prog.obj + </screen> + + <para> + + As usual, notice that &SCons; has taken care + of constructing the correct command lines + to link with the specified library on each system. + + </para> + + <para> + + Note also that, + if you only have a single library to link with, + you can specify the library name in single string, + instead of a Python list, + so that: + + </para> + + <programlisting> + Program('prog.c', LIBS='foo', LIBPATH='.') + </programlisting> + + <para> + + is equivalent to: + + </para> + + <programlisting> + Program('prog.c', LIBS=['foo'], LIBPATH='.') + </programlisting> + + <para> + + This is similar to the way that &SCons; + handles either a string or a list to + specify a single source file. + + </para> + + </section> + + <section> + <title>Finding Libraries: the &cv-LIBPATH; Construction Variable</title> + + <para> + + By default, the linker will only look in + certain system-defined directories for libraries. + &SCons; knows how to look for libraries + in directories that you specify with the + &cv-link-LIBPATH; construction variable. + &cv-LIBPATH; consists of a list of + directory names, like so: + + </para> + + <programlisting> + Program('prog.c', LIBS = 'm', + LIBPATH = ['/usr/lib', '/usr/local/lib']) + </programlisting> + + <para> + + Using a Python list is preferred because it's portable + across systems. Alternatively, you could put all of + the directory names in a single string, separated by the + system-specific path separator character: + a colon on POSIX systems: + + </para> + + <programlisting> + LIBPATH = '/usr/lib:/usr/local/lib' + </programlisting> + + <para> + + or a semi-colon on Windows systems: + + </para> + + <programlisting> + LIBPATH = 'C:\\lib;D:\\lib' + </programlisting> + + <para> + + (Note that Python requires that the backslash + separators in a Windows path name + be escaped within strings.) + + </para> + + <para> + + When the linker is executed, + &SCons; will create appropriate flags + so that the linker will look for + libraries in the same directories as &SCons;. + So on a POSIX or Linux system, + a build of the above example would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o prog.o -c prog.c + cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm + </screen> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Foprog.obj /c prog.c /nologo + link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj + </screen> + <!-- The link command is too wide in the PDF version. + There are some other examples of this throughout the document. --> + + <para> + + Note again that &SCons; has taken care of + the system-specific details of creating + the right command-line options. + + </para> + + </section> diff --git a/doc/user/main.in b/doc/user/main.in new file mode 100644 index 0000000..949a90a --- /dev/null +++ b/doc/user/main.in @@ -0,0 +1,385 @@ +<?xml version="1.0"?> +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ + + <!ENTITY % version SYSTEM "../version.xml"> + %version; + + <!ENTITY % scons SYSTEM "../scons.mod"> + %scons; + + <!ENTITY % builders-mod SYSTEM "builders.mod"> + %builders-mod; + + <!ENTITY % tools-mod SYSTEM "tools.mod"> + %tools-mod; + + <!ENTITY % variables-mod SYSTEM "variables.mod"> + %variables-mod; + + <!ENTITY actions SYSTEM "actions.xml"> + <!ENTITY alias SYSTEM "alias.xml"> + <!ENTITY ant SYSTEM "ant.xml"> + <!ENTITY build-install SYSTEM "build-install.xml"> + <!ENTITY builders SYSTEM "builders.xml"> + <!ENTITY builders-built-in SYSTEM "builders-built-in.xml"> + <!ENTITY builders-commands SYSTEM "builders-commands.xml"> + <!ENTITY builders-writing SYSTEM "builders-writing.xml"> + <!ENTITY add-method SYSTEM "add-method.xml"> + <!ENTITY caching SYSTEM "caching.xml"> + <!ENTITY command-line SYSTEM "command-line.xml"> + <!ENTITY copyright SYSTEM "copyright.xml"> + <!ENTITY depends SYSTEM "depends.xml"> + <!ENTITY environments SYSTEM "environments.xml"> + <!ENTITY errors SYSTEM "errors.xml"> + <!ENTITY example SYSTEM "example.xml"> + <!ENTITY factories SYSTEM "factories.xml"> + <!ENTITY file-removal SYSTEM "file-removal.xml"> + <!ENTITY hierarchy SYSTEM "hierarchy.xml"> + <!ENTITY java SYSTEM "java.xml"> + <!ENTITY install SYSTEM "install.xml"> + <!ENTITY less-simple SYSTEM "less-simple.xml"> + <!ENTITY libraries SYSTEM "libraries.xml"> + <!ENTITY make SYSTEM "make.xml"> + <!ENTITY mergeflags SYSTEM "mergeflags.xml"> + <!ENTITY misc SYSTEM "misc.xml"> + <!ENTITY nodes SYSTEM "nodes.xml"> + <!ENTITY output SYSTEM "output.xml"> + <!ENTITY parseconfig SYSTEM "parseconfig.xml"> + <!ENTITY parseflags SYSTEM "parseflags.xml"> + <!ENTITY preface SYSTEM "preface.xml"> + <!ENTITY python SYSTEM "python.xml"> + <!ENTITY repositories SYSTEM "repositories.xml"> + <!ENTITY run SYSTEM "run.xml"> + <!ENTITY scanners SYSTEM "scanners.xml"> + <!ENTITY sconf SYSTEM "sconf.xml"> + <!ENTITY separate SYSTEM "separate.xml"> + <!ENTITY simple SYSTEM "simple.xml"> + <!ENTITY sourcecode SYSTEM "sourcecode.xml"> + <!ENTITY tasks SYSTEM "tasks.xml"> + <!ENTITY tools SYSTEM "tools.xml"> + <!ENTITY troubleshoot SYSTEM "troubleshoot.xml"> + <!ENTITY variables-xml SYSTEM "variables.xml"> + <!ENTITY variants SYSTEM "variants.xml"> + + <!ENTITY builders-gen SYSTEM "builders.gen"> + <!ENTITY tools-gen SYSTEM "tools.gen"> + <!ENTITY variables-gen SYSTEM "variables.gen"> + +]> + + <!-- + + XXX FindFile() + XXX FindPathDirs() + XXX GetBuildPath() + XXX GetLaunchDir() + + XXX ParseDepends() + XXX Platform() + XXX SConsignFile() + XXX Tools() + + XXX GetOption('duplicate') + XXX SetOption('duplicate') + XXX - - duplicate= + + XXX CheckTypeSize() + + XXX - - diskcheck= + + XXX - - warn= + + --> + +<book> + <bookinfo> + <title>SCons User Guide &buildversion;</title> + + <author> + <firstname>Steven</firstname> + <surname>Knight</surname> + </author> + + <edition>Revision &buildrevision; (&builddate;)</edition> + + <pubdate>2004, 2005, 2006, 2007, 2008</pubdate> + + <copyright> + <year>2004, 2005, 2006, 2007, 2008</year> + <holder>Steven Knight</holder> + </copyright> + + <legalnotice> + ©right; + </legalnotice> + + <releaseinfo>version &buildversion;</releaseinfo> + + </bookinfo> + + <preface id="chap-preface"> + <title>Preface</title> + &preface; + </preface> + + <chapter id="chap-build-install"> + <title>Building and Installing &SCons;</title> + &build-install; + </chapter> + + <chapter id="chap-simple"> + <title>Simple Builds</title> + &simple; + </chapter> + + <chapter id="chap-less-simple"> + <title>Less Simple Things to Do With Builds</title> + &less-simple; + </chapter> + + <chapter id="chap-libraries"> + <title>Building and Linking with Libraries</title> + &libraries; + </chapter> + + <chapter id="chap-nodes"> + <title>Node Objects</title> + &nodes; + </chapter> + + <chapter id="chap-depends"> + <title>Dependencies</title> + &depends; + </chapter> + + <chapter id="chap-environments"> + <title>Environments</title> + &environments; + </chapter> + + <!-- These next three sections should be combined into one chapter --> + <chapter id="chap-mergeflags"> + <title>Merging Options into the Environment: the &MergeFlags; Function</title> + &mergeflags; + </chapter> + <chapter id="chap-parseflags"> + <title>Separating Compile Arguments into their Variables: the &ParseFlags; Function</title> + &parseflags; + </chapter> + <chapter id="chap-parseconfig"> + <title>Finding Installed Library Information: the &ParseConfig; Function</title> + &parseconfig; + </chapter> + + <chapter id="chap-output"> + <title>Controlling Build Output</title> + &output; + </chapter> + + <chapter id="chap-command-line"> + <title>Controlling a Build From the Command Line</title> + &command-line; + </chapter> + + <chapter id="chap-install"> + <title>Installing Files in Other Directories: the &Install; Builder</title> + &install; + </chapter> + + <chapter id="chap-factories"> + <title>Platform-Independent File System Manipulation</title> + &factories; + </chapter> + + <chapter id="chap-file-removal"> + <title>Controlling Removal of Targets</title> + &file-removal; + </chapter> + + <chapter id="chap-hierarchical"> + <title>Hierarchical Builds</title> + &hierarchy; + </chapter> + + <chapter id="chap-separate"> + <title>Separating Source and Build Directories</title> + &separate; + </chapter> + + <chapter id="chap-variants"> + <title>Variant Builds</title> + &variants; + </chapter> + + <!-- + + <chapter id="chap-builders-built-in"> + <title>Built-In Builders</title> + &builders-built-in; + </chapter> + + --> + + <chapter id="chap-builders-writing"> + <title>Writing Your Own Builders</title> + &builders-writing; + </chapter> + + <chapter id="chap-builders-commands"> + <title>Not Writing a Builder: the &Command; Builder</title> + &builders-commands; + </chapter> + + <chapter id="chap-add-method"> + <title>Pseudo-Builders: the AddMethod function</title> + &add-method; + </chapter> + + <!-- + + XXX Action() + XXX AddPostAction() + XXX AddPreAction() + + <chapter id="chap-actions"> + <title>&SCons; Actions</title> + &actions; + </chapter> + + --> + + <chapter id="chap-scanners"> + <title>Writing Scanners</title> + &scanners; + </chapter> + + <chapter id="chap-repositories"> + <title>Building From Code Repositories</title> + &repositories; + </chapter> + + <chapter id="chap-sconf"> + <title>Multi-Platform Configuration (&Autoconf; Functionality)</title> + &sconf; + </chapter> + + <!-- + + <chapter id="chap-sourcecode"> + <title>Fetching Files From Source Code Management Systems</title> + &sourcecode; + </chapter> + + --> + + <chapter id="chap-caching"> + <title>Caching Built Files</title> + &caching; + </chapter> + + <chapter id="chap-alias"> + <title>Alias Targets</title> + &alias; + </chapter> + + <chapter id="chap-java"> + <title>Java Builds</title> + &java; + </chapter> + + <!-- + + <chapter id="chap-run"> + <title>How to Run &SCons;</title> + &run; + </chapter> + + --> + + <chapter id="chap-misc"> + <title>Miscellaneous Functionality</title> + &misc; + </chapter> + + <chapter id="chap-troubleshooting"> + <title>Troubleshooting</title> + &troubleshoot; + </chapter> + + <appendix id="app-variables"> + <title>Construction Variables</title> + &variables-xml; + </appendix> + + <appendix id="app-builders"> + <title>Builders</title> + &builders; + </appendix> + + <appendix id="app-tools"> + <title>Tools</title> + &tools; + </appendix> + + <appendix id="app-tasks"> + <title>Handling Common Tasks</title> + &tasks; + </appendix> + + <!-- + + <appendix id="app-python"> + <title>Python Overview</title> + &example; + </appendix> + + <appendix id="app-example"> + <title>Complex &SCons; Example</title> + &example; + </appendix> + + <appendix id="app-make"> + <title>Converting From Make</title> + &make; + </appendix> + + <appendix id="app-cons"> + <title>Converting From Cons</title> + &cons; + </appendix> + + <appendix id="app-ant"> + <title>Converting From Ant</title> + &ant; + </appendix> + + --> + +</book> diff --git a/doc/user/main.xml b/doc/user/main.xml new file mode 100644 index 0000000..949a90a --- /dev/null +++ b/doc/user/main.xml @@ -0,0 +1,385 @@ +<?xml version="1.0"?> +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" +"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ + + <!ENTITY % version SYSTEM "../version.xml"> + %version; + + <!ENTITY % scons SYSTEM "../scons.mod"> + %scons; + + <!ENTITY % builders-mod SYSTEM "builders.mod"> + %builders-mod; + + <!ENTITY % tools-mod SYSTEM "tools.mod"> + %tools-mod; + + <!ENTITY % variables-mod SYSTEM "variables.mod"> + %variables-mod; + + <!ENTITY actions SYSTEM "actions.xml"> + <!ENTITY alias SYSTEM "alias.xml"> + <!ENTITY ant SYSTEM "ant.xml"> + <!ENTITY build-install SYSTEM "build-install.xml"> + <!ENTITY builders SYSTEM "builders.xml"> + <!ENTITY builders-built-in SYSTEM "builders-built-in.xml"> + <!ENTITY builders-commands SYSTEM "builders-commands.xml"> + <!ENTITY builders-writing SYSTEM "builders-writing.xml"> + <!ENTITY add-method SYSTEM "add-method.xml"> + <!ENTITY caching SYSTEM "caching.xml"> + <!ENTITY command-line SYSTEM "command-line.xml"> + <!ENTITY copyright SYSTEM "copyright.xml"> + <!ENTITY depends SYSTEM "depends.xml"> + <!ENTITY environments SYSTEM "environments.xml"> + <!ENTITY errors SYSTEM "errors.xml"> + <!ENTITY example SYSTEM "example.xml"> + <!ENTITY factories SYSTEM "factories.xml"> + <!ENTITY file-removal SYSTEM "file-removal.xml"> + <!ENTITY hierarchy SYSTEM "hierarchy.xml"> + <!ENTITY java SYSTEM "java.xml"> + <!ENTITY install SYSTEM "install.xml"> + <!ENTITY less-simple SYSTEM "less-simple.xml"> + <!ENTITY libraries SYSTEM "libraries.xml"> + <!ENTITY make SYSTEM "make.xml"> + <!ENTITY mergeflags SYSTEM "mergeflags.xml"> + <!ENTITY misc SYSTEM "misc.xml"> + <!ENTITY nodes SYSTEM "nodes.xml"> + <!ENTITY output SYSTEM "output.xml"> + <!ENTITY parseconfig SYSTEM "parseconfig.xml"> + <!ENTITY parseflags SYSTEM "parseflags.xml"> + <!ENTITY preface SYSTEM "preface.xml"> + <!ENTITY python SYSTEM "python.xml"> + <!ENTITY repositories SYSTEM "repositories.xml"> + <!ENTITY run SYSTEM "run.xml"> + <!ENTITY scanners SYSTEM "scanners.xml"> + <!ENTITY sconf SYSTEM "sconf.xml"> + <!ENTITY separate SYSTEM "separate.xml"> + <!ENTITY simple SYSTEM "simple.xml"> + <!ENTITY sourcecode SYSTEM "sourcecode.xml"> + <!ENTITY tasks SYSTEM "tasks.xml"> + <!ENTITY tools SYSTEM "tools.xml"> + <!ENTITY troubleshoot SYSTEM "troubleshoot.xml"> + <!ENTITY variables-xml SYSTEM "variables.xml"> + <!ENTITY variants SYSTEM "variants.xml"> + + <!ENTITY builders-gen SYSTEM "builders.gen"> + <!ENTITY tools-gen SYSTEM "tools.gen"> + <!ENTITY variables-gen SYSTEM "variables.gen"> + +]> + + <!-- + + XXX FindFile() + XXX FindPathDirs() + XXX GetBuildPath() + XXX GetLaunchDir() + + XXX ParseDepends() + XXX Platform() + XXX SConsignFile() + XXX Tools() + + XXX GetOption('duplicate') + XXX SetOption('duplicate') + XXX - - duplicate= + + XXX CheckTypeSize() + + XXX - - diskcheck= + + XXX - - warn= + + --> + +<book> + <bookinfo> + <title>SCons User Guide &buildversion;</title> + + <author> + <firstname>Steven</firstname> + <surname>Knight</surname> + </author> + + <edition>Revision &buildrevision; (&builddate;)</edition> + + <pubdate>2004, 2005, 2006, 2007, 2008</pubdate> + + <copyright> + <year>2004, 2005, 2006, 2007, 2008</year> + <holder>Steven Knight</holder> + </copyright> + + <legalnotice> + ©right; + </legalnotice> + + <releaseinfo>version &buildversion;</releaseinfo> + + </bookinfo> + + <preface id="chap-preface"> + <title>Preface</title> + &preface; + </preface> + + <chapter id="chap-build-install"> + <title>Building and Installing &SCons;</title> + &build-install; + </chapter> + + <chapter id="chap-simple"> + <title>Simple Builds</title> + &simple; + </chapter> + + <chapter id="chap-less-simple"> + <title>Less Simple Things to Do With Builds</title> + &less-simple; + </chapter> + + <chapter id="chap-libraries"> + <title>Building and Linking with Libraries</title> + &libraries; + </chapter> + + <chapter id="chap-nodes"> + <title>Node Objects</title> + &nodes; + </chapter> + + <chapter id="chap-depends"> + <title>Dependencies</title> + &depends; + </chapter> + + <chapter id="chap-environments"> + <title>Environments</title> + &environments; + </chapter> + + <!-- These next three sections should be combined into one chapter --> + <chapter id="chap-mergeflags"> + <title>Merging Options into the Environment: the &MergeFlags; Function</title> + &mergeflags; + </chapter> + <chapter id="chap-parseflags"> + <title>Separating Compile Arguments into their Variables: the &ParseFlags; Function</title> + &parseflags; + </chapter> + <chapter id="chap-parseconfig"> + <title>Finding Installed Library Information: the &ParseConfig; Function</title> + &parseconfig; + </chapter> + + <chapter id="chap-output"> + <title>Controlling Build Output</title> + &output; + </chapter> + + <chapter id="chap-command-line"> + <title>Controlling a Build From the Command Line</title> + &command-line; + </chapter> + + <chapter id="chap-install"> + <title>Installing Files in Other Directories: the &Install; Builder</title> + &install; + </chapter> + + <chapter id="chap-factories"> + <title>Platform-Independent File System Manipulation</title> + &factories; + </chapter> + + <chapter id="chap-file-removal"> + <title>Controlling Removal of Targets</title> + &file-removal; + </chapter> + + <chapter id="chap-hierarchical"> + <title>Hierarchical Builds</title> + &hierarchy; + </chapter> + + <chapter id="chap-separate"> + <title>Separating Source and Build Directories</title> + &separate; + </chapter> + + <chapter id="chap-variants"> + <title>Variant Builds</title> + &variants; + </chapter> + + <!-- + + <chapter id="chap-builders-built-in"> + <title>Built-In Builders</title> + &builders-built-in; + </chapter> + + --> + + <chapter id="chap-builders-writing"> + <title>Writing Your Own Builders</title> + &builders-writing; + </chapter> + + <chapter id="chap-builders-commands"> + <title>Not Writing a Builder: the &Command; Builder</title> + &builders-commands; + </chapter> + + <chapter id="chap-add-method"> + <title>Pseudo-Builders: the AddMethod function</title> + &add-method; + </chapter> + + <!-- + + XXX Action() + XXX AddPostAction() + XXX AddPreAction() + + <chapter id="chap-actions"> + <title>&SCons; Actions</title> + &actions; + </chapter> + + --> + + <chapter id="chap-scanners"> + <title>Writing Scanners</title> + &scanners; + </chapter> + + <chapter id="chap-repositories"> + <title>Building From Code Repositories</title> + &repositories; + </chapter> + + <chapter id="chap-sconf"> + <title>Multi-Platform Configuration (&Autoconf; Functionality)</title> + &sconf; + </chapter> + + <!-- + + <chapter id="chap-sourcecode"> + <title>Fetching Files From Source Code Management Systems</title> + &sourcecode; + </chapter> + + --> + + <chapter id="chap-caching"> + <title>Caching Built Files</title> + &caching; + </chapter> + + <chapter id="chap-alias"> + <title>Alias Targets</title> + &alias; + </chapter> + + <chapter id="chap-java"> + <title>Java Builds</title> + &java; + </chapter> + + <!-- + + <chapter id="chap-run"> + <title>How to Run &SCons;</title> + &run; + </chapter> + + --> + + <chapter id="chap-misc"> + <title>Miscellaneous Functionality</title> + &misc; + </chapter> + + <chapter id="chap-troubleshooting"> + <title>Troubleshooting</title> + &troubleshoot; + </chapter> + + <appendix id="app-variables"> + <title>Construction Variables</title> + &variables-xml; + </appendix> + + <appendix id="app-builders"> + <title>Builders</title> + &builders; + </appendix> + + <appendix id="app-tools"> + <title>Tools</title> + &tools; + </appendix> + + <appendix id="app-tasks"> + <title>Handling Common Tasks</title> + &tasks; + </appendix> + + <!-- + + <appendix id="app-python"> + <title>Python Overview</title> + &example; + </appendix> + + <appendix id="app-example"> + <title>Complex &SCons; Example</title> + &example; + </appendix> + + <appendix id="app-make"> + <title>Converting From Make</title> + &make; + </appendix> + + <appendix id="app-cons"> + <title>Converting From Cons</title> + &cons; + </appendix> + + <appendix id="app-ant"> + <title>Converting From Ant</title> + &ant; + </appendix> + + --> + +</book> diff --git a/doc/user/make.in b/doc/user/make.in new file mode 100644 index 0000000..e778c61 --- /dev/null +++ b/doc/user/make.in @@ -0,0 +1,121 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Why Cons? Why not Make? + +Cons is a B<make> replacement. In the following paragraphs, we look at a few +of the undesirable characteristics of make, and typical build environments +based on make, that motivated the development of Cons. + +=head2 Build complexity + +Traditional make-based systems of any size tend to become quite complex. The +original make utility and its derivatives have contributed to this tendency +in a number of ways. Make is not good at dealing with systems that are +spread over multiple directories. Various work-arounds are used to overcome +this difficulty; the usual choice is for make to invoke itself recursively +for each sub-directory of a build. This leads to complicated code, in which +it is often unclear how a variable is set, or what effect the setting of a +variable will have on the build as a whole. The make scripting language has +gradually been extended to provide more possibilities, but these have +largely served to clutter an already overextended language. Often, builds +are done in multiple passes in order to provide appropriate products from +one directory to another directory. This represents a further increase in +build complexity. + + +=head2 Build reproducibility + +The bane of all makes has always been the correct handling of +dependencies. Most often, an attempt is made to do a reasonable job of +dependencies within a single directory, but no serious attempt is made to do +the job between directories. Even when dependencies are working correctly, +make's reliance on a simple time stamp comparison to determine whether a +file is out of date with respect to its dependents is not, in general, +adequate for determining when a file should be rederived. If an external +library, for example, is rebuilt and then ``snapped'' into place, the +timestamps on its newly created files may well be earlier than the last +local build, since it was built before it became visible. + + +=head2 Variant builds + +Make provides only limited facilities for handling variant builds. With the +proliferation of hardware platforms and the need for debuggable +vs. optimized code, the ability to easily create these variants is +essential. More importantly, if variants are created, it is important to +either be able to separate the variants or to be able to reproduce the +original or variant at will. With make it is very difficult to separate the +builds into multiple build directories, separate from the source. And if +this technique isn't used, it's also virtually impossible to guarantee at +any given time which variant is present in the tree, without resorting to a +complete rebuild. + + +=head2 Repositories + +Make provides only limited support for building software from code that +exists in a central repository directory structure. The VPATH feature of +GNU make (and some other make implementations) is intended to provide this, +but doesn't work as expected: it changes the path of target file to the +VPATH name too early in its analysis, and therefore searches for all +dependencies in the VPATH directory. To ensure correct development builds, +it is important to be able to create a file in a local build directory and +have any files in a code repository (a VPATH directory, in make terms) that +depend on the local file get rebuilt properly. This isn't possible with +VPATH, without coding a lot of complex repository knowledge directly into +the makefiles. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Differences Between &Make; and &SCons;</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Advantages of &SCons; Over &Make;</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/make.xml b/doc/user/make.xml new file mode 100644 index 0000000..e778c61 --- /dev/null +++ b/doc/user/make.xml @@ -0,0 +1,121 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Why Cons? Why not Make? + +Cons is a B<make> replacement. In the following paragraphs, we look at a few +of the undesirable characteristics of make, and typical build environments +based on make, that motivated the development of Cons. + +=head2 Build complexity + +Traditional make-based systems of any size tend to become quite complex. The +original make utility and its derivatives have contributed to this tendency +in a number of ways. Make is not good at dealing with systems that are +spread over multiple directories. Various work-arounds are used to overcome +this difficulty; the usual choice is for make to invoke itself recursively +for each sub-directory of a build. This leads to complicated code, in which +it is often unclear how a variable is set, or what effect the setting of a +variable will have on the build as a whole. The make scripting language has +gradually been extended to provide more possibilities, but these have +largely served to clutter an already overextended language. Often, builds +are done in multiple passes in order to provide appropriate products from +one directory to another directory. This represents a further increase in +build complexity. + + +=head2 Build reproducibility + +The bane of all makes has always been the correct handling of +dependencies. Most often, an attempt is made to do a reasonable job of +dependencies within a single directory, but no serious attempt is made to do +the job between directories. Even when dependencies are working correctly, +make's reliance on a simple time stamp comparison to determine whether a +file is out of date with respect to its dependents is not, in general, +adequate for determining when a file should be rederived. If an external +library, for example, is rebuilt and then ``snapped'' into place, the +timestamps on its newly created files may well be earlier than the last +local build, since it was built before it became visible. + + +=head2 Variant builds + +Make provides only limited facilities for handling variant builds. With the +proliferation of hardware platforms and the need for debuggable +vs. optimized code, the ability to easily create these variants is +essential. More importantly, if variants are created, it is important to +either be able to separate the variants or to be able to reproduce the +original or variant at will. With make it is very difficult to separate the +builds into multiple build directories, separate from the source. And if +this technique isn't used, it's also virtually impossible to guarantee at +any given time which variant is present in the tree, without resorting to a +complete rebuild. + + +=head2 Repositories + +Make provides only limited support for building software from code that +exists in a central repository directory structure. The VPATH feature of +GNU make (and some other make implementations) is intended to provide this, +but doesn't work as expected: it changes the path of target file to the +VPATH name too early in its analysis, and therefore searches for all +dependencies in the VPATH directory. To ensure correct development builds, +it is important to be able to create a file in a local build directory and +have any files in a code repository (a VPATH directory, in make terms) that +depend on the local file get rebuilt properly. This isn't possible with +VPATH, without coding a lot of complex repository knowledge directly into +the makefiles. + +--> + + <para> + + XXX + + </para> + + <section> + <title>Differences Between &Make; and &SCons;</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Advantages of &SCons; Over &Make;</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/mergeflags.in b/doc/user/mergeflags.in new file mode 100644 index 0000000..b50992b --- /dev/null +++ b/doc/user/mergeflags.in @@ -0,0 +1,137 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; construction environments have a &MergeFlags; method + that merges a dictionary of values into the construction environment. + &MergeFlags; treats each value in the dictionary + as a list of options such as one might pass to a command + (such as a compiler or linker). + &MergeFlags; will not duplicate an option + if it already exists in the construction environment variable. + + </para> + + <para> + + &MergeFlags; tries to be intelligent about merging options. + When merging options to any variable + whose name ends in <varname>PATH</varname>, + &MergeFlags; keeps the leftmost occurrence of the option, + because in typical lists of directory paths, + the first occurrence "wins." + When merging options to any other variable name, + &MergeFlags; keeps the rightmost occurrence of the option, + because in a list of typical command-line options, + the last occurrence "wins." + + </para> + + <scons_example name="MergeFlags1"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Append(CCFLAGS = '-option -O3 -O1') + flags = { 'CCFLAGS' : '-whatever -O3' } + env.MergeFlags(flags) + print env['CCFLAGS'] + </file> + </scons_example> + + <scons_output example="MergeFlags1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that the default value for &cv-link-CCFLAGS; + <!-- + [TODO: for when we make CLVar public] + is a <varname>CLVar</varname>, + --> + is an internal &SCons; object + which automatically converts + the options we specified as a string into a list. + + </para> + + <scons_example name="MergeFlags2"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) + flags = { 'CPPPATH' : ['/usr/opt/include', '/usr/local/include'] } + env.MergeFlags(flags) + print env['CPPPATH'] + </file> + </scons_example> + + <scons_output example="MergeFlags2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that the default value for &cv-link-CPPPATH; + <!-- + [TODO: for when we make CLVar public] + is a Python list, not a <varname>CLVar</varname>, + --> + is a normal Python list, + so we must specify its values as a list + in the dictionary we pass to the &MergeFlags; function. + + </para> + + <para> + + If &MergeFlags; is passed anything other than a dictionary, + it calls the &ParseFlags; method to convert it into a dictionary. + + </para> + + <scons_example name="MergeFlags3"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Append(CCFLAGS = '-option -O3 -O1') + env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) + env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include') + print env['CCFLAGS'] + print env['CPPPATH'] + </file> + </scons_example> + + <scons_output example="MergeFlags3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + In the combined example above, + &ParseFlags; has sorted the options into their corresponding variables + and returned a dictionary for &MergeFlags; to apply + to the construction variables + in the specified construction environment. + + </para> diff --git a/doc/user/mergeflags.xml b/doc/user/mergeflags.xml new file mode 100644 index 0000000..7edc986 --- /dev/null +++ b/doc/user/mergeflags.xml @@ -0,0 +1,138 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; construction environments have a &MergeFlags; method + that merges a dictionary of values into the construction environment. + &MergeFlags; treats each value in the dictionary + as a list of options such as one might pass to a command + (such as a compiler or linker). + &MergeFlags; will not duplicate an option + if it already exists in the construction environment variable. + + </para> + + <para> + + &MergeFlags; tries to be intelligent about merging options. + When merging options to any variable + whose name ends in <varname>PATH</varname>, + &MergeFlags; keeps the leftmost occurrence of the option, + because in typical lists of directory paths, + the first occurrence "wins." + When merging options to any other variable name, + &MergeFlags; keeps the rightmost occurrence of the option, + because in a list of typical command-line options, + the last occurrence "wins." + + </para> + + <programlisting> + env = Environment() + env.Append(CCFLAGS = '-option -O3 -O1') + flags = { 'CCFLAGS' : '-whatever -O3' } + env.MergeFlags(flags) + print env['CCFLAGS'] + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + ['-option', '-O1', '-whatever', '-O3'] + scons: `.' is up to date. + </screen> + + <para> + + Note that the default value for &cv-link-CCFLAGS; + <!-- + [TODO: for when we make CLVar public] + is a <varname>CLVar</varname>, + --> + is an internal &SCons; object + which automatically converts + the options we specified as a string into a list. + + </para> + + <programlisting> + env = Environment() + env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) + flags = { 'CPPPATH' : ['/usr/opt/include', '/usr/local/include'] } + env.MergeFlags(flags) + print env['CPPPATH'] + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + ['/include', '/usr/local/include', '/usr/include', '/usr/opt/include'] + scons: `.' is up to date. + </screen> + + <para> + + Note that the default value for &cv-link-CPPPATH; + <!-- + [TODO: for when we make CLVar public] + is a Python list, not a <varname>CLVar</varname>, + --> + is a normal Python list, + so we must specify its values as a list + in the dictionary we pass to the &MergeFlags; function. + + </para> + + <para> + + If &MergeFlags; is passed anything other than a dictionary, + it calls the &ParseFlags; method to convert it into a dictionary. + + </para> + + <programlisting> + env = Environment() + env.Append(CCFLAGS = '-option -O3 -O1') + env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) + env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include') + print env['CCFLAGS'] + print env['CPPPATH'] + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + ['-option', '-O1', '-whatever', '-O3'] + ['/include', '/usr/local/include', '/usr/include', '/usr/opt/include'] + scons: `.' is up to date. + </screen> + + <para> + + In the combined example above, + &ParseFlags; has sorted the options into their corresponding variables + and returned a dictionary for &MergeFlags; to apply + to the construction variables + in the specified construction environment. + + </para> diff --git a/doc/user/misc.in b/doc/user/misc.in new file mode 100644 index 0000000..6679134 --- /dev/null +++ b/doc/user/misc.in @@ -0,0 +1,606 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; supports a lot of additional functionality + that doesn't readily fit into the other chapters. + + </para> + + <section> + <title>Verifying the Python Version: the &EnsurePythonVersion; Function</title> + + <para> + + Although the &SCons; code itself will run + on any Python version 1.5.2 or later, + you are perfectly free to make use of + Python syntax and modules from more modern versions + (for example, Python 2.4 or 2.5) + when writing your &SConscript; files + or your own local modules. + If you do this, it's usually helpful to + configure &SCons; to exit gracefully with an error message + if it's being run with a version of Python + that simply won't work with your code. + This is especially true if you're going to use &SCons; + to build source code that you plan to distribute publicly, + where you can't be sure of the Python version + that an anonymous remote user might use + to try to build your software. + + </para> + + <para> + + &SCons; provides an &EnsurePythonVersion; function for this. + You simply pass it the major and minor versions + numbers of the version of Python you require: + + </para> + + <!-- + + TODO: Figure out how to generate the error message + regardless of executing Python version by faking out + the infrastructure in some way. + + <scons_example name="EnsurePythonVersion"> + <file name="SConstruct" printme="1"> + EnsurePythonVersion(2, 5) + </file> + </scons_example> + + --> + + <sconstruct> + EnsurePythonVersion(2, 5) + </sconstruct> + + <para> + + And then &SCons will exit with the following error + message when a user runs it with an unsupported + earlier version of Python: + + </para> + + <!-- + + TODO: Figure out how to generate the error message + regardless of executing Python version by faking out + the infrastructure in some way. + + <scons_output example="EnsurePythonVersion"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + Python 2.5 or greater required, but you have Python 2.3.6 + </screen> + + </section> + + <section> + <title>Verifying the SCons Version: the &EnsureSConsVersion; Function</title> + + <para> + + You may, of course, write your &SConscript; files + to use features that were only added in + recent versions of &SCons;. + When you publicly distribute software that is built using &SCons;, + it's helpful to have &SCons; + verify the version being used and + exit gracefully with an error message + if the user's version of &SCons; won't work + with your &SConscript; files. + &SCons; provides an &EnsureSConsVersion; function + that verifies the version of &SCons; + in the same + the &EnsurePythonVersion; function + verifies the version of Python, + by passing in the major and minor versions + numbers of the version of SCons you require: + + </para> + + <!-- + + TODO: Figure out how to generate the error message + regardless of executing SCons version by faking out + the infrastructure in some way. + + <scons_example name="EnsureSConsVersion"> + <file name="SConstruct" printme="1"> + EnsureSConsVersion(1, 0) + </file> + </scons_example> + + --> + + <sconstruct> + EnsureSConsVersion(1, 0) + </sconstruct> + + <para> + + And then &SCons will exit with the following error + message when a user runs it with an unsupported + earlier version of &SCons;: + + </para> + + <!-- + + TODO: Figure out how to generate the error message + regardless of executing SCons version by faking out + the infrastructure in some way. + + <scons_output example="EnsureSConsVersion"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + SCons 1.0 or greater required, but you have SCons 0.98.5 + </screen> + + </section> + + <section> + <title>Explicitly Terminating &SCons; While Reading &SConscript; Files: the &Exit; Function</title> + + <para> + + &SCons; supports an &Exit; function + which can be used to terminate &SCons; + while reading the &SConscript; files, + usually because you've detected a condition + under which it doesn't make sense to proceed: + + </para> + + <scons_example name="Exit"> + <file name="SConstruct" printme="1"> + if ARGUMENTS.get('FUTURE'): + print "The FUTURE option is not supported yet!" + Exit(2) + env = Environment() + env.Program('hello.c') + </file> + <file name="hello.c"> + hello.c + </file> + </scons_example> + + <scons_output example="Exit"> + <scons_output_command>scons -Q FUTURE=1</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + The &Exit; function takes as an argument + the (numeric) exit status that you want &SCons; to exit with. + If you don't specify a value, + the default is to exit with <literal>0</literal>, + which indicates successful execution. + + </para> + + <para> + + Note that the &Exit; function + is equivalent to calling the Python + <function>sys.exit</function> function + (which the it actually calls), + but because &Exit; is a &SCons; function, + you don't have to import the Python + <literal>sys</literal> module to use it. + + </para> + + </section> + + <section> + <title>Searching for Files: the &FindFile; Function</title> + + <para> + + The &FindFile; function searches for a file in a list of directories. + If there is only one directory, it can be given as a simple string. + The function returns a File node if a matching file exists, + or None if no file is found. + (See the documentation for the &Glob; function for an alternative way + of searching for entries in a directory.) + + </para> + + <scons_example name="FindFile1a"> + <file name="SConstruct" printme="1"> + # one directory + print FindFile('missing', '.') + t = FindFile('exists', '.') + print t.__class__, t + </file> + <file name="exists"> + exists + </file> + </scons_example> + + <scons_output example="FindFile1a" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <scons_example name="FindFile1b"> + <file name="SConstruct" printme="1"> + # several directories + includes = [ '.', 'include', 'src/include'] + headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h'] + for hdr in headers: + print '%-12s' % ('%s:' % hdr), FindFile(hdr, includes) + </file> + <file name="config.h"> + exists + </file> + <directory name="src"></directory> + <directory name="src/include"></directory> + </file> + <file name="src/include/private.h"> + exists + <directory name="include"></directory> + </file> + <file name="include/dist.h"> + exists + </scons_example> + + <scons_output example="FindFile1b" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <!-- The man page says this should work, but it fails. + <para> + + If the 'file' parameter is a list of files, + a list of File nodes is returned. + + </para> + + <scons_example name="FindFile1c"> + <file name="SConstruct" printme="1"> + # several directories + includes = [ '.', 'include', 'src/include'] + headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h'] + print FindFile(headers, includes) + </file> + <file name="config.h"> + exists + </file> + <directory name="src"></directory> + <directory name="src/include"></directory> + </file> + <file name="src/include/private.h"> + exists + <directory name="include"></directory> + </file> + <file name="include/dist.h"> + exists + </scons_example> + + <scons_output example="FindFile1c" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + --> + + <para> + + If the file exists in more than one directory, + only the first occurrence is returned. + + </para> + + <scons_example name="FindFile1d"> + <file name="SConstruct" printme="1"> + print FindFile('multiple', ['sub1', 'sub2', 'sub3']) + print FindFile('multiple', ['sub2', 'sub3', 'sub1']) + print FindFile('multiple', ['sub3', 'sub1', 'sub2']) + </file> + <directory name="sub1"></directory> + <file name="sub1/multiple"> + exists + </file> + <directory name="sub2"></directory> + <file name="sub2/multiple"> + exists + </file> + <directory name="sub3"></directory> + <file name="sub3/multiple"> + exists + </file> + </scons_example> + + <scons_output example="FindFile1d" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <!-- file may be a list of file names or a single file name. --> + + <para> + + In addition to existing files, &FindFile; will also find derived files + (that is, non-leaf files) that haven't been built yet. + (Leaf files should already exist, or the build will fail!) + + </para> + + <scons_example name="FindFile2"> + <file name="SConstruct" printme="1"> + # Neither file exists, so build will fail + Command('derived', 'leaf', 'cat >$TARGET $SOURCE') + print FindFile('leaf', '.') + print FindFile('derived', '.') + </file> + </scons_example> + + <scons_output example="FindFile2" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <scons_example name="FindFile2"> + <file name="SConstruct" printme="1"> + # Only 'leaf' exists + Command('derived', 'leaf', 'cat >$TARGET $SOURCE') + print FindFile('leaf', '.') + print FindFile('derived', '.') + </file> + <file name="leaf"> + leaf + </file> + </scons_example> + + <scons_output example="FindFile2" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + If a source file exists, &FindFile; will correctly return the name + in the build directory. + + </para> + + <scons_example name="FindFile3"> + <file name="SConstruct" printme="1"> + # Only 'src/leaf' exists + VariantDir('build', 'src') + print FindFile('leaf', 'build') + </file> + <directory name="src"></directory> + <file name="src/leaf"> + leaf + </file> + </scons_example> + + <scons_output example="FindFile3" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Handling Nested Lists: the &Flatten; Function</title> + + <para> + + &SCons; supports a &Flatten; function + which takes an input Python sequence + (list or tuple) + and returns a flattened list + containing just the individual elements of + the sequence. + This can be handy when trying to examine + a list composed of the lists + returned by calls to various Builders. + For example, you might collect + object files built in different ways + into one call to the &Program; Builder + by just enclosing them in a list, as follows: + + </para> + + <scons_example name="Flatten1"> + <file name="SConstruct" printme="1"> + objects = [ + Object('prog1.c'), + Object('prog2.c', CCFLAGS='-DFOO'), + ] + Program(objects) + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> + + <para> + + Because the Builder calls in &SCons; + flatten their input lists, + this works just fine to build the program: + + </para> + + <scons_output example="Flatten1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + But if you were debugging your build + and wanted to print the absolute path + of each object file in the + <varname>objects</varname> list, + you might try the following simple approach, + trying to print each Node's + <literal>abspath</literal> + attribute: + + </para> + + <scons_example name="Flatten2"> + <file name="SConstruct" printme="1"> + objects = [ + Object('prog1.c'), + Object('prog2.c', CCFLAGS='-DFOO'), + ] + Program(objects) + + for object_file in objects: + print object_file.abspath + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> + + <para> + + This does not work as expected + because each call to <function>str</function> + is operating an embedded list returned by + each &Object; call, + not on the underlying Nodes within those lists: + + </para> + + <scons_output example="Flatten2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + The solution is to use the &Flatten; function + so that you can pass each Node to + the <function>str</function> separately: + + </para> + + <scons_example name="Flatten3"> + <file name="SConstruct" printme="1"> + objects = [ + Object('prog1.c'), + Object('prog2.c', CCFLAGS='-DFOO'), + ] + Program(objects) + + for object_file in Flatten(objects): + print object_file.abspath + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> + + <!-- + + TODO: can't use this now because it displays the temporary path name + + <scons_output example="Flatten3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + /home/me/project/prog1.o + /home/me/project/prog2.o + cc -o prog1.o -c prog1.c + cc -o prog2.o -c -DFOO prog2.c + cc -o prog1 prog1.o prog2.o + </screen> + + </section> + + <section> + <title>Finding the Invocation Directory: the &GetLaunchDir; Function</title> + + <para> + + If you need to find the directory from + which the user invoked the &scons; command, + you can use the &GetLaunchDir; function: + + </para> + + <sconstruct> + env = Environment( + LAUNCHDIR = GetLaunchDir(), + ) + env.Command('directory_build_info', + '$LAUNCHDIR/build_info' + Copy('$TARGET', '$SOURCE')) + </sconstruct> + + <para> + + Because &SCons; is usually invoked from the top-level + directory in which the &SConstruct; file lives, + the Python <function>os.getcwd()</function> + is often equivalent. + However, the &SCons; + <literal>-u</literal>, + <literal>-U</literal> + and + <literal>-D</literal> + command-line options, + when invoked from a subdirectory, + will cause &SCons; to change to the directory + in which the &SConstruct; file is found. + When those options are used, + &GetLaunchDir; will still return the path to the + user's invoking subdirectory, + allowing the &SConscript; configuration + to still get at configuration (or other) files + from the originating directory. + + </para> + + </section> diff --git a/doc/user/misc.xml b/doc/user/misc.xml new file mode 100644 index 0000000..a2305ee --- /dev/null +++ b/doc/user/misc.xml @@ -0,0 +1,565 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; supports a lot of additional functionality + that doesn't readily fit into the other chapters. + + </para> + + <section> + <title>Verifying the Python Version: the &EnsurePythonVersion; Function</title> + + <para> + + Although the &SCons; code itself will run + on any Python version 1.5.2 or later, + you are perfectly free to make use of + Python syntax and modules from more modern versions + (for example, Python 2.4 or 2.5) + when writing your &SConscript; files + or your own local modules. + If you do this, it's usually helpful to + configure &SCons; to exit gracefully with an error message + if it's being run with a version of Python + that simply won't work with your code. + This is especially true if you're going to use &SCons; + to build source code that you plan to distribute publicly, + where you can't be sure of the Python version + that an anonymous remote user might use + to try to build your software. + + </para> + + <para> + + &SCons; provides an &EnsurePythonVersion; function for this. + You simply pass it the major and minor versions + numbers of the version of Python you require: + + </para> + + <!-- + + TODO: Figure out how to generate the error message + regardless of executing Python version by faking out + the infrastructure in some way. + + <scons_example name="EnsurePythonVersion"> + <file name="SConstruct" printme="1"> + EnsurePythonVersion(2, 5) + </file> + </scons_example> + + --> + + <programlisting> + EnsurePythonVersion(2, 5) + </programlisting> + + <para> + + And then &SCons; will exit with the following error + message when a user runs it with an unsupported + earlier version of Python: + + </para> + + <!-- + + TODO: Figure out how to generate the error message + regardless of executing Python version by faking out + the infrastructure in some way. + + <scons_output example="EnsurePythonVersion"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + Python 2.5 or greater required, but you have Python 2.3.6 + </screen> + + </section> + + <section> + <title>Verifying the SCons Version: the &EnsureSConsVersion; Function</title> + + <para> + + You may, of course, write your &SConscript; files + to use features that were only added in + recent versions of &SCons;. + When you publicly distribute software that is built using &SCons;, + it's helpful to have &SCons; + verify the version being used and + exit gracefully with an error message + if the user's version of &SCons; won't work + with your &SConscript; files. + &SCons; provides an &EnsureSConsVersion; function + that verifies the version of &SCons; + in the same + the &EnsurePythonVersion; function + verifies the version of Python, + by passing in the major and minor versions + numbers of the version of SCons you require: + + </para> + + <!-- + + TODO: Figure out how to generate the error message + regardless of executing SCons version by faking out + the infrastructure in some way. + + <scons_example name="EnsureSConsVersion"> + <file name="SConstruct" printme="1"> + EnsureSConsVersion(1, 0) + </file> + </scons_example> + + --> + + <programlisting> + EnsureSConsVersion(1, 0) + </programlisting> + + <para> + + And then &SCons; will exit with the following error + message when a user runs it with an unsupported + earlier version of &SCons;: + + </para> + + <!-- + + TODO: Figure out how to generate the error message + regardless of executing SCons version by faking out + the infrastructure in some way. + + <scons_output example="EnsureSConsVersion"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + SCons 1.0 or greater required, but you have SCons 0.98.5 + </screen> + + </section> + + <section> + <title>Explicitly Terminating &SCons; While Reading &SConscript; Files: the &Exit; Function</title> + + <para> + + &SCons; supports an &Exit; function + which can be used to terminate &SCons; + while reading the &SConscript; files, + usually because you've detected a condition + under which it doesn't make sense to proceed: + + </para> + + <programlisting> + if ARGUMENTS.get('FUTURE'): + print "The FUTURE option is not supported yet!" + Exit(2) + env = Environment() + env.Program('hello.c') + </programlisting> + + <screen> + % <userinput>scons -Q FUTURE=1</userinput> + The FUTURE option is not supported yet! + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + The &Exit; function takes as an argument + the (numeric) exit status that you want &SCons; to exit with. + If you don't specify a value, + the default is to exit with <literal>0</literal>, + which indicates successful execution. + + </para> + + <para> + + Note that the &Exit; function + is equivalent to calling the Python + <function>sys.exit</function> function + (which the it actually calls), + but because &Exit; is a &SCons; function, + you don't have to import the Python + <literal>sys</literal> module to use it. + + </para> + + </section> + + <section> + <title>Searching for Files: the &FindFile; Function</title> + + <para> + + The &FindFile; function searches for a file in a list of directories. + If there is only one directory, it can be given as a simple string. + The function returns a File node if a matching file exists, + or None if no file is found. + (See the documentation for the &Glob; function for an alternative way + of searching for entries in a directory.) + + </para> + + <programlisting> + # one directory + print FindFile('missing', '.') + t = FindFile('exists', '.') + print t.__class__, t + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + None + SCons.Node.FS.File exists + scons: `.' is up to date. + </screen> + + <programlisting> + # several directories + includes = [ '.', 'include', 'src/include'] + headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h'] + for hdr in headers: + print '%-12s' % ('%s:' % hdr), FindFile(hdr, includes) +</programlisting> + + <screen> + % <userinput>scons -Q</userinput> + nonesuch.h: None + config.h: config.h + private.h: src/include/private.h + dist.h: include/dist.h + scons: `.' is up to date. + </screen> + + <!-- The man page says this should work, but it fails. + <para> + + If the 'file' parameter is a list of files, + a list of File nodes is returned. + + </para> + + <scons_example name="FindFile1c"> + <file name="SConstruct" printme="1"> + # several directories + includes = [ '.', 'include', 'src/include'] + headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h'] + print FindFile(headers, includes) + </file> + <file name="config.h"> + exists + </file> + <directory name="src"></directory> + <directory name="src/include"></directory> + </file> + <file name="src/include/private.h"> + exists + <directory name="include"></directory> + </file> + <file name="include/dist.h"> + exists + </scons_example> + + <scons_output example="FindFile1c" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + --> + + <para> + + If the file exists in more than one directory, + only the first occurrence is returned. + + </para> + + <programlisting> + print FindFile('multiple', ['sub1', 'sub2', 'sub3']) + print FindFile('multiple', ['sub2', 'sub3', 'sub1']) + print FindFile('multiple', ['sub3', 'sub1', 'sub2']) + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + sub1/multiple + sub2/multiple + sub3/multiple + scons: `.' is up to date. + </screen> + + <!-- file may be a list of file names or a single file name. --> + + <para> + + In addition to existing files, &FindFile; will also find derived files + (that is, non-leaf files) that haven't been built yet. + (Leaf files should already exist, or the build will fail!) + + </para> + + <programlisting> + # Neither file exists, so build will fail + Command('derived', 'leaf', 'cat >$TARGET $SOURCE') + print FindFile('leaf', '.') + print FindFile('derived', '.') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + None + derived + scons: *** [derived] Source `leaf' not found, needed by target `derived'. + </screen> + + <programlisting> + # Neither file exists, so build will fail + Command('derived', 'leaf', 'cat >$TARGET $SOURCE') + print FindFile('leaf', '.') + print FindFile('derived', '.') + + # Only 'leaf' exists + Command('derived', 'leaf', 'cat >$TARGET $SOURCE') + print FindFile('leaf', '.') + print FindFile('derived', '.') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + leaf + derived + cat > derived leaf + </screen> + + <para> + + If a source file exists, &FindFile; will correctly return the name + in the build directory. + + </para> + + <programlisting> + # Only 'src/leaf' exists + VariantDir('build', 'src') + print FindFile('leaf', 'build') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + build/leaf + scons: `.' is up to date. + </screen> + + </section> + + <section> + <title>Handling Nested Lists: the &Flatten; Function</title> + + <para> + + &SCons; supports a &Flatten; function + which takes an input Python sequence + (list or tuple) + and returns a flattened list + containing just the individual elements of + the sequence. + This can be handy when trying to examine + a list composed of the lists + returned by calls to various Builders. + For example, you might collect + object files built in different ways + into one call to the &Program; Builder + by just enclosing them in a list, as follows: + + </para> + + <programlisting> + objects = [ + Object('prog1.c'), + Object('prog2.c', CCFLAGS='-DFOO'), + ] + Program(objects) + </programlisting> + + <para> + + Because the Builder calls in &SCons; + flatten their input lists, + this works just fine to build the program: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o prog1.o -c prog1.c + cc -o prog2.o -c -DFOO prog2.c + cc -o prog1 prog1.o prog2.o + </screen> + + <para> + + But if you were debugging your build + and wanted to print the absolute path + of each object file in the + <varname>objects</varname> list, + you might try the following simple approach, + trying to print each Node's + <literal>abspath</literal> + attribute: + + </para> + + <programlisting> + objects = [ + Object('prog1.c'), + Object('prog2.c', CCFLAGS='-DFOO'), + ] + Program(objects) + + for object_file in objects: + print object_file.abspath + </programlisting> + + <para> + + This does not work as expected + because each call to <function>str</function> + is operating an embedded list returned by + each &Object; call, + not on the underlying Nodes within those lists: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + AttributeError: NodeList instance has no attribute 'abspath': + File "/home/my/project/SConstruct", line 8: + print object_file.abspath + </screen> + + <para> + + The solution is to use the &Flatten; function + so that you can pass each Node to + the <function>str</function> separately: + + </para> + + <programlisting> + objects = [ + Object('prog1.c'), + Object('prog2.c', CCFLAGS='-DFOO'), + ] + Program(objects) + + for object_file in Flatten(objects): + print object_file.abspath + </programlisting> + + <!-- + + TODO: can't use this now because it displays the temporary path name + + <scons_output example="Flatten3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + /home/me/project/prog1.o + /home/me/project/prog2.o + cc -o prog1.o -c prog1.c + cc -o prog2.o -c -DFOO prog2.c + cc -o prog1 prog1.o prog2.o + </screen> + + </section> + + <section> + <title>Finding the Invocation Directory: the &GetLaunchDir; Function</title> + + <para> + + If you need to find the directory from + which the user invoked the &scons; command, + you can use the &GetLaunchDir; function: + + </para> + + <programlisting> + env = Environment( + LAUNCHDIR = GetLaunchDir(), + ) + env.Command('directory_build_info', + '$LAUNCHDIR/build_info' + Copy('$TARGET', '$SOURCE')) + </programlisting> + + <para> + + Because &SCons; is usually invoked from the top-level + directory in which the &SConstruct; file lives, + the Python <function>os.getcwd()</function> + is often equivalent. + However, the &SCons; + <literal>-u</literal>, + <literal>-U</literal> + and + <literal>-D</literal> + command-line options, + when invoked from a subdirectory, + will cause &SCons; to change to the directory + in which the &SConstruct; file is found. + When those options are used, + &GetLaunchDir; will still return the path to the + user's invoking subdirectory, + allowing the &SConscript; configuration + to still get at configuration (or other) files + from the originating directory. + + </para> + + </section> diff --git a/doc/user/nodes.in b/doc/user/nodes.in new file mode 100644 index 0000000..c914ce5 --- /dev/null +++ b/doc/user/nodes.in @@ -0,0 +1,386 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Internally, &SCons; represents all of the files + and directories it knows about as &Nodes;. + These internal objects + (not object <emphasis>files</emphasis>) + can be used in a variety of ways + to make your &SConscript; + files portable and easy to read. + + </para> + + <section> + <title>Builder Methods Return Lists of Target Nodes</title> + + <para> + + All builder methods return a list of + &Node; objects that identify the + target file or files that will be built. + These returned &Nodes; can be passed + as arguments to other builder methods. + + </para> + + <para> + + For example, suppose that we want to build + the two object files that make up a program with different options. + This would mean calling the &b-link-Object; + builder once for each object file, + specifying the desired options: + + </para> + + <sconstruct> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + </sconstruct> + + <para> + + One way to combine these object files + into the resulting program + would be to call the &b-link-Program; + builder with the names of the object files + listed as sources: + + </para> + + <sconstruct> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(['hello.o', 'goodbye.o']) + </sconstruct> + + <para> + + The problem with specifying the names as strings + is that our &SConstruct; file is no longer portable + across operating systems. + It won't, for example, work on Windows + because the object files there would be + named &hello_obj; and &goodbye_obj;, + not &hello_o; and &goodbye_o;. + + </para> + + <para> + + A better solution is to assign the lists of targets + returned by the calls to the &b-Object; builder to variables, + which we can then concatenate in our + call to the &b-Program; builder: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + hello_list = Object('hello.c', CCFLAGS='-DHELLO') + goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(hello_list + goodbye_list) + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> + + <para> + + This makes our &SConstruct; file portable again, + the build output on Linux looking like: + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And on Windows: + + </para> + + <scons_output example="ex1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + We'll see examples of using the list of nodes + returned by builder methods throughout + the rest of this guide. + + </para> + + </section> + + <section> + <title>Explicitly Creating File and Directory Nodes</title> + + <para> + + It's worth mentioning here that + &SCons; maintains a clear distinction + between Nodes that represent files + and Nodes that represent directories. + &SCons; supports &File; and &Dir; + functions that, respectively, + return a file or directory Node: + + </para> + + <scons_example name="print"> + <file name="SConstruct" printme="1"> + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + </file> + </scons_example> + + <para> + + Normally, you don't need to call + &File; or &Dir; directly, + because calling a builder method automatically + treats strings as the names of files or directories, + and translates them into + the Node objects for you. + The &File; and &Dir; functions can come in handy + in situations where you need to explicitly + instruct &SCons; about the type of Node being + passed to a builder or other function, + or unambiguously refer to a specific + file in a directory tree. + <!-- + (For an example of when you might + need to use &File; or &Dir; to + prevent ambiguous interpretation of a string + naming a file or directory, see + <xref linkend="chap-hierarchy">.) + --> + + </para> + + <para> + + There are also times when you may need to + refer to an entry in a file system + without knowing in advance + whether it's a file or a directory. + For those situations, + &SCons; also supports an &Entry; function, + which returns a Node + that can represent either a file or a directory. + + </para> + + <sconstruct> + xyzzy = Entry('xyzzy') + </sconstruct> + + <para> + + The returned <literal>xyzzy</literal> Node + will be turned into a file or directory Node + the first time it is used by a builder method + or other function that + requires one vs. the other. + + </para> + + </section> + + <section> + <title>Printing &Node; File Names</title> + + <para> + + One of the most common things you can do + with a Node is use it to print the + file name that the node represents. + Keep in mind, though, that because the object + returned by a builder call + is a <emphasis>list</emphasis> of Nodes, + you must use Python subscripts + to fetch individual Nodes from the list. + For example, the following &SConstruct; file: + + </para> + + <scons_example name="print"> + <file name="SConstruct" printme="1"> + object_list = Object('hello.c') + program_list = Program(object_list) + print "The object file is:", object_list[0] + print "The program file is:", program_list[0] + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Would print the following file names on a POSIX system: + + </para> + + <scons_output example="print" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And the following file names on a Windows system: + + </para> + + <scons_output example="print" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that in the above example, + the <literal>object_list[0]</literal> + extracts an actual Node <emphasis>object</emphasis> + from the list, + and the Python <literal>print</literal> statement + converts the object to a string for printing. + + </para> + + </section> + + <section> + <title>Using a &Node;'s File Name as a String</title> + + <para> + + Printing a &Node;'s name + as described in the previous section + works because the string representation of a &Node; object + is the name of the file. + If you want to do something other than + print the name of the file, + you can fetch it by using the builtin Python + &str; function. + For example, if you want to use the Python + <function>os.path.exists</function> + to figure out whether a file + exists while the &SConstruct; file + is being read and executed, + you can fetch the string as follows: + + </para> + + <scons_example name="exists"> + <file name="SConstruct" printme="1"> + import os.path + program_list = Program('hello.c') + program_name = str(program_list[0]) + if not os.path.exists(program_name): + print program_name, "does not exist!" + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <scons_output example="exists" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <!-- + + <section> + <title>Fetching the Contents of a &Node;</title> + + <para> + + XXX Describe using read() and readlines() + when we add that as a public interface. + + </para> + + <scons_example name="read"> + <file name="SConstruct" printme="1"> + hello_c = File('hello.c') + contents = hello_c.read() + print "contents are:" + print contents + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <scons_output example="read" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + --> + + <!-- + + <section> + <title>Python Value &Node;</title> + + <para> + + XXX Value() + + </para> + + </section> + + --> diff --git a/doc/user/nodes.xml b/doc/user/nodes.xml new file mode 100644 index 0000000..46215c4 --- /dev/null +++ b/doc/user/nodes.xml @@ -0,0 +1,401 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Internally, &SCons; represents all of the files + and directories it knows about as &Nodes;. + These internal objects + (not object <emphasis>files</emphasis>) + can be used in a variety of ways + to make your &SConscript; + files portable and easy to read. + + </para> + + <section> + <title>Builder Methods Return Lists of Target Nodes</title> + + <para> + + All builder methods return a list of + &Node; objects that identify the + target file or files that will be built. + These returned &Nodes; can be passed + as arguments to other builder methods. + + </para> + + <para> + + For example, suppose that we want to build + the two object files that make up a program with different options. + This would mean calling the &b-link-Object; + builder once for each object file, + specifying the desired options: + + </para> + + <programlisting> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + </programlisting> + + <para> + + One way to combine these object files + into the resulting program + would be to call the &b-link-Program; + builder with the names of the object files + listed as sources: + + </para> + + <programlisting> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(['hello.o', 'goodbye.o']) + </programlisting> + + <para> + + The problem with specifying the names as strings + is that our &SConstruct; file is no longer portable + across operating systems. + It won't, for example, work on Windows + because the object files there would be + named &hello_obj; and &goodbye_obj;, + not &hello_o; and &goodbye_o;. + + </para> + + <para> + + A better solution is to assign the lists of targets + returned by the calls to the &b-Object; builder to variables, + which we can then concatenate in our + call to the &b-Program; builder: + + </para> + + <programlisting> + hello_list = Object('hello.c', CCFLAGS='-DHELLO') + goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(hello_list + goodbye_list) + </programlisting> + + <para> + + This makes our &SConstruct; file portable again, + the build output on Linux looking like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o goodbye.o -c -DGOODBYE goodbye.c + cc -o hello.o -c -DHELLO hello.c + cc -o hello hello.o goodbye.o + </screen> + + <para> + + And on Windows: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fogoodbye.obj /c goodbye.c -DGOODBYE + cl /Fohello.obj /c hello.c -DHELLO + link /nologo /OUT:hello.exe hello.obj goodbye.obj + </screen> + + <para> + + We'll see examples of using the list of nodes + returned by builder methods throughout + the rest of this guide. + + </para> + + </section> + + <section> + <title>Explicitly Creating File and Directory Nodes</title> + + <para> + + It's worth mentioning here that + &SCons; maintains a clear distinction + between Nodes that represent files + and Nodes that represent directories. + &SCons; supports &File; and &Dir; + functions that, respectively, + return a file or directory Node: + + </para> + + <programlisting> + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + </programlisting> + + <para> + + Normally, you don't need to call + &File; or &Dir; directly, + because calling a builder method automatically + treats strings as the names of files or directories, + and translates them into + the Node objects for you. + The &File; and &Dir; functions can come in handy + in situations where you need to explicitly + instruct &SCons; about the type of Node being + passed to a builder or other function, + or unambiguously refer to a specific + file in a directory tree. + <!-- + (For an example of when you might + need to use &File; or &Dir; to + prevent ambiguous interpretation of a string + naming a file or directory, see + <xref linkend="chap-hierarchy">.) + --> + + </para> + + <para> + + There are also times when you may need to + refer to an entry in a file system + without knowing in advance + whether it's a file or a directory. + For those situations, + &SCons; also supports an &Entry; function, + which returns a Node + that can represent either a file or a directory. + + </para> + + <programlisting> + xyzzy = Entry('xyzzy') + </programlisting> + + <para> + + The returned <literal>xyzzy</literal> Node + will be turned into a file or directory Node + the first time it is used by a builder method + or other function that + requires one vs. the other. + + </para> + + </section> + + <section> + <title>Printing &Node; File Names</title> + + <para> + + One of the most common things you can do + with a Node is use it to print the + file name that the node represents. + Keep in mind, though, that because the object + returned by a builder call + is a <emphasis>list</emphasis> of Nodes, + you must use Python subscripts + to fetch individual Nodes from the list. + For example, the following &SConstruct; file: + + </para> + + <programlisting> + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + + object_list = Object('hello.c') + program_list = Program(object_list) + print "The object file is:", object_list[0] + print "The program file is:", program_list[0] + </programlisting> + + <para> + + Would print the following file names on a POSIX system: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + The object file is: hello.o + The program file is: hello + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + And the following file names on a Windows system: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + The object file is: hello.obj + The program file is: hello.exe + cl /Fohello.obj /c hello.c /nologo + link /nologo /OUT:hello.exe hello.obj + </screen> + + <para> + + Note that in the above example, + the <literal>object_list[0]</literal> + extracts an actual Node <emphasis>object</emphasis> + from the list, + and the Python <literal>print</literal> statement + converts the object to a string for printing. + + </para> + + </section> + + <section> + <title>Using a &Node;'s File Name as a String</title> + + <para> + + Printing a &Node;'s name + as described in the previous section + works because the string representation of a &Node; object + is the name of the file. + If you want to do something other than + print the name of the file, + you can fetch it by using the builtin Python + &str; function. + For example, if you want to use the Python + <function>os.path.exists</function> + to figure out whether a file + exists while the &SConstruct; file + is being read and executed, + you can fetch the string as follows: + + </para> + + <programlisting> + import os.path + program_list = Program('hello.c') + program_name = str(program_list[0]) + if not os.path.exists(program_name): + print program_name, "does not exist!" + </programlisting> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + hello does not exist! + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + </section> + + <!-- + + <section> + <title>Fetching the Contents of a &Node;</title> + + <para> + + XXX Describe using read() and readlines() + when we add that as a public interface. + + </para> + + <scons_example name="read"> + <file name="SConstruct" printme="1"> + hello_c = File('hello.c') + contents = hello_c.read() + print "contents are:" + print contents + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <scons_output example="read" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + --> + + <!-- + + <section> + <title>Python Value &Node;</title> + + <para> + + XXX Value() + + </para> + + </section> + + --> diff --git a/doc/user/output.in b/doc/user/output.in new file mode 100644 index 0000000..1f600f3 --- /dev/null +++ b/doc/user/output.in @@ -0,0 +1,681 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + A key aspect of creating a usable build configuration + is providing good output from the build + so its users can readily understand + what the build is doing + and get information about how to control the build. + &SCons; provides several ways of + controlling output from the build configuration + to help make the build + more useful and understandable. + + </para> + + <section> + <title>Providing Build Help: the &Help; Function</title> + + <para> + + It's often very useful to be able to give + users some help that describes the + specific targets, build options, etc., + that can be used for your build. + &SCons; provides the &Help; function + to allow you to specify this help text: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + Help(""" + Type: 'scons program' to build the production program, + 'scons debug' to build the debug version. + """) + </file> + </scons_example> + + <para> + + (Note the above use of the Python triple-quote syntax, + which comes in very handy for + specifying multi-line strings like help text.) + + </para> + + <para> + + When the &SConstruct; or &SConscript; files + contain such a call to the &Help; function, + the specified help text will be displayed in response to + the &SCons; <literal>-h</literal> option: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> + + <para> + + The &SConscript; files may contain + multiple calls to the &Help; function, + in which case the specified text(s) + will be concatenated when displayed. + This allows you to split up the + help text across multiple &SConscript; files. + In this situation, the order in + which the &SConscript; files are called + will determine the order in which the &Help; functions are called, + which will determine the order in which + the various bits of text will get concatenated. + + </para> + + <para> + + Another use would be to make the help text conditional + on some variable. + For example, suppose you only want to display + a line about building a Windows-only + version of a program when actually + run on Windows. + The following &SConstruct; file: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> + env = Environment() + + Help("\nType: 'scons program' to build the production program.\n") + + if env['PLATFORM'] == 'win32': + Help("\nType: 'scons windebug' to build the Windows debug version.\n") + </file> + </scons_example> + + <para> + + Will display the complete help text on Windows: + + </para> + + <scons_output example="ex2" os="win32"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> + + <para> + + But only show the relevant option on a Linux or UNIX system: + + </para> + + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> + + <para> + + If there is no &Help; text in the &SConstruct; or + &SConscript; files, + &SCons; will revert to displaying its + standard list that describes the &SCons; command-line + options. + This list is also always displayed whenever + the <literal>-H</literal> option is used. + + </para> + + </section> + + <section> + <title>Controlling How &SCons; Prints Build Commands: the <envar>$*COMSTR</envar> Variables</title> + + <para> + + Sometimes the commands executed + to compile object files or link programs + (or build other targets) + can get very long, + long enough to make it difficult for users + to distinguish error messages or + other important build output + from the commands themselves. + All of the default <envar>$*COM</envar> variables + that specify the command lines + used to build various types of target files + have a corresponding <envar>$*COMSTR</envar> variable + that can be set to an alternative + string that will be displayed + when the target is built. + + </para> + + <para> + + For example, suppose you want to + have &SCons; display a + <literal>"Compiling"</literal> + message whenever it's compiling an object file, + and a + <literal>"Linking"</literal> + when it's linking an executable. + You could write a &SConstruct; file + that looks like: + + </para> + + <scons_example name="COMSTR"> + <file name="SConstruct" printme="1"> + env = Environment(CCCOMSTR = "Compiling $TARGET", + LINKCOMSTR = "Linking $TARGET") + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + Which would then yield the output: + + </para> + + <!-- + + <scons_output example="COMSTR" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + Compiling foo.o + Linking foo + </screen> + + <para> + + &SCons; performs complete variable substitution + on <envar>$*COMSTR</envar> variables, + so they have access to all of the + standard variables like &cv-TARGET; &cv-SOURCES;, etc., + as well as any construction variables + that happen to be configured in + the construction environment + used to build a specific target. + + </para> + + <para> + + Of course, sometimes it's still important to + be able to see the exact command + that &SCons; will execute to build a target. + For example, you may simply need to verify + that &SCons; is configured to supply + the right options to the compiler, + or a developer may want to + cut-and-paste a compile command + to add a few options + for a custom test. + + </para> + + <para> + + One common way to give users + control over whether or not + &SCons; should print the actual command line + or a short, configured summary + is to add support for a + <varname>VERBOSE</varname> + command-line variable to your &SConstruct; file. + A simple configuration for this might look like: + + </para> + + <scons_example name="COMSTR-VERBOSE"> + <file name="SConstruct" printme="1"> + env = Environment() + if ARGUMENTS.get('VERBOSE') != "1': + env['CCCOMSTR'] = "Compiling $TARGET" + env['LINKCOMSTR'] = "Linking $TARGET" + env.Program('foo.c') + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> + + <para> + + + By only setting the appropriate + <envar>$*COMSTR</envar> variables + if the user specifies + <literal>VERBOSE=1</literal> + on the command line, + the user has control + over how &SCons; + displays these particular command lines: + + </para> + + <!-- + + <scons_output example="COMSTR-VERBOSE" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q VERBOSE=1</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + Compiling foo.o + Linking foo + % <userinput>scons -Q -c</userinput> + Removed foo.o + Removed foo + % <userinput>scons -Q VERBOSE=1</userinput> + cc -o foo.o -c foo.c + cc -o foo foo.o + </screen> + + </section> + + <section> + <title>Providing Build Progress Output: the &Progress; Function</title> + + <para> + + Another aspect of providing good build output + is to give the user feedback + about what &SCons; is doing + even when nothing is being built at the moment. + This can be especially true for large builds + when most of the targets are already up-to-date. + Because &SCons; can take a long time + making absolutely sure that every + target is, in fact, up-to-date + with respect to a lot of dependency files, + it can be easy for users to mistakenly + conclude that &SCons; is hung + or that there is some other problem with the build. + + </para> + + <para> + + One way to deal with this perception + is to configure &SCons; to print something to + let the user know what it's "thinking about." + The &Progress; function + allows you to specify a string + that will be printed for every file + that &SCons; is "considering" + while it is traversing the dependency graph + to decide what targets are or are not up-to-date. + + </para> + + <scons_example name="Progress-TARGET"> + <file name="SConstruct" printme="1"> + Progress('Evaluating $TARGET\n') + Program('f1.c') + Program('f2.c') + </file> + <file name="f1.c"> + f1.c + </file> + <file name="f2.c"> + f2.c + </file> + </scons_example> + + <para> + + Note that the &Progress; function does not + arrange for a newline to be printed automatically + at the end of the string (as does the Python + <literal>print</literal> statement), + and we must specify the + <literal>\n</literal> + that we want printed at the end of the configured string. + This configuration, then, + will have &SCons; + print that it is <literal>Evaluating</literal> + each file that it encounters + in turn as it traverses the dependency graph: + + </para> + + <scons_output example="Progress-TARGET" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Of course, normally you don't want to add + all of these additional lines to your build output, + as that can make it difficult for the user + to find errors or other important messages. + A more useful way to display + this progress might be + to have the file names printed + directly to the user's screen, + not to the same standard output + stream where build output is printed, + and to use a carriage return character + (<literal>\r</literal>) + so that each file name gets re-printed on the same line. + Such a configuration would look like: + + </para> + + <sconstruct> + Progress('$TARGET\r', + file=open('/dev/tty', 'w'), + overwrite=True) + Program('f1.c') + Program('f2.c') + </sconstruct> + + <para> + + Note that we also specified the + <literal>overwrite=True</literal> argument + to the &Progress; function, + which causes &SCons; to + "wipe out" the previous string with space characters + before printing the next &Progress; string. + Without the + <literal>overwrite=True</literal> argument, + a shorter file name would not overwrite + all of the charactes in a longer file name that + precedes it, + making it difficult to tell what the + actual file name is on the output. + Also note that we opened up the + <filename>/dev/tty</filename> file + for direct access (on POSIX) to + the user's screen. + On Windows, the equivalent would be to open + the <filename>con:</filename> file name. + + </para> + + <para> + + Also, it's important to know that although you can use + <literal>$TARGET</literal> to substitute the name of + the node in the string, + the &Progress; function does <emphasis>not</emphasis> + perform general variable substitution + (because there's not necessarily a construction + environment involved in evaluating a node + like a source file, for example). + + </para> + + <para> + + You can also specify a list of strings + to the &Progress; function, + in which case &SCons; will + display each string in turn. + This can be used to implement a "spinner" + by having &SCons; cycle through a + sequence of strings: + + </para> + + <sconstruct> + Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5) + Program('f1.c') + Program('f2.c') + </sconstruct> + + <para> + + Note that here we have also used the + <literal>interval=</literal> + keyword argument to have &SCons; + only print a new "spinner" string + once every five evaluated nodes. + Using an <literal>interval=</literal> count, + even with strings that use <literal>$TARGET</literal> like + our examples above, + can be a good way to lessen the + work that &SCons; expends printing &Progress; strings, + while still giving the user feedback + that indicates &SCons; is still + working on evaluating the build. + + </para> + + <para> + + Lastly, you can have direct control + over how to print each evaluated node + by passing a Python function + (or other Python callable) + to the &Progress function. + Your function will be called + for each evaluated node, + allowing you to + implement more sophisticated logic + like adding a counter: + + </para> + + <scons_example name="Progress-callable"> + <file name="SConstruct" printme="1"> + screen = open('/dev/tty', 'w') + count = 0 + def progress_function(node) + count += 1 + screen.write('Node %4d: %s\r' % (count, node)) + + Progress(progress_function) + </file> + </scons_example> + + <para> + + Of course, if you choose, + you could completely ignore the + <varname>node</varname> argument to the function, + and just print a count, + or anything else you wish. + + </para> + + <para> + + (Note that there's an obvious follow-on question here: + how would you find the total number of nodes + that <emphasis>will be</emphasis> + evaluated so you can tell the user how + close the build is to finishing? + Unfortunately, in the general case, + there isn't a good way to do that, + short of having &SCons; evaluate its + dependency graph twice, + first to count the total and + the second time to actually build the targets. + This would be necessary because + you can't know in advance which + target(s) the user actually requested + to be built. + The entire build may consist of thousands of Nodes, + for example, + but maybe the user specifically requested + that only a single object file be built.) + + </para> + + </section> + + <section> + <title>Printing Detailed Build Status: the &GetBuildFailures; Function</title> + + <para> + + SCons, like most build tools, returns zero status to + the shell on success and nonzero status on failure. + Sometimes it's useful to give more information about + the build status at the end of the run, for instance + to print an informative message, send an email, or + page the poor slob who broke the build. + + </para> + + <para> + + SCons provides a &GetBuildFailures; method that + you can use in a python <function>atexit</function> function + to get a list of objects describing the actions that failed + while attempting to build targets. There can be more + than one if you're using <literal>-j</literal>. Here's a + simple example: + + </para> + + <scons_example name="gbf1"> + <file name="SConstruct" printme="1"> + import atexit + + def print_build_failures(): + from SCons.Script import GetBuildFailures + for bf in GetBuildFailures(): + print "%s failed: %s" % (bf.node, bf.errstr) + atexit.register(print_build_failures) + </file> + </scons_example> + + <para> + + The <function>atexit.register</function> call + registers <function>print_build_failures</function> + as an <function>atexit</function> callback, to be called + before &SCons; exits. When that function is called, + it calls &GetBuildFailures; to fetch the list of failed objects. + See the man page + for the detailed contents of the returned objects; + some of the more useful attributes are + <literal>.node</literal>, + <literal>.errstr</literal>, + <literal>.filename</literal>, and + <literal>.command</literal>. + The <literal>filename</literal> is not necessarily + the same file as the <literal>node</literal>; the + <literal>node</literal> is the target that was + being built when the error occurred, while the + <literal>filename</literal>is the file or dir that + actually caused the error. + Note: only call &GetBuildFailures; at the end of the + build; calling it at any other time is undefined. + + </para> + + <para> + + Here is a more complete example showing how to + turn each element of &GetBuildFailures; into a string: + + </para> + + <scons_example name="gbf2"> + <file name="SConstruct" printme="1"> + # Make the build fail if we pass fail=1 on the command line + if ARGUMENTS.get('fail', 0): + Command('target', 'source', ['/bin/false']) + + def bf_to_str(bf): + """Convert an element of GetBuildFailures() to a string + in a useful way.""" + import SCons.Errors + if bf is None: # unknown targets product None in list + return '(unknown tgt)' + elif isinstance(bf, SCons.Errors.StopError): + return str(bf) + elif bf.node: + return str(bf.node) + ': ' + bf.errstr + elif bf.filename: + return bf.filename + ': ' + bf.errstr + return 'unknown failure: ' + bf.errstr + import atexit + + def build_status(): + """Convert the build status to a 2-tuple, (status, msg).""" + from SCons.Script import GetBuildFailures + bf = GetBuildFailures() + if bf: + # bf is normally a list of build failures; if an element is None, + # it's because of a target that scons doesn't know anything about. + status = 'failed' + failures_message = "\n".join(["Failed building %s" % bf_to_str(x) + for x in bf if x is not None]) + else: + # if bf is None, the build completed successfully. + status = 'ok' + failures_message = '' + return (status, failures_message) + + def display_build_status(): + """Display the build status. Called by atexit. + Here you could do all kinds of complicated things.""" + status, failures_message = build_status() + if status == 'failed': + print "FAILED!!!!" # could display alert, ring bell, etc. + elif status == 'ok': + print "Build succeeded." + print failures_message + + atexit.register(display_build_status) + </file> + </scons_example> + + <para> + + When this runs, you'll see the appropriate output: + + </para> + + <scons_output example="gbf2"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q fail=1</scons_output_command> + </scons_output> + + </section> diff --git a/doc/user/output.xml b/doc/user/output.xml new file mode 100644 index 0000000..89b443b --- /dev/null +++ b/doc/user/output.xml @@ -0,0 +1,703 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + A key aspect of creating a usable build configuration + is providing good output from the build + so its users can readily understand + what the build is doing + and get information about how to control the build. + &SCons; provides several ways of + controlling output from the build configuration + to help make the build + more useful and understandable. + + </para> + + <section> + <title>Providing Build Help: the &Help; Function</title> + + <para> + + It's often very useful to be able to give + users some help that describes the + specific targets, build options, etc., + that can be used for your build. + &SCons; provides the &Help; function + to allow you to specify this help text: + + </para> + + <programlisting> + Help(""" + Type: 'scons program' to build the production program, + 'scons debug' to build the debug version. + """) + </programlisting> + + <para> + + (Note the above use of the Python triple-quote syntax, + which comes in very handy for + specifying multi-line strings like help text.) + + </para> + + <para> + + When the &SConstruct; or &SConscript; files + contain such a call to the &Help; function, + the specified help text will be displayed in response to + the &SCons; <literal>-h</literal> option: + + </para> + + <screen> + % <userinput>scons -h</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + + Type: 'scons program' to build the production program, + 'scons debug' to build the debug version. + + Use scons -H for help about command-line options. + </screen> + + <para> + + The &SConscript; files may contain + multiple calls to the &Help; function, + in which case the specified text(s) + will be concatenated when displayed. + This allows you to split up the + help text across multiple &SConscript; files. + In this situation, the order in + which the &SConscript; files are called + will determine the order in which the &Help; functions are called, + which will determine the order in which + the various bits of text will get concatenated. + + </para> + + <para> + + Another use would be to make the help text conditional + on some variable. + For example, suppose you only want to display + a line about building a Windows-only + version of a program when actually + run on Windows. + The following &SConstruct; file: + + </para> + + <programlisting> + env = Environment() + + Help("\nType: 'scons program' to build the production program.\n") + + if env['PLATFORM'] == 'win32': + Help("\nType: 'scons windebug' to build the Windows debug version.\n") + </programlisting> + + <para> + + Will display the complete help text on Windows: + + </para> + + <screen> + C:\><userinput>scons -h</userinput> + scons: Reading SConscript files ... + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + scons: done reading SConscript files. + + Type: 'scons program' to build the production program. + + Type: 'scons windebug' to build the Windows debug version. + + Use scons -H for help about command-line options. + </screen> + + <para> + + But only show the relevant option on a Linux or UNIX system: + + </para> + + <screen> + % <userinput>scons -h</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + + Type: 'scons program' to build the production program. + + Use scons -H for help about command-line options. + </screen> + + <para> + + If there is no &Help; text in the &SConstruct; or + &SConscript; files, + &SCons; will revert to displaying its + standard list that describes the &SCons; command-line + options. + This list is also always displayed whenever + the <literal>-H</literal> option is used. + + </para> + + </section> + + <section> + <title>Controlling How &SCons; Prints Build Commands: the <envar>$*COMSTR</envar> Variables</title> + + <para> + + Sometimes the commands executed + to compile object files or link programs + (or build other targets) + can get very long, + long enough to make it difficult for users + to distinguish error messages or + other important build output + from the commands themselves. + All of the default <envar>$*COM</envar> variables + that specify the command lines + used to build various types of target files + have a corresponding <envar>$*COMSTR</envar> variable + that can be set to an alternative + string that will be displayed + when the target is built. + + </para> + + <para> + + For example, suppose you want to + have &SCons; display a + <literal>"Compiling"</literal> + message whenever it's compiling an object file, + and a + <literal>"Linking"</literal> + when it's linking an executable. + You could write a &SConstruct; file + that looks like: + + </para> + + <programlisting> + env = Environment(CCCOMSTR = "Compiling $TARGET", + LINKCOMSTR = "Linking $TARGET") + env.Program('foo.c') + </programlisting> + + <para> + + Which would then yield the output: + + </para> + + <!-- + + <scons_output example="COMSTR" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + Compiling foo.o + Linking foo + </screen> + + <para> + + &SCons; performs complete variable substitution + on <envar>$*COMSTR</envar> variables, + so they have access to all of the + standard variables like &cv-TARGET; &cv-SOURCES;, etc., + as well as any construction variables + that happen to be configured in + the construction environment + used to build a specific target. + + </para> + + <para> + + Of course, sometimes it's still important to + be able to see the exact command + that &SCons; will execute to build a target. + For example, you may simply need to verify + that &SCons; is configured to supply + the right options to the compiler, + or a developer may want to + cut-and-paste a compile command + to add a few options + for a custom test. + + </para> + + <para> + + One common way to give users + control over whether or not + &SCons; should print the actual command line + or a short, configured summary + is to add support for a + <varname>VERBOSE</varname> + command-line variable to your &SConstruct; file. + A simple configuration for this might look like: + + </para> + + <programlisting> + env = Environment() + if ARGUMENTS.get('VERBOSE') != "1': + env['CCCOMSTR'] = "Compiling $TARGET" + env['LINKCOMSTR'] = "Linking $TARGET" + env.Program('foo.c') + </programlisting> + + <para> + + + By only setting the appropriate + <envar>$*COMSTR</envar> variables + if the user specifies + <literal>VERBOSE=1</literal> + on the command line, + the user has control + over how &SCons; + displays these particular command lines: + + </para> + + <!-- + + <scons_output example="COMSTR-VERBOSE" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q VERBOSE=1</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q</userinput> + Compiling foo.o + Linking foo + % <userinput>scons -Q -c</userinput> + Removed foo.o + Removed foo + % <userinput>scons -Q VERBOSE=1</userinput> + cc -o foo.o -c foo.c + cc -o foo foo.o + </screen> + + </section> + + <section> + <title>Providing Build Progress Output: the &Progress; Function</title> + + <para> + + Another aspect of providing good build output + is to give the user feedback + about what &SCons; is doing + even when nothing is being built at the moment. + This can be especially true for large builds + when most of the targets are already up-to-date. + Because &SCons; can take a long time + making absolutely sure that every + target is, in fact, up-to-date + with respect to a lot of dependency files, + it can be easy for users to mistakenly + conclude that &SCons; is hung + or that there is some other problem with the build. + + </para> + + <para> + + One way to deal with this perception + is to configure &SCons; to print something to + let the user know what it's "thinking about." + The &Progress; function + allows you to specify a string + that will be printed for every file + that &SCons; is "considering" + while it is traversing the dependency graph + to decide what targets are or are not up-to-date. + + </para> + + <programlisting> + Progress('Evaluating $TARGET\n') + Program('f1.c') + Program('f2.c') + </programlisting> + + <para> + + Note that the &Progress; function does not + arrange for a newline to be printed automatically + at the end of the string (as does the Python + <literal>print</literal> statement), + and we must specify the + <literal>\n</literal> + that we want printed at the end of the configured string. + This configuration, then, + will have &SCons; + print that it is <literal>Evaluating</literal> + each file that it encounters + in turn as it traverses the dependency graph: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Evaluating SConstruct + Evaluating f1.c + Evaluating f1.o + cc -o f1.o -c f1.c + Evaluating f1 + cc -o f1 f1.o + Evaluating f2.c + Evaluating f2.o + cc -o f2.o -c f2.c + Evaluating f2 + cc -o f2 f2.o + Evaluating . + </screen> + + <para> + + Of course, normally you don't want to add + all of these additional lines to your build output, + as that can make it difficult for the user + to find errors or other important messages. + A more useful way to display + this progress might be + to have the file names printed + directly to the user's screen, + not to the same standard output + stream where build output is printed, + and to use a carriage return character + (<literal>\r</literal>) + so that each file name gets re-printed on the same line. + Such a configuration would look like: + + </para> + + <programlisting> + Progress('$TARGET\r', + file=open('/dev/tty', 'w'), + overwrite=True) + Program('f1.c') + Program('f2.c') + </programlisting> + + <para> + + Note that we also specified the + <literal>overwrite=True</literal> argument + to the &Progress; function, + which causes &SCons; to + "wipe out" the previous string with space characters + before printing the next &Progress; string. + Without the + <literal>overwrite=True</literal> argument, + a shorter file name would not overwrite + all of the charactes in a longer file name that + precedes it, + making it difficult to tell what the + actual file name is on the output. + Also note that we opened up the + <filename>/dev/tty</filename> file + for direct access (on POSIX) to + the user's screen. + On Windows, the equivalent would be to open + the <filename>con:</filename> file name. + + </para> + + <para> + + Also, it's important to know that although you can use + <literal>$TARGET</literal> to substitute the name of + the node in the string, + the &Progress; function does <emphasis>not</emphasis> + perform general variable substitution + (because there's not necessarily a construction + environment involved in evaluating a node + like a source file, for example). + + </para> + + <para> + + You can also specify a list of strings + to the &Progress; function, + in which case &SCons; will + display each string in turn. + This can be used to implement a "spinner" + by having &SCons; cycle through a + sequence of strings: + + </para> + + <programlisting> + Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5) + Program('f1.c') + Program('f2.c') + </programlisting> + + <para> + + Note that here we have also used the + <literal>interval=</literal> + keyword argument to have &SCons; + only print a new "spinner" string + once every five evaluated nodes. + Using an <literal>interval=</literal> count, + even with strings that use <literal>$TARGET</literal> like + our examples above, + can be a good way to lessen the + work that &SCons; expends printing &Progress; strings, + while still giving the user feedback + that indicates &SCons; is still + working on evaluating the build. + + </para> + + <para> + + Lastly, you can have direct control + over how to print each evaluated node + by passing a Python function + (or other Python callable) + to the &Progress; function. + Your function will be called + for each evaluated node, + allowing you to + implement more sophisticated logic + like adding a counter: + + </para> + + <programlisting> + screen = open('/dev/tty', 'w') + count = 0 + def progress_function(node) + count += 1 + screen.write('Node %4d: %s\r' % (count, node)) + + Progress(progress_function) + </programlisting> + + <para> + + Of course, if you choose, + you could completely ignore the + <varname>node</varname> argument to the function, + and just print a count, + or anything else you wish. + + </para> + + <para> + + (Note that there's an obvious follow-on question here: + how would you find the total number of nodes + that <emphasis>will be</emphasis> + evaluated so you can tell the user how + close the build is to finishing? + Unfortunately, in the general case, + there isn't a good way to do that, + short of having &SCons; evaluate its + dependency graph twice, + first to count the total and + the second time to actually build the targets. + This would be necessary because + you can't know in advance which + target(s) the user actually requested + to be built. + The entire build may consist of thousands of Nodes, + for example, + but maybe the user specifically requested + that only a single object file be built.) + + </para> + + </section> + + <section> + <title>Printing Detailed Build Status: the &GetBuildFailures; Function</title> + + <para> + + SCons, like most build tools, returns zero status to + the shell on success and nonzero status on failure. + Sometimes it's useful to give more information about + the build status at the end of the run, for instance + to print an informative message, send an email, or + page the poor slob who broke the build. + + </para> + + <para> + + SCons provides a &GetBuildFailures; method that + you can use in a python <function>atexit</function> function + to get a list of objects describing the actions that failed + while attempting to build targets. There can be more + than one if you're using <literal>-j</literal>. Here's a + simple example: + + </para> + + <programlisting> + import atexit + + def print_build_failures(): + from SCons.Script import GetBuildFailures + for bf in GetBuildFailures(): + print "%s failed: %s" % (bf.node, bf.errstr) + atexit.register(print_build_failures) + </programlisting> + + <para> + + The <function>atexit.register</function> call + registers <function>print_build_failures</function> + as an <function>atexit</function> callback, to be called + before &SCons; exits. When that function is called, + it calls &GetBuildFailures; to fetch the list of failed objects. + See the man page + for the detailed contents of the returned objects; + some of the more useful attributes are + <literal>.node</literal>, + <literal>.errstr</literal>, + <literal>.filename</literal>, and + <literal>.command</literal>. + The <literal>filename</literal> is not necessarily + the same file as the <literal>node</literal>; the + <literal>node</literal> is the target that was + being built when the error occurred, while the + <literal>filename</literal>is the file or dir that + actually caused the error. + Note: only call &GetBuildFailures; at the end of the + build; calling it at any other time is undefined. + + </para> + + <para> + + Here is a more complete example showing how to + turn each element of &GetBuildFailures; into a string: + + </para> + + <programlisting> + # Make the build fail if we pass fail=1 on the command line + if ARGUMENTS.get('fail', 0): + Command('target', 'source', ['/bin/false']) + + def bf_to_str(bf): + """Convert an element of GetBuildFailures() to a string + in a useful way.""" + import SCons.Errors + if bf is None: # unknown targets product None in list + return '(unknown tgt)' + elif isinstance(bf, SCons.Errors.StopError): + return str(bf) + elif bf.node: + return str(bf.node) + ': ' + bf.errstr + elif bf.filename: + return bf.filename + ': ' + bf.errstr + return 'unknown failure: ' + bf.errstr + import atexit + + def build_status(): + """Convert the build status to a 2-tuple, (status, msg).""" + from SCons.Script import GetBuildFailures + bf = GetBuildFailures() + if bf: + # bf is normally a list of build failures; if an element is None, + # it's because of a target that scons doesn't know anything about. + status = 'failed' + failures_message = "\n".join(["Failed building %s" % bf_to_str(x) + for x in bf if x is not None]) + else: + # if bf is None, the build completed successfully. + status = 'ok' + failures_message = '' + return (status, failures_message) + + def display_build_status(): + """Display the build status. Called by atexit. + Here you could do all kinds of complicated things.""" + status, failures_message = build_status() + if status == 'failed': + print "FAILED!!!!" # could display alert, ring bell, etc. + elif status == 'ok': + print "Build succeeded." + print failures_message + + atexit.register(display_build_status) + </programlisting> + + <para> + + When this runs, you'll see the appropriate output: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + Build succeeded. + % <userinput>scons -Q fail=1</userinput> + scons: *** [target] Source `source' not found, needed by target `target'. + FAILED!!!! + Failed building target: Source `source' not found, needed by target `target'. + </screen> + + </section> diff --git a/doc/user/parseconfig.in b/doc/user/parseconfig.in new file mode 100644 index 0000000..db97c35 --- /dev/null +++ b/doc/user/parseconfig.in @@ -0,0 +1,114 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Configuring the right options to build programs to work with + libraries--especially shared libraries--that are available + on POSIX systems can be very complicated. + To help this situation, + various utilies with names that end in <filename>config</filename> + return the command-line options for the GNU Compiler Collection (GCC) + that are needed to use these libraries; + for example, the command-line options + to use a library named <filename>lib</filename> + would be found by calling a utility named <filename>lib-config</filename>. + + </para> + + <para> + + A more recent convention is that these options + are available from the generic <filename>pkg-config</filename> program, + which has common framework, error handling, and the like, + so that all the package creator has to do is provide the set of strings + for his particular package. + + </para> + + <para> + + &SCons; construction environments have a &ParseConfig; method + that executes a <filename>*config</filename> utility + (either <filename>pkg-config</filename> or a + more specific utility) + and configures the appropriate construction variables + in the environment + based on the command-line options + returned by the specified command. + + </para> + + <scons_example name="ParseConfig1"> + <file name="SConstruct" printme="1"> + env = Environment() + env['CPPPATH'] = ['/lib/compat'] + env.ParseConfig("pkg-config x11 --cflags --libs") + print env['CPPPATH'] + </file> + </scons_example> + + <para> + + &SCons; will execute the specified command string, + parse the resultant flags, + and add the flags to the appropriate environment variables. + + </para> + + <scons_output example="ParseConfig1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + In the example above, &SCons; has added the include directory to + <varname>CPPPATH</varname>. + (Depending upon what other flags are emitted by the + <filename>pkg-config</filename> command, + other variables may have been extended as well.) + + </para> + + <para> + + Note that the options are merged with existing options using + the &MergeFlags; method, + so that each option only occurs once in the construction variable: + + </para> + + <scons_example name="ParseConfig2"> + <file name="SConstruct" printme="1"> + env = Environment() + env.ParseConfig("pkg-config x11 --cflags --libs") + env.ParseConfig("pkg-config x11 --cflags --libs") + print env['CPPPATH'] + </file> + </scons_example> + + <scons_output example="ParseConfig2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> diff --git a/doc/user/parseconfig.xml b/doc/user/parseconfig.xml new file mode 100644 index 0000000..1f85ad0 --- /dev/null +++ b/doc/user/parseconfig.xml @@ -0,0 +1,132 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Configuring the right options to build programs to work with + libraries--especially shared libraries--that are available + on POSIX systems can be very complicated. + To help this situation, + various utilies with names that end in <filename>config</filename> + return the command-line options for the GNU Compiler Collection (GCC) + that are needed to use these libraries; + for example, the command-line options + to use a library named <filename>lib</filename> + would be found by calling a utility named <filename>lib-config</filename>. + + </para> + + <para> + + A more recent convention is that these options + are available from the generic <filename>pkg-config</filename> program, + which has common framework, error handling, and the like, + so that all the package creator has to do is provide the set of strings + for his particular package. + + </para> + + <para> + + &SCons; construction environments have a &ParseConfig; method + that executes a <filename>*config</filename> utility + (either <filename>pkg-config</filename> or a + more specific utility) + and configures the appropriate construction variables + in the environment + based on the command-line options + returned by the specified command. + + </para> + + <programlisting> + env = Environment() + env['CPPPATH'] = ['/lib/compat'] + env.ParseConfig("pkg-config x11 --cflags --libs") + print env['CPPPATH'] + </programlisting> + + <para> + + &SCons; will execute the specified command string, + parse the resultant flags, + and add the flags to the appropriate environment variables. + + </para> + + <screen> + % <userinput>scons -Q</userinput> + Package x11 was not found in the pkg-config search path. + Perhaps you should add the directory containing `x11.pc' + to the PKG_CONFIG_PATH environment variable + No package 'x11' found + OSError: 'pkg-config x11 --cflags --libs' exited 1: + File "/home/my/project/SConstruct", line 3: + env.ParseConfig("pkg-config x11 --cflags --libs") + File "bootstrap/src/engine/SCons/Environment.py", line 1474: + None + File "bootstrap/src/engine/SCons/Environment.py", line 593: + None + </screen> + + <para> + + In the example above, &SCons; has added the include directory to + <varname>CPPPATH</varname>. + (Depending upon what other flags are emitted by the + <filename>pkg-config</filename> command, + other variables may have been extended as well.) + + </para> + + <para> + + Note that the options are merged with existing options using + the &MergeFlags; method, + so that each option only occurs once in the construction variable: + + </para> + + <programlisting> + env = Environment() + env.ParseConfig("pkg-config x11 --cflags --libs") + env.ParseConfig("pkg-config x11 --cflags --libs") + print env['CPPPATH'] + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + Package x11 was not found in the pkg-config search path. + Perhaps you should add the directory containing `x11.pc' + to the PKG_CONFIG_PATH environment variable + No package 'x11' found + OSError: 'pkg-config x11 --cflags --libs' exited 1: + File "/home/my/project/SConstruct", line 2: + env.ParseConfig("pkg-config x11 --cflags --libs") + File "bootstrap/src/engine/SCons/Environment.py", line 1474: + None + File "bootstrap/src/engine/SCons/Environment.py", line 593: + None + </screen> diff --git a/doc/user/parseflags.in b/doc/user/parseflags.in new file mode 100644 index 0000000..b21df4f --- /dev/null +++ b/doc/user/parseflags.in @@ -0,0 +1,184 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; has a bewildering array of construction variables + for different types of options when building programs. + Sometimes you may not know exactly which variable + should be used for a particular option. + + </para> + + <para> + + &SCons; construction environments have a &ParseFlags; method + that takes a set of typical command-line options + and distrbutes them into the appropriate construction variables. + Historically, it was created to support the &ParseConfig; method, + so it focuses on options used by the GNU Compiler Collection (GCC) + for the C and C++ toolchains. + + </para> + + <para> + + &ParseFlags; returns a dictionary containing the options + distributed into their respective construction variables. + Normally, this dictionary would be passed to &MergeFlags; + to merge the options into a &consenv;, + but the dictionary can be edited if desired to provide + additional functionality. + (Note that if the flags are not going to be edited, + calling &MergeFlags; with the options directly + will avoid an additional step.) + + </para> + + <scons_example name="ParseFlags1"> + <file name="SConstruct" printme="1"> + env = Environment() + d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo") + l = d.items() + l.sort() + for k,v in l: + if v: + print k, v + env.MergeFlags(d) + env.Program('f1.c') + </file> + <file name="f1.c"> + int main() { return 0; } + </file> + </scons_example> + + <scons_output example="ParseFlags1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that if the options are limited to generic types + like those above, + they will be correctly translated for other platform types: + + </para> + + <scons_output example="ParseFlags1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Since the assumption is that the flags are used for the GCC toolchain, + unrecognized flags are placed in &cv-link-CCFLAGS; + so they will be used for both C and C++ compiles: + + </para> + + <scons_example name="ParseFlags2"> + <file name="SConstruct" printme="1"> + env = Environment() + d = env.ParseFlags("-whatever") + l = d.items() + l.sort() + for k,v in l: + if v: + print k, v + env.MergeFlags(d) + env.Program('f1.c') + </file> + <file name="f1.c"> + int main() { return 0; } + </file> + </scons_example> + + <scons_output example="ParseFlags2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + &ParseFlags; will also accept a (recursive) list of strings as input; + the list is flattened before the strings are processed: + + </para> + + <scons_example name="ParseFlags3"> + <file name="SConstruct" printme="1"> + env = Environment() + d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]]) + l = d.items() + l.sort() + for k,v in l: + if v: + print k, v + env.MergeFlags(d) + env.Program('f1.c') + </file> + <file name="f1.c"> + int main() { return 0; } + </file> + </scons_example> + + <scons_output example="ParseFlags3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + If a string begins with a "!" (an exclamation mark, often called a bang), + the string is passed to the shell for execution. + The output of the command is then parsed: + + </para> + + <scons_example name="ParseFlags4"> + <file name="SConstruct" printme="1"> + env = Environment() + d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"]) + l = d.items() + l.sort() + for k,v in l: + if v: + print k, v + env.MergeFlags(d) + env.Program('f1.c') + </file> + <file name="f1.c"> + int main() { return 0; } + </file> + </scons_example> + + <scons_output example="ParseFlags4"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + &ParseFlags; is regularly updated for new options; + consult the man page for details about those currently recognized. + + </para> diff --git a/doc/user/parseflags.xml b/doc/user/parseflags.xml new file mode 100644 index 0000000..6900291 --- /dev/null +++ b/doc/user/parseflags.xml @@ -0,0 +1,199 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; has a bewildering array of construction variables + for different types of options when building programs. + Sometimes you may not know exactly which variable + should be used for a particular option. + + </para> + + <para> + + &SCons; construction environments have a &ParseFlags; method + that takes a set of typical command-line options + and distrbutes them into the appropriate construction variables. + Historically, it was created to support the &ParseConfig; method, + so it focuses on options used by the GNU Compiler Collection (GCC) + for the C and C++ toolchains. + + </para> + + <para> + + &ParseFlags; returns a dictionary containing the options + distributed into their respective construction variables. + Normally, this dictionary would be passed to &MergeFlags; + to merge the options into a &consenv;, + but the dictionary can be edited if desired to provide + additional functionality. + (Note that if the flags are not going to be edited, + calling &MergeFlags; with the options directly + will avoid an additional step.) + + </para> + + <programlisting> + env = Environment() + d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo") + l = d.items() + l.sort() + for k,v in l: + if v: + print k, v + env.MergeFlags(d) + env.Program('f1.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + CPPPATH ['/opt/include'] + LIBPATH ['/opt/lib'] + LIBS ['foo'] + cc -o f1.o -c -I/opt/include f1.c + cc -o f1 f1.o -L/opt/lib -lfoo + </screen> + + <para> + + Note that if the options are limited to generic types + like those above, + they will be correctly translated for other platform types: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + CPPPATH ['/opt/include'] + LIBPATH ['/opt/lib'] + LIBS ['foo'] + cl /Fof1.obj /c f1.c /nologo /I\opt\include + link /nologo /OUT:f1.exe /LIBPATH:\opt\lib foo.lib f1.obj + </screen> + + <para> + + Since the assumption is that the flags are used for the GCC toolchain, + unrecognized flags are placed in &cv-link-CCFLAGS; + so they will be used for both C and C++ compiles: + + </para> + + <programlisting> + env = Environment() + d = env.ParseFlags("-whatever") + l = d.items() + l.sort() + for k,v in l: + if v: + print k, v + env.MergeFlags(d) + env.Program('f1.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + CCFLAGS -whatever + cc -o f1.o -c -whatever f1.c + cc -o f1 f1.o + </screen> + + <para> + + &ParseFlags; will also accept a (recursive) list of strings as input; + the list is flattened before the strings are processed: + + </para> + + <programlisting> + env = Environment() + d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]]) + l = d.items() + l.sort() + for k,v in l: + if v: + print k, v + env.MergeFlags(d) + env.Program('f1.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + CPPPATH ['/opt/include'] + LIBPATH ['/opt/lib'] + LIBS ['foo'] + cc -o f1.o -c -I/opt/include f1.c + cc -o f1 f1.o -L/opt/lib -lfoo + </screen> + + <para> + + If a string begins with a "!" (an exclamation mark, often called a bang), + the string is passed to the shell for execution. + The output of the command is then parsed: + + </para> + + <programlisting> + env = Environment() + d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"]) + l = d.items() + l.sort() + for k,v in l: + if v: + print k, v + env.MergeFlags(d) + env.Program('f1.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + CPPPATH ['/opt/include'] + LIBPATH ['/opt/lib'] + LIBS ['foo'] + cc -o f1.o -c -I/opt/include f1.c + cc -o f1 f1.o -L/opt/lib -lfoo + </screen> + + <para> + + &ParseFlags; is regularly updated for new options; + consult the man page for details about those currently recognized. + + </para> diff --git a/doc/user/preface.in b/doc/user/preface.in new file mode 100644 index 0000000..de4cb43 --- /dev/null +++ b/doc/user/preface.in @@ -0,0 +1,426 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Thank you for taking the time to read about &SCons;. + &SCons; is a next-generation + software construction tool, + or make tool--that is, a software utility + for building software (or other files) + and keeping built software up-to-date + whenever the underlying input files change. + + </para> + + <para> + + The most distinctive thing about &SCons; + is that its configuration files are + actually <emphasis>scripts</emphasis>, + written in the &Python; programming language. + This is in contrast to most alternative build tools, + which typically invent a new language to + configure the build. + &SCons; still has a learning curve, of course, + because you have to know what functions to call + to set up your build properly, + but the underlying syntax used should be familiar + to anyone who has ever looked at a Python script. + + </para> + + <para> + + Paradoxically, + using Python as the configuration file format + makes &SCons; + <emphasis>easier</emphasis> + for non-programmers to learn + than the cryptic languages of other build tools, + which are usually invented by programmers for other programmers. + This is in no small part due to the + consistency and readability that are hallmarks of Python. + It just so happens that making a real, live + scripting language the basis for the + configuration files + makes it a snap for more accomplished programmers + to do more complicated things with builds, + as necessary. + + </para> + + <!-- + + <section> + <title>Why &SCons;?</title> + + <para> + + &SCons; is a response to a perennial problem: + building software is harder than it should be. + In a nutshell: the old, reliable model of the + venerable and ubiquitous &Make; program + has had a hard time keeping up with + how complicated building software has become. + The fact that &Make; has kept up as well as it has is impressive, + and a testament to how the simplicity. + But anyone who has wrestled with &Automake; and &Autoconf; + to try to guarantee that a bit of software + will build correctly on multiple platforms + can tell you that it takes a lot of work to get right. + + </para> + + </section> + + --> + + <section> + <title>&SCons; Principles</title> + + <para> + + There are a few overriding principles + we try to live up to in designing and implementing &SCons: + + </para> + + <variablelist> + + <varlistentry> + <term>Correctness</term> + + <listitem> + <para> + + First and foremost, + by default, &SCons; guarantees a correct build + even if it means sacrificing performance a little. + We strive to guarantee the build is correct + regardless of how the software being built is structured, + how it may have been written, + or how unusual the tools are that build it. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Performance</term> + + <listitem> + <para> + + Given that the build is correct, + we try to make &SCons; build software + as quickly as possible. + In particular, wherever we may have needed to slow + down the default &SCons; behavior to guarantee a correct build, + we also try to make it easy to speed up &SCons; + through optimization options that let you trade off + guaranteed correctness in all end cases for + a speedier build in the usual cases. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Convenience</term> + + <listitem> + <para> + + &SCons; tries to do as much for you out of the box as reasonable, + including detecting the right tools on your system + and using them correctly to build the software. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + In a nutshell, we try hard to make &SCons; just + "do the right thing" and build software correctly, + with a minimum of hassles. + + </para> + + </section> + + <!-- + + <section> + <title>History</title> + + <para> + + &SCons; originated with a design + that was submitted to the Software Carpentry + design competition in 2000. + + </para> + + <para> + + &SCons; is the direct descendant + of a Perl utility called &Cons;. + &Cons; in turn based some of its ideas on &Jam;, + a build tool from Perforce Systems. + + </para> + + <para> + + XXX history of SCons + + </para> + + </section> + + --> + + <!-- + + <section> + <title>Conventions</title> + + <para> + + XXX conventions used in this manual + + </para> + + </section> + + --> + + <section> + <title>A Caveat About This Guide's Completeness</title> + + <para> + + One word of warning as you read through this Guide: + Like too much Open Source software out there, + the &SCons; documentation isn't always + kept up-to-date with the available features. + In other words, + there's a lot that &SCons; can do that + isn't yet covered in this User's Guide. + (Come to think of it, + that also describes a lot of proprietary software, doesn't it?) + + </para> + + <para> + + Although this User's Guide isn't as complete as we'd like it to be, + our development process does emphasize + making sure that the &SCons; man page is kept up-to-date + with new features. + So if you're trying to figure out how to do something + that &SCons; supports + but can't find enough (or any) information here, + it would be worth your while to look + at the man page to see if the information is covered there. + And if you do, + maybe you'd even consider contributing + a section to the User's Guide + so the next person looking for + that information won't have to + go through the same thing...? + + </para> + + </section> + + <section> + <title>Acknowledgements</title> + + <para> + + &SCons; would not exist without a lot of help + from a lot of people, + many of whom may not even be aware + that they helped or served as inspiration. + So in no particular order, + and at the risk of leaving out someone: + + </para> + + <para> + + First and foremost, + &SCons; owes a tremendous debt to Bob Sidebotham, + the original author of the classic Perl-based &Cons; tool + which Bob first released to the world back around 1996. + Bob's work on Cons classic provided the underlying architecture + and model of specifying a build configuration + using a real scripting language. + My real-world experience working on Cons + informed many of the design decisions in SCons, + including the improved parallel build support, + making Builder objects easily definable by users, + and separating the build engine from the wrapping interface. + + </para> + + <para> + + Greg Wilson was instrumental in getting + &SCons; started as a real project + when he initiated the Software Carpentry design + competition in February 2000. + Without that nudge, + marrying the advantages of the Cons classic + architecture with the readability of Python + might have just stayed no more than a nice idea. + + </para> + + <para> + + The entire &SCons; team have been + absolutely wonderful to work with, + and &SCons; would be nowhere near as useful a + tool without the energy, enthusiasm + and time people have contributed over the past few years. + The "core team" + of Chad Austin, Anthony Roach, + Bill Deegan, Charles Crain, Steve Leblanc, Greg Noel, + Gary Oberbrunner, Greg Spencer and Christoph Wiedemann + have been great about reviewing my (and other) changes + and catching problems before they get in the code base. + Of particular technical note: + Anthony's outstanding and innovative work on the tasking engine + has given &SCons; a vastly superior parallel build model; + Charles has been the master of the crucial Node infrastructure; + Christoph's work on the Configure infrastructure + has added crucial Autoconf-like functionality; + and Greg has provided excellent support + for Microsoft Visual Studio. + + </para> + + <para> + + Special thanks to David Snopek for contributing + his underlying "Autoscons" code that formed + the basis of Christoph's work with the Configure functionality. + David was extremely generous in making + this code available to &SCons;, + given that he initially released it under the GPL + and &SCons; is released under a less-restrictive MIT-style license. + + </para> + + <!-- + + <para> + + &SCons; has received contributions + from many other people, of course: + Matt Balvin (extending long command-line support on Windows), + Allen Bierbaum (extensions and fixes to Options), + Steve Christensen (help text sorting and function action signature fixes), + Michael Cook (avoiding losing signal bits from executed commands), + Derrick 'dman' Hudson (), + Alex Jacques (work on the Windows scons.bat file), + Stephen Kennedy (performance enhancements), + Lachlan O'Dea (SharedObject() support for masm + and normalized paths for the WhereIs() function), + Damyan Pepper (keeping output like Make), + Jeff Petkau (significant fixes for CacheDir and other areas), + Stefan Reichor (Ghostscript support), + Zed Shaw (Append() and Replace() environment methods), + Terrel Shumway (build and test fixes, as well as the SCons Wiki) + and + sam th (dynamic checks for utilities). + + </para> + + --> + + <para> + + Thanks to Peter Miller + for his splendid change management system, &Aegis;, + which has provided the &SCons; project + with a robust development methodology from day one, + and which showed me how you could + integrate incremental regression tests into + a practical development cycle + (years before eXtreme Programming arrived on the scene). + + </para> + + <para> + + And last, thanks to Guido van Rossum + for his elegant scripting language, + which is the basis not only for the &SCons; implementation, + but for the interface itself. + + </para> + + </section> + + <section> + <title>Contact</title> + + <para> + + The best way to contact people involved with SCons, + including the author, + is through the SCons mailing lists. + + </para> + + <para> + + If you want to ask general questions about how to use &SCons; + send email to &scons-users;. + + </para> + + <para> + + If you want to contact the &SCons; development community directly, + send email to &scons-devel;. + + </para> + + <para> + + If you want to receive announcements about &SCons, + join the low-volume &scons-announce; mailing list. + + </para> + + </section> diff --git a/doc/user/preface.xml b/doc/user/preface.xml new file mode 100644 index 0000000..2c6d8f4 --- /dev/null +++ b/doc/user/preface.xml @@ -0,0 +1,426 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Thank you for taking the time to read about &SCons;. + &SCons; is a next-generation + software construction tool, + or make tool--that is, a software utility + for building software (or other files) + and keeping built software up-to-date + whenever the underlying input files change. + + </para> + + <para> + + The most distinctive thing about &SCons; + is that its configuration files are + actually <emphasis>scripts</emphasis>, + written in the &Python; programming language. + This is in contrast to most alternative build tools, + which typically invent a new language to + configure the build. + &SCons; still has a learning curve, of course, + because you have to know what functions to call + to set up your build properly, + but the underlying syntax used should be familiar + to anyone who has ever looked at a Python script. + + </para> + + <para> + + Paradoxically, + using Python as the configuration file format + makes &SCons; + <emphasis>easier</emphasis> + for non-programmers to learn + than the cryptic languages of other build tools, + which are usually invented by programmers for other programmers. + This is in no small part due to the + consistency and readability that are hallmarks of Python. + It just so happens that making a real, live + scripting language the basis for the + configuration files + makes it a snap for more accomplished programmers + to do more complicated things with builds, + as necessary. + + </para> + + <!-- + + <section> + <title>Why &SCons;?</title> + + <para> + + &SCons; is a response to a perennial problem: + building software is harder than it should be. + In a nutshell: the old, reliable model of the + venerable and ubiquitous &Make; program + has had a hard time keeping up with + how complicated building software has become. + The fact that &Make; has kept up as well as it has is impressive, + and a testament to how the simplicity. + But anyone who has wrestled with &Automake; and &Autoconf; + to try to guarantee that a bit of software + will build correctly on multiple platforms + can tell you that it takes a lot of work to get right. + + </para> + + </section> + + --> + + <section> + <title>&SCons; Principles</title> + + <para> + + There are a few overriding principles + we try to live up to in designing and implementing &SCons;: + + </para> + + <variablelist> + + <varlistentry> + <term>Correctness</term> + + <listitem> + <para> + + First and foremost, + by default, &SCons; guarantees a correct build + even if it means sacrificing performance a little. + We strive to guarantee the build is correct + regardless of how the software being built is structured, + how it may have been written, + or how unusual the tools are that build it. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Performance</term> + + <listitem> + <para> + + Given that the build is correct, + we try to make &SCons; build software + as quickly as possible. + In particular, wherever we may have needed to slow + down the default &SCons; behavior to guarantee a correct build, + we also try to make it easy to speed up &SCons; + through optimization options that let you trade off + guaranteed correctness in all end cases for + a speedier build in the usual cases. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Convenience</term> + + <listitem> + <para> + + &SCons; tries to do as much for you out of the box as reasonable, + including detecting the right tools on your system + and using them correctly to build the software. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + In a nutshell, we try hard to make &SCons; just + "do the right thing" and build software correctly, + with a minimum of hassles. + + </para> + + </section> + + <!-- + + <section> + <title>History</title> + + <para> + + &SCons; originated with a design + that was submitted to the Software Carpentry + design competition in 2000. + + </para> + + <para> + + &SCons; is the direct descendant + of a Perl utility called &Cons;. + &Cons; in turn based some of its ideas on &Jam;, + a build tool from Perforce Systems. + + </para> + + <para> + + XXX history of SCons + + </para> + + </section> + + --> + + <!-- + + <section> + <title>Conventions</title> + + <para> + + XXX conventions used in this manual + + </para> + + </section> + + --> + + <section> + <title>A Caveat About This Guide's Completeness</title> + + <para> + + One word of warning as you read through this Guide: + Like too much Open Source software out there, + the &SCons; documentation isn't always + kept up-to-date with the available features. + In other words, + there's a lot that &SCons; can do that + isn't yet covered in this User's Guide. + (Come to think of it, + that also describes a lot of proprietary software, doesn't it?) + + </para> + + <para> + + Although this User's Guide isn't as complete as we'd like it to be, + our development process does emphasize + making sure that the &SCons; man page is kept up-to-date + with new features. + So if you're trying to figure out how to do something + that &SCons; supports + but can't find enough (or any) information here, + it would be worth your while to look + at the man page to see if the information is covered there. + And if you do, + maybe you'd even consider contributing + a section to the User's Guide + so the next person looking for + that information won't have to + go through the same thing...? + + </para> + + </section> + + <section> + <title>Acknowledgements</title> + + <para> + + &SCons; would not exist without a lot of help + from a lot of people, + many of whom may not even be aware + that they helped or served as inspiration. + So in no particular order, + and at the risk of leaving out someone: + + </para> + + <para> + + First and foremost, + &SCons; owes a tremendous debt to Bob Sidebotham, + the original author of the classic Perl-based &Cons; tool + which Bob first released to the world back around 1996. + Bob's work on Cons classic provided the underlying architecture + and model of specifying a build configuration + using a real scripting language. + My real-world experience working on Cons + informed many of the design decisions in SCons, + including the improved parallel build support, + making Builder objects easily definable by users, + and separating the build engine from the wrapping interface. + + </para> + + <para> + + Greg Wilson was instrumental in getting + &SCons; started as a real project + when he initiated the Software Carpentry design + competition in February 2000. + Without that nudge, + marrying the advantages of the Cons classic + architecture with the readability of Python + might have just stayed no more than a nice idea. + + </para> + + <para> + + The entire &SCons; team have been + absolutely wonderful to work with, + and &SCons; would be nowhere near as useful a + tool without the energy, enthusiasm + and time people have contributed over the past few years. + The "core team" + of Chad Austin, Anthony Roach, + Bill Deegan, Charles Crain, Steve Leblanc, Greg Noel, + Gary Oberbrunner, Greg Spencer and Christoph Wiedemann + have been great about reviewing my (and other) changes + and catching problems before they get in the code base. + Of particular technical note: + Anthony's outstanding and innovative work on the tasking engine + has given &SCons; a vastly superior parallel build model; + Charles has been the master of the crucial Node infrastructure; + Christoph's work on the Configure infrastructure + has added crucial Autoconf-like functionality; + and Greg has provided excellent support + for Microsoft Visual Studio. + + </para> + + <para> + + Special thanks to David Snopek for contributing + his underlying "Autoscons" code that formed + the basis of Christoph's work with the Configure functionality. + David was extremely generous in making + this code available to &SCons;, + given that he initially released it under the GPL + and &SCons; is released under a less-restrictive MIT-style license. + + </para> + + <!-- + + <para> + + &SCons; has received contributions + from many other people, of course: + Matt Balvin (extending long command-line support on Windows), + Allen Bierbaum (extensions and fixes to Options), + Steve Christensen (help text sorting and function action signature fixes), + Michael Cook (avoiding losing signal bits from executed commands), + Derrick 'dman' Hudson (), + Alex Jacques (work on the Windows scons.bat file), + Stephen Kennedy (performance enhancements), + Lachlan O'Dea (SharedObject() support for masm + and normalized paths for the WhereIs() function), + Damyan Pepper (keeping output like Make), + Jeff Petkau (significant fixes for CacheDir and other areas), + Stefan Reichor (Ghostscript support), + Zed Shaw (Append() and Replace() environment methods), + Terrel Shumway (build and test fixes, as well as the SCons Wiki) + and + sam th (dynamic checks for utilities). + + </para> + + --> + + <para> + + Thanks to Peter Miller + for his splendid change management system, &Aegis;, + which has provided the &SCons; project + with a robust development methodology from day one, + and which showed me how you could + integrate incremental regression tests into + a practical development cycle + (years before eXtreme Programming arrived on the scene). + + </para> + + <para> + + And last, thanks to Guido van Rossum + for his elegant scripting language, + which is the basis not only for the &SCons; implementation, + but for the interface itself. + + </para> + + </section> + + <section> + <title>Contact</title> + + <para> + + The best way to contact people involved with SCons, + including the author, + is through the SCons mailing lists. + + </para> + + <para> + + If you want to ask general questions about how to use &SCons; + send email to &scons-users;. + + </para> + + <para> + + If you want to contact the &SCons; development community directly, + send email to &scons-devel;. + + </para> + + <para> + + If you want to receive announcements about &SCons;, + join the low-volume &scons-announce; mailing list. + + </para> + + </section> diff --git a/doc/user/python.in b/doc/user/python.in new file mode 100644 index 0000000..aa49030 --- /dev/null +++ b/doc/user/python.in @@ -0,0 +1,154 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <!-- + + <section> + <title>Python Overview</title> + + <para> + + This section will provide a brief overview of + the Python programming language. + Skip this section if you are already familiar with Python + (or you're really intent on diving into &SCons; + and just picking up things as you go). + + </para> + + <para> + + Python has a lot of good + documentation freely available on-line + to help you get started. + The standard tutorial is available at XXX. + + + </para> + + <para> + + Python is very easy to pick up. + + </para> + + <para> + + Python variables must be assigned to before they can be referenced. + + </para> + + <para> + + Assignment is like most programming languages: + + x = 1 + 2 + z = 3 * x + + </para> + + <para> + + Function calls look like most language function calls: + + a = f(g) + + </para> + + <para> + + Define functions like so: + + def func(arg1, arg2): + return arg1 * arg 2 + + The number of parameters + + </para> + + <para> + + Strings can be enclosed in single quotes or double quotes, + backslashes are used to escape characters, + triple-quote syntax lets you include quotes and newlines, + raw strings begin with 'r'. + + </para> + + <para> + + Lists are enclosed in square brackets, + list items are separated by commas. + List references use square brackets and integer index values, + slice notation lets you select, delete or replace a range. + + </para> + + <para> + + Dictionaries (hashes) are enclosed in curly brackets, + : separates keys from values, + , separates items. + Dictionary values are referenced using square brackets. + + </para> + + <para> + + Access class attributes (including methods) using a '.'. + + </para> + + <para> + + if: statements look like + + elif: statements look like + + else: statements look like + + </para> + + <para> + + for: statements look like + + while: statements look like + + break statements look like + + continue statements look like + + </para> + + <para> + + pass + + </para> + + </section> + + --> diff --git a/doc/user/python.xml b/doc/user/python.xml new file mode 100644 index 0000000..aa49030 --- /dev/null +++ b/doc/user/python.xml @@ -0,0 +1,154 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <!-- + + <section> + <title>Python Overview</title> + + <para> + + This section will provide a brief overview of + the Python programming language. + Skip this section if you are already familiar with Python + (or you're really intent on diving into &SCons; + and just picking up things as you go). + + </para> + + <para> + + Python has a lot of good + documentation freely available on-line + to help you get started. + The standard tutorial is available at XXX. + + + </para> + + <para> + + Python is very easy to pick up. + + </para> + + <para> + + Python variables must be assigned to before they can be referenced. + + </para> + + <para> + + Assignment is like most programming languages: + + x = 1 + 2 + z = 3 * x + + </para> + + <para> + + Function calls look like most language function calls: + + a = f(g) + + </para> + + <para> + + Define functions like so: + + def func(arg1, arg2): + return arg1 * arg 2 + + The number of parameters + + </para> + + <para> + + Strings can be enclosed in single quotes or double quotes, + backslashes are used to escape characters, + triple-quote syntax lets you include quotes and newlines, + raw strings begin with 'r'. + + </para> + + <para> + + Lists are enclosed in square brackets, + list items are separated by commas. + List references use square brackets and integer index values, + slice notation lets you select, delete or replace a range. + + </para> + + <para> + + Dictionaries (hashes) are enclosed in curly brackets, + : separates keys from values, + , separates items. + Dictionary values are referenced using square brackets. + + </para> + + <para> + + Access class attributes (including methods) using a '.'. + + </para> + + <para> + + if: statements look like + + elif: statements look like + + else: statements look like + + </para> + + <para> + + for: statements look like + + while: statements look like + + break statements look like + + continue statements look like + + </para> + + <para> + + pass + + </para> + + </section> + + --> diff --git a/doc/user/repositories.in b/doc/user/repositories.in new file mode 100644 index 0000000..8c97b02 --- /dev/null +++ b/doc/user/repositories.in @@ -0,0 +1,641 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Often, a software project will have + one or more central repositories, + directory trees that contain + source code, or derived files, or both. + You can eliminate additional unnecessary + rebuilds of files by having &SCons; + use files from one or more code repositories + to build files in your local build tree. + + </para> + + <section> + <title>The &Repository; Method</title> + + <!-- + + The repository directories specified may contain source files, derived files + (objects, libraries and executables), or both. If there is no local file + (source or derived) under the directory in which Cons is executed, then the + first copy of a same-named file found under a repository directory will be + used to build any local derived files. + + --> + + <para> + + It's often useful to allow multiple programmers working + on a project to build software from + source files and/or derived files that + are stored in a centrally-accessible repository, + a directory copy of the source code tree. + (Note that this is not the sort of repository + maintained by a source code management system + like BitKeeper, CVS, or Subversion.) + <!-- + For information about using &SCons; + with these systems, see the section, + "Fetching Files From Source Code Management Systems," + below.) + --> + You use the &Repository; method + to tell &SCons; to search one or more + central code repositories (in order) + for any source files and derived files + that are not present in the local build tree: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Program('hello.c') + Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Multiple calls to the &Repository; method + will simply add repositories to the global list + that &SCons; maintains, + with the exception that &SCons; will automatically eliminate + the current directory and any non-existent + directories from the list. + + </para> + + </section> + + <section> + <title>Finding source files in repositories</title> + + <para> + + The above example + specifies that &SCons; + will first search for files under + the <filename>/usr/repository1</filename> tree + and next under the <filename>/usr/repository2</filename> tree. + &SCons; expects that any files it searches + for will be found in the same position + relative to the top-level directory. + In the above example, if the &hello_c; file is not + found in the local build tree, + &SCons; will search first for + a <filename>/usr/repository1/hello.c</filename> file + and then for a <filename>/usr/repository2/hello.c</filename> file + to use in its place. + + </para> + + <para> + + So given the &SConstruct; file above, + if the &hello_c; file exists in the local + build directory, + &SCons; will rebuild the &hello; program + as normal: + + </para> + + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + If, however, there is no local &hello_c; file, + but one exists in <filename>/usr/repository1</filename>, + &SCons; will recompile the &hello; program + from the source file it finds in the repository: + + </para> + + <scons_example name="ex2"> + <file name="SConstruct"> + env = Environment() + env.Program('hello.c') + Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') + </file> + <file name="__ROOT__/usr/repository1/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And similarly, if there is no local &hello_c; file + and no <filename>/usr/repository1/hello.c</filename>, + but one exists in <filename>/usr/repository2</filename>: + + </para> + + <scons_example name="ex3"> + <file name="SConstruct"> + env = Environment() + env.Program('hello.c') + Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') + </file> + <file name="__ROOT__/usr/repository2/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="ex3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + </para> + + </section> + + <section> + <title>Finding <literal>#include</literal> files in repositories</title> + + <para> + + We've already seen that SCons will scan the contents of + a source file for <literal>#include</literal> file names + and realize that targets built from that source file + also depend on the <literal>#include</literal> file(s). + For each directory in the &cv-link-CPPPATH; list, + &SCons; will actually search the corresponding directories + in any repository trees and establish the + correct dependencies on any + <literal>#include</literal> files that it finds + in repository directory. + + </para> + + <para> + + Unless the C compiler also knows about these directories + in the repository trees, though, + it will be unable to find the <literal>#include</literal> files. + If, for example, the &hello_c; file in + our previous example includes the &hello.h; + in its current directory, + and the &hello.h; only exists in the repository: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + hello.c:1: hello.h: No such file or directory + </screen> + + <para> + + In order to inform the C compiler about the repositories, + &SCons; will add appropriate + <literal>-I</literal> flags to the compilation commands + for each directory in the &cv-CPPPATH; list. + So if we add the current directory to the + construction environment &cv-CPPPATH; like so: + + </para> + + <scons_example name="CPPPATH"> + <file name="SConstruct" printme="1"> + env = Environment(CPPPATH = ['.']) + env.Program('hello.c') + Repository('__ROOT__/usr/repository1') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Then re-executing &SCons; yields: + + </para> + + <scons_output example="CPPPATH"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + The order of the <literal>-I</literal> options replicates, + for the C preprocessor, + the same repository-directory search path + that &SCons; uses for its own dependency analysis. + If there are multiple repositories and multiple &cv-CPPPATH; + directories, &SCons; will add the repository directories + to the beginning of each &cv-CPPPATH; directory, + rapidly multiplying the number of <literal>-I</literal> flags. + If, for example, the &cv-CPPPATH; contains three directories + (and shorter repository path names!): + + </para> + + <scons_example name="CPPPATH3"> + <file name="SConstruct" printme="1"> + env = Environment(CPPPATH = ['dir1', 'dir2', 'dir3']) + env.Program('hello.c') + Repository('__ROOT__/r1', '__ROOT__/r2') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Then we'll end up with nine <literal>-I</literal> options + on the command line, + three (for each of the &cv-CPPPATH; directories) + times three (for the local directory plus the two repositories): + + </para> + + <scons_output example="CPPPATH3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + +<!-- + +Cons classic did the following, does SCons? + +In order to shorten the command lines as much as possible, Cons will +remove C<-I> flags for any directories, locally or in the repositories, +which do not actually exist. (Note that the C<-I> flags are not included +in the MD5 signature calculation for the target file, so the target will +not be recompiled if the compilation command changes due to a directory +coming into existence.) + +--> + + <section> + <title>Limitations on <literal>#include</literal> files in repositories</title> + + <para> + + &SCons; relies on the C compiler's + <literal>-I</literal> options to control the order in which + the preprocessor will search the repository directories + for <literal>#include</literal> files. + This causes a problem, however, with how the C preprocessor + handles <literal>#include</literal> lines with + the file name included in double-quotes. + + </para> + + <para> + + As we've seen, + &SCons; will compile the &hello_c; file from + the repository if it doesn't exist in + the local directory. + If, however, the &hello_c; file in the repository contains + a <literal>#include</literal> line with the file name in + double quotes: + + </para> + + <programlisting> + #include "hello.h" + int + main(int argc, char *argv[]) + { + printf(HELLO_MESSAGE); + return (0); + } + </programlisting> + + <para> + + Then the C preprocessor will <emphasis>always</emphasis> + use a &hello_h; file from the repository directory first, + even if there is a &hello_h; file in the local directory, + despite the fact that the command line specifies + <literal>-I</literal> as the first option: + + </para> + + <scons_example name="quote1"> + <file name="SConstruct"> + env = Environment(CPPPATH = ['.']) + env.Program('hello.c') + Repository('__ROOT__/usr/repository1') + </file> + <file name="__ROOT__/usr/repository1/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="quote1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + This behavior of the C preprocessor--always search + for a <literal>#include</literal> file in double-quotes + first in the same directory as the source file, + and only then search the <literal>-I</literal>--can + not, in general, be changed. + In other words, it's a limitation + that must be lived with if you want to use + code repositories in this way. + There are three ways you can possibly + work around this C preprocessor behavior: + + </para> + + <orderedlist> + + <listitem> + <para> + + Some modern versions of C compilers do have an option + to disable or control this behavior. + If so, add that option to &cv-link-CFLAGS; + (or &cv-link-CXXFLAGS; or both) in your construction environment(s). + Make sure the option is used for all construction + environments that use C preprocessing! + + </para> + </listitem> + + <listitem> + <para> + + Change all occurrences of <literal>#include "file.h"</literal> + to <literal>#include &lt;file.h&gt;</literal>. + Use of <literal>#include</literal> with angle brackets + does not have the same behavior--the <literal>-I</literal> + directories are searched first + for <literal>#include</literal> files--which + gives &SCons; direct control over the list of + directories the C preprocessor will search. + + </para> + </listitem> + + <listitem> + <para> + + Require that everyone working with compilation from + repositories check out and work on entire directories of files, + not individual files. + (If you use local wrapper scripts around + your source code control system's command, + you could add logic to enforce this restriction there. + + </para> + </listitem> + + </orderedlist> + + </section> + + </section> + + <section> + <title>Finding the &SConstruct; file in repositories</title> + + <para> + + &SCons; will also search in repositories + for the &SConstruct; file and any specified &SConscript; files. + This poses a problem, though: how can &SCons; search a + repository tree for an &SConstruct; file + if the &SConstruct; file itself contains the information + about the pathname of the repository? + To solve this problem, &SCons; allows you + to specify repository directories + on the command line using the <literal>-Y</literal> option: + + </para> + + <screen> + % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput> + </screen> + + <para> + + When looking for source or derived files, + &SCons; will first search the repositories + specified on the command line, + and then search the repositories + specified in the &SConstruct; or &SConscript; files. + + </para> + + </section> + + <section> + <title>Finding derived files in repositories</title> + + <para> + + If a repository contains not only source files, + but also derived files (such as object files, + libraries, or executables), &SCons; will perform + its normal MD5 signature calculation to + decide if a derived file in a repository is up-to-date, + or the derived file must be rebuilt in the local build directory. + For the &SCons; signature calculation to work correctly, + a repository tree must contain the &sconsign; files + that &SCons; uses to keep track of signature information. + + </para> + + <para> + + Usually, this would be done by a build integrator + who would run &SCons; in the repository + to create all of its derived files and &sconsign; files, + or who would run &SCons; in a separate build directory + and copy the resulting tree to the desired repository: + + </para> + + <scons_example name="ex4"> + <file name="SConstruct"> + env = Environment() + env.Program(['hello.c', 'file1.c', 'file2.c']) + Repository('/usr/repository1', '/usr/repository2') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="file1.c"> + int f1() { printf("file1\n"); } + </file> + <file name="file2.c"> + int f2() { printf("file2.c\n"); } + </file> + </scons_example> + + <scons_output example="ex4"> + <scons_output_command>cd /usr/repository1</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + (Note that this is safe even if the &SConstruct; file + lists <filename>/usr/repository1</filename> as a repository, + because &SCons; will remove the current build directory + from its repository list for that invocation.) + + </para> + + <para> + + Now, with the repository populated, + we only need to create the one local source file + we're interested in working with at the moment, + and use the <literal>-Y</literal> option to + tell &SCons; to fetch any other files it needs + from the repository: + + </para> + + <!-- + <scons_output example="ex4"> + <scons_output_command>cd $HOME/build</scons_output_command> + <scons_output_command>edit hello.c</scons_output_command> + <scons_output_command>scons -Q -Y __ROOT__/usr/repository1</scons_output_command> + </scons_output> + --> + <screen> + % <userinput>cd $HOME/build</userinput> + % <userinput>edit hello.c</userinput> + % <userinput>scons -Q -Y /usr/repository1</userinput> + cc -c -o hello.o hello.c + cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o + </screen> + + <para> + + Notice that &SCons; realizes that it does not need to + rebuild local copies <filename>file1.o</filename> and <filename>file2.o</filename> files, + but instead uses the already-compiled files + from the repository. + + </para> + + </section> + + <section> + <title>Guaranteeing local copies of files</title> + + <para> + + If the repository tree contains the complete results of a build, + and we try to build from the repository + without any files in our local tree, + something moderately surprising happens: + + </para> + + <screen> + % <userinput>mkdir $HOME/build2</userinput> + % <userinput>cd $HOME/build2</userinput> + % <userinput>scons -Q -Y /usr/all/repository hello</userinput> + scons: `hello' is up-to-date. + </screen> + + <para> + + Why does &SCons; say that the &hello; program + is up-to-date when there is no &hello; program + in the local build directory? + Because the repository (not the local directory) + contains the up-to-date &hello; program, + and &SCons; correctly determines that nothing + needs to be done to rebuild that + up-to-date copy of the file. + + </para> + + <para> + + There are, however, many times when you want to ensure that a + local copy of a file always exists. + A packaging or testing script, for example, + may assume that certain generated files exist locally. + To tell &SCons; to make a copy of any up-to-date repository + file in the local build directory, + use the &Local; function: + + </para> + + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> + env = Environment() + hello = env.Program('hello.c') + Local(hello) + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + If we then run the same command, + &SCons; will make a local copy of the program + from the repository copy, + and tell you that it is doing so: + + </para> + + <screen> + % <userinput>scons -Y /usr/all/repository hello</userinput> + Local copy of hello from /usr/all/repository/hello + scons: `hello' is up-to-date. + </screen> + + <para> + + (Notice that, because the act of making the local copy + is not considered a "build" of the &hello; file, + &SCons; still reports that it is up-to-date.) + + </para> + + </section> diff --git a/doc/user/repositories.xml b/doc/user/repositories.xml new file mode 100644 index 0000000..7d955c3 --- /dev/null +++ b/doc/user/repositories.xml @@ -0,0 +1,595 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + Often, a software project will have + one or more central repositories, + directory trees that contain + source code, or derived files, or both. + You can eliminate additional unnecessary + rebuilds of files by having &SCons; + use files from one or more code repositories + to build files in your local build tree. + + </para> + + <section> + <title>The &Repository; Method</title> + + <!-- + + The repository directories specified may contain source files, derived files + (objects, libraries and executables), or both. If there is no local file + (source or derived) under the directory in which Cons is executed, then the + first copy of a same-named file found under a repository directory will be + used to build any local derived files. + + --> + + <para> + + It's often useful to allow multiple programmers working + on a project to build software from + source files and/or derived files that + are stored in a centrally-accessible repository, + a directory copy of the source code tree. + (Note that this is not the sort of repository + maintained by a source code management system + like BitKeeper, CVS, or Subversion.) + <!-- + For information about using &SCons; + with these systems, see the section, + "Fetching Files From Source Code Management Systems," + below.) + --> + You use the &Repository; method + to tell &SCons; to search one or more + central code repositories (in order) + for any source files and derived files + that are not present in the local build tree: + + </para> + + <programlisting> + env = Environment() + env.Program('hello.c') + Repository('/usr/repository1', '/usr/repository2') + </programlisting> + + <para> + + Multiple calls to the &Repository; method + will simply add repositories to the global list + that &SCons; maintains, + with the exception that &SCons; will automatically eliminate + the current directory and any non-existent + directories from the list. + + </para> + + </section> + + <section> + <title>Finding source files in repositories</title> + + <para> + + The above example + specifies that &SCons; + will first search for files under + the <filename>/usr/repository1</filename> tree + and next under the <filename>/usr/repository2</filename> tree. + &SCons; expects that any files it searches + for will be found in the same position + relative to the top-level directory. + In the above example, if the &hello_c; file is not + found in the local build tree, + &SCons; will search first for + a <filename>/usr/repository1/hello.c</filename> file + and then for a <filename>/usr/repository2/hello.c</filename> file + to use in its place. + + </para> + + <para> + + So given the &SConstruct; file above, + if the &hello_c; file exists in the local + build directory, + &SCons; will rebuild the &hello; program + as normal: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + <para> + + If, however, there is no local &hello_c; file, + but one exists in <filename>/usr/repository1</filename>, + &SCons; will recompile the &hello; program + from the source file it finds in the repository: + + </para> + + + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c /usr/repository1/hello.c + cc -o hello hello.o + </screen> + + <para> + + And similarly, if there is no local &hello_c; file + and no <filename>/usr/repository1/hello.c</filename>, + but one exists in <filename>/usr/repository2</filename>: + + </para> + + + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c /usr/repository2/hello.c + cc -o hello hello.o + </screen> + + <para> + + </para> + + </section> + + <section> + <title>Finding <literal>#include</literal> files in repositories</title> + + <para> + + We've already seen that SCons will scan the contents of + a source file for <literal>#include</literal> file names + and realize that targets built from that source file + also depend on the <literal>#include</literal> file(s). + For each directory in the &cv-link-CPPPATH; list, + &SCons; will actually search the corresponding directories + in any repository trees and establish the + correct dependencies on any + <literal>#include</literal> files that it finds + in repository directory. + + </para> + + <para> + + Unless the C compiler also knows about these directories + in the repository trees, though, + it will be unable to find the <literal>#include</literal> files. + If, for example, the &hello_c; file in + our previous example includes the &hello;.h; + in its current directory, + and the &hello;.h; only exists in the repository: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + hello.c:1: hello.h: No such file or directory + </screen> + + <para> + + In order to inform the C compiler about the repositories, + &SCons; will add appropriate + <literal>-I</literal> flags to the compilation commands + for each directory in the &cv-CPPPATH; list. + So if we add the current directory to the + construction environment &cv-CPPPATH; like so: + + </para> + + <programlisting> + env = Environment(CPPPATH = ['.']) + env.Program('hello.c') + Repository('/usr/repository1') + </programlisting> + + <para> + + Then re-executing &SCons; yields: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -I. -I/usr/repository1 hello.c + cc -o hello hello.o + </screen> + + <para> + + The order of the <literal>-I</literal> options replicates, + for the C preprocessor, + the same repository-directory search path + that &SCons; uses for its own dependency analysis. + If there are multiple repositories and multiple &cv-CPPPATH; + directories, &SCons; will add the repository directories + to the beginning of each &cv-CPPPATH; directory, + rapidly multiplying the number of <literal>-I</literal> flags. + If, for example, the &cv-CPPPATH; contains three directories + (and shorter repository path names!): + + </para> + + <programlisting> + env = Environment(CPPPATH = ['dir1', 'dir2', 'dir3']) + env.Program('hello.c') + Repository('/r1', '/r2') + </programlisting> + + <para> + + Then we'll end up with nine <literal>-I</literal> options + on the command line, + three (for each of the &cv-CPPPATH; directories) + times three (for the local directory plus the two repositories): + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -Idir1 -I/r1/dir1 -I/r2/dir1 -Idir2 -I/r1/dir2 -I/r2/dir2 -Idir3 -I/r1/dir3 -I/r2/dir3 hello.c + cc -o hello hello.o + </screen> + +<!-- + +Cons classic did the following, does SCons? + +In order to shorten the command lines as much as possible, Cons will +remove C<-I> flags for any directories, locally or in the repositories, +which do not actually exist. (Note that the C<-I> flags are not included +in the MD5 signature calculation for the target file, so the target will +not be recompiled if the compilation command changes due to a directory +coming into existence.) + +--> + + <section> + <title>Limitations on <literal>#include</literal> files in repositories</title> + + <para> + + &SCons; relies on the C compiler's + <literal>-I</literal> options to control the order in which + the preprocessor will search the repository directories + for <literal>#include</literal> files. + This causes a problem, however, with how the C preprocessor + handles <literal>#include</literal> lines with + the file name included in double-quotes. + + </para> + + <para> + + As we've seen, + &SCons; will compile the &hello_c; file from + the repository if it doesn't exist in + the local directory. + If, however, the &hello_c; file in the repository contains + a <literal>#include</literal> line with the file name in + double quotes: + + </para> + + <programlisting> + #include "hello.h" + int + main(int argc, char *argv[]) + { + printf(HELLO_MESSAGE); + return (0); + } + </programlisting> + + <para> + + Then the C preprocessor will <emphasis>always</emphasis> + use a &hello_h; file from the repository directory first, + even if there is a &hello_h; file in the local directory, + despite the fact that the command line specifies + <literal>-I</literal> as the first option: + + </para> + + + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -I. -I/usr/repository1 /usr/repository1/hello.c + cc -o hello hello.o + </screen> + + <para> + + This behavior of the C preprocessor--always search + for a <literal>#include</literal> file in double-quotes + first in the same directory as the source file, + and only then search the <literal>-I</literal>--can + not, in general, be changed. + In other words, it's a limitation + that must be lived with if you want to use + code repositories in this way. + There are three ways you can possibly + work around this C preprocessor behavior: + + </para> + + <orderedlist> + + <listitem> + <para> + + Some modern versions of C compilers do have an option + to disable or control this behavior. + If so, add that option to &cv-link-CFLAGS; + (or &cv-link-CXXFLAGS; or both) in your construction environment(s). + Make sure the option is used for all construction + environments that use C preprocessing! + + </para> + </listitem> + + <listitem> + <para> + + Change all occurrences of <literal>#include "file.h"</literal> + to <literal>#include <file.h></literal>. + Use of <literal>#include</literal> with angle brackets + does not have the same behavior--the <literal>-I</literal> + directories are searched first + for <literal>#include</literal> files--which + gives &SCons; direct control over the list of + directories the C preprocessor will search. + + </para> + </listitem> + + <listitem> + <para> + + Require that everyone working with compilation from + repositories check out and work on entire directories of files, + not individual files. + (If you use local wrapper scripts around + your source code control system's command, + you could add logic to enforce this restriction there. + + </para> + </listitem> + + </orderedlist> + + </section> + + </section> + + <section> + <title>Finding the &SConstruct; file in repositories</title> + + <para> + + &SCons; will also search in repositories + for the &SConstruct; file and any specified &SConscript; files. + This poses a problem, though: how can &SCons; search a + repository tree for an &SConstruct; file + if the &SConstruct; file itself contains the information + about the pathname of the repository? + To solve this problem, &SCons; allows you + to specify repository directories + on the command line using the <literal>-Y</literal> option: + + </para> + + <screen> + % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput> + </screen> + + <para> + + When looking for source or derived files, + &SCons; will first search the repositories + specified on the command line, + and then search the repositories + specified in the &SConstruct; or &SConscript; files. + + </para> + + </section> + + <section> + <title>Finding derived files in repositories</title> + + <para> + + If a repository contains not only source files, + but also derived files (such as object files, + libraries, or executables), &SCons; will perform + its normal MD5 signature calculation to + decide if a derived file in a repository is up-to-date, + or the derived file must be rebuilt in the local build directory. + For the &SCons; signature calculation to work correctly, + a repository tree must contain the &sconsign; files + that &SCons; uses to keep track of signature information. + + </para> + + <para> + + Usually, this would be done by a build integrator + who would run &SCons; in the repository + to create all of its derived files and &sconsign; files, + or who would run &SCons; in a separate build directory + and copy the resulting tree to the desired repository: + + </para> + + + + <screen> + % <userinput>cd /usr/repository1</userinput> + % <userinput>scons -Q</userinput> + cc -o file1.o -c file1.c + cc -o file2.o -c file2.c + cc -o hello.o -c hello.c + cc -o hello hello.o file1.o file2.o + </screen> + + <para> + + (Note that this is safe even if the &SConstruct; file + lists <filename>/usr/repository1</filename> as a repository, + because &SCons; will remove the current build directory + from its repository list for that invocation.) + + </para> + + <para> + + Now, with the repository populated, + we only need to create the one local source file + we're interested in working with at the moment, + and use the <literal>-Y</literal> option to + tell &SCons; to fetch any other files it needs + from the repository: + + </para> + + <!-- + <scons_output example="ex4"> + <scons_output_command>cd $HOME/build</scons_output_command> + <scons_output_command>edit hello.c</scons_output_command> + <scons_output_command>scons -Q -Y __ROOT__/usr/repository1</scons_output_command> + </scons_output> + --> + <screen> + % <userinput>cd $HOME/build</userinput> + % <userinput>edit hello.c</userinput> + % <userinput>scons -Q -Y /usr/repository1</userinput> + cc -c -o hello.o hello.c + cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o + </screen> + + <para> + + Notice that &SCons; realizes that it does not need to + rebuild local copies <filename>file1.o</filename> and <filename>file2.o</filename> files, + but instead uses the already-compiled files + from the repository. + + </para> + + </section> + + <section> + <title>Guaranteeing local copies of files</title> + + <para> + + If the repository tree contains the complete results of a build, + and we try to build from the repository + without any files in our local tree, + something moderately surprising happens: + + </para> + + <screen> + % <userinput>mkdir $HOME/build2</userinput> + % <userinput>cd $HOME/build2</userinput> + % <userinput>scons -Q -Y /usr/all/repository hello</userinput> + scons: `hello' is up-to-date. + </screen> + + <para> + + Why does &SCons; say that the &hello; program + is up-to-date when there is no &hello; program + in the local build directory? + Because the repository (not the local directory) + contains the up-to-date &hello; program, + and &SCons; correctly determines that nothing + needs to be done to rebuild that + up-to-date copy of the file. + + </para> + + <para> + + There are, however, many times when you want to ensure that a + local copy of a file always exists. + A packaging or testing script, for example, + may assume that certain generated files exist locally. + To tell &SCons; to make a copy of any up-to-date repository + file in the local build directory, + use the &Local; function: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + Local(hello) + </programlisting> + + <para> + + If we then run the same command, + &SCons; will make a local copy of the program + from the repository copy, + and tell you that it is doing so: + + </para> + + <screen> + % <userinput>scons -Y /usr/all/repository hello</userinput> + Local copy of hello from /usr/all/repository/hello + scons: `hello' is up-to-date. + </screen> + + <para> + + (Notice that, because the act of making the local copy + is not considered a "build" of the &hello; file, + &SCons; still reports that it is up-to-date.) + + </para> + + </section> diff --git a/doc/user/run.in b/doc/user/run.in new file mode 100644 index 0000000..946a7ed --- /dev/null +++ b/doc/user/run.in @@ -0,0 +1,375 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Invoking Cons + +The C<cons> command is usually invoked from the root of the build tree. A +F<Construct> file must exist in that directory. If the C<-f> argument is +used, then an alternate F<Construct> file may be used (and, possibly, an +alternate root, since C<cons> will cd to F<Construct> file's containing +directory). + +If C<cons> is invoked from a child of the root of the build tree with +the C<-t> argument, it will walk up the directory hierarchy looking for a +F<Construct> file. (An alternate name may still be specified with C<-f>.) +The targets supplied on the command line will be modified to be relative +to the discovered F<Construct> file. For example, from a directory +containing a top-level F<Construct> file, the following invocation: + + % cd libfoo/subdir + % cons -t target + +is exactly equivalent to: + + % cons libfoo/subdir/target + +If there are any C<Default> targets specified in the directory hierarchy's +F<Construct> or F<Conscript> files, only the default targets at or below +the directory from which C<cons -t> was invoked will be built. + +The command is invoked as follows: + + cons <arguments> , <construct-args> + +where I<arguments> can be any of the following, in any order: + +=over 10 + +=item I<target> + +Build the specified target. If I<target> is a directory, then recursively +build everything within that directory. + +=item I<+pattern> + +Limit the F<Conscript> files considered to just those that match I<pattern>, +which is a Perl regular expression. Multiple C<+> arguments are accepted. + +=item I<name>=<val> + +Sets I<name> to value I<val> in the C<ARG> hash passed to the top-level +F<Construct> file. + +=item C<-cc> + +Show command that would have been executed, when retrieving from cache. No +indication that the file has been retrieved is given; this is useful for +generating build logs that can be compared with real build logs. + +=item C<-cd> + +Disable all caching. Do not retrieve from cache nor flush to cache. + +=item C<-cr> + +Build dependencies in random order. This is useful when building multiple +similar trees with caching enabled. + +=item C<-cs> + +Synchronize existing build targets that are found to be up-to-date with +cache. This is useful if caching has been disabled with -cc or just recently +enabled with UseCache. + +=item C<-d> + +Enable dependency debugging. + +=item C<-f> <file> + +Use the specified file instead of F<Construct> (but first change to +containing directory of I<file>). + +=item C<-h> + +Show a help message local to the current build if one such is defined, and +exit. + +=item C<-k> + +Keep going as far as possible after errors. + +=item C<-o> <file> + +Read override file I<file>. + +=item C<-p> + +Show construction products in specified trees. No build is attempted. + +=item C<-pa> + +Show construction products and associated actions. No build is attempted. + +=item C<-pw> + +Show products and where they are defined. No build is attempted. + +=item C<-q> + +Make the build quiet. Multiple C<-q> options may be specified. + +A single C<-q> options suppress messages about Installing and Removing +targets. + +Two C<-q> options suppress build command lines and target up-to-date +messages. + +=item C<-r> + +Remove construction products associated with <targets>. No build is +attempted. + +=item C<-R> <repos> + +Search for files in I<repos>. Multiple B<-R> I<repos> directories are +searched in the order specified. + +=item C<-S> <pkg> + +Use the sig::<pkg> package to calculate. Supported <pkg> values +include "md5" for MD5 signature calculation and "md5::debug" for debug +information about MD5 signature calculation. + +If the specified package ends in <::debug>, signature debug information +will be printed to the file name specified in the C<CONS_SIG_DEBUG> +environment variable, or to standard output if the environment variable +is not set. + +=item C<-t> + +Traverse up the directory hierarchy looking for a F<Construct> file, +if none exists in the current directory. Targets will be modified to +be relative to the F<Construct> file. + +Internally, C<cons> will change its working directory to the directory +which contains the top-level F<Construct> file and report: + + cons: Entering directory `top-level-directory' + +This message indicates to an invoking editor (such as emacs) or build +environment that Cons will now report all file names relative to the +top-level directory. This message can not be suppressed with the C<-q> +option. + +=item C<-v> + +Show C<cons> version and continue processing. + +=item C<-V> + +Show C<cons> version and exit. + +=item C<-wf> <file> + +Write all filenames considered into I<file>. + +=item C<-x> + +Show a help message similar to this one, and exit. + +=back + +And I<construct-args> can be any arguments that you wish to process in the +F<Construct> file. Note that there should be a B<-,-> separating the arguments +to cons and the arguments that you wish to process in the F<Construct> file. + +Processing of I<construct-args> can be done by any standard package like +B<Getopt> or its variants, or any user defined package. B<cons> will pass in +the I<construct-args> as B<@ARGV> and will not attempt to interpret anything +after the B<-,->. + + % cons -R /usr/local/repository -d os=solaris +driver -,- -c test -f DEBUG + +would pass the following to cons + + -R /usr/local/repository -d os=solaris +driver + +and the following, to the top level F<Construct> file as B<@ARGV> + + -c test -f DEBUG + +Note that C<cons -r .> is equivalent to a full recursive C<make clean>, +but requires no support in the F<Construct> file or any F<Conscript> +files. This is most useful if you are compiling files into source +directories (if you separate the F<build> and F<export> directories, +then you can just remove the directories). + +The options C<-p>, C<-pa>, and C<-pw> are extremely useful for use as an aid +in reading scripts or debugging them. If you want to know what script +installs F<export/include/foo.h>, for example, just type: + + % cons -pw export/include/foo.h + +=head1 Selective builds + +Cons provides two methods for reducing the size of given build. The first is +by specifying targets on the command line, and the second is a method for +pruning the build tree. We'll consider target specification first. + + +=head2 Selective targeting + +Like make, Cons allows the specification of ``targets'' on the command +line. Cons targets may be either files or directories. When a directory is +specified, this is simply a short-hand notation for every derivable +product-,-that Cons knows about-,-in the specified directory and below. For +example: + + % cons build/hello/hello.o + +means build F<hello.o> and everything that F<hello.o> might need. This is +from a previous version of the B<Hello, World!> program in which F<hello.o> +depended upon F<export/include/world.h>. If that file is not up-to-date +(because someone modified F<src/world/world.h)>, then it will be rebuilt, +even though it is in a directory remote from F<build/hello>. + +In this example: + + % cons build + +Everything in the F<build> directory is built, if necessary. Again, this may +cause more files to be built. In particular, both F<export/include/world.h> +and F<export/lib/libworld.a> are required by the F<build/hello> directory, +and so they will be built if they are out-of-date. + +If we do, instead: + + % cons export + +then only the files that should be installed in the export directory will be +rebuilt, if necessary, and then installed there. Note that C<cons build> +might build files that C<cons export> doesn't build, and vice-versa. + + +=head1 Build Pruning + +In conjunction with target selection, B<build pruning> can be used to reduce +the scope of the build. In the previous peAcH and baNaNa example, we have +already seen how script-driven build pruning can be used to make only half +of the potential build available for any given invocation of C<cons>. Cons +also provides, as a convenience, a command line convention that allows you +to specify which F<Conscript> files actually get ``built''-,-that is, +incorporated into the build tree. For example: + + % cons build +world + +The C<+> argument introduces a Perl regular expression. This must, of +course, be quoted at the shell level if there are any shell meta-characters +within the expression. The expression is matched against each F<Conscript> +file which has been mentioned in a C<Build> statement, and only those +scripts with matching names are actually incorporated into the build +tree. Multiple such arguments are allowed, in which case a match against any +of them is sufficient to cause a script to be included. + +In the example, above, the F<hello> program will not be built, since Cons +will have no knowledge of the script F<hello/Conscript>. The F<libworld.a> +archive will be built, however, if need be. + +There are a couple of uses for build pruning via the command line. Perhaps +the most useful is the ability to make local changes, and then, with +sufficient knowledge of the consequences of those changes, restrict the size +of the build tree in order to speed up the rebuild time. A second use for +build pruning is to actively prevent the recompilation of certain files that +you know will recompile due to, for example, a modified header file. You may +know that either the changes to the header file are immaterial, or that the +changes may be safely ignored for most of the tree, for testing +purposes.With Cons, the view is that it is pragmatic to admit this type of +behavior, with the understanding that on the next full build everything that +needs to be rebuilt will be. There is no equivalent to a ``make touch'' +command, to mark files as permanently up-to-date. So any risk that is +incurred by build pruning is mitigated. For release quality work, obviously, +we recommend that you do not use build pruning (it's perfectly OK to use +during integration, however, for checking compilation, etc. Just be sure to +do an unconstrained build before committing the integration). + +--> + + <para> + + XXX + + </para> + + <section> + <title>Command-Line Options</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Getting at Command-Line Arguments</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Selective Builds</title> + + <para> + + XXX + + </para> + + </section> + + <!-- + + <section> + <title>Build Pruning</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <section> + <title>Overriding Construction Variables</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/run.xml b/doc/user/run.xml new file mode 100644 index 0000000..946a7ed --- /dev/null +++ b/doc/user/run.xml @@ -0,0 +1,375 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Invoking Cons + +The C<cons> command is usually invoked from the root of the build tree. A +F<Construct> file must exist in that directory. If the C<-f> argument is +used, then an alternate F<Construct> file may be used (and, possibly, an +alternate root, since C<cons> will cd to F<Construct> file's containing +directory). + +If C<cons> is invoked from a child of the root of the build tree with +the C<-t> argument, it will walk up the directory hierarchy looking for a +F<Construct> file. (An alternate name may still be specified with C<-f>.) +The targets supplied on the command line will be modified to be relative +to the discovered F<Construct> file. For example, from a directory +containing a top-level F<Construct> file, the following invocation: + + % cd libfoo/subdir + % cons -t target + +is exactly equivalent to: + + % cons libfoo/subdir/target + +If there are any C<Default> targets specified in the directory hierarchy's +F<Construct> or F<Conscript> files, only the default targets at or below +the directory from which C<cons -t> was invoked will be built. + +The command is invoked as follows: + + cons <arguments> , <construct-args> + +where I<arguments> can be any of the following, in any order: + +=over 10 + +=item I<target> + +Build the specified target. If I<target> is a directory, then recursively +build everything within that directory. + +=item I<+pattern> + +Limit the F<Conscript> files considered to just those that match I<pattern>, +which is a Perl regular expression. Multiple C<+> arguments are accepted. + +=item I<name>=<val> + +Sets I<name> to value I<val> in the C<ARG> hash passed to the top-level +F<Construct> file. + +=item C<-cc> + +Show command that would have been executed, when retrieving from cache. No +indication that the file has been retrieved is given; this is useful for +generating build logs that can be compared with real build logs. + +=item C<-cd> + +Disable all caching. Do not retrieve from cache nor flush to cache. + +=item C<-cr> + +Build dependencies in random order. This is useful when building multiple +similar trees with caching enabled. + +=item C<-cs> + +Synchronize existing build targets that are found to be up-to-date with +cache. This is useful if caching has been disabled with -cc or just recently +enabled with UseCache. + +=item C<-d> + +Enable dependency debugging. + +=item C<-f> <file> + +Use the specified file instead of F<Construct> (but first change to +containing directory of I<file>). + +=item C<-h> + +Show a help message local to the current build if one such is defined, and +exit. + +=item C<-k> + +Keep going as far as possible after errors. + +=item C<-o> <file> + +Read override file I<file>. + +=item C<-p> + +Show construction products in specified trees. No build is attempted. + +=item C<-pa> + +Show construction products and associated actions. No build is attempted. + +=item C<-pw> + +Show products and where they are defined. No build is attempted. + +=item C<-q> + +Make the build quiet. Multiple C<-q> options may be specified. + +A single C<-q> options suppress messages about Installing and Removing +targets. + +Two C<-q> options suppress build command lines and target up-to-date +messages. + +=item C<-r> + +Remove construction products associated with <targets>. No build is +attempted. + +=item C<-R> <repos> + +Search for files in I<repos>. Multiple B<-R> I<repos> directories are +searched in the order specified. + +=item C<-S> <pkg> + +Use the sig::<pkg> package to calculate. Supported <pkg> values +include "md5" for MD5 signature calculation and "md5::debug" for debug +information about MD5 signature calculation. + +If the specified package ends in <::debug>, signature debug information +will be printed to the file name specified in the C<CONS_SIG_DEBUG> +environment variable, or to standard output if the environment variable +is not set. + +=item C<-t> + +Traverse up the directory hierarchy looking for a F<Construct> file, +if none exists in the current directory. Targets will be modified to +be relative to the F<Construct> file. + +Internally, C<cons> will change its working directory to the directory +which contains the top-level F<Construct> file and report: + + cons: Entering directory `top-level-directory' + +This message indicates to an invoking editor (such as emacs) or build +environment that Cons will now report all file names relative to the +top-level directory. This message can not be suppressed with the C<-q> +option. + +=item C<-v> + +Show C<cons> version and continue processing. + +=item C<-V> + +Show C<cons> version and exit. + +=item C<-wf> <file> + +Write all filenames considered into I<file>. + +=item C<-x> + +Show a help message similar to this one, and exit. + +=back + +And I<construct-args> can be any arguments that you wish to process in the +F<Construct> file. Note that there should be a B<-,-> separating the arguments +to cons and the arguments that you wish to process in the F<Construct> file. + +Processing of I<construct-args> can be done by any standard package like +B<Getopt> or its variants, or any user defined package. B<cons> will pass in +the I<construct-args> as B<@ARGV> and will not attempt to interpret anything +after the B<-,->. + + % cons -R /usr/local/repository -d os=solaris +driver -,- -c test -f DEBUG + +would pass the following to cons + + -R /usr/local/repository -d os=solaris +driver + +and the following, to the top level F<Construct> file as B<@ARGV> + + -c test -f DEBUG + +Note that C<cons -r .> is equivalent to a full recursive C<make clean>, +but requires no support in the F<Construct> file or any F<Conscript> +files. This is most useful if you are compiling files into source +directories (if you separate the F<build> and F<export> directories, +then you can just remove the directories). + +The options C<-p>, C<-pa>, and C<-pw> are extremely useful for use as an aid +in reading scripts or debugging them. If you want to know what script +installs F<export/include/foo.h>, for example, just type: + + % cons -pw export/include/foo.h + +=head1 Selective builds + +Cons provides two methods for reducing the size of given build. The first is +by specifying targets on the command line, and the second is a method for +pruning the build tree. We'll consider target specification first. + + +=head2 Selective targeting + +Like make, Cons allows the specification of ``targets'' on the command +line. Cons targets may be either files or directories. When a directory is +specified, this is simply a short-hand notation for every derivable +product-,-that Cons knows about-,-in the specified directory and below. For +example: + + % cons build/hello/hello.o + +means build F<hello.o> and everything that F<hello.o> might need. This is +from a previous version of the B<Hello, World!> program in which F<hello.o> +depended upon F<export/include/world.h>. If that file is not up-to-date +(because someone modified F<src/world/world.h)>, then it will be rebuilt, +even though it is in a directory remote from F<build/hello>. + +In this example: + + % cons build + +Everything in the F<build> directory is built, if necessary. Again, this may +cause more files to be built. In particular, both F<export/include/world.h> +and F<export/lib/libworld.a> are required by the F<build/hello> directory, +and so they will be built if they are out-of-date. + +If we do, instead: + + % cons export + +then only the files that should be installed in the export directory will be +rebuilt, if necessary, and then installed there. Note that C<cons build> +might build files that C<cons export> doesn't build, and vice-versa. + + +=head1 Build Pruning + +In conjunction with target selection, B<build pruning> can be used to reduce +the scope of the build. In the previous peAcH and baNaNa example, we have +already seen how script-driven build pruning can be used to make only half +of the potential build available for any given invocation of C<cons>. Cons +also provides, as a convenience, a command line convention that allows you +to specify which F<Conscript> files actually get ``built''-,-that is, +incorporated into the build tree. For example: + + % cons build +world + +The C<+> argument introduces a Perl regular expression. This must, of +course, be quoted at the shell level if there are any shell meta-characters +within the expression. The expression is matched against each F<Conscript> +file which has been mentioned in a C<Build> statement, and only those +scripts with matching names are actually incorporated into the build +tree. Multiple such arguments are allowed, in which case a match against any +of them is sufficient to cause a script to be included. + +In the example, above, the F<hello> program will not be built, since Cons +will have no knowledge of the script F<hello/Conscript>. The F<libworld.a> +archive will be built, however, if need be. + +There are a couple of uses for build pruning via the command line. Perhaps +the most useful is the ability to make local changes, and then, with +sufficient knowledge of the consequences of those changes, restrict the size +of the build tree in order to speed up the rebuild time. A second use for +build pruning is to actively prevent the recompilation of certain files that +you know will recompile due to, for example, a modified header file. You may +know that either the changes to the header file are immaterial, or that the +changes may be safely ignored for most of the tree, for testing +purposes.With Cons, the view is that it is pragmatic to admit this type of +behavior, with the understanding that on the next full build everything that +needs to be rebuilt will be. There is no equivalent to a ``make touch'' +command, to mark files as permanently up-to-date. So any risk that is +incurred by build pruning is mitigated. For release quality work, obviously, +we recommend that you do not use build pruning (it's perfectly OK to use +during integration, however, for checking compilation, etc. Just be sure to +do an unconstrained build before committing the integration). + +--> + + <para> + + XXX + + </para> + + <section> + <title>Command-Line Options</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Getting at Command-Line Arguments</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Selective Builds</title> + + <para> + + XXX + + </para> + + </section> + + <!-- + + <section> + <title>Build Pruning</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <section> + <title>Overriding Construction Variables</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/scanners.in b/doc/user/scanners.in new file mode 100644 index 0000000..8fa36d7 --- /dev/null +++ b/doc/user/scanners.in @@ -0,0 +1,331 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Using and writing dependency scanners + +QuickScan allows simple target-independent scanners to be set up for +source files. Only one QuickScan scanner may be associated with any given +source file and environment, although the same scanner may (and should) +be used for multiple files of a given type. + +A QuickScan scanner is only ever invoked once for a given source file, +and it is only invoked if the file is used by some target in the tree +(i.e., there is a dependency on the source file). + +QuickScan is invoked as follows: + + QuickScan CONSENV CODEREF, FILENAME [, PATH] + +The subroutine referenced by CODEREF is expected to return a list of +filenames included directly by FILE. These filenames will, in turn, be +scanned. The optional PATH argument supplies a lookup path for finding +FILENAME and/or files returned by the user-supplied subroutine. The PATH +may be a reference to an array of lookup-directory names, or a string of +names separated by the system's separator character (':' on UNIX systems, +';' on Windows NT). + +The subroutine is called once for each line in the file, with $_ set to the +current line. If the subroutine needs to look at additional lines, or, for +that matter, the entire file, then it may read them itself, from the +filehandle SCAN. It may also terminate the loop, if it knows that no further +include information is available, by closing the filehandle. + +Whether or not a lookup path is provided, QuickScan first tries to lookup +the file relative to the current directory (for the top-level file +supplied directly to QuickScan), or from the directory containing the +file which referenced the file. This is not very general, but seems good +enough, especially if you have the luxury of writing your own utilities +and can control the use of the search path in a standard way. + +Here's a real example, taken from a F<Construct> file here: + + sub cons::SMFgen { + my($env, @tables) = @_; + foreach $t (@tables) { + $env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf", + $env->{SMF_INCLUDE_PATH}); + $env->Command(["$t.smdb.cc","$t.smdb.h","$t.snmp.cc", + "$t.ami.cc", "$t.http.cc"], "$t.smf", + q(smfgen %( %SMF_INCLUDE_OPT %) %<)); + } + } + +The subroutine above finds all names of the form <name>.smf in the +file. It will return the names even if they're found within comments, +but that's OK (the mechanism is forgiving of extra files; they're just +ignored on the assumption that the missing file will be noticed when +the program, in this example, smfgen, is actually invoked). + +[NOTE that the form C<$env-E<gt>QuickScan ...> and C<$env-E<gt>Command +...> should not be necessary, but, for some reason, is required +for this particular invocation. This appears to be a bug in Perl or +a misunderstanding on my part; this invocation style does not always +appear to be necessary.] + +Here is another way to build the same scanner. This one uses an +explicit code reference, and also (unnecessarily, in this case) reads +the whole file itself: + + sub myscan { + my(@includes); + do { + push(@includes, /\b\S*?\.smf\b/g); + } while <SCAN>; + @includes + } + +Note that the order of the loop is reversed, with the loop test at the +end. This is because the first line is already read for you. This scanner +can be attached to a source file by: + + QuickScan $env \&myscan, "$_.smf"; + +This final example, which scans a different type of input file, takes +over the file scanning rather than being called for each input line: + + $env->QuickScan( + sub { my(@includes) = (); + do { + push(@includes, $3) + if /^(#include|import)\s+(\")(.+)(\")/ && $3 + } while <SCAN>; + @includes + }, + "$idlFileName", + "$env->{CPPPATH};$BUILD/ActiveContext/ACSCLientInterfaces" + ); + +--> + + <para> + + &SCons; has built-in scanners that know how to look in + C, Fortran and IDL source files for information about + other files that targets built from those files depend on--for example, + in the case of files that use the C preprocessor, + the <filename>.h</filename> files that are specified + using <literal>#include</literal> lines in the source. + You can use the same mechanisms that &SCons; uses to create + its built-in scanners to write scanners of your own for file types + that &SCons; does not know how to scan "out of the box." + + </para> + + <section> + <title>A Simple Scanner Example</title> + + <para> + + Suppose, for example, that we want to create a simple scanner + for <filename>.foo</filename> files. + A <filename>.foo</filename> file contains some text that + will be processed, + and can include other files on lines that begin + with <literal>include</literal> + followed by a file name: + + </para> + + <programlisting> + include filename.foo + </programlisting> + + <para> + + Scanning a file will be handled by a Python function + that you must supply. + Here is a function that will use the Python + <filename>re</filename> module + to scan for the <literal>include</literal> lines in our example: + + </para> + + <programlisting> + import re + + include_re = re.compile(r'^include\s+(\S+)$', re.M) + + def kfile_scan(node, env, path, arg): + contents = node.get_text_contents() + return include_re.findall(contents) + </programlisting> + + <para> + + The scanner function must + accept the four specified arguments + and return a list of implicit dependencies. + Presumably, these would be dependencies found + from examining the contents of the file, + although the function can perform any + manipulation at all to generate the list of + dependencies. + + </para> + + <variablelist> + + <varlistentry> + <term>node</term> + + <listitem> + <para> + + An &SCons; node object representing the file being scanned. + The path name to the file can be + used by converting the node to a string + using the <literal>str()</literal> function, + or an internal &SCons; <literal>get_text_contents()</literal> + object method can be used to fetch the contents. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>env</term> + + <listitem> + <para> + + The construction environment in effect for this scan. + The scanner function may choose to use construction + variables from this environment to affect its behavior. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>path</term> + + <listitem> + <para> + + A list of directories that form the search path for included files + for this scanner. + This is how &SCons; handles the &cv-link-CPPPATH; and &cv-link-LIBPATH; + variables. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>arg</term> + + <listitem> + <para> + + An optional argument that you can choose to + have passed to this scanner function by + various scanner instances. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + A Scanner object is created using the &Scanner; function, + which typically takes an <literal>skeys</literal> argument + to associate the type of file suffix with this scanner. + The Scanner object must then be associated with the + &cv-link-SCANNERS; construction variable of a construction environment, + typically by using the &Append; method: + + </para> + + <programlisting> + kscan = Scanner(function = kfile_scan, + skeys = ['.k']) + env.Append(SCANNERS = kscan) + </programlisting> + + <para> + + When we put it all together, it looks like: + + </para> + + <scons_example name="scan"> + <file name="SConstruct" printme="1"> + import re + + include_re = re.compile(r'^include\s+(\S+)$', re.M) + + def kfile_scan(node, env, path): + contents = node.get_text_contents() + includes = include_re.findall(contents) + return includes + + kscan = Scanner(function = kfile_scan, + skeys = ['.k']) + + env = Environment(ENV = {'PATH' : '__ROOT__/usr/local/bin'}) + env.Append(SCANNERS = kscan) + + env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET') + </file> + <file name="foo.k"> + include other_file + </file> + <file name="other_file"> + other_file + </file> + <directory name="__ROOT__/usr"></directory> + <directory name="__ROOT__/usr/local"></directory> + <directory name="__ROOT__/usr/local/bin"></directory> + <file name="__ROOT_/usr/local/bin/kprocess" chmod="755"> + cat + </file> + </scons_example> + + <!-- + + <para> + + Now if we run &scons; + and then re-run it after changing the contents of + <filename>other_file</filename>, + the <filename>foo</filename> + target file will be automatically rebuilt: + + </para> + + <scons_output example="scan"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF other_file]">edit other_file</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + </section> diff --git a/doc/user/scanners.xml b/doc/user/scanners.xml new file mode 100644 index 0000000..d34b222 --- /dev/null +++ b/doc/user/scanners.xml @@ -0,0 +1,317 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Using and writing dependency scanners + +QuickScan allows simple target-independent scanners to be set up for +source files. Only one QuickScan scanner may be associated with any given +source file and environment, although the same scanner may (and should) +be used for multiple files of a given type. + +A QuickScan scanner is only ever invoked once for a given source file, +and it is only invoked if the file is used by some target in the tree +(i.e., there is a dependency on the source file). + +QuickScan is invoked as follows: + + QuickScan CONSENV CODEREF, FILENAME [, PATH] + +The subroutine referenced by CODEREF is expected to return a list of +filenames included directly by FILE. These filenames will, in turn, be +scanned. The optional PATH argument supplies a lookup path for finding +FILENAME and/or files returned by the user-supplied subroutine. The PATH +may be a reference to an array of lookup-directory names, or a string of +names separated by the system's separator character (':' on UNIX systems, +';' on Windows NT). + +The subroutine is called once for each line in the file, with $_ set to the +current line. If the subroutine needs to look at additional lines, or, for +that matter, the entire file, then it may read them itself, from the +filehandle SCAN. It may also terminate the loop, if it knows that no further +include information is available, by closing the filehandle. + +Whether or not a lookup path is provided, QuickScan first tries to lookup +the file relative to the current directory (for the top-level file +supplied directly to QuickScan), or from the directory containing the +file which referenced the file. This is not very general, but seems good +enough, especially if you have the luxury of writing your own utilities +and can control the use of the search path in a standard way. + +Here's a real example, taken from a F<Construct> file here: + + sub cons::SMFgen { + my($env, @tables) = @_; + foreach $t (@tables) { + $env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf", + $env->{SMF_INCLUDE_PATH}); + $env->Command(["$t.smdb.cc","$t.smdb.h","$t.snmp.cc", + "$t.ami.cc", "$t.http.cc"], "$t.smf", + q(smfgen %( %SMF_INCLUDE_OPT %) %<)); + } + } + +The subroutine above finds all names of the form <name>.smf in the +file. It will return the names even if they're found within comments, +but that's OK (the mechanism is forgiving of extra files; they're just +ignored on the assumption that the missing file will be noticed when +the program, in this example, smfgen, is actually invoked). + +[NOTE that the form C<$env-E<gt>QuickScan ...> and C<$env-E<gt>Command +...> should not be necessary, but, for some reason, is required +for this particular invocation. This appears to be a bug in Perl or +a misunderstanding on my part; this invocation style does not always +appear to be necessary.] + +Here is another way to build the same scanner. This one uses an +explicit code reference, and also (unnecessarily, in this case) reads +the whole file itself: + + sub myscan { + my(@includes); + do { + push(@includes, /\b\S*?\.smf\b/g); + } while <SCAN>; + @includes + } + +Note that the order of the loop is reversed, with the loop test at the +end. This is because the first line is already read for you. This scanner +can be attached to a source file by: + + QuickScan $env \&myscan, "$_.smf"; + +This final example, which scans a different type of input file, takes +over the file scanning rather than being called for each input line: + + $env->QuickScan( + sub { my(@includes) = (); + do { + push(@includes, $3) + if /^(#include|import)\s+(\")(.+)(\")/ && $3 + } while <SCAN>; + @includes + }, + "$idlFileName", + "$env->{CPPPATH};$BUILD/ActiveContext/ACSCLientInterfaces" + ); + +--> + + <para> + + &SCons; has built-in scanners that know how to look in + C, Fortran and IDL source files for information about + other files that targets built from those files depend on--for example, + in the case of files that use the C preprocessor, + the <filename>.h</filename> files that are specified + using <literal>#include</literal> lines in the source. + You can use the same mechanisms that &SCons; uses to create + its built-in scanners to write scanners of your own for file types + that &SCons; does not know how to scan "out of the box." + + </para> + + <section> + <title>A Simple Scanner Example</title> + + <para> + + Suppose, for example, that we want to create a simple scanner + for <filename>.foo</filename> files. + A <filename>.foo</filename> file contains some text that + will be processed, + and can include other files on lines that begin + with <literal>include</literal> + followed by a file name: + + </para> + + <programlisting> + include filename.foo + </programlisting> + + <para> + + Scanning a file will be handled by a Python function + that you must supply. + Here is a function that will use the Python + <filename>re</filename> module + to scan for the <literal>include</literal> lines in our example: + + </para> + + <programlisting> + import re + + include_re = re.compile(r'^include\s+(\S+)$', re.M) + + def kfile_scan(node, env, path, arg): + contents = node.get_text_contents() + return include_re.findall(contents) + </programlisting> + + <para> + + The scanner function must + accept the four specified arguments + and return a list of implicit dependencies. + Presumably, these would be dependencies found + from examining the contents of the file, + although the function can perform any + manipulation at all to generate the list of + dependencies. + + </para> + + <variablelist> + + <varlistentry> + <term>node</term> + + <listitem> + <para> + + An &SCons; node object representing the file being scanned. + The path name to the file can be + used by converting the node to a string + using the <literal>str()</literal> function, + or an internal &SCons; <literal>get_text_contents()</literal> + object method can be used to fetch the contents. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>env</term> + + <listitem> + <para> + + The construction environment in effect for this scan. + The scanner function may choose to use construction + variables from this environment to affect its behavior. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>path</term> + + <listitem> + <para> + + A list of directories that form the search path for included files + for this scanner. + This is how &SCons; handles the &cv-link-CPPPATH; and &cv-link-LIBPATH; + variables. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>arg</term> + + <listitem> + <para> + + An optional argument that you can choose to + have passed to this scanner function by + various scanner instances. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + A Scanner object is created using the &Scanner; function, + which typically takes an <literal>skeys</literal> argument + to associate the type of file suffix with this scanner. + The Scanner object must then be associated with the + &cv-link-SCANNERS; construction variable of a construction environment, + typically by using the &Append; method: + + </para> + + <programlisting> + kscan = Scanner(function = kfile_scan, + skeys = ['.k']) + env.Append(SCANNERS = kscan) + </programlisting> + + <para> + + When we put it all together, it looks like: + + </para> + + <programlisting> + import re + + include_re = re.compile(r'^include\s+(\S+)$', re.M) + + def kfile_scan(node, env, path): + contents = node.get_text_contents() + includes = include_re.findall(contents) + return includes + + kscan = Scanner(function = kfile_scan, + skeys = ['.k']) + + env = Environment(ENV = {'PATH' : '/usr/local/bin'}) + env.Append(SCANNERS = kscan) + + env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET') + </programlisting> + + <!-- + + <para> + + Now if we run &scons; + and then re-run it after changing the contents of + <filename>other_file</filename>, + the <filename>foo</filename> + target file will be automatically rebuilt: + + </para> + + <scons_output example="scan"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF other_file]">edit other_file</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> + + </section> diff --git a/doc/user/sconf.in b/doc/user/sconf.in new file mode 100644 index 0000000..c4092c9 --- /dev/null +++ b/doc/user/sconf.in @@ -0,0 +1,486 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; has integrated support for multi-platform build configuration + similar to that offered by GNU &Autoconf;, + such as + figuring out what libraries or header files + are available on the local system. + This section describes how to use + this &SCons feature. + + </para> + + <note> + <para> + This chapter is still under development, + so not everything is explained as well as it should be. + See the &SCons; man page for additional information. + </para> + </note> + + <section> + <title>&Configure_Contexts;</title> + + <para> + + The basic framework for multi-platform build configuration + in &SCons; is to attach a &configure_context; to a + construction environment by calling the &Configure; function, + perform a number of checks for + libraries, functions, header files, etc., + and to then call the configure context's &Finish; method + to finish off the configuration: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + # Checks for libraries, header files, etc. go here! + env = conf.Finish() + </sconstruct> + + <para> + + &SCons; provides a number of basic checks, + as well as a mechanism for adding your own custom checks. + + </para> + + <para> + + Note that &SCons; uses its own dependency + mechanism to determine when a check + needs to be run--that is, + &SCons; does not run the checks + every time it is invoked, + but caches the values returned by previous checks + and uses the cached values unless something has changed. + This saves a tremendous amount + of developer time while working on + cross-platform build issues. + + </para> + + <para> + + The next sections describe + the basic checks that &SCons; supports, + as well as how to add your own custom checks. + + </para> + + </section> + + <section> + <title>Checking for the Existence of Header Files</title> + + <para> + + Testing the existence of a header file + requires knowing what language the header file is. + A configure context has a &CheckCHeader; method + that checks for the existence of a C header file: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckCHeader('math.h'): + print 'Math.h must be installed!' + Exit(1) + if conf.CheckCHeader('foo.h'): + conf.env.Append('-DHAS_FOO_H') + env = conf.Finish() + </sconstruct> + + <para> + + Note that you can choose to terminate + the build if a given header file doesn't exist, + or you can modify the construction environment + based on the existence of a header file. + + </para> + + <para> + + If you need to check for the existence + a C++ header file, + use the &CheckCXXHeader; method: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckCXXHeader('vector.h'): + print 'vector.h must be installed!' + Exit(1) + env = conf.Finish() + </sconstruct> + + </section> + + <section> + <title>Checking for the Availability of a Function</title> + + <para> + + Check for the availability of a specific function + using the &CheckFunc; method: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckFunc('strcpy'): + print 'Did not find strcpy(), using local version' + conf.env.Append(CPPDEFINES = '-Dstrcpy=my_local_strcpy') + env = conf.Finish() + </sconstruct> + + </section> + + <section> + <title>Checking for the Availability of a Library</title> + + <para> + + Check for the availability of a library + using the &CheckLib; method. + You only specify the basename of the library, + you don't need to add a <literal>lib</literal> + prefix or a <literal>.a</literal> or <literal>.lib</literal> suffix: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckLib('m'): + print 'Did not find libm.a or m.lib, exiting!' + Exit(1) + env = conf.Finish() + </sconstruct> + + <para> + + Because the ability to use a library successfully + often depends on having access to a header file + that describes the library's interface, + you can check for a library + <emphasis>and</emphasis> a header file + at the same time by using the + &CheckLibWithHeader; method: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckLibWithHeader('m', 'math.h', 'c'): + print 'Did not find libm.a or m.lib, exiting!' + Exit(1) + env = conf.Finish() + </sconstruct> + + <para> + + This is essentially shorthand for + separate calls to the &CheckHeader; and &CheckLib; + functions. + + </para> + + </section> + + <section> + <title>Checking for the Availability of a &typedef;</title> + + <para> + + Check for the availability of a &typedef; + by using the &CheckType; method: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckType('off_t'): + print 'Did not find off_t typedef, assuming int' + conf.env.Append(CCFLAGS = '-Doff_t=int') + env = conf.Finish() + </sconstruct> + + <para> + + You can also add a string that will be + placed at the beginning of the test file + that will be used to check for the &typedef;. + This provide a way to specify + files that must be included to find the &typedef;: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckType('off_t', '#include &lt;sys/types.h&gt;\n'): + print 'Did not find off_t typedef, assuming int' + conf.env.Append(CCFLAGS = '-Doff_t=int') + env = conf.Finish() + </sconstruct> + + </section> + + <section> + <title>Adding Your Own Custom Checks</title> + + <para> + + A custom check is a Python function + that checks for a certain condition to exist + on the running system, + usually using methods that &SCons; + supplies to take care of the details + of checking whether a compilation succeeds, + a link succeeds, + a program is runnable, + etc. + A simple custom check for the existence of + a specific library might look as follows: + + </para> + + <sconstruct> + mylib_test_source_file = """ + #include &lt;mylib.h&gt; + int main(int argc, char **argv) + { + MyLibrary mylib(argc, argv); + return 0; + } + """ + + def CheckMyLibrary(context): + context.Message('Checking for MyLibrary...') + result = context.TryLink(mylib_test_source_file, '.c') + context.Result(result) + return result + </sconstruct> + + <para> + + The &Message; and &Result; methods + should typically begin and end a custom check to + let the user know what's going on: + the &Message; call prints the + specified message (with no trailing newline) + and the &Result; call prints + <literal>yes</literal> if the check succeeds and + <literal>no</literal> if it doesn't. + The &TryLink; method + actually tests for whether the + specified program text + will successfully link. + + </para> + + <para> + + (Note that a custom check can modify + its check based on any arguments you + choose to pass it, + or by using or modifying the configure context environment + in the <literal>context.env</literal> attribute.) + + </para> + + <para> + + This custom check function is + then attached to the &configure_context; + by passing a dictionary + to the &Configure; call + that maps a name of the check + to the underlying function: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + </sconstruct> + + <para> + + You'll typically want to make + the check and the function name the same, + as we've done here, + to avoid potential confusion. + + </para> + + <para> + + We can then put these pieces together + and actually call the <literal>CheckMyLibrary</literal> check + as follows: + + </para> + + <sconstruct> + mylib_test_source_file = """ + #include &lt;mylib.h&gt; + int main(int argc, char **argv) + { + MyLibrary mylib(argc, argv); + return 0; + } + """ + + def CheckMyLibrary(context): + context.Message('Checking for MyLibrary... ') + result = context.TryLink(mylib_test_source_file, '.c') + context.Result(result) + return result + + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + if not conf.CheckMyLibrary(): + print 'MyLibrary is not installed!' + Exit(1) + env = conf.Finish() + + # We would then add actual calls like Program() to build + # something using the "env" construction environment. + </sconstruct> + + <para> + + If MyLibrary is not installed on the system, + the output will look like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript file ... + Checking for MyLibrary... failed + MyLibrary is not installed! + </screen> + + <para> + + If MyLibrary is installed, + the output will look like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript file ... + Checking for MyLibrary... failed + scons: done reading SConscript + scons: Building targets ... + . + . + . + </screen> + + </section> + + <section> + <title>Not Configuring When Cleaning Targets</title> + + <para> + + Using multi-platform configuration + as described in the previous sections + will run the configuration commands + even when invoking + <userinput>scons -c</userinput> + to clean targets: + + </para> + + <screen> + % <userinput>scons -Q -c</userinput> + Checking for MyLibrary... yes + Removed foo.o + Removed foo + </screen> + + <para> + + Although running the platform checks + when removing targets doesn't hurt anything, + it's usually unnecessary. + You can avoid this by using the + &GetOption(); method to + check whether the <option>-c</option> (clean) + option has been invoked on the command line: + + </para> + + <sconstruct> + env = Environment() + if not env.GetOption('clean'): + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + if not conf.CheckMyLibrary(): + print 'MyLibrary is not installed!' + Exit(1) + env = conf.Finish() + </sconstruct> + + <screen> + % <userinput>scons -Q -c</userinput> + Removed foo.o + Removed foo + </screen> + + </section> + + <!-- + + <section> + <title>Controlling Configuration: the &config; Option</title> + + <para> + + XXX -D, -u and -U + + </para> + + </section> + + --> diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml new file mode 100644 index 0000000..16ba534 --- /dev/null +++ b/doc/user/sconf.xml @@ -0,0 +1,486 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; has integrated support for multi-platform build configuration + similar to that offered by GNU &Autoconf;, + such as + figuring out what libraries or header files + are available on the local system. + This section describes how to use + this &SCons; feature. + + </para> + + <note> + <para> + This chapter is still under development, + so not everything is explained as well as it should be. + See the &SCons; man page for additional information. + </para> + </note> + + <section> + <title>&Configure_Contexts;</title> + + <para> + + The basic framework for multi-platform build configuration + in &SCons; is to attach a &configure_context; to a + construction environment by calling the &Configure; function, + perform a number of checks for + libraries, functions, header files, etc., + and to then call the configure context's &Finish; method + to finish off the configuration: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + # Checks for libraries, header files, etc. go here! + env = conf.Finish() + </programlisting> + + <para> + + &SCons; provides a number of basic checks, + as well as a mechanism for adding your own custom checks. + + </para> + + <para> + + Note that &SCons; uses its own dependency + mechanism to determine when a check + needs to be run--that is, + &SCons; does not run the checks + every time it is invoked, + but caches the values returned by previous checks + and uses the cached values unless something has changed. + This saves a tremendous amount + of developer time while working on + cross-platform build issues. + + </para> + + <para> + + The next sections describe + the basic checks that &SCons; supports, + as well as how to add your own custom checks. + + </para> + + </section> + + <section> + <title>Checking for the Existence of Header Files</title> + + <para> + + Testing the existence of a header file + requires knowing what language the header file is. + A configure context has a &CheckCHeader; method + that checks for the existence of a C header file: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckCHeader('math.h'): + print 'Math.h must be installed!' + Exit(1) + if conf.CheckCHeader('foo.h'): + conf.env.Append('-DHAS_FOO_H') + env = conf.Finish() + </programlisting> + + <para> + + Note that you can choose to terminate + the build if a given header file doesn't exist, + or you can modify the construction environment + based on the existence of a header file. + + </para> + + <para> + + If you need to check for the existence + a C++ header file, + use the &CheckCXXHeader; method: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckCXXHeader('vector.h'): + print 'vector.h must be installed!' + Exit(1) + env = conf.Finish() + </programlisting> + + </section> + + <section> + <title>Checking for the Availability of a Function</title> + + <para> + + Check for the availability of a specific function + using the &CheckFunc; method: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckFunc('strcpy'): + print 'Did not find strcpy(), using local version' + conf.env.Append(CPPDEFINES = '-Dstrcpy=my_local_strcpy') + env = conf.Finish() + </programlisting> + + </section> + + <section> + <title>Checking for the Availability of a Library</title> + + <para> + + Check for the availability of a library + using the &CheckLib; method. + You only specify the basename of the library, + you don't need to add a <literal>lib</literal> + prefix or a <literal>.a</literal> or <literal>.lib</literal> suffix: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckLib('m'): + print 'Did not find libm.a or m.lib, exiting!' + Exit(1) + env = conf.Finish() + </programlisting> + + <para> + + Because the ability to use a library successfully + often depends on having access to a header file + that describes the library's interface, + you can check for a library + <emphasis>and</emphasis> a header file + at the same time by using the + &CheckLibWithHeader; method: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckLibWithHeader('m', 'math.h', 'c'): + print 'Did not find libm.a or m.lib, exiting!' + Exit(1) + env = conf.Finish() + </programlisting> + + <para> + + This is essentially shorthand for + separate calls to the &CheckHeader; and &CheckLib; + functions. + + </para> + + </section> + + <section> + <title>Checking for the Availability of a &typedef;</title> + + <para> + + Check for the availability of a &typedef; + by using the &CheckType; method: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckType('off_t'): + print 'Did not find off_t typedef, assuming int' + conf.env.Append(CCFLAGS = '-Doff_t=int') + env = conf.Finish() + </programlisting> + + <para> + + You can also add a string that will be + placed at the beginning of the test file + that will be used to check for the &typedef;. + This provide a way to specify + files that must be included to find the &typedef;: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckType('off_t', '#include <sys/types.h>\n'): + print 'Did not find off_t typedef, assuming int' + conf.env.Append(CCFLAGS = '-Doff_t=int') + env = conf.Finish() + </programlisting> + + </section> + + <section> + <title>Adding Your Own Custom Checks</title> + + <para> + + A custom check is a Python function + that checks for a certain condition to exist + on the running system, + usually using methods that &SCons; + supplies to take care of the details + of checking whether a compilation succeeds, + a link succeeds, + a program is runnable, + etc. + A simple custom check for the existence of + a specific library might look as follows: + + </para> + + <programlisting> + mylib_test_source_file = """ + #include <mylib.h> + int main(int argc, char **argv) + { + MyLibrary mylib(argc, argv); + return 0; + } + """ + + def CheckMyLibrary(context): + context.Message('Checking for MyLibrary...') + result = context.TryLink(mylib_test_source_file, '.c') + context.Result(result) + return result + </programlisting> + + <para> + + The &Message; and &Result; methods + should typically begin and end a custom check to + let the user know what's going on: + the &Message; call prints the + specified message (with no trailing newline) + and the &Result; call prints + <literal>yes</literal> if the check succeeds and + <literal>no</literal> if it doesn't. + The &TryLink; method + actually tests for whether the + specified program text + will successfully link. + + </para> + + <para> + + (Note that a custom check can modify + its check based on any arguments you + choose to pass it, + or by using or modifying the configure context environment + in the <literal>context.env</literal> attribute.) + + </para> + + <para> + + This custom check function is + then attached to the &configure_context; + by passing a dictionary + to the &Configure; call + that maps a name of the check + to the underlying function: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + </programlisting> + + <para> + + You'll typically want to make + the check and the function name the same, + as we've done here, + to avoid potential confusion. + + </para> + + <para> + + We can then put these pieces together + and actually call the <literal>CheckMyLibrary</literal> check + as follows: + + </para> + + <programlisting> + mylib_test_source_file = """ + #include <mylib.h> + int main(int argc, char **argv) + { + MyLibrary mylib(argc, argv); + return 0; + } + """ + + def CheckMyLibrary(context): + context.Message('Checking for MyLibrary... ') + result = context.TryLink(mylib_test_source_file, '.c') + context.Result(result) + return result + + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + if not conf.CheckMyLibrary(): + print 'MyLibrary is not installed!' + Exit(1) + env = conf.Finish() + + # We would then add actual calls like Program() to build + # something using the "env" construction environment. + </programlisting> + + <para> + + If MyLibrary is not installed on the system, + the output will look like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript file ... + Checking for MyLibrary... failed + MyLibrary is not installed! + </screen> + + <para> + + If MyLibrary is installed, + the output will look like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript file ... + Checking for MyLibrary... failed + scons: done reading SConscript + scons: Building targets ... + . + . + . + </screen> + + </section> + + <section> + <title>Not Configuring When Cleaning Targets</title> + + <para> + + Using multi-platform configuration + as described in the previous sections + will run the configuration commands + even when invoking + <userinput>scons -c</userinput> + to clean targets: + + </para> + + <screen> + % <userinput>scons -Q -c</userinput> + Checking for MyLibrary... yes + Removed foo.o + Removed foo + </screen> + + <para> + + Although running the platform checks + when removing targets doesn't hurt anything, + it's usually unnecessary. + You can avoid this by using the + &GetOption;(); method to + check whether the <option>-c</option> (clean) + option has been invoked on the command line: + + </para> + + <programlisting> + env = Environment() + if not env.GetOption('clean'): + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + if not conf.CheckMyLibrary(): + print 'MyLibrary is not installed!' + Exit(1) + env = conf.Finish() + </programlisting> + + <screen> + % <userinput>scons -Q -c</userinput> + Removed foo.o + Removed foo + </screen> + + </section> + + <!-- + + <section> + <title>Controlling Configuration: the &config; Option</title> + + <para> + + XXX -D, -u and -U + + </para> + + </section> + + --> diff --git a/doc/user/separate.in b/doc/user/separate.in new file mode 100644 index 0000000..edc6da8 --- /dev/null +++ b/doc/user/separate.in @@ -0,0 +1,540 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Separating source and build trees + +It's often desirable to keep any derived files from the build completely +separate from the source files. This makes it much easier to keep track of +just what is a source file, and also makes it simpler to handle B<variant> +builds, especially if you want the variant builds to co-exist. + +=head2 Separating build and source directories using the Link command + +Cons provides a simple mechanism that handles all of these requirements. The +C<Link> command is invoked as in this example: + + Link 'build' => 'src'; + +The specified directories are ``linked'' to the specified source +directory. Let's suppose that you setup a source directory, F<src>, with the +sub-directories F<world> and F<hello> below it, as in the previous +example. You could then substitute for the original build lines the +following: + + Build qw( + build/world/Conscript + build/hello/Conscript + ); + +Notice that you treat the F<Conscript> file as if it existed in the build +directory. Now if you type the same command as before, you will get the +following results: + + % cons export + Install build/world/world.h as export/include/world.h + cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o + cc -Iexport/include -c build/world/world.c -o build/world/world.o + ar r build/world/libworld.a build/world/world.o + ar: creating build/world/libworld.a + ranlib build/world/libworld.a + Install build/world/libworld.a as export/lib/libworld.a + cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld + Install build/hello/hello as export/bin/hello + +Again, Cons has taken care of the details for you. In particular, you will +notice that all the builds are done using source files and object files from +the build directory. For example, F<build/world/world.o> is compiled from +F<build/world/world.c>, and F<export/include/world.h> is installed from +F<build/world/world.h>. This is accomplished on most systems by the simple +expedient of ``hard'' linking the required files from each source directory +into the appropriate build directory. + +The links are maintained correctly by Cons, no matter what you do to the +source directory. If you modify a source file, your editor may do this ``in +place'' or it may rename it first and create a new file. In the latter case, +any hard link will be lost. Cons will detect this condition the next time +the source file is needed, and will relink it appropriately. + +You'll also notice, by the way, that B<no> changes were required to the +underlying F<Conscript> files. And we can go further, as we shall see in the +next section. + +=head2 Explicit references to the source directory + +When using the C<Link> command on some operating systems or with some +tool chains, it's sometimes useful to have a command actually use +the path name to the source directory, not the build directory. For +example, on systems that must copy, not "hard link," the F<src/> and +F<build/> copies of C<Linked> files, using the F<src/> path of a file +name might make an editor aware that a syntax error must be fixed in the +source directory, not the build directory. + +You can tell Cons that you want to use the "source path" for a file by +preceding the file name with a ``!'' (exclamation point). For example, +if we add a ``!'' to the beginning of a source file: + + Program $env "foo", "!foo.c"; # Notice initial ! on foo.c + +Cons will compile the target as follows: + + cc -c src/foo.c -o build/foo.o + cc -o build/foo build/foo.o + +Notice that Cons has compiled the program from the the F<src/foo.c> +source file. Without the initial ``!'', Cons would have compiled the +program using the F<build/foo.c> path name. + +--> + + <para> + + It's often useful to keep any built files completely + separate from the source files. + In &SCons;, this is usually done by creating one or more separate + <emphasis>variant directory trees</emphasis> + that are used to hold the built objects files, libraries, + and executable programs, etc. + for a specific flavor, or variant, of build. + &SCons; provides two ways to do this, + one through the &SConscript; function that we've already seen, + and the second through a more flexible &VariantDir; function. + + </para> + + <para> + + One historical note: the &VariantDir; function + used to be called &BuildDir;. + That name is still supported + but has been deprecated + because the &SCons; functionality + differs from the model of a "build directory" + implemented by other build systems like the GNU Autotools. + + </para> + + <section> + <title>Specifying a Variant Directory Tree as Part of an &SConscript; Call</title> + + <para> + + The most straightforward way to establish a variant directory tree + uses the fact that the usual way to + set up a build hierarchy is to have an + &SConscript; file in the source subdirectory. + If you then pass a &variant_dir; argument to the + &SConscript; function call: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + SConscript('src/SConscript', variant_dir='build') + </file> + <file name="src/SConscript"> + env = Environment() + env.Program('hello.c') + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + &SCons; will then build all of the files in + the &build; subdirectory: + + </para> + + <scons_output example="ex1"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> + + <para> + + But wait a minute--what's going on here? + &SCons; created the object file + <filename>build/hello.o</filename> + in the &build; subdirectory, + as expected. + But even though our &hello_c; file lives in the &src; subdirectory, + &SCons; has actually compiled a + <filename>build/hello.c</filename> file + to create the object file. + + </para> + + <para> + + What's happened is that &SCons; has <emphasis>duplicated</emphasis> + the &hello_c; file from the &src; subdirectory + to the &build; subdirectory, + and built the program from there. + The next section explains why &SCons; does this. + + </para> + + </section> + + <section> + <title>Why &SCons; Duplicates Source Files in a Variant Directory Tree</title> + + <para> + + &SCons; duplicates source files in variant directory trees + because it's the most straightforward way to guarantee a correct build + <emphasis>regardless of include-file directory paths, + relative references between files, + or tool support for putting files in different locations</emphasis>, + and the &SCons; philosophy is to, by default, + guarantee a correct build in all cases. + + </para> + + <para> + + The most direct reason to duplicate source files + in variant directories + is simply that some tools (mostly older versions) + are written to only build their output files + in the same directory as the source files. + In this case, the choices are either + to build the output file in the source directory + and move it to the variant directory, + or to duplicate the source files in the variant directory. + + </para> + + <para> + + Additionally, + relative references between files + can cause problems if we don't + just duplicate the hierarchy of source files + in the variant directory. + You can see this at work in + use of the C preprocessor <literal>#include</literal> + mechanism with double quotes, not angle brackets: + + </para> + + <sconstruct> + #include "file.h" + </sconstruct> + + <para> + + The <emphasis>de facto</emphasis> standard behavior + for most C compilers in this case + is to first look in the same directory + as the source file that contains the <literal>#include</literal> line, + then to look in the directories in the preprocessor search path. + Add to this that the &SCons; implementation of + support for code repositories + (described below) + means not all of the files + will be found in the same directory hierarchy, + and the simplest way to make sure + that the right include file is found + is to duplicate the source files into the variant directory, + which provides a correct build + regardless of the original location(s) of the source files. + + </para> + + <para> + + Although source-file duplication guarantees a correct build + even in these end-cases, + it <emphasis>can</emphasis> usually be safely disabled. + The next section describes + how you can disable the duplication of source files + in the variant directory. + + </para> + + </section> + + <section> + <title>Telling &SCons; to Not Duplicate Source Files in the Variant Directory Tree</title> + + <para> + + In most cases and with most tool sets, + &SCons; can place its target files in a build subdirectory + <emphasis>without</emphasis> + duplicating the source files + and everything will work just fine. + You can disable the default &SCons; behavior + by specifying <literal>duplicate=0</literal> + when you call the &SConscript; function: + + </para> + + <sconstruct> + SConscript('src/SConscript', variant_dir='build', duplicate=0) + </sconstruct> + + <para> + + When this flag is specified, + &SCons; uses the variant directory + like most people expect--that is, + the output files are placed in the variant directory + while the source files stay in the source directory: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript + hello.c + % <userinput>scons -Q</userinput> + cc -c src/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + hello + hello.o + </screen> + + </section> + + <section> + <title>The &VariantDir; Function</title> + + <para> + + Use the &VariantDir; function to establish that target + files should be built in a separate directory + from the source files: + + </para> + + <scons_example name="ex_builddir"> + <file name="SConstruct" printme="1"> + VariantDir('build', 'src') + env = Environment() + env.Program('build/hello.c') + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Note that when you're not using + an &SConscript; file in the &src; subdirectory, + you must actually specify that + the program must be built from + the <filename>build/hello.c</filename> + file that &SCons; will duplicate in the + &build; subdirectory. + + </para> + + <para> + + When using the &VariantDir; function directly, + &SCons; still duplicates the source files + in the variant directory by default: + + </para> + + <scons_output example="ex_builddir"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> + + <para> + + You can specify the same <literal>duplicate=0</literal> argument + that you can specify for an &SConscript; call: + + </para> + + <scons_example name="ex_duplicate_0"> + <file name="SConstruct" printme="1"> + VariantDir('build', 'src', duplicate=0) + env = Environment() + env.Program('build/hello.c') + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + In which case &SCons; + will disable duplication of the source files: + + </para> + + <scons_output example="ex_duplicate_0"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Using &VariantDir; With an &SConscript; File</title> + + <para> + + Even when using the &VariantDir; function, + it's much more natural to use it with + a subsidiary &SConscript; file. + For example, if the + <filename>src/SConscript</filename> + looks like this: + + </para> + + <scons_example name="example_builddir_sconscript"> + <file name="SConstruct"> + VariantDir('build', 'src') + SConscript('build/SConscript') + </file> + <file name="src/SConscript" printme="1"> + env = Environment() + env.Program('hello.c') + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Then our &SConstruct; file could look like: + + </para> + + <scons_example_file example="example_builddir_sconscript" name="SConstruct"> + </scons_example_file> + + <para> + + Yielding the following output: + + </para> + + <scons_output example="example_builddir_sconscript"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> + + <para> + + Notice that this is completely equivalent + to the use of &SConscript; that we + learned about in the previous section. + + </para> + + </section> + + <section> + <title>Using &Glob; with &VariantDir;</title> + + <para> + + The &Glob; file name pattern matching function + works just as usual when using &VariantDir;. + For example, if the + <filename>src/SConscript</filename> + looks like this: + + </para> + + <scons_example name="example_glob_builddir_sconscript"> + <file name="SConstruct"> + VariantDir('build', 'src') + SConscript('build/SConscript') + </file> + <file name="src/SConscript" printme="1"> + env = Environment() + env.Program('hello', Glob('*.c')) + </file> + <file name="src/f1.c"> + #include "f2.h" + int main() { printf(f2()); } + </file> + <file name="src/f2.c"> + const char * f2() { return("Hello, world!\n"); } + </file> + <file name="src/f2.h"> + const char * f2(); + </file> + </scons_example> + + <para> + + Then with the same &SConstruct; file as in the previous section, + and source files <filename>f1.c</filename> + and <filename>f2.c</filename> in src, + we would see the following output: + + </para> + + <scons_output example="example_glob_builddir_sconscript"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> + + <para> + + The &Glob; function returns Nodes in the + <filename>build/</filename> tree, as you'd expect. + + </para> + + </section> + + <!-- + + <section> + <title>Why You'd Want to Call &VariantDir; Instead of &SConscript;</title> + + <para> + + XXX why call VariantDir() instead of SConscript(variant_dir=) + + </para> + + </section> + + --> diff --git a/doc/user/separate.xml b/doc/user/separate.xml new file mode 100644 index 0000000..fd5bdf0 --- /dev/null +++ b/doc/user/separate.xml @@ -0,0 +1,520 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Separating source and build trees + +It's often desirable to keep any derived files from the build completely +separate from the source files. This makes it much easier to keep track of +just what is a source file, and also makes it simpler to handle B<variant> +builds, especially if you want the variant builds to co-exist. + +=head2 Separating build and source directories using the Link command + +Cons provides a simple mechanism that handles all of these requirements. The +C<Link> command is invoked as in this example: + + Link 'build' => 'src'; + +The specified directories are ``linked'' to the specified source +directory. Let's suppose that you setup a source directory, F<src>, with the +sub-directories F<world> and F<hello> below it, as in the previous +example. You could then substitute for the original build lines the +following: + + Build qw( + build/world/Conscript + build/hello/Conscript + ); + +Notice that you treat the F<Conscript> file as if it existed in the build +directory. Now if you type the same command as before, you will get the +following results: + + % cons export + Install build/world/world.h as export/include/world.h + cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o + cc -Iexport/include -c build/world/world.c -o build/world/world.o + ar r build/world/libworld.a build/world/world.o + ar: creating build/world/libworld.a + ranlib build/world/libworld.a + Install build/world/libworld.a as export/lib/libworld.a + cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld + Install build/hello/hello as export/bin/hello + +Again, Cons has taken care of the details for you. In particular, you will +notice that all the builds are done using source files and object files from +the build directory. For example, F<build/world/world.o> is compiled from +F<build/world/world.c>, and F<export/include/world.h> is installed from +F<build/world/world.h>. This is accomplished on most systems by the simple +expedient of ``hard'' linking the required files from each source directory +into the appropriate build directory. + +The links are maintained correctly by Cons, no matter what you do to the +source directory. If you modify a source file, your editor may do this ``in +place'' or it may rename it first and create a new file. In the latter case, +any hard link will be lost. Cons will detect this condition the next time +the source file is needed, and will relink it appropriately. + +You'll also notice, by the way, that B<no> changes were required to the +underlying F<Conscript> files. And we can go further, as we shall see in the +next section. + +=head2 Explicit references to the source directory + +When using the C<Link> command on some operating systems or with some +tool chains, it's sometimes useful to have a command actually use +the path name to the source directory, not the build directory. For +example, on systems that must copy, not "hard link," the F<src/> and +F<build/> copies of C<Linked> files, using the F<src/> path of a file +name might make an editor aware that a syntax error must be fixed in the +source directory, not the build directory. + +You can tell Cons that you want to use the "source path" for a file by +preceding the file name with a ``!'' (exclamation point). For example, +if we add a ``!'' to the beginning of a source file: + + Program $env "foo", "!foo.c"; # Notice initial ! on foo.c + +Cons will compile the target as follows: + + cc -c src/foo.c -o build/foo.o + cc -o build/foo build/foo.o + +Notice that Cons has compiled the program from the the F<src/foo.c> +source file. Without the initial ``!'', Cons would have compiled the +program using the F<build/foo.c> path name. + +--> + + <para> + + It's often useful to keep any built files completely + separate from the source files. + In &SCons;, this is usually done by creating one or more separate + <emphasis>variant directory trees</emphasis> + that are used to hold the built objects files, libraries, + and executable programs, etc. + for a specific flavor, or variant, of build. + &SCons; provides two ways to do this, + one through the &SConscript; function that we've already seen, + and the second through a more flexible &VariantDir; function. + + </para> + + <para> + + One historical note: the &VariantDir; function + used to be called &BuildDir;. + That name is still supported + but has been deprecated + because the &SCons; functionality + differs from the model of a "build directory" + implemented by other build systems like the GNU Autotools. + + </para> + + <section> + <title>Specifying a Variant Directory Tree as Part of an &SConscript; Call</title> + + <para> + + The most straightforward way to establish a variant directory tree + uses the fact that the usual way to + set up a build hierarchy is to have an + &SConscript; file in the source subdirectory. + If you then pass a &variant_dir; argument to the + &SConscript; function call: + + </para> + + <programlisting> + SConscript('src/SConscript', variant_dir='build') + </programlisting> + + <para> + + &SCons; will then build all of the files in + the &build; subdirectory: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript hello.c + % <userinput>scons -Q</userinput> + cc -o build/hello.o -c build/hello.c + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + SConscript hello hello.c hello.o + </screen> + + <para> + + But wait a minute--what's going on here? + &SCons; created the object file + <filename>build/hello.o</filename> + in the &build; subdirectory, + as expected. + But even though our &hello_c; file lives in the &src; subdirectory, + &SCons; has actually compiled a + <filename>build/hello.c</filename> file + to create the object file. + + </para> + + <para> + + What's happened is that &SCons; has <emphasis>duplicated</emphasis> + the &hello_c; file from the &src; subdirectory + to the &build; subdirectory, + and built the program from there. + The next section explains why &SCons; does this. + + </para> + + </section> + + <section> + <title>Why &SCons; Duplicates Source Files in a Variant Directory Tree</title> + + <para> + + &SCons; duplicates source files in variant directory trees + because it's the most straightforward way to guarantee a correct build + <emphasis>regardless of include-file directory paths, + relative references between files, + or tool support for putting files in different locations</emphasis>, + and the &SCons; philosophy is to, by default, + guarantee a correct build in all cases. + + </para> + + <para> + + The most direct reason to duplicate source files + in variant directories + is simply that some tools (mostly older versions) + are written to only build their output files + in the same directory as the source files. + In this case, the choices are either + to build the output file in the source directory + and move it to the variant directory, + or to duplicate the source files in the variant directory. + + </para> + + <para> + + Additionally, + relative references between files + can cause problems if we don't + just duplicate the hierarchy of source files + in the variant directory. + You can see this at work in + use of the C preprocessor <literal>#include</literal> + mechanism with double quotes, not angle brackets: + + </para> + + <programlisting> + #include "file.h" + </programlisting> + + <para> + + The <emphasis>de facto</emphasis> standard behavior + for most C compilers in this case + is to first look in the same directory + as the source file that contains the <literal>#include</literal> line, + then to look in the directories in the preprocessor search path. + Add to this that the &SCons; implementation of + support for code repositories + (described below) + means not all of the files + will be found in the same directory hierarchy, + and the simplest way to make sure + that the right include file is found + is to duplicate the source files into the variant directory, + which provides a correct build + regardless of the original location(s) of the source files. + + </para> + + <para> + + Although source-file duplication guarantees a correct build + even in these end-cases, + it <emphasis>can</emphasis> usually be safely disabled. + The next section describes + how you can disable the duplication of source files + in the variant directory. + + </para> + + </section> + + <section> + <title>Telling &SCons; to Not Duplicate Source Files in the Variant Directory Tree</title> + + <para> + + In most cases and with most tool sets, + &SCons; can place its target files in a build subdirectory + <emphasis>without</emphasis> + duplicating the source files + and everything will work just fine. + You can disable the default &SCons; behavior + by specifying <literal>duplicate=0</literal> + when you call the &SConscript; function: + + </para> + + <programlisting> + SConscript('src/SConscript', variant_dir='build', duplicate=0) + </programlisting> + + <para> + + When this flag is specified, + &SCons; uses the variant directory + like most people expect--that is, + the output files are placed in the variant directory + while the source files stay in the source directory: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript + hello.c + % <userinput>scons -Q</userinput> + cc -c src/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + hello + hello.o + </screen> + + </section> + + <section> + <title>The &VariantDir; Function</title> + + <para> + + Use the &VariantDir; function to establish that target + files should be built in a separate directory + from the source files: + + </para> + + <programlisting> + VariantDir('build', 'src') + env = Environment() + env.Program('build/hello.c') + </programlisting> + + <para> + + Note that when you're not using + an &SConscript; file in the &src; subdirectory, + you must actually specify that + the program must be built from + the <filename>build/hello.c</filename> + file that &SCons; will duplicate in the + &build; subdirectory. + + </para> + + <para> + + When using the &VariantDir; function directly, + &SCons; still duplicates the source files + in the variant directory by default: + + </para> + + <screen> + % <userinput>ls src</userinput> + hello.c + % <userinput>scons -Q</userinput> + cc -o build/hello.o -c build/hello.c + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + hello hello.c hello.o + </screen> + + <para> + + You can specify the same <literal>duplicate=0</literal> argument + that you can specify for an &SConscript; call: + + </para> + + <programlisting> + VariantDir('build', 'src', duplicate=0) + env = Environment() + env.Program('build/hello.c') + </programlisting> + + <para> + + In which case &SCons; + will disable duplication of the source files: + + </para> + + <screen> + % <userinput>ls src</userinput> + hello.c + % <userinput>scons -Q</userinput> + cc -o build/hello.o -c src/hello.c + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + hello hello.o + </screen> + + </section> + + <section> + <title>Using &VariantDir; With an &SConscript; File</title> + + <para> + + Even when using the &VariantDir; function, + it's much more natural to use it with + a subsidiary &SConscript; file. + For example, if the + <filename>src/SConscript</filename> + looks like this: + + </para> + + <programlisting> + env = Environment() + env.Program('hello.c') + </programlisting> + + <para> + + Then our &SConstruct; file could look like: + + </para> + + + <programlisting> + VariantDir('build', 'src') + SConscript('build/SConscript') + </programlisting> + + <para> + + Yielding the following output: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript hello.c + % <userinput>scons -Q</userinput> + cc -o build/hello.o -c build/hello.c + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + SConscript hello hello.c hello.o + </screen> + + <para> + + Notice that this is completely equivalent + to the use of &SConscript; that we + learned about in the previous section. + + </para> + + </section> + + <section> + <title>Using &Glob; with &VariantDir;</title> + + <para> + + The &Glob; file name pattern matching function + works just as usual when using &VariantDir;. + For example, if the + <filename>src/SConscript</filename> + looks like this: + + </para> + + <programlisting> + env = Environment() + env.Program('hello', Glob('*.c')) + </programlisting> + + <para> + + Then with the same &SConstruct; file as in the previous section, + and source files <filename>f1.c</filename> + and <filename>f2.c</filename> in src, + we would see the following output: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript f1.c f2.c f2.h + % <userinput>scons -Q</userinput> + cc -o build/f1.o -c build/f1.c + cc -o build/f2.o -c build/f2.c + cc -o build/hello build/f1.o build/f2.o + % <userinput>ls build</userinput> + SConscript f1.c f1.o f2.c f2.h f2.o hello + </screen> + + <para> + + The &Glob; function returns Nodes in the + <filename>build/</filename> tree, as you'd expect. + + </para> + + </section> + + <!-- + + <section> + <title>Why You'd Want to Call &VariantDir; Instead of &SConscript;</title> + + <para> + + XXX why call VariantDir() instead of SConscript(variant_dir=) + + </para> + + </section> + + --> diff --git a/doc/user/sideeffect.in b/doc/user/sideeffect.in new file mode 100644 index 0000000..58c7306 --- /dev/null +++ b/doc/user/sideeffect.in @@ -0,0 +1,216 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <!-- + + <para> + + If &SCons; is unaware that a build step produces an extra file, + the &SideEffect; method can be used to identify it, + so that the file can be used as a dependency in subsequent build steps. + However, the primary use for the &SideEffect; method + is to prevent two build steps from simultaneously modifying the same file. + + </para> + + TODO: currently doesn't work due to issue #2154: + http://scons.tigris.org/issues/show_bug.cgi?id=2154 + + <para> + + If more than one build step creates or manipulates the same file, + it can cause unpleasant results if both build steps are run at the same time. + The shared file is declared as a side-effect of building the primary targets + and &SCons; will prevent the two build steps from running in parallel. + + </para> + + <para> + + In this example, the <filename>SConscript</filename> uses + &SideEffect; to inform &SCons; about the additional output file. + + </para> + + <scons_example name="SideEffectSimple"> + <file name="SConstruct" printme="1"> + env = Environment() + f2 = env.Command('file2', 'log', Copy('$TARGET', '$SOURCE')) + f1 = env.Command('file1', [], + 'echo >$TARGET data1; echo >log updated file1')) + env.SideEffect('log', env.Command('file1', [], + 'echo >$TARGET data1; echo >log updated file1')) + </file> + </scons_example> + + <para> + + Even when run in parallel mode, &SCons; will run the two steps in order: + + </para> + + <scons_output example="SideEffectSimple"> + <scons_output_command>scons -Q --jobs=2</scons_output_command> + </scons_output> + + --> + + <para> + + Sometimes a program the you need to call + to build a target file + will also update another file, + such as a log file describing what the program + does while building the target. + For example, we the folowing configuration + would have &SCons; invoke a hypothetical + script named <application>build</application> + (in the local directory) + with command-line arguments that write + log information to a common + <filename>logfile.txt</filename> file: + + </para> + + <screen> + env = Environment() + env.Command('file1.out', 'file.in', + './build --log logfile.txt $SOURCE $TARGET') + env.Command('file2.out', 'file.in', + './build --log logfile.txt $SOURCE $TARGET') + <screen> + + <para> + + This can cause problems when running + the build in parallel if + &SCons; decides to update both targets + by running both program invocations at the same time. + The multiple program invocations + may interfere with each other + writing to the common log file, + leading at best to intermixed output in the log file, + and at worst to an actual failed build + (on a system like Windows, for example, + where only one process at a time can open the log file for writing). + + </para> + + <para> + + We can make sure that &SCons; does not + run these <application>build</application> + commands at the same time + by using the &SideEffect; function + to specify that updating + the <filename>logfile.txt</filename> file + is a side effect of building the specified + <filename>file1</filename> + and + <filename>file2</filename> + target files: + + </para> + + <scons_example name="SideEffectShared"> + <file name="SConstruct" printme="1"> + env = Environment() + f1 = env.Command('file1.out', 'file1.in', + './build --log logfile.txt $SOURCE $TARGET') + f2 = env.Command('file2.out', 'file2.in', + './build --log logfile.txt $SOURCE $TARGET') + env.SideEffect('logfile.txt', f1 + f2) + </file> + <file name="file1.in">file1.in</file> + <file name="file2.in">file2.in</file> + <file name="build" chmod="0755"> + cat + </file> + </scons_example> + + <para> + + </para> + + <para> + + This makes sure the the two + <application>./build</application> steps are run sequentially, + even withthe <filename>--jobs=2</filename> in the command line: + + </para> + + <scons_output example="SideEffectShared"> + <scons_output_command>scons -Q --jobs=2</scons_output_command> + </scons_output> + + <para> + + The &SideEffect; function can be called multiple + times for the same side-effect file. + Additionally, the name used as a &SideEffect; does not + even need to actually exist as a file on disk. + &SCons; will still make sure + that the relevant targets + will be executed sequentially, not in parallel: + + </para> + + <scons_example name="SideEffectParallel"> + <file name="SConstruct" printme="1"> + env = Environment() + f1 = env.Command('file1.out', [], 'echo >$TARGET data1') + env.SideEffect('not_really_updated', f1) + f2 = env.Command('file2.out', [], 'echo >$TARGET data2') + env.SideEffect('not_really_updated', f2) + </file> + </scons_example> + + <scons_output example="SideEffectParallel"> + <scons_output_command>scons -Q --jobs=2</scons_output_command> + </scons_output> + + <para> + + Note that it might be tempting to + use &SideEffect; for additional target files + that a command produces. + For example, versions the Microsoft Visual C/C++ compiler + produce a <filename>foo.ilk</filename> + alongside compiling <filename>foo.obj</filename> file. + Specifying <filename>foo.ilk</filename> as a + side-effect of <filename>foo.obj</filename> + is <emphasis>not</emphasis> a recommended use of &SideEffect;, + because &SCons; handle side-effect files + slightly differently in its analysis of the dependency graph. + When a command produces multiple output files, + they should be specified as multiple targets of + the call to the relevant builder function, + and the &SideEffect; function itself should really only be used + when it's important to ensure that commands are not executed in parallel, + such as when a "peripheral" file (such as a log file) + may actually updated by more than one command invocation. + + </para> diff --git a/doc/user/sideeffect.xml b/doc/user/sideeffect.xml new file mode 100644 index 0000000..df62eca --- /dev/null +++ b/doc/user/sideeffect.xml @@ -0,0 +1,211 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <!-- + + <para> + + If &SCons; is unaware that a build step produces an extra file, + the &SideEffect; method can be used to identify it, + so that the file can be used as a dependency in subsequent build steps. + However, the primary use for the &SideEffect; method + is to prevent two build steps from simultaneously modifying the same file. + + </para> + + TODO: currently doesn't work due to issue #2154: + http://scons.tigris.org/issues/show_bug.cgi?id=2154 + + <para> + + If more than one build step creates or manipulates the same file, + it can cause unpleasant results if both build steps are run at the same time. + The shared file is declared as a side-effect of building the primary targets + and &SCons; will prevent the two build steps from running in parallel. + + </para> + + <para> + + In this example, the <filename>SConscript</filename> uses + &SideEffect; to inform &SCons; about the additional output file. + + </para> + + <scons_example name="SideEffectSimple"> + <file name="SConstruct" printme="1"> + env = Environment() + f2 = env.Command('file2', 'log', Copy('$TARGET', '$SOURCE')) + f1 = env.Command('file1', [], + 'echo >$TARGET data1; echo >log updated file1')) + env.SideEffect('log', env.Command('file1', [], + 'echo >$TARGET data1; echo >log updated file1')) + </file> + </scons_example> + + <para> + + Even when run in parallel mode, &SCons; will run the two steps in order: + + </para> + + <scons_output example="SideEffectSimple"> + <scons_output_command>scons -Q --jobs=2</scons_output_command> + </scons_output> + + --> + + <para> + + Sometimes a program the you need to call + to build a target file + will also update another file, + such as a log file describing what the program + does while building the target. + For example, we the folowing configuration + would have &SCons; invoke a hypothetical + script named <application>build</application> + (in the local directory) + with command-line arguments that write + log information to a common + <filename>logfile.txt</filename> file: + + </para> + + <screen> + env = Environment() + env.Command('file1.out', 'file.in', + './build --log logfile.txt $SOURCE $TARGET') + env.Command('file2.out', 'file.in', + './build --log logfile.txt $SOURCE $TARGET') + <screen> + + <para> + + This can cause problems when running + the build in parallel if + &SCons; decides to update both targets + by running both program invocations at the same time. + The multiple program invocations + may interfere with each other + writing to the common log file, + leading at best to intermixed output in the log file, + and at worst to an actual failed build + (on a system like Windows, for example, + where only one process at a time can open the log file for writing). + + </para> + + <para> + + We can make sure that &SCons; does not + run these <application>build</application> + commands at the same time + by using the &SideEffect; function + to specify that updating + the <filename>logfile.txt</filename> file + is a side effect of building the specified + <filename>file1</filename> + and + <filename>file2</filename> + target files: + + </para> + + <programlisting> + env = Environment() + f1 = env.Command('file1.out', 'file1.in', + './build --log logfile.txt $SOURCE $TARGET') + f2 = env.Command('file2.out', 'file2.in', + './build --log logfile.txt $SOURCE $TARGET') + env.SideEffect('logfile.txt', f1 + f2) + </programlisting> + + <para> + + </para> + + <para> + + This makes sure the the two + <application>./build</application> steps are run sequentially, + even withthe <filename>--jobs=2</filename> in the command line: + + </para> + + <screen> + % <userinput>scons -Q --jobs=2</userinput> + ./build --log logfile.txt file1.in file1.out + ./build --log logfile.txt file2.in file2.out + </screen> + + <para> + + The &SideEffect; function can be called multiple + times for the same side-effect file. + Additionally, the name used as a &SideEffect; does not + even need to actually exist as a file on disk. + &SCons; will still make sure + that the relevant targets + will be executed sequentially, not in parallel: + + </para> + + <programlisting> + env = Environment() + f1 = env.Command('file1.out', [], 'echo >$TARGET data1') + env.SideEffect('not_really_updated', f1) + f2 = env.Command('file2.out', [], 'echo >$TARGET data2') + env.SideEffect('not_really_updated', f2) + </programlisting> + + <screen> + % <userinput>scons -Q --jobs=2</userinput> + echo > file1.out data1 + echo > file2.out data2 + </screen> + + <para> + + Note that it might be tempting to + use &SideEffect; for additional target files + that a command produces. + For example, versions the Microsoft Visual C/C++ compiler + produce a <filename>foo.ilk</filename> + alongside compiling <filename>foo.obj</filename> file. + Specifying <filename>foo.ilk</filename> as a + side-effect of <filename>foo.obj</filename> + is <emphasis>not</emphasis> a recommended use of &SideEffect;, + because &SCons; handle side-effect files + slightly differently in its analysis of the dependency graph. + When a command produces multiple output files, + they should be specified as multiple targets of + the call to the relevant builder function, + and the &SideEffect; function itself should really only be used + when it's important to ensure that commands are not executed in parallel, + such as when a "peripheral" file (such as a log file) + may actually updated by more than one command invocation. + + </para> diff --git a/doc/user/simple.in b/doc/user/simple.in new file mode 100644 index 0000000..4d42934 --- /dev/null +++ b/doc/user/simple.in @@ -0,0 +1,517 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + In this chapter, + you will see several examples of + very simple build configurations using &SCons;, + which will demonstrate how easy + it is to use &SCons; to + build programs from several different programming languages + on different types of systems. + + </para> + + <section> + <title>Building Simple C / C++ Programs</title> + + <para> + + Here's the famous "Hello, World!" program in C: + + </para> + + <programlisting> + int + main() + { + printf("Hello, world!\n"); + } + </programlisting> + + <para> + + And here's how to build it using &SCons;. + Enter the following into a file named &SConstruct;: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + Program('hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + This minimal configuration file gives + &SCons; two pieces of information: + what you want to build + (an executable program), + and the input file from + which you want it built + (the <filename>hello.c</filename> file). + &b-link-Program; is a <firstterm>builder_method</firstterm>, + a Python call that tells &SCons; that you want to build an + executable program. + + </para> + + <para> + + That's it. Now run the &scons; command to build the program. + On a POSIX-compliant system like Linux or UNIX, + you'll see something like: + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + On a Windows system with the Microsoft Visual C++ compiler, + you'll see something like: + + </para> + + <scons_output example="ex1" os="win32"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + First, notice that you only need + to specify the name of the source file, + and that &SCons; correctly deduces the names of + the object and executable files to be built + from the base of the source file name. + + </para> + + <para> + + Second, notice that the same input &SConstruct; file, + without any changes, + generates the correct output file names on both systems: + <filename>hello.o</filename> and <filename>hello</filename> + on POSIX systems, + <filename>hello.obj</filename> and <filename>hello.exe</filename> + on Windows systems. + This is a simple example of how &SCons; + makes it extremely easy to + write portable software builds. + + </para> + + <para> + + (Note that we won't provide duplicate side-by-side + POSIX and Windows output for all of the examples in this guide; + just keep in mind that, unless otherwise specified, + any of the examples should work equally well on both types of systems.) + + </para> + + </section> + + <section> + <title>Building Object Files</title> + + <para> + + The &b-link-Program; builder method is only one of + many builder methods that &SCons; provides + to build different types of files. + Another is the &b-link-Object; builder method, + which tells &SCons; to build an object file + from the specified source file: + + </para> + + <scons_example name="Object"> + <file name="SConstruct" printme="1"> + Object('hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Now when you run the &scons; command to build the program, + it will build just the &hello_o; object file on a POSIX system: + + </para> + + <scons_output example="Object" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + And just the &hello_obj; object file + on a Windows system (with the Microsoft Visual C++ compiler): + + </para> + + <scons_output example="Object" os="win32"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Simple Java Builds</title> + + <para> + + &SCons; also makes building with Java extremely easy. + Unlike the &b-link-Program; and &b-link-Object; builder methods, + however, the &b-link-Java; builder method + requires that you specify + the name of a destination directory in which + you want the class files placed, + followed by the source directory + in which the <filename>.java</filename> files live: + + </para> + + <scons_example name="java"> + <file name="SConstruct" printme="1"> + Java('classes', 'src') + </file> + <file name="src/hello.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> + + <para> + + If the <filename>src</filename> directory + contains a single <filename>hello.java</filename> file, + then the output from running the &scons; command + would look something like this + (on a POSIX system): + + </para> + + <scons_output example="java" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + We'll cover Java builds in more detail, + including building Java archive (<filename>.jar</filename>) + and other types of file, + in <xref linkend="chap-java"></xref>. + + </para> + + </section> + + <section> + <title>Cleaning Up After a Build</title> + + <para> + + When using &SCons;, it is unnecessary to add special + commands or target names to clean up after a build. + Instead, you simply use the + <literal>-c</literal> or <literal>--clean</literal> + option when you invoke &SCons;, + and &SCons; removes the appropriate built files. + So if we build our example above + and then invoke <literal>scons -c</literal> + afterwards, the output on POSIX looks like: + + </para> + + <scons_example name="clean"> + <file name="SConstruct"> + Program('hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="clean" os="posix"> + <scons_output_command>scons</scons_output_command> + <scons_output_command>scons -c</scons_output_command> + </scons_output> + + <para> + + And the output on Windows looks like: + + </para> + + <scons_output example="clean" os="win32"> + <scons_output_command>scons</scons_output_command> + <scons_output_command>scons -c</scons_output_command> + </scons_output> + + <para> + + Notice that &SCons; changes its output to tell you that it + is <literal>Cleaning targets ...</literal> and + <literal>done cleaning targets.</literal> + + </para> + + </section> + + <section> + <title>The &SConstruct; File</title> + + <para> + + If you're used to build systems like &Make; + you've already figured out that the &SConstruct; file + is the &SCons; equivalent of a &Makefile;. + That is, the &SConstruct; file is the input file + that &SCons; reads to control the build. + + </para> + + <section> + <title>&SConstruct; Files Are Python Scripts</title> + + <para> + + There is, however, an important difference between + an &SConstruct; file and a &Makefile;: + the &SConstruct; file is actually a Python script. + If you're not already familiar with Python, don't worry. + This User's Guide will introduce you step-by-step + to the relatively small amount of Python you'll + need to know to be able to use &SCons; effectively. + And Python is very easy to learn. + + </para> + + <para> + + One aspect of using Python as the + scripting language is that you can put comments + in your &SConstruct; file using Python's commenting convention; + that is, everything between a '#' and the end of the line + will be ignored: + + </para> + + <programlisting> + # Arrange to build the "hello" program. + Program('hello.c') # "hello.c" is the source file. + </programlisting> + + <para> + + You'll see throughout the remainder of this Guide + that being able to use the power of a + real scripting language + can greatly simplify the solutions + to complex requirements of real-world builds. + + </para> + + </section> + + <section> + <title>&SCons; Functions Are Order-Independent</title> + + <para> + + One important way in which the &SConstruct; + file is not exactly like a normal Python script, + and is more like a &Makefile, + is that the order in which + the &SCons; functions are called in + the &SConstruct; file + does <emphasis>not</emphasis> + affect the order in which &SCons; + actually builds the programs and object files + you want it to build.<footnote> + <para>In programming parlance, + the &SConstruct; file is + <emphasis>declarative</emphasis>, + meaning you tell &SCons; what you want done + and let it figure out the order in which to do it, + rather than strictly <emphasis>imperative</emphasis>, + where you specify explicitly the order in + which to do things. + </para> + </footnote> + In other words, when you call the &b-link-Program; builder + (or any other builder method), + you're not telling &SCons; to build + the program at the instant the builder method is called. + Instead, you're telling &SCons; to build the program + that you want, for example, + a program built from a file named &hello_c;, + and it's up to &SCons; to build that program + (and any other files) whenever it's necessary. + (We'll learn more about how + &SCons; decides when building or rebuilding a file + is necessary in <xref linkend="chap-depends"></xref>, below.) + + </para> + + <para> + + &SCons; reflects this distinction between + <emphasis>calling a builder method like</emphasis> &b-Program; + and <emphasis>actually building the program</emphasis> + by printing the status messages that indicate + when it's "just reading" the &SConstruct; file, + and when it's actually building the target files. + This is to make it clear when &SCons; is + executing the Python statements that make up the &SConstruct; file, + and when &SCons; is actually executing the + commands or other actions to + build the necessary files. + + </para> + + <para> + + Let's clarify this with an example. + Python has a <literal>print</literal> statement that + prints a string of characters to the screen. + If we put <literal>print</literal> statements around + our calls to the &b-Program; builder method: + + </para> + + <scons_example name="declarative"> + <file name="SConstruct" printme="1"> + print "Calling Program('hello.c')" + Program('hello.c') + print "Calling Program('goodbye.c')" + Program('goodbye.c') + print "Finished calling Program()" + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> + + <para> + + Then when we execute &SCons;, + we see the output from the <literal>print</literal> + statements in between the messages about + reading the &SConscript; files, + indicating that that is when the + Python statements are being executed: + + </para> + + <scons_output example="declarative" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + Notice also that &SCons; built the &goodbye; program first, + even though the "reading &SConscript" output + shows that we called <literal>Program('hello.c')</literal> + first in the &SConstruct; file. + + </para> + + </section> + + </section> + + <section> + <title>Making the &SCons; Output Less Verbose</title> + + <para> + + You've already seen how &SCons; prints + some messages about what it's doing, + surrounding the actual commands used to build the software: + + </para> + + <scons_output example="ex1" os="win32"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + These messages emphasize the + order in which &SCons; does its work: + all of the configuration files + (generically referred to as &SConscript; files) + are read and executed first, + and only then are the target files built. + Among other benefits, these messages help to distinguish between + errors that occur while the configuration files are read, + and errors that occur while targets are being built. + + </para> + + <para> + + One drawback, of course, is that these messages clutter the output. + Fortunately, they're easily disabled by using + the &Q; option when invoking &SCons;: + + </para> + + <scons_output example="ex1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Because we want this User's Guide to focus + on what &SCons; is actually doing, + we're going to use the &Q; option + to remove these messages from the + output of all the remaining examples in this Guide. + + </para> + + </section> diff --git a/doc/user/simple.xml b/doc/user/simple.xml new file mode 100644 index 0000000..598d44b --- /dev/null +++ b/doc/user/simple.xml @@ -0,0 +1,587 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + In this chapter, + you will see several examples of + very simple build configurations using &SCons;, + which will demonstrate how easy + it is to use &SCons; to + build programs from several different programming languages + on different types of systems. + + </para> + + <section> + <title>Building Simple C / C++ Programs</title> + + <para> + + Here's the famous "Hello, World!" program in C: + + </para> + + <programlisting> + int + main() + { + printf("Hello, world!\n"); + } + </programlisting> + + <para> + + And here's how to build it using &SCons;. + Enter the following into a file named &SConstruct;: + + </para> + + <programlisting> + Program('hello.c') + </programlisting> + + <para> + + This minimal configuration file gives + &SCons; two pieces of information: + what you want to build + (an executable program), + and the input file from + which you want it built + (the <filename>hello.c</filename> file). + &b-link-Program; is a <firstterm>builder_method</firstterm>, + a Python call that tells &SCons; that you want to build an + executable program. + + </para> + + <para> + + That's it. Now run the &scons; command to build the program. + On a POSIX-compliant system like Linux or UNIX, + you'll see something like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + cc -o hello.o -c hello.c + cc -o hello hello.o + scons: done building targets. + </screen> + + <para> + + On a Windows system with the Microsoft Visual C++ compiler, + you'll see something like: + + </para> + + <screen> + C:\><userinput>scons</userinput> + scons: Reading SConscript files ... + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + scons: done reading SConscript files. + scons: Building targets ... + cl /Fohello.obj /c hello.c /nologo + link /nologo /OUT:hello.exe hello.obj + scons: done building targets. + </screen> + + <para> + + First, notice that you only need + to specify the name of the source file, + and that &SCons; correctly deduces the names of + the object and executable files to be built + from the base of the source file name. + + </para> + + <para> + + Second, notice that the same input &SConstruct; file, + without any changes, + generates the correct output file names on both systems: + <filename>hello.o</filename> and <filename>hello</filename> + on POSIX systems, + <filename>hello.obj</filename> and <filename>hello.exe</filename> + on Windows systems. + This is a simple example of how &SCons; + makes it extremely easy to + write portable software builds. + + </para> + + <para> + + (Note that we won't provide duplicate side-by-side + POSIX and Windows output for all of the examples in this guide; + just keep in mind that, unless otherwise specified, + any of the examples should work equally well on both types of systems.) + + </para> + + </section> + + <section> + <title>Building Object Files</title> + + <para> + + The &b-link-Program; builder method is only one of + many builder methods that &SCons; provides + to build different types of files. + Another is the &b-link-Object; builder method, + which tells &SCons; to build an object file + from the specified source file: + + </para> + + <programlisting> + Object('hello.c') + </programlisting> + + <para> + + Now when you run the &scons; command to build the program, + it will build just the &hello_o; object file on a POSIX system: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + cc -o hello.o -c hello.c + scons: done building targets. + </screen> + + <para> + + And just the &hello_obj; object file + on a Windows system (with the Microsoft Visual C++ compiler): + + </para> + + <screen> + C:\><userinput>scons</userinput> + scons: Reading SConscript files ... + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + scons: done reading SConscript files. + scons: Building targets ... + cl /Fohello.obj /c hello.c /nologo + scons: done building targets. + </screen> + + </section> + + <section> + <title>Simple Java Builds</title> + + <para> + + &SCons; also makes building with Java extremely easy. + Unlike the &b-link-Program; and &b-link-Object; builder methods, + however, the &b-link-Java; builder method + requires that you specify + the name of a destination directory in which + you want the class files placed, + followed by the source directory + in which the <filename>.java</filename> files live: + + </para> + + <programlisting> + Java('classes', 'src') + </programlisting> + + <para> + + If the <filename>src</filename> directory + contains a single <filename>hello.java</filename> file, + then the output from running the &scons; command + would look something like this + (on a POSIX system): + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + javac -d classes -sourcepath src src/hello.java + scons: done building targets. + </screen> + + <para> + + We'll cover Java builds in more detail, + including building Java archive (<filename>.jar</filename>) + and other types of file, + in <xref linkend="chap-java"></xref>. + + </para> + + </section> + + <section> + <title>Cleaning Up After a Build</title> + + <para> + + When using &SCons;, it is unnecessary to add special + commands or target names to clean up after a build. + Instead, you simply use the + <literal>-c</literal> or <literal>--clean</literal> + option when you invoke &SCons;, + and &SCons; removes the appropriate built files. + So if we build our example above + and then invoke <literal>scons -c</literal> + afterwards, the output on POSIX looks like: + + </para> + + + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + cc -o hello.o -c hello.c + cc -o hello hello.o + scons: done building targets. + % <userinput>scons -c</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Cleaning targets ... + Removed hello.o + Removed hello + scons: done cleaning targets. + </screen> + + <para> + + And the output on Windows looks like: + + </para> + + <screen> + C:\><userinput>scons</userinput> + scons: Reading SConscript files ... + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + scons: done reading SConscript files. + scons: Building targets ... + cl /Fohello.obj /c hello.c /nologo + link /nologo /OUT:hello.exe hello.obj + scons: done building targets. + C:\><userinput>scons -c</userinput> + scons: Reading SConscript files ... + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + scons: done reading SConscript files. + scons: Cleaning targets ... + Removed hello.obj + Removed hello.exe + scons: done cleaning targets. + </screen> + + <para> + + Notice that &SCons; changes its output to tell you that it + is <literal>Cleaning targets ...</literal> and + <literal>done cleaning targets.</literal> + + </para> + + </section> + + <section> + <title>The &SConstruct; File</title> + + <para> + + If you're used to build systems like &Make; + you've already figured out that the &SConstruct; file + is the &SCons; equivalent of a &Makefile;. + That is, the &SConstruct; file is the input file + that &SCons; reads to control the build. + + </para> + + <section> + <title>&SConstruct; Files Are Python Scripts</title> + + <para> + + There is, however, an important difference between + an &SConstruct; file and a &Makefile;: + the &SConstruct; file is actually a Python script. + If you're not already familiar with Python, don't worry. + This User's Guide will introduce you step-by-step + to the relatively small amount of Python you'll + need to know to be able to use &SCons; effectively. + And Python is very easy to learn. + + </para> + + <para> + + One aspect of using Python as the + scripting language is that you can put comments + in your &SConstruct; file using Python's commenting convention; + that is, everything between a '#' and the end of the line + will be ignored: + + </para> + + <programlisting> + # Arrange to build the "hello" program. + Program('hello.c') # "hello.c" is the source file. + </programlisting> + + <para> + + You'll see throughout the remainder of this Guide + that being able to use the power of a + real scripting language + can greatly simplify the solutions + to complex requirements of real-world builds. + + </para> + + </section> + + <section> + <title>&SCons; Functions Are Order-Independent</title> + + <para> + + One important way in which the &SConstruct; + file is not exactly like a normal Python script, + and is more like a &Makefile;, + is that the order in which + the &SCons; functions are called in + the &SConstruct; file + does <emphasis>not</emphasis> + affect the order in which &SCons; + actually builds the programs and object files + you want it to build.<footnote> + <para>In programming parlance, + the &SConstruct; file is + <emphasis>declarative</emphasis>, + meaning you tell &SCons; what you want done + and let it figure out the order in which to do it, + rather than strictly <emphasis>imperative</emphasis>, + where you specify explicitly the order in + which to do things. + </para> + </footnote> + In other words, when you call the &b-link-Program; builder + (or any other builder method), + you're not telling &SCons; to build + the program at the instant the builder method is called. + Instead, you're telling &SCons; to build the program + that you want, for example, + a program built from a file named &hello_c;, + and it's up to &SCons; to build that program + (and any other files) whenever it's necessary. + (We'll learn more about how + &SCons; decides when building or rebuilding a file + is necessary in <xref linkend="chap-depends"></xref>, below.) + + </para> + + <para> + + &SCons; reflects this distinction between + <emphasis>calling a builder method like</emphasis> &b-Program; + and <emphasis>actually building the program</emphasis> + by printing the status messages that indicate + when it's "just reading" the &SConstruct; file, + and when it's actually building the target files. + This is to make it clear when &SCons; is + executing the Python statements that make up the &SConstruct; file, + and when &SCons; is actually executing the + commands or other actions to + build the necessary files. + + </para> + + <para> + + Let's clarify this with an example. + Python has a <literal>print</literal> statement that + prints a string of characters to the screen. + If we put <literal>print</literal> statements around + our calls to the &b-Program; builder method: + + </para> + + <programlisting> + print "Calling Program('hello.c')" + Program('hello.c') + print "Calling Program('goodbye.c')" + Program('goodbye.c') + print "Finished calling Program()" + </programlisting> + + <para> + + Then when we execute &SCons;, + we see the output from the <literal>print</literal> + statements in between the messages about + reading the &SConscript; files, + indicating that that is when the + Python statements are being executed: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + Calling Program('hello.c') + Calling Program('goodbye.c') + Finished calling Program() + scons: done reading SConscript files. + scons: Building targets ... + cc -o goodbye.o -c goodbye.c + cc -o goodbye goodbye.o + cc -o hello.o -c hello.c + cc -o hello hello.o + scons: done building targets. + </screen> + + <para> + + Notice also that &SCons; built the &goodbye; program first, + even though the "reading &SConscript;" output + shows that we called <literal>Program('hello.c')</literal> + first in the &SConstruct; file. + + </para> + + </section> + + </section> + + <section> + <title>Making the &SCons; Output Less Verbose</title> + + <para> + + You've already seen how &SCons; prints + some messages about what it's doing, + surrounding the actual commands used to build the software: + + </para> + + <screen> + C:\><userinput>scons</userinput> + scons: Reading SConscript files ... + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + scons: done reading SConscript files. + scons: Building targets ... + cl /Fohello.obj /c hello.c /nologo + link /nologo /OUT:hello.exe hello.obj + scons: done building targets. + </screen> + + <para> + + These messages emphasize the + order in which &SCons; does its work: + all of the configuration files + (generically referred to as &SConscript; files) + are read and executed first, + and only then are the target files built. + Among other benefits, these messages help to distinguish between + errors that occur while the configuration files are read, + and errors that occur while targets are being built. + + </para> + + <para> + + One drawback, of course, is that these messages clutter the output. + Fortunately, they're easily disabled by using + the &Q; option when invoking &SCons;: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fohello.obj /c hello.c /nologo + link /nologo /OUT:hello.exe hello.obj + </screen> + + <para> + + Because we want this User's Guide to focus + on what &SCons; is actually doing, + we're going to use the &Q; option + to remove these messages from the + output of all the remaining examples in this Guide. + + </para> + + </section> diff --git a/doc/user/sourcecode.in b/doc/user/sourcecode.in new file mode 100644 index 0000000..5cbbe1a --- /dev/null +++ b/doc/user/sourcecode.in @@ -0,0 +1,162 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +--> + + <para> + + XXX + + </para> + + <section> + <title>Fetching Source Code From BitKeeper</title> + + <para> + + XXX + + </para> + + <scons_example name="ex_bitkeeper"> + <file name="SConstruct" printme="1"> + env = Environment() + env.SourceCode('.', env.BitKeeper()) + env.Program('hello.c') + </file> + <file name="s.hello.c"> + s.hello.c + </file> + </scons_example> + + <scons_output example="ex_bitkeeper"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Fetching Source Code From CVS</title> + + <para> + + XXX + + </para> + + <scons_example name="ex_cvs"> + <file name="SConstruct" printme="1"> + env = Environment() + env.SourceCode('.', env.CVS('/usr/local/CVS')) + env.Program('hello.c') + </file> + </scons_example> + + <scons_output example="ex_cvs"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Fetching Source Code From RCS</title> + + <para> + + XXX + + </para> + + <scons_example name="ex_rcs"> + <file name="SConstruct" printme="1"> + env = Environment() + env.SourceCode('.', env.RCS()) + env.Program('hello.c') + </file> + <file name="hello.c,v"> + hello.c,v + </file> + </scons_example> + + <scons_output example="ex_rcs"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>Fetching Source Code From SCCS</title> + + <para> + + XXX + + </para> + + <scons_example name="ex_sccs"> + <file name="SConstruct" printme="1"> + env = Environment() + env.SourceCode('.', env.SCCS()) + env.Program('hello.c') + </file> + <file name="s.hello.c"> + s.hello.c + </file> + </scons_example> + + <scons_output example="ex_sccs"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <!-- + + <section> + <title>Fetching Source Code From Subversion</title> + + <para> + + XXX + + </para> + + <scons_example name="ex_subversion"> + <file name="SConstruct" printme="1"> + env = Environment() + env.SourceCode('.', env.Subversion('XXX')) + env.Program('hello.c') + </file> + </scons_example> + + <scons_output example="ex_subversion"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + --> diff --git a/doc/user/sourcecode.xml b/doc/user/sourcecode.xml new file mode 100644 index 0000000..aebcd20 --- /dev/null +++ b/doc/user/sourcecode.xml @@ -0,0 +1,157 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +--> + + <para> + + XXX + + </para> + + <section> + <title>Fetching Source Code From BitKeeper</title> + + <para> + + XXX + + </para> + + <programlisting> + env = Environment() + env.SourceCode('.', env.BitKeeper()) + env.Program('hello.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + bk get hello.c + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Fetching Source Code From CVS</title> + + <para> + + XXX + + </para> + + <programlisting> + env = Environment() + env.SourceCode('.', env.CVS('/usr/local/CVS')) + env.Program('hello.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + cvs -d /usr/local/CVS co hello.c + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Fetching Source Code From RCS</title> + + <para> + + XXX + + </para> + + <programlisting> + env = Environment() + env.SourceCode('.', env.RCS()) + env.Program('hello.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + co hello.c + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + </section> + + <section> + <title>Fetching Source Code From SCCS</title> + + <para> + + XXX + + </para> + + <programlisting> + env = Environment() + env.SourceCode('.', env.SCCS()) + env.Program('hello.c') + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + sccs get hello.c + cc -o hello.o -c hello.c + cc -o hello hello.o + </screen> + + </section> + + <!-- + + <section> + <title>Fetching Source Code From Subversion</title> + + <para> + + XXX + + </para> + + <scons_example name="ex_subversion"> + <file name="SConstruct" printme="1"> + env = Environment() + env.SourceCode('.', env.Subversion('XXX')) + env.Program('hello.c') + </file> + </scons_example> + + <scons_output example="ex_subversion"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + --> diff --git a/doc/user/tasks.in b/doc/user/tasks.in new file mode 100644 index 0000000..14775c8 --- /dev/null +++ b/doc/user/tasks.in @@ -0,0 +1,108 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<para> +There is a common set of simple tasks that many build configurations rely +on as they become more complex. Most build tools have special +purpose constructs for performing these tasks, but since &SConscript; +files are &Python; scripts, you can use more flexible built-in &Python; +services to perform these tasks. This appendix lists a number of these +tasks and how to implement them in &Python;. +</para> + +<example> +<title>Wildcard globbing to create a list of filenames</title> +<programlisting> +files = Glob(wildcard) +</programlisting> +</example> + +<example> +<title>Filename extension substitution</title> +<programlisting> +import os.path +filename = os.path.splitext(filename)[0]+extension +</programlisting> +</example> + +<example> +<title>Appending a path prefix to a list of filenames</title> +<programlisting> +import os.path +filenames = [os.path.join(prefix, x) for x in filenames] +</programlisting> + +<simpara>or in Python 1.5.2:</simpara> + +<programlisting> +import os.path +new_filenames = [] +for x in filenames: + new_filenames.append(os.path.join(prefix, x)) +</programlisting> +</example> + +<example> +<title>Substituting a path prefix with another one</title> +<programlisting> +if filename.find(old_prefix) == 0: + filename = filename.replace(old_prefix, new_prefix) +</programlisting> + +<simpara>or in Python 1.5.2:</simpara> + +<programlisting> +import string +if string.find(filename, old_prefix) == 0: + filename = string.replace(filename, old_prefix, new_prefix) +</programlisting> +</example> + +<example> +<title>Filtering a filename list to exclude/retain only a specific set +of extensions</title> +<programlisting> +import os.path +filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions] +</programlisting> + +<simpara>or in Python 1.5.2:</simpara> + +<programlisting> +import os.path +new_filenames = [] +for x in filenames: + if os.path.splitext(x)[1] in extensions: + new_filenames.append(x) +</programlisting> +</example> + +<example> +<title>The "backtick function": run a shell command and capture the +output</title> +<programlisting>import os +output = os.popen(command).read() +</programlisting> +</example> diff --git a/doc/user/tasks.xml b/doc/user/tasks.xml new file mode 100644 index 0000000..14775c8 --- /dev/null +++ b/doc/user/tasks.xml @@ -0,0 +1,108 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<para> +There is a common set of simple tasks that many build configurations rely +on as they become more complex. Most build tools have special +purpose constructs for performing these tasks, but since &SConscript; +files are &Python; scripts, you can use more flexible built-in &Python; +services to perform these tasks. This appendix lists a number of these +tasks and how to implement them in &Python;. +</para> + +<example> +<title>Wildcard globbing to create a list of filenames</title> +<programlisting> +files = Glob(wildcard) +</programlisting> +</example> + +<example> +<title>Filename extension substitution</title> +<programlisting> +import os.path +filename = os.path.splitext(filename)[0]+extension +</programlisting> +</example> + +<example> +<title>Appending a path prefix to a list of filenames</title> +<programlisting> +import os.path +filenames = [os.path.join(prefix, x) for x in filenames] +</programlisting> + +<simpara>or in Python 1.5.2:</simpara> + +<programlisting> +import os.path +new_filenames = [] +for x in filenames: + new_filenames.append(os.path.join(prefix, x)) +</programlisting> +</example> + +<example> +<title>Substituting a path prefix with another one</title> +<programlisting> +if filename.find(old_prefix) == 0: + filename = filename.replace(old_prefix, new_prefix) +</programlisting> + +<simpara>or in Python 1.5.2:</simpara> + +<programlisting> +import string +if string.find(filename, old_prefix) == 0: + filename = string.replace(filename, old_prefix, new_prefix) +</programlisting> +</example> + +<example> +<title>Filtering a filename list to exclude/retain only a specific set +of extensions</title> +<programlisting> +import os.path +filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions] +</programlisting> + +<simpara>or in Python 1.5.2:</simpara> + +<programlisting> +import os.path +new_filenames = [] +for x in filenames: + if os.path.splitext(x)[1] in extensions: + new_filenames.append(x) +</programlisting> +</example> + +<example> +<title>The "backtick function": run a shell command and capture the +output</title> +<programlisting>import os +output = os.popen(command).read() +</programlisting> +</example> diff --git a/doc/user/tools.in b/doc/user/tools.in new file mode 100644 index 0000000..cc0628e --- /dev/null +++ b/doc/user/tools.in @@ -0,0 +1,38 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<para> + +This appendix contains descriptions of all of the +Tools modules that are +available "out of the box" in this version of SCons. + +</para> + +<variablelist> + +&tools-gen; + +</variablelist> diff --git a/doc/user/tools.xml b/doc/user/tools.xml new file mode 100644 index 0000000..cc0628e --- /dev/null +++ b/doc/user/tools.xml @@ -0,0 +1,38 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<para> + +This appendix contains descriptions of all of the +Tools modules that are +available "out of the box" in this version of SCons. + +</para> + +<variablelist> + +&tools-gen; + +</variablelist> diff --git a/doc/user/troubleshoot.in b/doc/user/troubleshoot.in new file mode 100644 index 0000000..c729149 --- /dev/null +++ b/doc/user/troubleshoot.in @@ -0,0 +1,875 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + The experience of configuring any + software build tool to build a large code base + usually, at some point, + involves trying to figure out why + the tool is behaving a certain way, + and how to get it to behave the way you want. + &SCons; is no different. + This appendix contains a number of + different ways in which you can + get some additional insight into &SCons' behavior. + + </para> + + <para> + + Note that we're always interested in trying to + improve how you can troubleshoot configuration problems. + If you run into a problem that has + you scratching your head, + and which there just doesn't seem to be a good way to debug, + odds are pretty good that someone else will run into + the same problem, too. + If so, please let the SCons development team know + (preferably by filing a bug report + or feature request at our project pages at tigris.org) + so that we can use your feedback + to try to come up with a better way to help you, + and others, get the necessary insight into &SCons; behavior + to help identify and fix configuration issues. + + </para> + + <section> + <title>Why is That Target Being Rebuilt? the &debug-explain; Option</title> + + <para> + + Let's look at a simple example of + a misconfigured build + that causes a target to be rebuilt + every time &SCons; is run: + + </para> + + <scons_example name="explain1"> + <file name="SConstruct" printme="1"> + # Intentionally misspell the output file name in the + # command used to create the file: + Command('file.out', 'file.in', 'cp $SOURCE file.oout') + </file> + <file name="file.in"> + file.in + </file> + </scons_example> + + <para> + + (Note to Windows users: The POSIX &cp; command + copies the first file named on the command line + to the second file. + In our example, it copies the &file_in; file + to the &file_out; file.) + + </para> + + <para> + + Now if we run &SCons; multiple times on this example, + we see that it re-runs the &cp; + command every time: + + </para> + + <scons_output example="explain1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + In this example, + the underlying cause is obvious: + we've intentionally misspelled the output file name + in the &cp; command, + so the command doesn't actually + build the &file_out; file that we've told &SCons; to expect. + But if the problem weren't obvious, + it would be helpful + to specify the &debug-explain; option + on the command line + to have &SCons; tell us very specifically + why it's decided to rebuild the target: + + </para> + + <scons_output example="explain1" os="posix"> + <scons_output_command>scons -Q --debug=explain</scons_output_command> + </scons_output> + + <para> + + If this had been a more complicated example + involving a lot of build output, + having &SCons; tell us that + it's trying to rebuild the target file + because it doesn't exist + would be an important clue + that something was wrong with + the command that we invoked to build it. + + </para> + + <para> + + The &debug-explain; option also comes in handy + to help figure out what input file changed. + Given a simple configuration that builds + a program from three source files, + changing one of the source files + and rebuilding with the &debug-explain; + option shows very specifically + why &SCons; rebuilds the files that it does: + + </para> + + <scons_example name="explain2"> + <file name="SConstruct"> + Program('prog', ['file1.c', 'file2.c', 'file3.c']) + </file> + <file name="file1.c"> + file1.c + </file> + <file name="file2.c"> + file2.c + </file> + <file name="file3.c"> + file3.c + </file> + </scons_example> + + <scons_output example="explain2" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF file2.c]">edit file2.c</scons_output_command> + <scons_output_command>scons -Q --debug=explain</scons_output_command> + </scons_output> + + <para> + + This becomes even more helpful + in identifying when a file is rebuilt + due to a change in an implicit dependency, + such as an incuded <filename>.h</filename> file. + If the <filename>file1.c</filename> + and <filename>file3.c</filename> files + in our example + both included a &hello_h; file, + then changing that included file + and re-running &SCons; with the &debug-explain; option + will pinpoint that it's the change to the included file + that starts the chain of rebuilds: + + </para> + + <scons_example name="explain3"> + <file name="SConstruct"> + Program('prog', ['file1.c', 'file2.c', 'file3.c'], CPPPATH='.') + </file> + <file name="file1.c"> + #include <hello.h> + file1.c + </file> + <file name="file2.c"> + file2.c + </file> + <file name="file3.c"> + #include <hello.h> + file3.c + </file> + <file name="hello.h"> + #define string "world" + </file> + </scons_example> + + <scons_output example="explain3" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> + <scons_output_command>scons -Q --debug=explain</scons_output_command> + </scons_output> + + <para> + + (Note that the &debug-explain; option will only tell you + why &SCons; decided to rebuild necessary targets. + It does not tell you what files it examined + when deciding <emphasis>not</emphasis> + to rebuild a target file, + which is often a more valuable question to answer.) + + </para> + + </section> + + <section> + <title>What's in That Construction Environment? the &Dump; Method</title> + + <para> + + When you create a construction environment, + &SCons; populates it + with construction variables that are set up + for various compilers, linkers and utilities + that it finds on your system. + Although this is usually helpful and what you want, + it might be frustrating if &SCons; + doesn't set certain variables that you + expect to be set. + In situations like this, + it's sometimes helpful to use the + construction environment &Dump; method + to print all or some of + the construction variables. + Note that the &Dump; method + <emphasis>returns</emphasis> + the representation of the variables + in the environment + for you to print (or otherwise manipulate): + + </para> + + <scons_example name="Dump"> + <file name="SConstruct" printme="1"> + env = Environment() + print env.Dump() + </file> + </scons_example> + + <para> + + On a POSIX system with gcc installed, + this might generate: + + </para> + + <scons_output example="Dump" os="posix" tools="gcc"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + On a Windows system with Visual C++ + the output might look like: + + </para> + + <scons_output example="Dump" os="win32" tools="msvc"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + The construction environments in these examples have + actually been restricted to just gcc and Visual C++, + respectively. + In a real-life situation, + the construction environments will + likely contain a great many more variables. + Also note that we've massaged the example output above + to make the memory address of all objects a constant 0x700000. + In reality, you would see a different hexadecimal + number for each object. + + </para> + + <para> + + To make it easier to see just what you're + interested in, + the &Dump; method allows you to + specify a specific constrcution variable + that you want to disply. + For example, + it's not unusual to want to verify + the external environment used to execute build commands, + to make sure that the PATH and other + environment variables are set up the way they should be. + You can do this as follows: + + </para> + + <scons_example name="Dump_ENV"> + <file name="SConstruct" printme="1"> + env = Environment() + print env.Dump('ENV') + </file> + </scons_example> + + <para> + + Which might display the following when executed on a POSIX system: + + </para> + + <scons_output example="Dump_ENV" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + <para> + + And the following when executed on a Windows system: + + </para> + + <scons_output example="Dump_ENV" os="win32"> + <scons_output_command>scons</scons_output_command> + </scons_output> + + </section> + + <section> + + <title>What Dependencies Does &SCons; Know About? the &tree; Option</title> + + <para> + + Sometimes the best way to try to figure out what + &SCons; is doing is simply to take a look at the + dependency graph that it constructs + based on your &SConscript; files. + The <literal>--tree</literal> option + will display all or part of the + &SCons; dependency graph in an + "ASCII art" graphical format + that shows the dependency hierarchy. + + </para> + + <para> + + For example, given the following input &SConstruct; file: + + </para> + + <scons_example name="tree1"> + <file name="SConstruct" printme="1"> + env = Environment(CPPPATH = ['.']) + env.Program('prog', ['f1.c', 'f2.c', 'f3.c']) + </file> + <file name="f1.c"> + #include "inc.h" + </file> + <file name="f2.c"> + #include "inc.h" + </file> + <file name="f3.c"> + #include "inc.h" + </file> + <file name="inc.h"> + inc.h + </file> + </scons_example> + + <para> + + Running &SCons; with the <literal>--tree=all</literal> + option yields: + + </para> + + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=all</scons_output_command> + </scons_output> + + <para> + + The tree will also be printed when the + <literal>-n</literal> (no execute) option is used, + which allows you to examine the dependency graph + for a configuration without actually + rebuilding anything in the tree. + + </para> + + <para> + + The <literaL>--tree</literal> option only prints + the dependency graph for the specified targets + (or the default target(s) if none are specified on the command line). + So if you specify a target like <filename>f2.o</filename> + on the command line, + the <literaL>--tree</literal> option will only + print the dependency graph for that file: + + </para> + + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=all f2.o</scons_output_command> + </scons_output> + + <para> + + This is, of course, useful for + restricting the output from a very large + build configuration to just a + portion in which you're interested. + Multiple targets are fine, + in which case a tree will be printed + for each specified target: + + </para> + + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=all f1.o f3.o</scons_output_command> + </scons_output> + + <para> + + The <literal>status</literal> argument may be used + to tell &SCons; to print status information about + each file in the dependency graph: + + </para> + + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=status</scons_output_command> + </scons_output> + + <para> + + Note that <literal>--tree=all,status</literal> is equivalent; + the <literal>all</literal> + is assumed if only <literal>status</literal> is present. + As an alternative to <literal>all</literal>, + you can specify <literal>--tree=derived</literal> + to have &SCons; only print derived targets + in the tree output, + skipping source files + (like <filename>.c</filename> and <filename>.h</filename> files): + + </para> + + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=derived</scons_output_command> + </scons_output> + + <para> + + You can use the <literal>status</literal> + modifier with <literal>derived</literal> as well: + + </para> + + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=derived,status</scons_output_command> + </scons_output> + + <para> + + Note that the order of the <literal>--tree=</literal> + arguments doesn't matter; + <literal>--tree=status,derived</literal> is + completely equivalent. + + </para> + + <para> + + The default behavior of the <literal>--tree</literal> option + is to repeat all of the dependencies each time the library dependency + (or any other dependency file) is encountered in the tree. + If certain target files share other target files, + such as two programs that use the same library: + + </para> + + <scons_example name="tree2"> + <file name="SConstruct" printme="1"> + env = Environment(CPPPATH = ['.'], + LIBS = ['foo'], + LIBPATH = ['.']) + env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.Program('prog1.c') + env.Program('prog2.c') + </file> + <file name="prog1.c"> + #include "inc.h" + </file> + <file name="prog2.c"> + #include "inc.h" + </file> + <file name="f1.c"> + #include "inc.h" + </file> + <file name="f2.c"> + #include "inc.h" + </file> + <file name="f3.c"> + #include "inc.h" + </file> + <file name="inc.h"> + inc.h + </file> + </scons_example> + + <para> + + Then there can be a <emphasis>lot</emphasis> of repetition in the + <literal>--tree=</literal> output: + + </para> + + <scons_output example="tree2"> + <scons_output_command>scons -Q --tree=all</scons_output_command> + </scons_output> + + <para> + + In a large configuration with many internal libraries + and include files, + this can very quickly lead to huge output trees. + To help make this more manageable, + a <literal>prune</literal> modifier may + be added to the option list, + in which case &SCons; + will print the name of a target that has + already been visited during the tree-printing + in <literal>[square brackets]</literal> + as an indication that the dependencies + of the target file may be found + by looking farther up the tree: + + </para> + + <scons_output example="tree2"> + <scons_output_command>scons -Q --tree=prune</scons_output_command> + </scons_output> + + <para> + + Like the <literal>status</literal> keyword, + the <literal>prune</literal> argument by itself + is equivalent to <literal>--tree=all,prune</literal>. + + </para> + + </section> + + <section> + + <title>How is &SCons; Constructing the Command Lines It Executes? the &debug-presub; Option</title> + + <para> + + Sometimes it's useful to look at the + pre-substitution string + that &SCons; uses to generate + the command lines it executes. + This can be done with the &debug-presub; option: + + </para> + + <scons_example name="presub"> + <file name="SConstruct"> + env = Environment(CPPPATH = ['.']) + env.Program('prog', 'prog.c') + </file> + <file name="prog.c"> + prog.c + </file> + </scons_example> + + <!-- + + Have to capture output here, otherwise the - -debug=presub output + shows the Python functions from the sconsdoc.py execution wrapper + used to generate this manual, not the underlying command-line strings. + + <scons_output example="presub"> + <scons_output_command>scons -Q - -debug=presub</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q --debug=presub</userinput> + Building prog.o with action: + $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCOMCOM $SOURCES + cc -o prog.o -c -I. prog.c + Building prog with action: + $SMART_LINKCOM + cc -o prog prog.o + </screen> + + </section> + + <section> + + <title>Where is &SCons; Searching for Libraries? the &debug-findlibs; Option</title> + + <para> + + To get some insight into what library names + &SCons; is searching for, + and in which directories it is searching, + Use the <literal>--debug=findlibs</literal> option. + Given the following input &SConstruct; file: + + </para> + + <scons_example name="findlibs"> + <file name="SConstruct" printme="1"> + env = Environment(LIBPATH = ['libs1', 'libs2']) + env.Program('prog.c', LIBS=['foo', 'bar']) + </file> + <file name="prog.c"> + prog.c + </file> + <file name="libs1/libfoo.a"> + libs1/libfoo.a + </file> + <file name="libs2/libbar.a"> + libs2/libbar.a + </file> + </scons_example> + + <para> + + And the libraries <filename>libfoo.a</filename> + and <filename>libbar.a</filename> + in <filename>libs1</filename> and <filename>libs2</filename>, + respectively, + use of the <literal>--debug=findlibs</literal> option yields: + + </para> + + <scons_output example="findlibs"> + <scons_output_command>scons -Q --debug=findlibs</scons_output_command> + </scons_output> + + </section> + + <!-- + + <section> + + <title>What Implicit Dependencies Did the &SCons; Scanner find? the &debug-includes; Option</title> + + <para> + + XXX explain the - - debug=includes option + + </para> + + <scons_example name="includes"> + <file name="SConstruct" printme="1"> + env = Environment(CPPPATH = ['inc1', 'inc2']) + env.Program('prog.c') + </file> + <file name="prog.c"> + #include "file1.h" + #include "file2.h" + prog.c + </file> + <file name="inc1/file1.h"> + inc1/file1.h + </file> + <file name="inc2/file2.h"> + inc2/file2.h + </file> + </scons_example> + + <scons_output example="includes"> + <scons_output_command>scons -Q - - debug=includes prog</scons_output_command> + </scons_output> + + </section> + + --> + + <section> + + <title>Where is &SCons; Blowing Up? the &debug-stacktrace; Option</title> + + <para> + + In general, &SCons; tries to keep its error + messages short and informative. + That means we usually try to avoid showing + the stack traces that are familiar + to experienced Python programmers, + since they usually contain much more + information than is useful to most people. + + </para> + + <para> + + For example, the following &SConstruct file: + + </para> + + <scons_example name="stacktrace"> + <file name="SConstruct" printme="1"> + Program('prog.c') + </file> + </scons_example> + + <para> + + Generates the following error if the + <filename>prog.c</filename> file + does not exist: + + </para> + + <scons_output example="stacktrace"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + In this case, + the error is pretty obvious. + But if it weren't, + and you wanted to try to get more information + about the error, + the &debug-stacktrace; option + would show you exactly where in the &SCons; source code + the problem occurs: + + </para> + + <scons_output example="stacktrace"> + <scons_output_command>scons -Q --debug=stacktrace</scons_output_command> + </scons_output> + + <para> + + Of course, if you do need to dive into the &SCons; source code, + we'd like to know if, or how, + the error messages or troubleshooting options + could have been improved to avoid that. + Not everyone has the necessary time or + Python skill to dive into the source code, + and we'd like to improve &SCons; + for those people as well... + + </para> + + </section> + + <section> + + <title>How is &SCons; Making Its Decisions? the &taskmastertrace; Option</title> + + <para> + + The internal &SCons; subsystem that handles walking + the dependency graph + and controls the decision-making about what to rebuild + is the <literal>Taskmaster</literal>. + &SCons; supports a <literal>--taskmastertrace</literal> + option that tells the Taskmaster to print + information about the children (dependencies) + of the various Nodes on its walk down the graph, + which specific dependent Nodes are being evaluated, + and in what order. + + </para> + + <para> + + The <literal>--taskmastertrace</literal> option + takes as an argument the name of a file in + which to put the trace output, + with <filename>-</filename> (a single hyphen) + indicating that the trace messages + should be printed to the standard output: + + </para> + + <scons_example name="taskmastertrace"> + <file name="SConstruct" printme="1"> + env = Environment(CPPPATH = ['.']) + env.Program('prog.c') + </file> + <file name="prog.c"> + #include "inc.h" + prog.c + </file> + <file name="inc.h"> + #define STRING "one" + </file> + </scons_example> + + <scons_output example="taskmastertrace" os="posix"> + <scons_output_command>scons -Q --taskmastertrace=- prog</scons_output_command> + </scons_output> + + <para> + + The <literal>--taskmastertrace</literal> option + doesn't provide information about the actual + calculations involved in deciding if a file is up-to-date, + but it does show all of the dependencies + it knows about for each Node, + and the order in which those dependencies are evaluated. + This can be useful as an alternate way to determine + whether or not your &SCons; configuration, + or the implicit dependency scan, + has actually identified all the correct dependencies + you want it to. + + </para> + + </section> + + <!-- + + <section> + + <title>Where Are My Build Bottlenecks? the &profile; Option</title> + + <para> + + XXX explain the - - profile= option + + </para> + + </section> + + --> + + <!-- + + <section> + <title>Troubleshooting Shared Caching: the &cache-debug; Option</title> + + <para> + + XXX describe the - - cache-debug option + XXX maybe point to the caching.in chapter? + + </para> + + </section> + + --> diff --git a/doc/user/troubleshoot.xml b/doc/user/troubleshoot.xml new file mode 100644 index 0000000..6bd53f9 --- /dev/null +++ b/doc/user/troubleshoot.xml @@ -0,0 +1,1313 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + The experience of configuring any + software build tool to build a large code base + usually, at some point, + involves trying to figure out why + the tool is behaving a certain way, + and how to get it to behave the way you want. + &SCons; is no different. + This appendix contains a number of + different ways in which you can + get some additional insight into &SCons;' behavior. + + </para> + + <para> + + Note that we're always interested in trying to + improve how you can troubleshoot configuration problems. + If you run into a problem that has + you scratching your head, + and which there just doesn't seem to be a good way to debug, + odds are pretty good that someone else will run into + the same problem, too. + If so, please let the SCons development team know + (preferably by filing a bug report + or feature request at our project pages at tigris.org) + so that we can use your feedback + to try to come up with a better way to help you, + and others, get the necessary insight into &SCons; behavior + to help identify and fix configuration issues. + + </para> + + <section> + <title>Why is That Target Being Rebuilt? the &debug-explain; Option</title> + + <para> + + Let's look at a simple example of + a misconfigured build + that causes a target to be rebuilt + every time &SCons; is run: + + </para> + + <programlisting> + # Intentionally misspell the output file name in the + # command used to create the file: + Command('file.out', 'file.in', 'cp $SOURCE file.oout') + </programlisting> + + <para> + + (Note to Windows users: The POSIX &cp; command + copies the first file named on the command line + to the second file. + In our example, it copies the &file_in; file + to the &file_out; file.) + + </para> + + <para> + + Now if we run &SCons; multiple times on this example, + we see that it re-runs the &cp; + command every time: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cp file.in file.oout + % <userinput>scons -Q</userinput> + cp file.in file.oout + % <userinput>scons -Q</userinput> + cp file.in file.oout + </screen> + + <para> + + In this example, + the underlying cause is obvious: + we've intentionally misspelled the output file name + in the &cp; command, + so the command doesn't actually + build the &file_out; file that we've told &SCons; to expect. + But if the problem weren't obvious, + it would be helpful + to specify the &debug-explain; option + on the command line + to have &SCons; tell us very specifically + why it's decided to rebuild the target: + + </para> + + <screen> + % <userinput>scons -Q --debug=explain</userinput> + scons: building `file.out' because it doesn't exist + cp file.in file.oout + </screen> + + <para> + + If this had been a more complicated example + involving a lot of build output, + having &SCons; tell us that + it's trying to rebuild the target file + because it doesn't exist + would be an important clue + that something was wrong with + the command that we invoked to build it. + + </para> + + <para> + + The &debug-explain; option also comes in handy + to help figure out what input file changed. + Given a simple configuration that builds + a program from three source files, + changing one of the source files + and rebuilding with the &debug-explain; + option shows very specifically + why &SCons; rebuilds the files that it does: + + </para> + + + + <screen> + % <userinput>scons -Q</userinput> + cc -o file1.o -c file1.c + cc -o file2.o -c file2.c + cc -o file3.o -c file3.c + cc -o prog file1.o file2.o file3.o + % <userinput>edit file2.c</userinput> + [CHANGE THE CONTENTS OF file2.c] + % <userinput>scons -Q --debug=explain</userinput> + scons: rebuilding `file2.o' because `file2.c' changed + cc -o file2.o -c file2.c + scons: rebuilding `prog' because `file2.o' changed + cc -o prog file1.o file2.o file3.o + </screen> + + <para> + + This becomes even more helpful + in identifying when a file is rebuilt + due to a change in an implicit dependency, + such as an incuded <filename>.h</filename> file. + If the <filename>file1.c</filename> + and <filename>file3.c</filename> files + in our example + both included a &hello_h; file, + then changing that included file + and re-running &SCons; with the &debug-explain; option + will pinpoint that it's the change to the included file + that starts the chain of rebuilds: + + </para> + + + + <screen> + % <userinput>scons -Q</userinput> + cc -o file1.o -c -I. file1.c + cc -o file2.o -c -I. file2.c + cc -o file3.o -c -I. file3.c + cc -o prog file1.o file2.o file3.o + % <userinput>edit hello.h</userinput> + [CHANGE THE CONTENTS OF hello.h] + % <userinput>scons -Q --debug=explain</userinput> + scons: rebuilding `file1.o' because `hello.h' changed + cc -o file1.o -c -I. file1.c + scons: rebuilding `file3.o' because `hello.h' changed + cc -o file3.o -c -I. file3.c + scons: rebuilding `prog' because: + `file1.o' changed + `file3.o' changed + cc -o prog file1.o file2.o file3.o + </screen> + + <para> + + (Note that the &debug-explain; option will only tell you + why &SCons; decided to rebuild necessary targets. + It does not tell you what files it examined + when deciding <emphasis>not</emphasis> + to rebuild a target file, + which is often a more valuable question to answer.) + + </para> + + </section> + + <section> + <title>What's in That Construction Environment? the &Dump; Method</title> + + <para> + + When you create a construction environment, + &SCons; populates it + with construction variables that are set up + for various compilers, linkers and utilities + that it finds on your system. + Although this is usually helpful and what you want, + it might be frustrating if &SCons; + doesn't set certain variables that you + expect to be set. + In situations like this, + it's sometimes helpful to use the + construction environment &Dump; method + to print all or some of + the construction variables. + Note that the &Dump; method + <emphasis>returns</emphasis> + the representation of the variables + in the environment + for you to print (or otherwise manipulate): + + </para> + + <programlisting> + env = Environment() + print env.Dump() + </programlisting> + + <para> + + On a POSIX system with gcc installed, + this might generate: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + { 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>}, + 'CONFIGUREDIR': '#/.sconf_temp', + 'CONFIGURELOG': '#/config.log', + 'CPPSUFFIXES': [ '.c', + '.C', + '.cxx', + '.cpp', + '.c++', + '.cc', + '.h', + '.H', + '.hxx', + '.hpp', + '.hh', + '.F', + '.fpp', + '.FPP', + '.m', + '.mm', + '.S', + '.spp', + '.SPP'], + 'DSUFFIXES': ['.d'], + 'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'ENV': {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}, + 'ESCAPE': <function escape at 0x700000>, + 'File': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'HOST_ARCH': None, + 'HOST_OS': None, + 'IDLSUFFIXES': ['.idl', '.IDL'], + 'INSTALL': <function copyFunc at 0x700000>, + 'LIBPREFIX': 'lib', + 'LIBPREFIXES': ['$LIBPREFIX'], + 'LIBSUFFIX': '.a', + 'LIBSUFFIXES': ['$LIBSUFFIX', '$SHLIBSUFFIX'], + 'MAXLINELENGTH': 128072, + 'OBJPREFIX': '', + 'OBJSUFFIX': '.o', + 'PLATFORM': 'posix', + 'PROGPREFIX': '', + 'PROGSUFFIX': '', + 'PSPAWN': <function piped_env_spawn at 0x700000>, + 'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'SCANNERS': [], + 'SHELL': 'sh', + 'SHLIBPREFIX': '$LIBPREFIX', + 'SHLIBSUFFIX': '.so', + 'SHOBJPREFIX': '$OBJPREFIX', + 'SHOBJSUFFIX': '$OBJSUFFIX', + 'SPAWN': <function spawnvpe_spawn at 0x700000>, + 'TARGET_ARCH': None, + 'TARGET_OS': None, + 'TEMPFILE': <class SCons.Platform.TempFileMunge at 0x700000>, + 'TEMPFILEPREFIX': '@', + 'TOOLS': ['install', 'install'], + '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', + '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', + '__RPATH': '$_RPATH', + '_concat': <function _concat at 0x700000>, + '_defines': <function _defines at 0x700000>, + '_stripixes': <function _stripixes at 0x700000>} + scons: done reading SConscript files. + scons: Building targets ... + scons: `.' is up to date. + scons: done building targets. + </screen> + + <para> + + On a Windows system with Visual C++ + the output might look like: + + </para> + + <screen> + C:\><userinput>scons</userinput> + scons: Reading SConscript files ... + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + { 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000>, 'Object': <SCons.Builder.CompositeBuilder instance at 0x700000>, 'PCH': <SCons.Builder.BuilderBase instance at 0x700000>, 'RES': <SCons.Builder.BuilderBase instance at 0x700000>, 'SharedObject': <SCons.Builder.CompositeBuilder instance at 0x700000>, 'StaticObject': <SCons.Builder.CompositeBuilder instance at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>}, + 'CC': 'cl', + 'CCCOM': <SCons.Action.FunctionAction instance at 0x700000>, + 'CCFLAGS': ['/nologo'], + 'CCPCHFLAGS': ['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'], + 'CCPDBFLAGS': ['${(PDB and "/Z7") or ""}'], + 'CFILESUFFIX': '.c', + 'CFLAGS': [], + 'CONFIGUREDIR': '#/.sconf_temp', + 'CONFIGURELOG': '#/config.log', + 'CPPDEFPREFIX': '/D', + 'CPPDEFSUFFIX': '', + 'CPPSUFFIXES': [ '.c', + '.C', + '.cxx', + '.cpp', + '.c++', + '.cc', + '.h', + '.H', + '.hxx', + '.hpp', + '.hh', + '.F', + '.fpp', + '.FPP', + '.m', + '.mm', + '.S', + '.spp', + '.SPP'], + 'CXX': '$CC', + 'CXXCOM': '$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM', + 'CXXFILESUFFIX': '.cc', + 'CXXFLAGS': ['$(', '/TP', '$)'], + 'DSUFFIXES': ['.d'], + 'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'ENV': { 'PATH': 'C:/WINDOWS\\System32', + 'PATHEXT': '.COM;.EXE;.BAT;.CMD', + 'SystemRoot': 'C:/WINDOWS'}, + 'ESCAPE': <function escape at 0x700000>, + 'File': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'HOST_ARCH': '', + 'HOST_OS': 'win32', + 'IDLSUFFIXES': ['.idl', '.IDL'], + 'INCPREFIX': '/I', + 'INCSUFFIX': '', + 'INSTALL': <function copyFunc at 0x700000>, + 'LIBPREFIX': '', + 'LIBPREFIXES': ['$LIBPREFIX'], + 'LIBSUFFIX': '.lib', + 'LIBSUFFIXES': ['$LIBSUFFIX'], + 'MAXLINELENGTH': 2048, + 'MSVC_SETUP_RUN': True, + 'OBJPREFIX': '', + 'OBJSUFFIX': '.obj', + 'PCHCOM': '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS', + 'PCHPDBFLAGS': ['${(PDB and "/Yd") or ""}'], + 'PLATFORM': 'win32', + 'PROGPREFIX': '', + 'PROGSUFFIX': '.exe', + 'PSPAWN': <function piped_spawn at 0x700000>, + 'RC': 'rc', + 'RCCOM': <SCons.Action.FunctionAction instance at 0x700000>, + 'RCFLAGS': [], + 'RCSUFFIXES': ['.rc', '.rc2'], + 'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>, + 'SCANNERS': [], + 'SHCC': '$CC', + 'SHCCCOM': <SCons.Action.FunctionAction instance at 0x700000>, + 'SHCCFLAGS': ['$CCFLAGS'], + 'SHCFLAGS': ['$CFLAGS'], + 'SHCXX': '$CXX', + 'SHCXXCOM': '$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM', + 'SHCXXFLAGS': ['$CXXFLAGS'], + 'SHELL': None, + 'SHLIBPREFIX': '', + 'SHLIBSUFFIX': '.dll', + 'SHOBJPREFIX': '$OBJPREFIX', + 'SHOBJSUFFIX': '$OBJSUFFIX', + 'SPAWN': <function spawn at 0x700000>, + 'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1, + 'TARGET_ARCH': '', + 'TARGET_OS': 'win32', + 'TEMPFILE': <class SCons.Platform.TempFileMunge at 0x700000>, + 'TEMPFILEPREFIX': '@', + 'TOOLS': ['msvc', 'install', 'install'], + '_CCCOMCOM': '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS', + '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', + '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', + '_MSVC_OUTPUT_FLAG': <function msvc_output_flag at 0x700000>, + '_concat': <function _concat at 0x700000>, + '_defines': <function _defines at 0x700000>, + '_stripixes': <function _stripixes at 0x700000>} + scons: done reading SConscript files. + scons: Building targets ... + scons: `.' is up to date. + scons: done building targets. + </screen> + + <para> + + The construction environments in these examples have + actually been restricted to just gcc and Visual C++, + respectively. + In a real-life situation, + the construction environments will + likely contain a great many more variables. + Also note that we've massaged the example output above + to make the memory address of all objects a constant 0x700000. + In reality, you would see a different hexadecimal + number for each object. + + </para> + + <para> + + To make it easier to see just what you're + interested in, + the &Dump; method allows you to + specify a specific constrcution variable + that you want to disply. + For example, + it's not unusual to want to verify + the external environment used to execute build commands, + to make sure that the PATH and other + environment variables are set up the way they should be. + You can do this as follows: + + </para> + + <programlisting> + env = Environment() + print env.Dump('ENV') + </programlisting> + + <para> + + Which might display the following when executed on a POSIX system: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'} + scons: done reading SConscript files. + scons: Building targets ... + scons: `.' is up to date. + scons: done building targets. + </screen> + + <para> + + And the following when executed on a Windows system: + + </para> + + <screen> + C:\><userinput>scons</userinput> + scons: Reading SConscript files ... + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + { 'PATH': 'C:/WINDOWS\\System32', + 'PATHEXT': '.COM;.EXE;.BAT;.CMD', + 'SystemRoot': 'C:/WINDOWS'} + scons: done reading SConscript files. + scons: Building targets ... + scons: `.' is up to date. + scons: done building targets. + </screen> + + </section> + + <section> + + <title>What Dependencies Does &SCons; Know About? the &tree; Option</title> + + <para> + + Sometimes the best way to try to figure out what + &SCons; is doing is simply to take a look at the + dependency graph that it constructs + based on your &SConscript; files. + The <literal>--tree</literal> option + will display all or part of the + &SCons; dependency graph in an + "ASCII art" graphical format + that shows the dependency hierarchy. + + </para> + + <para> + + For example, given the following input &SConstruct; file: + + </para> + + <programlisting> + env = Environment(CPPPATH = ['.']) + env.Program('prog', ['f1.c', 'f2.c', 'f3.c']) + </programlisting> + + <para> + + Running &SCons; with the <literal>--tree=all</literal> + option yields: + + </para> + + <screen> + % <userinput>scons -Q --tree=all</userinput> + cc -o f1.o -c -I. f1.c + cc -o f2.o -c -I. f2.c + cc -o f3.o -c -I. f3.c + cc -o prog f1.o f2.o f3.o + +-. + +-SConstruct + +-f1.c + +-f1.o + | +-f1.c + | +-inc.h + +-f2.c + +-f2.o + | +-f2.c + | +-inc.h + +-f3.c + +-f3.o + | +-f3.c + | +-inc.h + +-inc.h + +-prog + +-f1.o + | +-f1.c + | +-inc.h + +-f2.o + | +-f2.c + | +-inc.h + +-f3.o + +-f3.c + +-inc.h + </screen> + + <para> + + The tree will also be printed when the + <literal>-n</literal> (no execute) option is used, + which allows you to examine the dependency graph + for a configuration without actually + rebuilding anything in the tree. + + </para> + + <para> + + The <literal>--tree</literal> option only prints + the dependency graph for the specified targets + (or the default target(s) if none are specified on the command line). + So if you specify a target like <filename>f2.o</filename> + on the command line, + the <literal>--tree</literal> option will only + print the dependency graph for that file: + + </para> + + <screen> + % <userinput>scons -Q --tree=all f2.o</userinput> + cc -o f2.o -c -I. f2.c + +-f2.o + +-f2.c + +-inc.h + </screen> + + <para> + + This is, of course, useful for + restricting the output from a very large + build configuration to just a + portion in which you're interested. + Multiple targets are fine, + in which case a tree will be printed + for each specified target: + + </para> + + <screen> + % <userinput>scons -Q --tree=all f1.o f3.o</userinput> + cc -o f1.o -c -I. f1.c + +-f1.o + +-f1.c + +-inc.h + cc -o f3.o -c -I. f3.c + +-f3.o + +-f3.c + +-inc.h + </screen> + + <para> + + The <literal>status</literal> argument may be used + to tell &SCons; to print status information about + each file in the dependency graph: + + </para> + + <screen> + % <userinput>scons -Q --tree=status</userinput> + cc -o f1.o -c -I. f1.c + cc -o f2.o -c -I. f2.c + cc -o f3.o -c -I. f3.c + cc -o prog f1.o f2.o f3.o + E = exists + R = exists in repository only + b = implicit builder + B = explicit builder + S = side effect + P = precious + A = always build + C = current + N = no clean + H = no cache + + [E b ]+-. + [E C ] +-SConstruct + [E C ] +-f1.c + [E B C ] +-f1.o + [E C ] | +-f1.c + [E C ] | +-inc.h + [E C ] +-f2.c + [E B C ] +-f2.o + [E C ] | +-f2.c + [E C ] | +-inc.h + [E C ] +-f3.c + [E B C ] +-f3.o + [E C ] | +-f3.c + [E C ] | +-inc.h + [E C ] +-inc.h + [E B C ] +-prog + [E B C ] +-f1.o + [E C ] | +-f1.c + [E C ] | +-inc.h + [E B C ] +-f2.o + [E C ] | +-f2.c + [E C ] | +-inc.h + [E B C ] +-f3.o + [E C ] +-f3.c + [E C ] +-inc.h + </screen> + + <para> + + Note that <literal>--tree=all,status</literal> is equivalent; + the <literal>all</literal> + is assumed if only <literal>status</literal> is present. + As an alternative to <literal>all</literal>, + you can specify <literal>--tree=derived</literal> + to have &SCons; only print derived targets + in the tree output, + skipping source files + (like <filename>.c</filename> and <filename>.h</filename> files): + + </para> + + <screen> + % <userinput>scons -Q --tree=derived</userinput> + cc -o f1.o -c -I. f1.c + cc -o f2.o -c -I. f2.c + cc -o f3.o -c -I. f3.c + cc -o prog f1.o f2.o f3.o + +-. + +-f1.o + +-f2.o + +-f3.o + +-prog + +-f1.o + +-f2.o + +-f3.o + </screen> + + <para> + + You can use the <literal>status</literal> + modifier with <literal>derived</literal> as well: + + </para> + + <screen> + % <userinput>scons -Q --tree=derived,status</userinput> + cc -o f1.o -c -I. f1.c + cc -o f2.o -c -I. f2.c + cc -o f3.o -c -I. f3.c + cc -o prog f1.o f2.o f3.o + E = exists + R = exists in repository only + b = implicit builder + B = explicit builder + S = side effect + P = precious + A = always build + C = current + N = no clean + H = no cache + + [E b ]+-. + [E B C ] +-f1.o + [E B C ] +-f2.o + [E B C ] +-f3.o + [E B C ] +-prog + [E B C ] +-f1.o + [E B C ] +-f2.o + [E B C ] +-f3.o + </screen> + + <para> + + Note that the order of the <literal>--tree=</literal> + arguments doesn't matter; + <literal>--tree=status,derived</literal> is + completely equivalent. + + </para> + + <para> + + The default behavior of the <literal>--tree</literal> option + is to repeat all of the dependencies each time the library dependency + (or any other dependency file) is encountered in the tree. + If certain target files share other target files, + such as two programs that use the same library: + + </para> + + <programlisting> + env = Environment(CPPPATH = ['.'], + LIBS = ['foo'], + LIBPATH = ['.']) + env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.Program('prog1.c') + env.Program('prog2.c') + </programlisting> + + <para> + + Then there can be a <emphasis>lot</emphasis> of repetition in the + <literal>--tree=</literal> output: + + </para> + + <screen> + % <userinput>scons -Q --tree=all</userinput> + cc -o f1.o -c -I. f1.c + cc -o f2.o -c -I. f2.c + cc -o f3.o -c -I. f3.c + ar rc libfoo.a f1.o f2.o f3.o + ranlib libfoo.a + cc -o prog1.o -c -I. prog1.c + cc -o prog1 prog1.o -L. -lfoo + cc -o prog2.o -c -I. prog2.c + cc -o prog2 prog2.o -L. -lfoo + +-. + +-SConstruct + +-f1.c + +-f1.o + | +-f1.c + | +-inc.h + +-f2.c + +-f2.o + | +-f2.c + | +-inc.h + +-f3.c + +-f3.o + | +-f3.c + | +-inc.h + +-inc.h + +-libfoo.a + | +-f1.o + | | +-f1.c + | | +-inc.h + | +-f2.o + | | +-f2.c + | | +-inc.h + | +-f3.o + | +-f3.c + | +-inc.h + +-prog1 + | +-prog1.o + | | +-prog1.c + | | +-inc.h + | +-libfoo.a + | +-f1.o + | | +-f1.c + | | +-inc.h + | +-f2.o + | | +-f2.c + | | +-inc.h + | +-f3.o + | +-f3.c + | +-inc.h + +-prog1.c + +-prog1.o + | +-prog1.c + | +-inc.h + +-prog2 + | +-prog2.o + | | +-prog2.c + | | +-inc.h + | +-libfoo.a + | +-f1.o + | | +-f1.c + | | +-inc.h + | +-f2.o + | | +-f2.c + | | +-inc.h + | +-f3.o + | +-f3.c + | +-inc.h + +-prog2.c + +-prog2.o + +-prog2.c + +-inc.h + </screen> + + <para> + + In a large configuration with many internal libraries + and include files, + this can very quickly lead to huge output trees. + To help make this more manageable, + a <literal>prune</literal> modifier may + be added to the option list, + in which case &SCons; + will print the name of a target that has + already been visited during the tree-printing + in <literal>[square brackets]</literal> + as an indication that the dependencies + of the target file may be found + by looking farther up the tree: + + </para> + + <screen> + % <userinput>scons -Q --tree=prune</userinput> + cc -o f1.o -c -I. f1.c + cc -o f2.o -c -I. f2.c + cc -o f3.o -c -I. f3.c + ar rc libfoo.a f1.o f2.o f3.o + ranlib libfoo.a + cc -o prog1.o -c -I. prog1.c + cc -o prog1 prog1.o -L. -lfoo + cc -o prog2.o -c -I. prog2.c + cc -o prog2 prog2.o -L. -lfoo + +-. + +-SConstruct + +-f1.c + +-f1.o + | +-f1.c + | +-inc.h + +-f2.c + +-f2.o + | +-f2.c + | +-inc.h + +-f3.c + +-f3.o + | +-f3.c + | +-inc.h + +-inc.h + +-libfoo.a + | +-[f1.o] + | +-[f2.o] + | +-[f3.o] + +-prog1 + | +-prog1.o + | | +-prog1.c + | | +-inc.h + | +-[libfoo.a] + +-prog1.c + +-[prog1.o] + +-prog2 + | +-prog2.o + | | +-prog2.c + | | +-inc.h + | +-[libfoo.a] + +-prog2.c + +-[prog2.o] + </screen> + + <para> + + Like the <literal>status</literal> keyword, + the <literal>prune</literal> argument by itself + is equivalent to <literal>--tree=all,prune</literal>. + + </para> + + </section> + + <section> + + <title>How is &SCons; Constructing the Command Lines It Executes? the &debug-presub; Option</title> + + <para> + + Sometimes it's useful to look at the + pre-substitution string + that &SCons; uses to generate + the command lines it executes. + This can be done with the &debug-presub; option: + + </para> + + + + <!-- + + Have to capture output here, otherwise the - -debug=presub output + shows the Python functions from the sconsdoc.py execution wrapper + used to generate this manual, not the underlying command-line strings. + + <scons_output example="presub"> + <scons_output_command>scons -Q - -debug=presub</scons_output_command> + </scons_output> + + --> + + <screen> + % <userinput>scons -Q --debug=presub</userinput> + Building prog.o with action: + $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCOMCOM $SOURCES + cc -o prog.o -c -I. prog.c + Building prog with action: + $SMART_LINKCOM + cc -o prog prog.o + </screen> + + </section> + + <section> + + <title>Where is &SCons; Searching for Libraries? the &debug-findlibs; Option</title> + + <para> + + To get some insight into what library names + &SCons; is searching for, + and in which directories it is searching, + Use the <literal>--debug=findlibs</literal> option. + Given the following input &SConstruct; file: + + </para> + + <programlisting> + env = Environment(LIBPATH = ['libs1', 'libs2']) + env.Program('prog.c', LIBS=['foo', 'bar']) + </programlisting> + + <para> + + And the libraries <filename>libfoo.a</filename> + and <filename>libbar.a</filename> + in <filename>libs1</filename> and <filename>libs2</filename>, + respectively, + use of the <literal>--debug=findlibs</literal> option yields: + + </para> + + <screen> + % <userinput>scons -Q --debug=findlibs</userinput> + findlibs: looking for 'libfoo.a' in 'libs1' ... + findlibs: ... FOUND 'libfoo.a' in 'libs1' + findlibs: looking for 'libfoo.so' in 'libs1' ... + findlibs: looking for 'libfoo.so' in 'libs2' ... + findlibs: looking for 'libbar.a' in 'libs1' ... + findlibs: looking for 'libbar.a' in 'libs2' ... + findlibs: ... FOUND 'libbar.a' in 'libs2' + findlibs: looking for 'libbar.so' in 'libs1' ... + findlibs: looking for 'libbar.so' in 'libs2' ... + cc -o prog.o -c prog.c + cc -o prog prog.o -Llibs1 -Llibs2 -lfoo -lbar + </screen> + + </section> + + <!-- + + <section> + + <title>What Implicit Dependencies Did the &SCons; Scanner find? the &debug-includes; Option</title> + + <para> + + XXX explain the - - debug=includes option + + </para> + + <scons_example name="includes"> + <file name="SConstruct" printme="1"> + env = Environment(CPPPATH = ['inc1', 'inc2']) + env.Program('prog.c') + </file> + <file name="prog.c"> + #include "file1.h" + #include "file2.h" + prog.c + </file> + <file name="inc1/file1.h"> + inc1/file1.h + </file> + <file name="inc2/file2.h"> + inc2/file2.h + </file> + </scons_example> + + <scons_output example="includes"> + <scons_output_command>scons -Q - - debug=includes prog</scons_output_command> + </scons_output> + + </section> + + --> + + <section> + + <title>Where is &SCons; Blowing Up? the &debug-stacktrace; Option</title> + + <para> + + In general, &SCons; tries to keep its error + messages short and informative. + That means we usually try to avoid showing + the stack traces that are familiar + to experienced Python programmers, + since they usually contain much more + information than is useful to most people. + + </para> + + <para> + + For example, the following &SConstruct; file: + + </para> + + <programlisting> + Program('prog.c') + </programlisting> + + <para> + + Generates the following error if the + <filename>prog.c</filename> file + does not exist: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. + </screen> + + <para> + + In this case, + the error is pretty obvious. + But if it weren't, + and you wanted to try to get more information + about the error, + the &debug-stacktrace; option + would show you exactly where in the &SCons; source code + the problem occurs: + + </para> + + <screen> + % <userinput>scons -Q --debug=stacktrace</userinput> + scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. + scons: internal stack trace: + File "bootstrap/src/engine/SCons/Job.py", line 197, in start + File "bootstrap/src/engine/SCons/Script/Main.py", line 167, in prepare + File "bootstrap/src/engine/SCons/Taskmaster.py", line 190, in prepare + File "bootstrap/src/engine/SCons/Executor.py", line 397, in prepare + </screen> + + <para> + + Of course, if you do need to dive into the &SCons; source code, + we'd like to know if, or how, + the error messages or troubleshooting options + could have been improved to avoid that. + Not everyone has the necessary time or + Python skill to dive into the source code, + and we'd like to improve &SCons; + for those people as well... + + </para> + + </section> + + <section> + + <title>How is &SCons; Making Its Decisions? the &taskmastertrace; Option</title> + + <para> + + The internal &SCons; subsystem that handles walking + the dependency graph + and controls the decision-making about what to rebuild + is the <literal>Taskmaster</literal>. + &SCons; supports a <literal>--taskmastertrace</literal> + option that tells the Taskmaster to print + information about the children (dependencies) + of the various Nodes on its walk down the graph, + which specific dependent Nodes are being evaluated, + and in what order. + + </para> + + <para> + + The <literal>--taskmastertrace</literal> option + takes as an argument the name of a file in + which to put the trace output, + with <filename>-</filename> (a single hyphen) + indicating that the trace messages + should be printed to the standard output: + + </para> + + <programlisting> + env = Environment(CPPPATH = ['.']) + env.Program('prog.c') + </programlisting> + + <screen> + % <userinput>scons -Q --taskmastertrace=- prog</userinput> + + Taskmaster: Looking for a node to evaluate + Taskmaster: Considering node <no_state 0 'prog'> and its children: + Taskmaster: <no_state 0 'prog.o'> + Taskmaster: adjusted ref count: <pending 1 'prog'>, child 'prog.o' + Taskmaster: Considering node <no_state 0 'prog.o'> and its children: + Taskmaster: <no_state 0 'prog.c'> + Taskmaster: <no_state 0 'inc.h'> + Taskmaster: adjusted ref count: <pending 1 'prog.o'>, child 'prog.c' + Taskmaster: adjusted ref count: <pending 2 'prog.o'>, child 'inc.h' + Taskmaster: Considering node <no_state 0 'prog.c'> and its children: + Taskmaster: Evaluating <pending 0 'prog.c'> + + Task.make_ready_current(): node <pending 0 'prog.c'> + Task.prepare(): node <up_to_date 0 'prog.c'> + Task.executed_with_callbacks(): node <up_to_date 0 'prog.c'> + Task.postprocess(): node <up_to_date 0 'prog.c'> + Task.postprocess(): removing <up_to_date 0 'prog.c'> + Task.postprocess(): adjusted parent ref count <pending 1 'prog.o'> + + Taskmaster: Looking for a node to evaluate + Taskmaster: Considering node <no_state 0 'inc.h'> and its children: + Taskmaster: Evaluating <pending 0 'inc.h'> + + Task.make_ready_current(): node <pending 0 'inc.h'> + Task.prepare(): node <up_to_date 0 'inc.h'> + Task.executed_with_callbacks(): node <up_to_date 0 'inc.h'> + Task.postprocess(): node <up_to_date 0 'inc.h'> + Task.postprocess(): removing <up_to_date 0 'inc.h'> + Task.postprocess(): adjusted parent ref count <pending 0 'prog.o'> + + Taskmaster: Looking for a node to evaluate + Taskmaster: Considering node <pending 0 'prog.o'> and its children: + Taskmaster: <up_to_date 0 'prog.c'> + Taskmaster: <up_to_date 0 'inc.h'> + Taskmaster: Evaluating <pending 0 'prog.o'> + + Task.make_ready_current(): node <pending 0 'prog.o'> + Task.prepare(): node <executing 0 'prog.o'> + Task.execute(): node <executing 0 'prog.o'> + cc -o prog.o -c -I. prog.c + Task.executed_with_callbacks(): node <executing 0 'prog.o'> + Task.postprocess(): node <executed 0 'prog.o'> + Task.postprocess(): removing <executed 0 'prog.o'> + Task.postprocess(): adjusted parent ref count <pending 0 'prog'> + + Taskmaster: Looking for a node to evaluate + Taskmaster: Considering node <pending 0 'prog'> and its children: + Taskmaster: <executed 0 'prog.o'> + Taskmaster: Evaluating <pending 0 'prog'> + + Task.make_ready_current(): node <pending 0 'prog'> + Task.prepare(): node <executing 0 'prog'> + Task.execute(): node <executing 0 'prog'> + cc -o prog prog.o + Task.executed_with_callbacks(): node <executing 0 'prog'> + Task.postprocess(): node <executed 0 'prog'> + + Taskmaster: Looking for a node to evaluate + Taskmaster: No candidate anymore. + </screen> + + <para> + + The <literal>--taskmastertrace</literal> option + doesn't provide information about the actual + calculations involved in deciding if a file is up-to-date, + but it does show all of the dependencies + it knows about for each Node, + and the order in which those dependencies are evaluated. + This can be useful as an alternate way to determine + whether or not your &SCons; configuration, + or the implicit dependency scan, + has actually identified all the correct dependencies + you want it to. + + </para> + + </section> + + <!-- + + <section> + + <title>Where Are My Build Bottlenecks? the &profile; Option</title> + + <para> + + XXX explain the - - profile= option + + </para> + + </section> + + --> + + <!-- + + <section> + <title>Troubleshooting Shared Caching: the &cache-debug; Option</title> + + <para> + + XXX describe the - - cache-debug option + XXX maybe point to the caching.in chapter? + + </para> + + </section> + + --> diff --git a/doc/user/variables.in b/doc/user/variables.in new file mode 100644 index 0000000..85fb9cd --- /dev/null +++ b/doc/user/variables.in @@ -0,0 +1,56 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<para> + +This appendix contains descriptions of all of the +construction variables that are <emphasis>potentially</emphasis> +available "out of the box" in this version of SCons. +Whether or not setting a construction variable +in a construction environment +will actually have an effect depends on +whether any of the Tools and/or Builders +that use the variable have been +included in the construction environment. + +</para> + +<para> + +In this appendix, we have +appended the initial <envar>$</envar> +(dollar sign) to the beginning of each +variable name when it appears in the text, +but left off the dollar sign +in the left-hand column +where the name appears for each entry. + +</para> + +<variablelist> + +&variables-gen; + +</variablelist> diff --git a/doc/user/variables.xml b/doc/user/variables.xml new file mode 100644 index 0000000..85fb9cd --- /dev/null +++ b/doc/user/variables.xml @@ -0,0 +1,56 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<para> + +This appendix contains descriptions of all of the +construction variables that are <emphasis>potentially</emphasis> +available "out of the box" in this version of SCons. +Whether or not setting a construction variable +in a construction environment +will actually have an effect depends on +whether any of the Tools and/or Builders +that use the variable have been +included in the construction environment. + +</para> + +<para> + +In this appendix, we have +appended the initial <envar>$</envar> +(dollar sign) to the beginning of each +variable name when it appears in the text, +but left off the dollar sign +in the left-hand column +where the name appears for each entry. + +</para> + +<variablelist> + +&variables-gen; + +</variablelist> diff --git a/doc/user/variants.in b/doc/user/variants.in new file mode 100644 index 0000000..696e174 --- /dev/null +++ b/doc/user/variants.in @@ -0,0 +1,151 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Variant builds + +=head2 Variations on a theme + +Other variations of this model are possible. For example, you might decide +that you want to separate out your include files into platform dependent and +platform independent files. In this case, you'd have to define an +alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript> +files, generating purely platform-independent include files, would not have +to change. + +You might also want to be able to compile your whole system with debugging +or profiling, for example, enabled. You could do this with appropriate +command line options, such as C<DEBUG=on>. This would then be translated +into the appropriate platform-specific requirements to enable debugging +(this might include turning off optimization, for example). You could +optionally vary the name space for these different types of systems, but, as +we'll see in the next section, it's not B<essential> to do this, since Cons +is pretty smart about rebuilding things when you change options. + +--> + + <para> + + The &variant_dir; keyword argument of + the &SConscript; function provides everything + we need to show how easy it is to create + variant builds using &SCons;. + Suppose, for example, that we want to + build a program for both Windows and Linux platforms, + but that we want to build it in a shared directory + with separate side-by-side build directories + for the Windows and Linux versions of the program. + + </para> + + <scons_example name="ex_variants"> + <file name="SConstruct" printme="1"> + platform = ARGUMENTS.get('OS', Platform()) + + include = "#export/$PLATFORM/include" + lib = "#export/$PLATFORM/lib" + bin = "#export/$PLATFORM/bin" + + env = Environment(PLATFORM = platform, + BINDIR = bin, + INCDIR = include, + LIBDIR = lib, + CPPPATH = [include], + LIBPATH = [lib], + LIBS = 'world') + + Export('env') + + env.SConscript('src/SConscript', variant_dir='build/$PLATFORM') + </file> + <directory name="src"></directory> + <directory name="src/hello"></directory> + <directory name="src/world"></directory> + <file name="src/SConscript"> + Import('env') + SConscript('hello/SConscript') + SConscript('world/SConscript') + </file> + <file name="src/hello/SConscript"> + Import('env') + hello = env.Program('hello.c') + env.Install('$BINDIR', hello) + </file> + <file name="src/hello/hello.c"> + #include "world.h" + int main(int argc, char *argv[]) { printf "hello.c\n"; world(); } + </file> + <file name="src/world/SConscript"> + Import('env') + world = env.Library('world.c') + env.Install('$LIBDIR', world) + env.Install('$INCDIR', 'world.h') + </file> + <file name="src/world/world.h"> + #define STRING "world.h" + extern int world(); + </file> + <file name="src/world/world.c"> + int world() { printf "world.c\n"; } + </file> + </scons_example> + + <para> + + This SConstruct file, + when run on a Linux system, yields: + + </para> + + <scons_output example="ex_variants" os="posix"> + <scons_output_command>scons -Q OS=linux</scons_output_command> + </scons_output> + + <para> + + The same SConstruct file on Windows would build: + + </para> + + <scons_output example="ex_variants" os="win32"> + <scons_output_command>scons -Q OS=windows</scons_output_command> + </scons_output> + + <!-- + + <scons_example name="ex_var2"> + <file name="SConstruct" printme="1"> + env = Environment(OS = ARGUMENTS.get('OS')) + for os in ['newell', 'post']: + SConscript('src/SConscript', variant_dir='build/' + os) + </file> + </scons_example> + + <scons_output example="ex_var2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> diff --git a/doc/user/variants.xml b/doc/user/variants.xml new file mode 100644 index 0000000..016202a --- /dev/null +++ b/doc/user/variants.xml @@ -0,0 +1,146 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Variant builds + +=head2 Variations on a theme + +Other variations of this model are possible. For example, you might decide +that you want to separate out your include files into platform dependent and +platform independent files. In this case, you'd have to define an +alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript> +files, generating purely platform-independent include files, would not have +to change. + +You might also want to be able to compile your whole system with debugging +or profiling, for example, enabled. You could do this with appropriate +command line options, such as C<DEBUG=on>. This would then be translated +into the appropriate platform-specific requirements to enable debugging +(this might include turning off optimization, for example). You could +optionally vary the name space for these different types of systems, but, as +we'll see in the next section, it's not B<essential> to do this, since Cons +is pretty smart about rebuilding things when you change options. + +--> + + <para> + + The &variant_dir; keyword argument of + the &SConscript; function provides everything + we need to show how easy it is to create + variant builds using &SCons;. + Suppose, for example, that we want to + build a program for both Windows and Linux platforms, + but that we want to build it in a shared directory + with separate side-by-side build directories + for the Windows and Linux versions of the program. + + </para> + + <programlisting> + platform = ARGUMENTS.get('OS', Platform()) + + include = "#export/$PLATFORM/include" + lib = "#export/$PLATFORM/lib" + bin = "#export/$PLATFORM/bin" + + env = Environment(PLATFORM = platform, + BINDIR = bin, + INCDIR = include, + LIBDIR = lib, + CPPPATH = [include], + LIBPATH = [lib], + LIBS = 'world') + + Export('env') + + env.SConscript('src/SConscript', variant_dir='build/$PLATFORM') + </programlisting> + + <para> + + This SConstruct file, + when run on a Linux system, yields: + + </para> + + <screen> + % <userinput>scons -Q OS=linux</userinput> + Install file: "build/linux/world/world.h" as "export/linux/include/world.h" + cc -o build/linux/hello/hello.o -c -Iexport/linux/include build/linux/hello/hello.c + cc -o build/linux/world/world.o -c -Iexport/linux/include build/linux/world/world.c + ar rc build/linux/world/libworld.a build/linux/world/world.o + ranlib build/linux/world/libworld.a + Install file: "build/linux/world/libworld.a" as "export/linux/lib/libworld.a" + cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld + Install file: "build/linux/hello/hello" as "export/linux/bin/hello" + </screen> + + <para> + + The same SConstruct file on Windows would build: + + </para> + + <screen> + C:\><userinput>scons -Q OS=windows</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + Install file: "build/windows/world/world.h" as "export/windows/include/world.h" + cl /Fobuild\windows\hello\hello.obj /c build\windows\hello\hello.c /nologo /Iexport\windows\include + cl /Fobuild\windows\world\world.obj /c build\windows\world\world.c /nologo /Iexport\windows\include + lib /nologo /OUT:build\windows\world\world.lib build\windows\world\world.obj + Install file: "build/windows/world/world.lib" as "export/windows/lib/world.lib" + link /nologo /OUT:build\windows\hello\hello.exe /LIBPATH:export\windows\lib world.lib build\windows\hello\hello.obj + Install file: "build/windows/hello/hello.exe" as "export/windows/bin/hello.exe" + </screen> + + <!-- + + <scons_example name="ex_var2"> + <file name="SConstruct" printme="1"> + env = Environment(OS = ARGUMENTS.get('OS')) + for os in ['newell', 'post']: + SConscript('src/SConscript', variant_dir='build/' + os) + </file> + </scons_example> + + <scons_output example="ex_var2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + --> |