4 SPDX-FileCopyrightText: Copyright The SCons Foundation (https://scons.org)
5 SPDX-License-Identifier: MIT
6 SPDX-FileType: DOCUMENTATION
8 This file is processed by the bin/SConsDoc.py module.
12 <!ENTITY % scons SYSTEM "../scons.mod">
15 <!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
17 <!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
19 <!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
21 <!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
26 <chapter id="chap-add-method"
27 xmlns="http://www.scons.org/dbxsd/v1.0"
28 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
29 xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
31 <title>Extending &SCons;: Pseudo-Builders and the AddMethod function</title>
35 The &f-link-AddMethod; function is used to add a method
36 to an environment. It is typically used to add a "pseudo-builder,"
37 a function that looks like a &Builder; but
38 wraps up calls to multiple other &Builders;
39 or otherwise processes its arguments
40 before calling one or more &Builders;.
46 In the following example,
47 we want to install the program into the standard
48 <filename>/usr/bin</filename> directory hierarchy,
49 but also copy it into a local <filename>install/bin</filename>
50 directory from which a package might be built:
54 <scons_example name="addmethod_ex1">
55 <file name="SConstruct" printme="1">
56 def install_in_bin_dirs(env, source):
57 """Install source in both bin directories"""
58 i1 = env.Install("$BIN", source)
59 i2 = env.Install("$LOCALBIN", source)
60 return [i1[0], i2[0]] # Return a list, like a normal builder
62 env = Environment(BIN='__ROOT__/usr/bin', LOCALBIN='#install/bin')
63 env.AddMethod(install_in_bin_dirs, "InstallInBinDirs")
64 env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin directories
67 int main() { printf("Hello, world!\n"); }
72 This produces the following:
75 <scons_output example="addmethod_ex1" suffix="1">
76 <scons_output_command>scons -Q /</scons_output_command>
81 A pseudo-builder is useful because it gives you more flexibility
82 parsing arguments than you can get with a standard &Builder;.
83 The next example shows a pseudo-builder with a
84 named argument that modifies the filename, and a separate optional
85 argument for a resource file (rather than having the builder figure it out
86 by file extension). This example also demonstrates using the global
87 &AddMethod; function to add a method to the global Environment class,
88 so it will be available in all subsequently created environments.
92 <scons_example name="addmethod_ex2">
93 <file name="SConstruct" printme="1">
94 def BuildTestProg(env, testfile, resourcefile="", testdir="tests"):
95 """Build the test program.
97 Prepends "test_" to src and target and puts the target into testdir.
98 If the build is running on Windows, also make use of a resource file,
101 srcfile = f"test_{testfile}.c"
102 target = f"{testdir}/test_{testfile}"
103 if env['PLATFORM'] == 'win32' and resourcefile:
104 resfile = env.RES(resourcefile)
105 p = env.Program(target, [srcfile, resfile])
107 p = env.Program(target, srcfile)
110 AddMethod(Environment, BuildTestProg)
113 env.BuildTestProg('stuff', resourcefile='res.rc')
115 <file name="test_stuff.c">
116 int main() { printf("Hello, world!\n"); }
124 This produces the following on Linux:
127 <scons_output example="addmethod_ex2" suffix="1">
128 <scons_output_command>scons -Q</scons_output_command>
132 And the following on Windows:
135 <scons_output example="addmethod_ex2" os="win32" suffix="2">
136 <scons_output_command>scons -Q</scons_output_command>
140 Using &AddMethod; is better than just adding an instance method
141 to a &consenv; because it gets called as a proper method,
142 and because &AddMethod; provides for copying the method
143 to any clones of the &consenv; instance.