<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=BAILOPAN</id>
	<title>AlliedModders Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=BAILOPAN"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/BAILOPAN"/>
	<updated>2026-04-18T09:28:45Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11675</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11675"/>
		<updated>2023-11-10T03:47:26Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Protobufs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
* See [[#Protoc as a Tool]]&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
 &amp;lt;li&amp;gt;''StaticLibrary'': Helper to create a C++ static library out of .proto files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Invoking protoc==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Protobuf Libraries==&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Protoc as a Tool==&lt;br /&gt;
&lt;br /&gt;
You can also embed generated protobufs directly into BinaryBuilders. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    prog = cxx.Program('prog')&lt;br /&gt;
    protos = builder.tools.Protoc(sources = ['myproto.proto'])&lt;br /&gt;
    prog.custom += [protos]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This compiles the pb.cc files in the same context as the binary. The &amp;lt;tt&amp;gt;Protoc()&amp;lt;/tt&amp;gt; constructor takes two arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;''protoc'': Optional detected protoc. If omitted, &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt; is called automatically.&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;''sources'': Optional list of protobuf source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The return value is a &amp;lt;tt&amp;gt;ProtocJob&amp;lt;/tt&amp;gt;, which has the attributes ''protoc'' and ''sources'' as above. Both are copies/clones and thus can be modified without affecting the variables that were passed in.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11674</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11674"/>
		<updated>2023-11-09T06:59:29Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Protoc as a Tool */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
* See [[#Protoc as a Tool]]&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Invoking protoc==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Protobuf Libraries==&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Protoc as a Tool==&lt;br /&gt;
&lt;br /&gt;
You can also embed generated protobufs directly into BinaryBuilders. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    prog = cxx.Program('prog')&lt;br /&gt;
    protos = builder.tools.Protoc(sources = ['myproto.proto'])&lt;br /&gt;
    prog.custom += [protos]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This compiles the pb.cc files in the same context as the binary. The &amp;lt;tt&amp;gt;Protoc()&amp;lt;/tt&amp;gt; constructor takes two arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;''protoc'': Optional detected protoc. If omitted, &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt; is called automatically.&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;''sources'': Optional list of protobuf source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The return value is a &amp;lt;tt&amp;gt;ProtocJob&amp;lt;/tt&amp;gt;, which has the attributes ''protoc'' and ''sources'' as above. Both are copies/clones and thus can be modified without affecting the variables that were passed in.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11673</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11673"/>
		<updated>2023-11-09T06:32:06Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Protobufs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
* See [[#Protoc as a Tool]]&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Invoking protoc==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Protobuf Libraries==&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Protoc as a Tool==&lt;br /&gt;
&lt;br /&gt;
You can also embed generated protobufs directly into BinaryBuilders. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    prog = cxx.Program('prog')&lt;br /&gt;
    protos = builder.tools.Protoc(sources = ['myproto.proto'])&lt;br /&gt;
    prog.custom += [protos]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This compiles the pb.cc files in the same context as the binary. The &amp;lt;tt&amp;gt;Protoc()&amp;lt;/tt&amp;gt; constructor takes two arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;''protoc'': Optional detected protoc. If omitted, &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt; is called automatically.&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;''sources'': Optional list of protobuf source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The return value is a &amp;lt;tt&amp;gt;ProtocJob&amp;lt;/tt&amp;gt;, which has the attributes ''protoc'' and ''sources'' as given up. Both are clones and thus can be modified without affecting other callers.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11672</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11672"/>
		<updated>2023-11-09T06:26:34Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
* See [[#Protoc as a Tool]]&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Invoking protoc==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Protobuf Libraries==&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11671</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11671"/>
		<updated>2023-11-09T06:26:06Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Protobufs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
* See [[#Protoc as a Tool]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11670</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11670"/>
		<updated>2023-11-09T06:25:08Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Predefined Custom C++ Tools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Invoking protoc==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Protobuf Libraries==&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
* See [[#Protoc as a Tool]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11669</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11669"/>
		<updated>2023-11-09T06:02:16Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Manual Invocation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Invoking protoc==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Protobuf Libraries==&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11668</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11668"/>
		<updated>2023-11-09T06:02:02Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* C++ Libraries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manual Invocation==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Protobuf Libraries==&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11667</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11667"/>
		<updated>2023-11-09T06:01:50Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Protobufs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manual Invocation==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Libraries==&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11666</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11666"/>
		<updated>2023-11-09T05:01:18Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Protobufs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
prog = builder.Program('myprogram')&lt;br /&gt;
prog.compiler.sourcedeps += out.headers&lt;br /&gt;
prog.compiler.linkflags += [out.lib.binary]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11665</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11665"/>
		<updated>2023-11-09T04:58:13Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Protobufs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make a static library out of generated protobufs, you can use the &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt; helper, which takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': Binary name.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': Build context.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''cxx'': C++ compiler object from DetectCxx().&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': List of protobuf files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': Optional list of additional includes.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
protoc = builder.DetectProtoc()&lt;br /&gt;
&lt;br /&gt;
proto_files = [&lt;br /&gt;
    'game.proto',&lt;br /&gt;
    'player.proto',&lt;br /&gt;
]&lt;br /&gt;
out = protoc.StaticLibrary('protos', builder, cxx, proto_files)&lt;br /&gt;
&lt;br /&gt;
# Static library node is out.lib&lt;br /&gt;
# Header list (for adding to other BinaryBuilders via sourcedeps) is out.headers&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11664</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11664"/>
		<updated>2023-11-08T06:35:17Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''DetectProtoc(**kwargs)'' - Detects the protobuf compiler (protoc). Only one kwarg is supported, &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;, which optionally specifies a specific binary to use for protoc. The returned &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object is documented under [[#Protobufs]]. This API is only available on 2.2.4 and higher.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Protobufs=&lt;br /&gt;
&lt;br /&gt;
AMBuild has builtin support for protobufs as of version 2.2.4. The lowest-level way to use this support is via &amp;lt;tt&amp;gt;DetectProtoc()&amp;lt;/tt&amp;gt;, which returns a &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object. This object has the following attributes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''path'': Either 'protoc' or an explicitly given path to protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''name'': The name reported by 'protoc --version', eg 'libprotoc'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''version'': The protoc version, as a comparable object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''extra_argv'': A list to add extra arguments to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of include paths to add to every protoc invocation.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects also have the following methods:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''clone'': Duplicate the &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; object, except lists are copied to avoid affecting both &amp;lt;tt&amp;gt;Protoc&amp;lt;/tt&amp;gt; objects.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''Generate'': Add build steps for compiling protobuf files.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; method takes the following arguments:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''builder'': A &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''sources'': A list of source files.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''outputs'': A list of language targets. Each language target is either a language name, or a tuple of &amp;quot;(language name, folder)&amp;quot; where folder is None (build root) or an entry from &amp;lt;tt&amp;gt;builder.AddFolder()&amp;lt;/tt&amp;gt;. Languages supported are 'cpp' and 'python'.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;''includes'': A list of additional include paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Generate&amp;lt;/tt&amp;gt; returns a dictionary to assist linking protoc outputs with other build rules. Each key of the dictionary is one of the languages requested:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'cpp': If cpp was requested, will contain a sub-dict with the keys 'sources' and 'headers'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the .pb.cc and .pb.h files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'python': If python was requested, will contain a sub-dict with the keys 'sources'. Each of these is a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects corresponding to the _pb2.py files created by protoc.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of such a dict for 'game.proto' and 'player.proto' files, when all languages are requested:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    'cpp': {&lt;br /&gt;
         'sources': [Entry('game.pb.cc'), Entry('player.pb.cc')],&lt;br /&gt;
         'headers': [Entry('game.pb.h'), Entry('player.pb.h')],&lt;br /&gt;
     },&lt;br /&gt;
    'python': {&lt;br /&gt;
         'sources': [Entry('game_pb2.py'), Entry('player_pb2.py')],&lt;br /&gt;
     },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11257</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11257"/>
		<updated>2021-11-22T05:33:57Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Compiler */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; objects both have a single method, &amp;lt;tt&amp;gt;link(name)&amp;lt;/tt&amp;gt;, which returns whether the argument style derives from 'gcc' or 'msvc'.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11256</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11256"/>
		<updated>2021-11-22T05:32:43Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Attributes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following attributes are available on 2.2.3 and higher:&lt;br /&gt;
* ''linker'' - A &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; object representing the linker (eg, ld or link.exe).&lt;br /&gt;
* ''linker_argv'' - Array of arguments to invoke the linker.&lt;br /&gt;
* ''archiver'' - An &amp;lt;tt&amp;gt;Archiver&amp;lt;/tt&amp;gt; object representing the archiver (eg, ar or lib.exe).&lt;br /&gt;
* ''archiver_argv'' - Array of arguments to invoke the archiver.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11231</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11231"/>
		<updated>2021-09-22T17:13:44Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback on GitHub if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
AMBuild 2.2.1 is the latest release. It supports cross-compiling, multi-architecture builds, and precompiled headers.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
Additionally, pip and setuptools (both Python components) are also required. If your distribution or Python installation does not provide for these, see [https://pip.pypa.io/en/stable/installing/ Installing Pip] for manual instructions.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: By default, pip will perform per-user installations. To install globally for all users, you will need to use &amp;quot;sudo&amp;quot; (or run as Administrator on Windows).&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. There is not an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11230</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11230"/>
		<updated>2021-09-22T17:13:19Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
* ''CallBuilder(fun)'' - Runs ''fun'' (a callback) in a child context. This is useful when a child folder is needed, but an entirely new build script would be too heavyweight. The return value of the function is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''linkdeps'' - An array of entries that will act as strong inputs to the linker. Normally, linker flags are scanned for paths to detect dependencies. This can fail if the linker flag is complicated or the path is embedded in a flag. In this case, the source path can be manually added to ''linkdeps''.&lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11097</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11097"/>
		<updated>2020-08-25T04:05:18Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback on GitHub if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
AMBuild 2.2 is the latest release. It supports cross-compiling, multi-architecture builds, and precompiled headers.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 2.7 or higher is required. If using Python 3, then 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
Additionally, pip and setuptools (both Python components) are also required. If your distribution or Python installation does not provide for these, see [https://pip.pypa.io/en/stable/installing/ Installing Pip] for manual instructions.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: By default, pip will perform per-user installations. To install globally for all users, you will need to use &amp;quot;sudo&amp;quot; (or run as Administrator on Windows).&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. There is not an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11096</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11096"/>
		<updated>2020-08-25T04:04:49Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Tup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback (see the bottom of this page) if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
AMBuild 2.2 is the latest release. It supports cross-compiling, multi-architecture builds, and precompiled headers.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 2.7 or higher is required. If using Python 3, then 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
Additionally, pip and setuptools (both Python components) are also required. If your distribution or Python installation does not provide for these, see [https://pip.pypa.io/en/stable/installing/ Installing Pip] for manual instructions.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: By default, pip will perform per-user installations. To install globally for all users, you will need to use &amp;quot;sudo&amp;quot; (or run as Administrator on Windows).&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. There is not an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11095</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11095"/>
		<updated>2020-08-25T04:02:22Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Make, Accuracy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback (see the bottom of this page) if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
AMBuild 2.2 is the latest release. It supports cross-compiling, multi-architecture builds, and precompiled headers.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 2.7 or higher is required. If using Python 3, then 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
Additionally, pip and setuptools (both Python components) are also required. If your distribution or Python installation does not provide for these, see [https://pip.pypa.io/en/stable/installing/ Installing Pip] for manual instructions.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: By default, pip will perform per-user installations. To install globally for all users, you will need to use &amp;quot;sudo&amp;quot; (or run as Administrator on Windows).&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. There is not an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;br /&gt;
&lt;br /&gt;
==Tup==&lt;br /&gt;
AMBuild is designed to be, essentially, a miniature clone of Tup written entirely in Python. In particular it closely follows concepts in [http://gittup.org/tup/build_system_rules_and_algorithms.pdf the Tup whitepaper]. However there are a few differences that may make one more desirable over the other:&lt;br /&gt;
* Tup has been around longer than AMBuild 2, and has been more thoroughly tested. &lt;br /&gt;
* Tup uses complex file system features to optimize updates. Algorithms that are O(n) in AMBuild tend to be O(1) in Tup.&lt;br /&gt;
* AMBuild only requires a default Python installation to work. Tup, due to being written in C and using very platform specific file system features, may not be as accessible.&lt;br /&gt;
* Tup has more features for speeding up very large projects. It can do minimal reparsing and it can reduce the number of links in large graphs.&lt;br /&gt;
* AMBuild is designed to be a front-end in addition to a back-end. It has a simple API and script syntax, and is designed to support multiple output formats. For example, it could conceivably generate Visual Studio or XCode project files.&lt;br /&gt;
&lt;br /&gt;
Since AMBuild is also a frontend, AMBuild may one day eliminate its backend in favor of emitting Tupfiles instead.&lt;br /&gt;
&lt;br /&gt;
AMBuild's IPC implementation is very low-level, and it has not yet been ported beyond Windows, Mac/BSD, or Linux. However it's not difficult to port to Unix-like systems, and if needed a generic (albeit suboptimal) cross-platform implementation could be provided.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_Tutorial&amp;diff=11094</id>
		<title>AMBuild Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_Tutorial&amp;diff=11094"/>
		<updated>2020-08-25T04:00:27Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Multiple Scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Writing project files with AMBuild is fairly easy. This tutorial will guide you through making simple AMBuild scripts to compile and package a C++ project.&lt;br /&gt;
&lt;br /&gt;
For information on the full API, see [[AMBuild API]].&lt;br /&gt;
&lt;br /&gt;
==Simple Project==&lt;br /&gt;
To begin, let's say we have a sample project with the following files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
goodbye.cpp  helpers.cpp  README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To start, we need to generate a default AMBuild configure script. This is the script that will perform the &amp;quot;configure&amp;quot; step for your build. You can generate one with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --new-project&lt;br /&gt;
$ ls&lt;br /&gt;
AMBuildScript  configure.py  goodbye.cpp  helpers.cpp  README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The configure script simply invokes AMBuild. It can be modified (as we'll see later) to take extra command line options.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cat configure.py&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys&lt;br /&gt;
from ambuild2 import run&lt;br /&gt;
&lt;br /&gt;
prep = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
prep.Configure()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, we're ready to actually make a build script for our project. The master build script must be a file called &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;, and it must be written in [http://python.org/ Python] syntax. The full Python API on your system is available to AMBuild scripts, but the important aspect we'll deal with here is the AMBuild API.&lt;br /&gt;
&lt;br /&gt;
The first step is to tell AMBuild to detect the first available C or C++ compiler. This is done with the following line:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With just this line in your build script, you can now try to configure build. You should see something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ python ../configure.py&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you get an error - it's likely you don't have a compiler installed. Make sure gcc, clang, or Microsoft Visual Studio is available where appropriate.&lt;br /&gt;
&lt;br /&gt;
Now, we're ready to complete our AMBuildScript:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
program = cxx.Program(&amp;quot;hello&amp;quot;)&lt;br /&gt;
program.sources = [&lt;br /&gt;
  'main.cpp',&lt;br /&gt;
  'helpers.cpp',&lt;br /&gt;
]&lt;br /&gt;
builder.Add(program)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object is an instance of an AMBuild ''context'' - more about this is in the [[AMBuild API]] documentation. Every AMBuild script has access to a &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;builder.cxx&amp;lt;/tt&amp;gt; object has information about the C/C++ compiler for the configure session. The &amp;lt;tt&amp;gt;Program()&amp;lt;/tt&amp;gt; method will return an object used to create C++ compilation tasks. In this case, we're asking to build an executable that will be named 'hello' (or &amp;lt;tt&amp;gt;hello.exe&amp;lt;/tt&amp;gt; on Windows). You can also specified shared libraries with &amp;lt;tt&amp;gt;Library&amp;lt;/tt&amp;gt;, and static libraries with &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can attach a list of source files to your Program via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute. Finally, use &amp;lt;tt&amp;gt;builder.Add&amp;lt;/tt&amp;gt; to take your C++ configuration and construct the necessary dependency graph and build steps.&lt;br /&gt;
&lt;br /&gt;
Now, we can actually attempt to build. First, let's make sure AMBuild computed our graph and dependencies correctly:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ python ../configure.py&lt;br /&gt;
$ ambuild --show-graph&lt;br /&gt;
 : mkdir &amp;quot;hello&amp;quot;&lt;br /&gt;
 - hello/hello&lt;br /&gt;
   - c++ main.o helpers.o -o hello&lt;br /&gt;
     - hello/main.o&lt;br /&gt;
       - [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
         - /home/dvander/projects/ambuild/ambuild2/main.cpp&lt;br /&gt;
     - hello/helpers.o&lt;br /&gt;
       - [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
         - /home/dvander/projects/ambuild/ambuild2/helpers.cpp&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
mkdir -p hello&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
  -&amp;gt; hello/main.o&lt;br /&gt;
task 1: [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
  -&amp;gt; hello/helpers.o&lt;br /&gt;
task 2: c++ main.o helpers.o -o hello&lt;br /&gt;
  -&amp;gt; hello/hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It looks good! Now we can build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild&lt;br /&gt;
mkdir -p hello&lt;br /&gt;
Spawned task master (pid: 15563)&lt;br /&gt;
Spawned worker (pid: 15564)&lt;br /&gt;
Spawned worker (pid: 15565)&lt;br /&gt;
[15564] c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
[15565] c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
[15565] c++ main.o helpers.o -o hello&lt;br /&gt;
[15565] Child process terminating normally.&lt;br /&gt;
[15564] Child process terminating normally.&lt;br /&gt;
[15563] Child process terminating normally.&lt;br /&gt;
Build succeeded.&lt;br /&gt;
$ ./hello/hello&lt;br /&gt;
Hello!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that AMBuild gives each C++ binary its own folder. For example, if you build a static library called &amp;lt;tt&amp;gt;egg.a&amp;lt;/tt&amp;gt;, a shared library called &amp;lt;tt&amp;gt;egg.so&amp;lt;/tt&amp;gt;, and an executable called &amp;lt;tt&amp;gt;egg&amp;lt;/tt&amp;gt; all in the same folder, AMBuild will actually perform each of these builds in separate folders, and the binary paths will look like:&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg.a/egg.a&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg.so/egg.so&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg/egg&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is to allow complex build scenarios where the same files are rebuilt multiple times.&lt;br /&gt;
&lt;br /&gt;
==Packaging==&lt;br /&gt;
&lt;br /&gt;
Now that our project builds, let's add to our build script so that we can create a build package. We'd like to make a folder we can zip or tar for distribution, with the following files:&lt;br /&gt;
* &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt;, our readme&lt;br /&gt;
* &amp;lt;tt&amp;gt;hello&amp;lt;/tt&amp;gt;, our final binary&lt;br /&gt;
&lt;br /&gt;
First, we have to add a step to the build to create the distribution folder:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
dist_folder = builder.AddFolder('dist')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The return value from &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; is a dependency graph node, that we can use as an input to future steps.&lt;br /&gt;
&lt;br /&gt;
Now we can copy our files:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
outputs = builder.Add(program)&lt;br /&gt;
&lt;br /&gt;
folder = builder.AddFolder('dist')&lt;br /&gt;
builder.AddCopy(os.path.join(builder.sourcePath, 'README.txt'), folder)&lt;br /&gt;
builder.AddCopy(outputs.binary, folder)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; can be copied directly from the source tree. To copy the executable, we use the return value of &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;. We could construct its path ourselves, but having the dependency object already available is much more convenient.&lt;br /&gt;
&lt;br /&gt;
Now, when we build, we see:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
[5952] cp &amp;quot;/home/dvander/projects/ambuild/ambuild2/README.txt&amp;quot; &amp;quot;./dist/README.txt&amp;quot;&lt;br /&gt;
Spawned worker (pid: 5953)&lt;br /&gt;
[5952] c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
[5954] c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
[5954] c++ main.o helpers.o -o hello&lt;br /&gt;
[5954] cp &amp;quot;hello/hello&amp;quot; &amp;quot;./dist/hello&amp;quot;&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since copying &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; has no dependencies, it can execute in parallel with other jobs, even before compilation has finished. It won't be copied again unless &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; changes. However the copy of &amp;lt;tt&amp;gt;hello/hello&amp;lt;/tt&amp;gt; has to occur last. We can see that it succeeded with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -l dist/&lt;br /&gt;
total 12&lt;br /&gt;
-rwxr-xr-x 1 dvander dvander 7036 Oct 16 22:32 hello&lt;br /&gt;
-rw-r--r-- 1 dvander dvander   23 Oct 16 22:32 README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is also possible to add a step to execute a command like &amp;quot;tar&amp;quot; or &amp;quot;zip&amp;quot;, but there's a complication. There must be a dependency to every file that would be included in the command, otherwise, the commands might occur out of order. We are still looking into easier ways to automate this.&lt;br /&gt;
&lt;br /&gt;
==Multiple Scripts==&lt;br /&gt;
&lt;br /&gt;
Non-trivial projects usually need more than one build script. AMBuild allows build scripts to nest; any script can run another script. Each script gets its own &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, known internally as a ''context''. All jobs are created within a context and associated with that context. This allows AMBuild to reparse a minimal number of build scripts when a build script changes.&lt;br /&gt;
&lt;br /&gt;
Contexts, by default, are associated with the folder they exist in relative to the source tree. For example, a build script in &amp;lt;tt&amp;gt;/source-tree/src/game/AMBuild&amp;lt;/tt&amp;gt; will have a context associated with &amp;lt;tt&amp;gt;src/game&amp;lt;/tt&amp;gt;. This folder structure is mirrored in the build folder, and all jobs occur within the context's local folder. For example, let's move our packaging into a separate script, &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# PackageScript&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
builder.SetBuildFolder('dist')&lt;br /&gt;
builder.AddCopy(os.path.join(builder.sourcePath, 'README.txt'), '.')&lt;br /&gt;
builder.AddCopy(Hello.binary, '.')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we modify our main &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
&lt;br /&gt;
program = cxx.Program(&amp;quot;hello&amp;quot;)&lt;br /&gt;
program.sources = [&lt;br /&gt;
  'main.cpp',&lt;br /&gt;
  'helpers.cpp',&lt;br /&gt;
]&lt;br /&gt;
outputs = builder.Add(program)&lt;br /&gt;
&lt;br /&gt;
builder.Build(&lt;br /&gt;
  ['PackageScript'],&lt;br /&gt;
  { 'Hello': outputs }&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter is an array of script paths to run, and the second is a dictionary of global variables to give each script. Note that since our &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt; is in the root of the source tree, by default its build folder is &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, so we manually override its build folder.&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt; is parsed during the configure step, all of its jobs will automatically be configured to occur inside a &amp;lt;tt&amp;gt;dist&amp;lt;/tt&amp;gt; folder within the build folder, so &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt; actually refers to &amp;lt;tt&amp;gt;./dist/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you have only one script, you can use &amp;lt;tt&amp;gt;Build&amp;lt;/tt&amp;gt; instead. This also lets scripts return a value. For example:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
folders = builder.Build('MakeFolders')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# MakeFolders&lt;br /&gt;
folders = [&lt;br /&gt;
  builder.AddFolder('egg'),&lt;br /&gt;
  builder.AddFolder('yam'),&lt;br /&gt;
  builder.AddFolder('plant'),&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Magic variable; assigning to &amp;quot;rvalue&amp;quot; will propagate the value&lt;br /&gt;
# back up to Build().&lt;br /&gt;
rvalue = folders&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is possible to pass variables to other scripts (they appear as global variables), or they can be attached to the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object and they will automatically be propagated down. It's useful to propagate compiler objects this way, so they don't have to be re-detected and reconfigured in every subsequent script. For more information, see [[AMBuild API]].&lt;br /&gt;
&lt;br /&gt;
For example, to pass our compiler around, we can use:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
builder.cxx = builder.DetectCxx()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead. This does not work for multi-architecture builds (for example, a single build producing x86 and x86_64 binaries), so if you support those, you will need a list of compilers instead.&lt;br /&gt;
&lt;br /&gt;
==Custom Options==&lt;br /&gt;
&lt;br /&gt;
It is possible to add custom options to the configure step using Python's [http://docs.python.org/2/library/optparse.html optparse] module. Recall the default &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; that AMBuild generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys, ambuild2.run&lt;br /&gt;
&lt;br /&gt;
parser = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
parser.Configure()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;parser&amp;lt;/tt&amp;gt; object has an &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; attribute, which is an instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;. You can add to it, for example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys, ambuild2.run&lt;br /&gt;
&lt;br /&gt;
parser = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
parser.options.add_argument('--enable-debug', action='store_true', dest='debug', default=False,&lt;br /&gt;
                            help='Enable debugging symbols')&lt;br /&gt;
parser.options.add_argument('--enable-optimize', action='store_true', dest='opt', default=False,&lt;br /&gt;
                            help='Enable optimization')&lt;br /&gt;
parser.Configure()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These options can be accessed from any &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
if builder.options.debug:&lt;br /&gt;
  cxx.cflags += ['-O0', '-ggdb3']&lt;br /&gt;
  cxx.cdefines += ['DEBUG']&lt;br /&gt;
if builder.options.opt:&lt;br /&gt;
  cxx.cflags += ['-O3']&lt;br /&gt;
  cxx.cdefines += ['NDEBUG']&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Weak Dependencies==&lt;br /&gt;
&lt;br /&gt;
Sometimes it is useful to force build steps to occur in distinct phases. Normally, this would be the antithesis of what we want: the dependency graph should precisely and perfectly represent dependencies, and there should be no need to enforce order manually. That's true, but there are situations that warrant relaxing how we construct the graph.&lt;br /&gt;
&lt;br /&gt;
One example is generated headers in particular pose a problem. If we created dependencies on a &amp;quot;generate headers&amp;quot; task, then generating new headers would trigger recompiling every source file - even ones that never included those headers. Furthermore, if we created dependencies on each individual generated header, we'd have a huge dependency graph - 50 includes and 800 source files would mean 80,000 dependency links. AMBuild solves the first problem in the same way [http://gittup.org/tup/ tup] does. We do not yet attempt to solve the second problem, though it is planned for the future.&lt;br /&gt;
&lt;br /&gt;
First, we introduce the concept of a ''weak dependency''. A weak dependency is one that theoretically exists, and must exist for ordering, but does not propagate damage. For example, let's say that &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; has a weak dependency on &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; doesn't &amp;lt;tt&amp;gt;#include &amp;quot;generated.h&amp;quot;&amp;lt;/tt&amp;gt;, then no changes to &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt; should ever trigger a rebuild of &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt;. However, if &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; is changed to include &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt;, then the weak dependency ensures those jobs are executed in the right order. (It is illegal in AMBuild to depend on a generated file without having an explicit dependency.) The weak dependency can then be upgraded to a strong dependency, and possibly downgraded again later if the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; is removed.&lt;br /&gt;
&lt;br /&gt;
As an example, let's say we have two steps: generating headers and actual compilation. First, we add a shell command and save its outputs in a global variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
generated_headers = builder.AddCommand(&lt;br /&gt;
  argv = ['python', os.path.join(builder.buildPath, 'tools', 'buildbot', 'generate_headers.py')],&lt;br /&gt;
  inputs = [os.path.join(builder.sourcePath, '.hg', 'dirstate')],&lt;br /&gt;
  outputs = ['sourcemod_auto_version.h']&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In another build script, assuming we communicated the &amp;lt;tt&amp;gt;headers&amp;lt;/tt&amp;gt; object through, we could add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
library = cxx.Library('cstrike')&lt;br /&gt;
library.sources = ['cstrike.cpp', 'smsdk_ext.cpp']&lt;br /&gt;
library.sourcedeps += generated_headers&lt;br /&gt;
builder.Add(library)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now when our generated headers change, we are guaranteed that if our library's sources need to be recompiled, they will be compiled after the headers are generated.&lt;br /&gt;
&lt;br /&gt;
==Many Source Groups==&lt;br /&gt;
&lt;br /&gt;
Projects may have complex components that form a single, monolithic unit. For example, portions of code may need certain compile options that other areas do not need. This can be accomplished in AMBuild using modules. For example, the root of a project might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
program = cxx.Program('sample')&lt;br /&gt;
&lt;br /&gt;
builder.Build(['cairo/AMBuild', 'gtk/AMBuild'], {&lt;br /&gt;
  'program': program&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
builder.Add(program)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, &amp;lt;tt&amp;gt;cairo/AMBuild&amp;lt;/tt&amp;gt; can do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
module = program.Module(builder, 'cairo')&lt;br /&gt;
module.sources += [&lt;br /&gt;
  'file.cc',&lt;br /&gt;
]&lt;br /&gt;
module.cxxflags += ['-Wno-flag-needed-for-cairo']&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The module will build as part of the entire binary.&lt;br /&gt;
&lt;br /&gt;
==Reconfiguring==&lt;br /&gt;
&lt;br /&gt;
Reconfiguring can happen for two reasons. One is if you change some properties of the build, for example, configuring a debug build over an existing optimized build. Another is if a build script changes, AMBuild will automatically reconfigure the build using the previous configure options.&lt;br /&gt;
&lt;br /&gt;
===Output Cleaning===&lt;br /&gt;
When a reconfigure occurs, AMBuild will produce a new dependency graph alongside the old dependency graph, and these graphs are then merged. Any generated files in the old graph that are not present in the new graph are removed from the file system. This is necessary to ensure that builds do not become inconsistent or corrupt: every incremental build should be identical to a clean build.&lt;br /&gt;
&lt;br /&gt;
For example, our object folder for our original script might look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander  933 Nov 11 02:26 goodbye.o&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander 1232 Nov 11 02:26 helpers.o&lt;br /&gt;
-rwxrwxr-x 1 dvander dvander 8509 Nov 11 02:26 sample&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we comment out 'goodbye.cpp' from &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;, and build again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Reparsing build scripts.&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', '-fno-exceptions', '-fno-rtti', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Removing old output: sample/goodbye.o&lt;br /&gt;
Spawned taskmaster (pid: 41899)&lt;br /&gt;
Spawned worker (pid: 41900)&lt;br /&gt;
[41900] c++ helpers.o -o sample&lt;br /&gt;
Build succeeded.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And indeed, &amp;lt;tt&amp;gt;goodbye.o&amp;lt;/tt&amp;gt; is gone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander 1232 Nov 11 02:26 helpers.o&lt;br /&gt;
-rwxrwxr-x 1 dvander dvander 8473 Nov 11 02:28 sample&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Minimal Reparsing===&lt;br /&gt;
Unlike the normal dependency graph, AMBuild scripts can depend on each other. For example, a nested script may propagate a graph object back to the root script, which then propagates it down again. This creates an implicit cycle: if either script changes, the entire cycle must be reparsed. Avoiding this is extremely difficult as it is easy to construct situations in which a minimal reparse algorithm would fail. Thus, at the moment, AMBuild performs full reparses instead.&lt;br /&gt;
&lt;br /&gt;
If this becomes a performance bottleneck, which it might in a huge project with hundreds of build scripts, we would like to implement minimal reparsing. It would likely require transitioning to a more restricted API that disallows (or discourages) arbitrary dataflow between build scripts. To solve the problem mentioned earlier, we would need specific functions that allow AMBuild to track script inter-dependencies.&lt;br /&gt;
&lt;br /&gt;
Even with full reparsing however, AMBuild will only remove or rebuild individual jobs that have changed. If you add a single .cpp file to a source list, a full reparse will only result in that file being built and its binary relinked (and of course, any tasks depending on that binary).&lt;br /&gt;
&lt;br /&gt;
===Refactoring===&lt;br /&gt;
Sometimes, it is useful to see whether changing build scripts would actually change the dependency graph. For example, refactoring them, or tracking down excessive rebuild problems. In Tup, this can be done with a &amp;quot;refactoring&amp;quot; build, and AMBuild (sort of) supports this feature. It is still new and may not catch all problems.&lt;br /&gt;
&lt;br /&gt;
An example of a refactoring build where the dependency graph has changed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dvander@linux64:~/temp$ ambuild --refactor obj-linux-x86_64&lt;br /&gt;
Reparsing build scripts.&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', '-fno-exceptions', '-fno-rtti', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
New output introduced: sample&lt;br /&gt;
Failed to reparse build scripts.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_Tutorial&amp;diff=11093</id>
		<title>AMBuild Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_Tutorial&amp;diff=11093"/>
		<updated>2020-08-25T03:58:12Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Multiple Scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Writing project files with AMBuild is fairly easy. This tutorial will guide you through making simple AMBuild scripts to compile and package a C++ project.&lt;br /&gt;
&lt;br /&gt;
For information on the full API, see [[AMBuild API]].&lt;br /&gt;
&lt;br /&gt;
==Simple Project==&lt;br /&gt;
To begin, let's say we have a sample project with the following files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
goodbye.cpp  helpers.cpp  README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To start, we need to generate a default AMBuild configure script. This is the script that will perform the &amp;quot;configure&amp;quot; step for your build. You can generate one with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --new-project&lt;br /&gt;
$ ls&lt;br /&gt;
AMBuildScript  configure.py  goodbye.cpp  helpers.cpp  README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The configure script simply invokes AMBuild. It can be modified (as we'll see later) to take extra command line options.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cat configure.py&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys&lt;br /&gt;
from ambuild2 import run&lt;br /&gt;
&lt;br /&gt;
prep = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
prep.Configure()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, we're ready to actually make a build script for our project. The master build script must be a file called &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;, and it must be written in [http://python.org/ Python] syntax. The full Python API on your system is available to AMBuild scripts, but the important aspect we'll deal with here is the AMBuild API.&lt;br /&gt;
&lt;br /&gt;
The first step is to tell AMBuild to detect the first available C or C++ compiler. This is done with the following line:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With just this line in your build script, you can now try to configure build. You should see something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ python ../configure.py&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you get an error - it's likely you don't have a compiler installed. Make sure gcc, clang, or Microsoft Visual Studio is available where appropriate.&lt;br /&gt;
&lt;br /&gt;
Now, we're ready to complete our AMBuildScript:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
program = cxx.Program(&amp;quot;hello&amp;quot;)&lt;br /&gt;
program.sources = [&lt;br /&gt;
  'main.cpp',&lt;br /&gt;
  'helpers.cpp',&lt;br /&gt;
]&lt;br /&gt;
builder.Add(program)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object is an instance of an AMBuild ''context'' - more about this is in the [[AMBuild API]] documentation. Every AMBuild script has access to a &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;builder.cxx&amp;lt;/tt&amp;gt; object has information about the C/C++ compiler for the configure session. The &amp;lt;tt&amp;gt;Program()&amp;lt;/tt&amp;gt; method will return an object used to create C++ compilation tasks. In this case, we're asking to build an executable that will be named 'hello' (or &amp;lt;tt&amp;gt;hello.exe&amp;lt;/tt&amp;gt; on Windows). You can also specified shared libraries with &amp;lt;tt&amp;gt;Library&amp;lt;/tt&amp;gt;, and static libraries with &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can attach a list of source files to your Program via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute. Finally, use &amp;lt;tt&amp;gt;builder.Add&amp;lt;/tt&amp;gt; to take your C++ configuration and construct the necessary dependency graph and build steps.&lt;br /&gt;
&lt;br /&gt;
Now, we can actually attempt to build. First, let's make sure AMBuild computed our graph and dependencies correctly:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ python ../configure.py&lt;br /&gt;
$ ambuild --show-graph&lt;br /&gt;
 : mkdir &amp;quot;hello&amp;quot;&lt;br /&gt;
 - hello/hello&lt;br /&gt;
   - c++ main.o helpers.o -o hello&lt;br /&gt;
     - hello/main.o&lt;br /&gt;
       - [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
         - /home/dvander/projects/ambuild/ambuild2/main.cpp&lt;br /&gt;
     - hello/helpers.o&lt;br /&gt;
       - [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
         - /home/dvander/projects/ambuild/ambuild2/helpers.cpp&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
mkdir -p hello&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
  -&amp;gt; hello/main.o&lt;br /&gt;
task 1: [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
  -&amp;gt; hello/helpers.o&lt;br /&gt;
task 2: c++ main.o helpers.o -o hello&lt;br /&gt;
  -&amp;gt; hello/hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It looks good! Now we can build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild&lt;br /&gt;
mkdir -p hello&lt;br /&gt;
Spawned task master (pid: 15563)&lt;br /&gt;
Spawned worker (pid: 15564)&lt;br /&gt;
Spawned worker (pid: 15565)&lt;br /&gt;
[15564] c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
[15565] c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
[15565] c++ main.o helpers.o -o hello&lt;br /&gt;
[15565] Child process terminating normally.&lt;br /&gt;
[15564] Child process terminating normally.&lt;br /&gt;
[15563] Child process terminating normally.&lt;br /&gt;
Build succeeded.&lt;br /&gt;
$ ./hello/hello&lt;br /&gt;
Hello!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that AMBuild gives each C++ binary its own folder. For example, if you build a static library called &amp;lt;tt&amp;gt;egg.a&amp;lt;/tt&amp;gt;, a shared library called &amp;lt;tt&amp;gt;egg.so&amp;lt;/tt&amp;gt;, and an executable called &amp;lt;tt&amp;gt;egg&amp;lt;/tt&amp;gt; all in the same folder, AMBuild will actually perform each of these builds in separate folders, and the binary paths will look like:&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg.a/egg.a&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg.so/egg.so&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg/egg&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is to allow complex build scenarios where the same files are rebuilt multiple times.&lt;br /&gt;
&lt;br /&gt;
==Packaging==&lt;br /&gt;
&lt;br /&gt;
Now that our project builds, let's add to our build script so that we can create a build package. We'd like to make a folder we can zip or tar for distribution, with the following files:&lt;br /&gt;
* &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt;, our readme&lt;br /&gt;
* &amp;lt;tt&amp;gt;hello&amp;lt;/tt&amp;gt;, our final binary&lt;br /&gt;
&lt;br /&gt;
First, we have to add a step to the build to create the distribution folder:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
dist_folder = builder.AddFolder('dist')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The return value from &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; is a dependency graph node, that we can use as an input to future steps.&lt;br /&gt;
&lt;br /&gt;
Now we can copy our files:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
outputs = builder.Add(program)&lt;br /&gt;
&lt;br /&gt;
folder = builder.AddFolder('dist')&lt;br /&gt;
builder.AddCopy(os.path.join(builder.sourcePath, 'README.txt'), folder)&lt;br /&gt;
builder.AddCopy(outputs.binary, folder)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; can be copied directly from the source tree. To copy the executable, we use the return value of &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;. We could construct its path ourselves, but having the dependency object already available is much more convenient.&lt;br /&gt;
&lt;br /&gt;
Now, when we build, we see:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
[5952] cp &amp;quot;/home/dvander/projects/ambuild/ambuild2/README.txt&amp;quot; &amp;quot;./dist/README.txt&amp;quot;&lt;br /&gt;
Spawned worker (pid: 5953)&lt;br /&gt;
[5952] c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
[5954] c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
[5954] c++ main.o helpers.o -o hello&lt;br /&gt;
[5954] cp &amp;quot;hello/hello&amp;quot; &amp;quot;./dist/hello&amp;quot;&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since copying &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; has no dependencies, it can execute in parallel with other jobs, even before compilation has finished. It won't be copied again unless &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; changes. However the copy of &amp;lt;tt&amp;gt;hello/hello&amp;lt;/tt&amp;gt; has to occur last. We can see that it succeeded with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -l dist/&lt;br /&gt;
total 12&lt;br /&gt;
-rwxr-xr-x 1 dvander dvander 7036 Oct 16 22:32 hello&lt;br /&gt;
-rw-r--r-- 1 dvander dvander   23 Oct 16 22:32 README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is also possible to add a step to execute a command like &amp;quot;tar&amp;quot; or &amp;quot;zip&amp;quot;, but there's a complication. There must be a dependency to every file that would be included in the command, otherwise, the commands might occur out of order. We are still looking into easier ways to automate this.&lt;br /&gt;
&lt;br /&gt;
==Multiple Scripts==&lt;br /&gt;
&lt;br /&gt;
Non-trivial projects usually need more than one build script. AMBuild allows build scripts to nest; any script can run another script. Each script gets its own &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, known internally as a ''context''. All jobs are created within a context and associated with that context. This allows AMBuild to reparse a minimal number of build scripts when a build script changes.&lt;br /&gt;
&lt;br /&gt;
Contexts, by default, are associated with the folder they exist in relative to the source tree. For example, a build script in &amp;lt;tt&amp;gt;/source-tree/src/game/AMBuild&amp;lt;/tt&amp;gt; will have a context associated with &amp;lt;tt&amp;gt;src/game&amp;lt;/tt&amp;gt;. This folder structure is mirrored in the build folder, and all jobs occur within the context's local folder. For example, let's move our packaging into a separate script, &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# PackageScript&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
builder.SetBuildFolder('dist')&lt;br /&gt;
builder.AddCopy(os.path.join(builder.sourcePath, 'README.txt'), '.')&lt;br /&gt;
builder.AddCopy(Hello.binary, '.')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we modify our main &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
builder.DetectCxx()&lt;br /&gt;
&lt;br /&gt;
program = cxx.Program(&amp;quot;hello&amp;quot;)&lt;br /&gt;
program.sources = [&lt;br /&gt;
  'main.cpp',&lt;br /&gt;
  'helpers.cpp',&lt;br /&gt;
]&lt;br /&gt;
outputs = builder.Add(program)&lt;br /&gt;
&lt;br /&gt;
builder.Build(&lt;br /&gt;
  ['PackageScript'],&lt;br /&gt;
  { 'Hello': outputs }&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter is an array of script paths to run, and the second is a dictionary of global variables to give each script. Note that since our &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt; is in the root of the source tree, by default its build folder is &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, so we manually override its build folder.&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt; is parsed during the configure step, all of its jobs will automatically be configured to occur inside a &amp;lt;tt&amp;gt;dist&amp;lt;/tt&amp;gt; folder within the build folder, so &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt; actually refers to &amp;lt;tt&amp;gt;./dist/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you have only one script, you can use &amp;lt;tt&amp;gt;Build&amp;lt;/tt&amp;gt; instead. This also lets scripts return a value. For example:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
folders = builder.Build('MakeFolders')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# MakeFolders&lt;br /&gt;
folders = [&lt;br /&gt;
  builder.AddFolder('egg'),&lt;br /&gt;
  builder.AddFolder('yam'),&lt;br /&gt;
  builder.AddFolder('plant'),&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Magic variable; assigning to &amp;quot;rvalue&amp;quot; will propagate the value&lt;br /&gt;
# back up to Build().&lt;br /&gt;
rvalue = folders&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is possible to pass variables to other scripts (they appear as global variables), or they can be attached to the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object and they will automatically be propagated down. It's useful to propagate compiler objects this way, so they don't have to be re-detected and reconfigured in every subsequent script. For more information, see [[AMBuild API]].&lt;br /&gt;
&lt;br /&gt;
==Custom Options==&lt;br /&gt;
&lt;br /&gt;
It is possible to add custom options to the configure step using Python's [http://docs.python.org/2/library/optparse.html optparse] module. Recall the default &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; that AMBuild generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys, ambuild2.run&lt;br /&gt;
&lt;br /&gt;
parser = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
parser.Configure()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;parser&amp;lt;/tt&amp;gt; object has an &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; attribute, which is an instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;. You can add to it, for example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys, ambuild2.run&lt;br /&gt;
&lt;br /&gt;
parser = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
parser.options.add_argument('--enable-debug', action='store_true', dest='debug', default=False,&lt;br /&gt;
                            help='Enable debugging symbols')&lt;br /&gt;
parser.options.add_argument('--enable-optimize', action='store_true', dest='opt', default=False,&lt;br /&gt;
                            help='Enable optimization')&lt;br /&gt;
parser.Configure()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These options can be accessed from any &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
if builder.options.debug:&lt;br /&gt;
  cxx.cflags += ['-O0', '-ggdb3']&lt;br /&gt;
  cxx.cdefines += ['DEBUG']&lt;br /&gt;
if builder.options.opt:&lt;br /&gt;
  cxx.cflags += ['-O3']&lt;br /&gt;
  cxx.cdefines += ['NDEBUG']&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Weak Dependencies==&lt;br /&gt;
&lt;br /&gt;
Sometimes it is useful to force build steps to occur in distinct phases. Normally, this would be the antithesis of what we want: the dependency graph should precisely and perfectly represent dependencies, and there should be no need to enforce order manually. That's true, but there are situations that warrant relaxing how we construct the graph.&lt;br /&gt;
&lt;br /&gt;
One example is generated headers in particular pose a problem. If we created dependencies on a &amp;quot;generate headers&amp;quot; task, then generating new headers would trigger recompiling every source file - even ones that never included those headers. Furthermore, if we created dependencies on each individual generated header, we'd have a huge dependency graph - 50 includes and 800 source files would mean 80,000 dependency links. AMBuild solves the first problem in the same way [http://gittup.org/tup/ tup] does. We do not yet attempt to solve the second problem, though it is planned for the future.&lt;br /&gt;
&lt;br /&gt;
First, we introduce the concept of a ''weak dependency''. A weak dependency is one that theoretically exists, and must exist for ordering, but does not propagate damage. For example, let's say that &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; has a weak dependency on &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; doesn't &amp;lt;tt&amp;gt;#include &amp;quot;generated.h&amp;quot;&amp;lt;/tt&amp;gt;, then no changes to &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt; should ever trigger a rebuild of &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt;. However, if &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; is changed to include &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt;, then the weak dependency ensures those jobs are executed in the right order. (It is illegal in AMBuild to depend on a generated file without having an explicit dependency.) The weak dependency can then be upgraded to a strong dependency, and possibly downgraded again later if the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; is removed.&lt;br /&gt;
&lt;br /&gt;
As an example, let's say we have two steps: generating headers and actual compilation. First, we add a shell command and save its outputs in a global variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
generated_headers = builder.AddCommand(&lt;br /&gt;
  argv = ['python', os.path.join(builder.buildPath, 'tools', 'buildbot', 'generate_headers.py')],&lt;br /&gt;
  inputs = [os.path.join(builder.sourcePath, '.hg', 'dirstate')],&lt;br /&gt;
  outputs = ['sourcemod_auto_version.h']&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In another build script, assuming we communicated the &amp;lt;tt&amp;gt;headers&amp;lt;/tt&amp;gt; object through, we could add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
library = cxx.Library('cstrike')&lt;br /&gt;
library.sources = ['cstrike.cpp', 'smsdk_ext.cpp']&lt;br /&gt;
library.sourcedeps += generated_headers&lt;br /&gt;
builder.Add(library)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now when our generated headers change, we are guaranteed that if our library's sources need to be recompiled, they will be compiled after the headers are generated.&lt;br /&gt;
&lt;br /&gt;
==Many Source Groups==&lt;br /&gt;
&lt;br /&gt;
Projects may have complex components that form a single, monolithic unit. For example, portions of code may need certain compile options that other areas do not need. This can be accomplished in AMBuild using modules. For example, the root of a project might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
program = cxx.Program('sample')&lt;br /&gt;
&lt;br /&gt;
builder.Build(['cairo/AMBuild', 'gtk/AMBuild'], {&lt;br /&gt;
  'program': program&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
builder.Add(program)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, &amp;lt;tt&amp;gt;cairo/AMBuild&amp;lt;/tt&amp;gt; can do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
module = program.Module(builder, 'cairo')&lt;br /&gt;
module.sources += [&lt;br /&gt;
  'file.cc',&lt;br /&gt;
]&lt;br /&gt;
module.cxxflags += ['-Wno-flag-needed-for-cairo']&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The module will build as part of the entire binary.&lt;br /&gt;
&lt;br /&gt;
==Reconfiguring==&lt;br /&gt;
&lt;br /&gt;
Reconfiguring can happen for two reasons. One is if you change some properties of the build, for example, configuring a debug build over an existing optimized build. Another is if a build script changes, AMBuild will automatically reconfigure the build using the previous configure options.&lt;br /&gt;
&lt;br /&gt;
===Output Cleaning===&lt;br /&gt;
When a reconfigure occurs, AMBuild will produce a new dependency graph alongside the old dependency graph, and these graphs are then merged. Any generated files in the old graph that are not present in the new graph are removed from the file system. This is necessary to ensure that builds do not become inconsistent or corrupt: every incremental build should be identical to a clean build.&lt;br /&gt;
&lt;br /&gt;
For example, our object folder for our original script might look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander  933 Nov 11 02:26 goodbye.o&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander 1232 Nov 11 02:26 helpers.o&lt;br /&gt;
-rwxrwxr-x 1 dvander dvander 8509 Nov 11 02:26 sample&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we comment out 'goodbye.cpp' from &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;, and build again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Reparsing build scripts.&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', '-fno-exceptions', '-fno-rtti', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Removing old output: sample/goodbye.o&lt;br /&gt;
Spawned taskmaster (pid: 41899)&lt;br /&gt;
Spawned worker (pid: 41900)&lt;br /&gt;
[41900] c++ helpers.o -o sample&lt;br /&gt;
Build succeeded.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And indeed, &amp;lt;tt&amp;gt;goodbye.o&amp;lt;/tt&amp;gt; is gone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander 1232 Nov 11 02:26 helpers.o&lt;br /&gt;
-rwxrwxr-x 1 dvander dvander 8473 Nov 11 02:28 sample&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Minimal Reparsing===&lt;br /&gt;
Unlike the normal dependency graph, AMBuild scripts can depend on each other. For example, a nested script may propagate a graph object back to the root script, which then propagates it down again. This creates an implicit cycle: if either script changes, the entire cycle must be reparsed. Avoiding this is extremely difficult as it is easy to construct situations in which a minimal reparse algorithm would fail. Thus, at the moment, AMBuild performs full reparses instead.&lt;br /&gt;
&lt;br /&gt;
If this becomes a performance bottleneck, which it might in a huge project with hundreds of build scripts, we would like to implement minimal reparsing. It would likely require transitioning to a more restricted API that disallows (or discourages) arbitrary dataflow between build scripts. To solve the problem mentioned earlier, we would need specific functions that allow AMBuild to track script inter-dependencies.&lt;br /&gt;
&lt;br /&gt;
Even with full reparsing however, AMBuild will only remove or rebuild individual jobs that have changed. If you add a single .cpp file to a source list, a full reparse will only result in that file being built and its binary relinked (and of course, any tasks depending on that binary).&lt;br /&gt;
&lt;br /&gt;
===Refactoring===&lt;br /&gt;
Sometimes, it is useful to see whether changing build scripts would actually change the dependency graph. For example, refactoring them, or tracking down excessive rebuild problems. In Tup, this can be done with a &amp;quot;refactoring&amp;quot; build, and AMBuild (sort of) supports this feature. It is still new and may not catch all problems.&lt;br /&gt;
&lt;br /&gt;
An example of a refactoring build where the dependency graph has changed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dvander@linux64:~/temp$ ambuild --refactor obj-linux-x86_64&lt;br /&gt;
Reparsing build scripts.&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', '-fno-exceptions', '-fno-rtti', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
New output introduced: sample&lt;br /&gt;
Failed to reparse build scripts.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_Tutorial&amp;diff=11092</id>
		<title>AMBuild Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_Tutorial&amp;diff=11092"/>
		<updated>2020-08-25T03:56:31Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Multiple Scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Writing project files with AMBuild is fairly easy. This tutorial will guide you through making simple AMBuild scripts to compile and package a C++ project.&lt;br /&gt;
&lt;br /&gt;
For information on the full API, see [[AMBuild API]].&lt;br /&gt;
&lt;br /&gt;
==Simple Project==&lt;br /&gt;
To begin, let's say we have a sample project with the following files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
goodbye.cpp  helpers.cpp  README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To start, we need to generate a default AMBuild configure script. This is the script that will perform the &amp;quot;configure&amp;quot; step for your build. You can generate one with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --new-project&lt;br /&gt;
$ ls&lt;br /&gt;
AMBuildScript  configure.py  goodbye.cpp  helpers.cpp  README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The configure script simply invokes AMBuild. It can be modified (as we'll see later) to take extra command line options.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cat configure.py&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys&lt;br /&gt;
from ambuild2 import run&lt;br /&gt;
&lt;br /&gt;
prep = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
prep.Configure()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, we're ready to actually make a build script for our project. The master build script must be a file called &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;, and it must be written in [http://python.org/ Python] syntax. The full Python API on your system is available to AMBuild scripts, but the important aspect we'll deal with here is the AMBuild API.&lt;br /&gt;
&lt;br /&gt;
The first step is to tell AMBuild to detect the first available C or C++ compiler. This is done with the following line:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With just this line in your build script, you can now try to configure build. You should see something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ python ../configure.py&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you get an error - it's likely you don't have a compiler installed. Make sure gcc, clang, or Microsoft Visual Studio is available where appropriate.&lt;br /&gt;
&lt;br /&gt;
Now, we're ready to complete our AMBuildScript:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
program = cxx.Program(&amp;quot;hello&amp;quot;)&lt;br /&gt;
program.sources = [&lt;br /&gt;
  'main.cpp',&lt;br /&gt;
  'helpers.cpp',&lt;br /&gt;
]&lt;br /&gt;
builder.Add(program)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object is an instance of an AMBuild ''context'' - more about this is in the [[AMBuild API]] documentation. Every AMBuild script has access to a &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;builder.cxx&amp;lt;/tt&amp;gt; object has information about the C/C++ compiler for the configure session. The &amp;lt;tt&amp;gt;Program()&amp;lt;/tt&amp;gt; method will return an object used to create C++ compilation tasks. In this case, we're asking to build an executable that will be named 'hello' (or &amp;lt;tt&amp;gt;hello.exe&amp;lt;/tt&amp;gt; on Windows). You can also specified shared libraries with &amp;lt;tt&amp;gt;Library&amp;lt;/tt&amp;gt;, and static libraries with &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can attach a list of source files to your Program via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute. Finally, use &amp;lt;tt&amp;gt;builder.Add&amp;lt;/tt&amp;gt; to take your C++ configuration and construct the necessary dependency graph and build steps.&lt;br /&gt;
&lt;br /&gt;
Now, we can actually attempt to build. First, let's make sure AMBuild computed our graph and dependencies correctly:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ python ../configure.py&lt;br /&gt;
$ ambuild --show-graph&lt;br /&gt;
 : mkdir &amp;quot;hello&amp;quot;&lt;br /&gt;
 - hello/hello&lt;br /&gt;
   - c++ main.o helpers.o -o hello&lt;br /&gt;
     - hello/main.o&lt;br /&gt;
       - [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
         - /home/dvander/projects/ambuild/ambuild2/main.cpp&lt;br /&gt;
     - hello/helpers.o&lt;br /&gt;
       - [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
         - /home/dvander/projects/ambuild/ambuild2/helpers.cpp&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
mkdir -p hello&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
  -&amp;gt; hello/main.o&lt;br /&gt;
task 1: [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
  -&amp;gt; hello/helpers.o&lt;br /&gt;
task 2: c++ main.o helpers.o -o hello&lt;br /&gt;
  -&amp;gt; hello/hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It looks good! Now we can build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild&lt;br /&gt;
mkdir -p hello&lt;br /&gt;
Spawned task master (pid: 15563)&lt;br /&gt;
Spawned worker (pid: 15564)&lt;br /&gt;
Spawned worker (pid: 15565)&lt;br /&gt;
[15564] c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
[15565] c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
[15565] c++ main.o helpers.o -o hello&lt;br /&gt;
[15565] Child process terminating normally.&lt;br /&gt;
[15564] Child process terminating normally.&lt;br /&gt;
[15563] Child process terminating normally.&lt;br /&gt;
Build succeeded.&lt;br /&gt;
$ ./hello/hello&lt;br /&gt;
Hello!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that AMBuild gives each C++ binary its own folder. For example, if you build a static library called &amp;lt;tt&amp;gt;egg.a&amp;lt;/tt&amp;gt;, a shared library called &amp;lt;tt&amp;gt;egg.so&amp;lt;/tt&amp;gt;, and an executable called &amp;lt;tt&amp;gt;egg&amp;lt;/tt&amp;gt; all in the same folder, AMBuild will actually perform each of these builds in separate folders, and the binary paths will look like:&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg.a/egg.a&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg.so/egg.so&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg/egg&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is to allow complex build scenarios where the same files are rebuilt multiple times.&lt;br /&gt;
&lt;br /&gt;
==Packaging==&lt;br /&gt;
&lt;br /&gt;
Now that our project builds, let's add to our build script so that we can create a build package. We'd like to make a folder we can zip or tar for distribution, with the following files:&lt;br /&gt;
* &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt;, our readme&lt;br /&gt;
* &amp;lt;tt&amp;gt;hello&amp;lt;/tt&amp;gt;, our final binary&lt;br /&gt;
&lt;br /&gt;
First, we have to add a step to the build to create the distribution folder:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
dist_folder = builder.AddFolder('dist')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The return value from &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; is a dependency graph node, that we can use as an input to future steps.&lt;br /&gt;
&lt;br /&gt;
Now we can copy our files:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
outputs = builder.Add(program)&lt;br /&gt;
&lt;br /&gt;
folder = builder.AddFolder('dist')&lt;br /&gt;
builder.AddCopy(os.path.join(builder.sourcePath, 'README.txt'), folder)&lt;br /&gt;
builder.AddCopy(outputs.binary, folder)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; can be copied directly from the source tree. To copy the executable, we use the return value of &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;. We could construct its path ourselves, but having the dependency object already available is much more convenient.&lt;br /&gt;
&lt;br /&gt;
Now, when we build, we see:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
[5952] cp &amp;quot;/home/dvander/projects/ambuild/ambuild2/README.txt&amp;quot; &amp;quot;./dist/README.txt&amp;quot;&lt;br /&gt;
Spawned worker (pid: 5953)&lt;br /&gt;
[5952] c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
[5954] c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
[5954] c++ main.o helpers.o -o hello&lt;br /&gt;
[5954] cp &amp;quot;hello/hello&amp;quot; &amp;quot;./dist/hello&amp;quot;&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since copying &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; has no dependencies, it can execute in parallel with other jobs, even before compilation has finished. It won't be copied again unless &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; changes. However the copy of &amp;lt;tt&amp;gt;hello/hello&amp;lt;/tt&amp;gt; has to occur last. We can see that it succeeded with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -l dist/&lt;br /&gt;
total 12&lt;br /&gt;
-rwxr-xr-x 1 dvander dvander 7036 Oct 16 22:32 hello&lt;br /&gt;
-rw-r--r-- 1 dvander dvander   23 Oct 16 22:32 README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is also possible to add a step to execute a command like &amp;quot;tar&amp;quot; or &amp;quot;zip&amp;quot;, but there's a complication. There must be a dependency to every file that would be included in the command, otherwise, the commands might occur out of order. We are still looking into easier ways to automate this.&lt;br /&gt;
&lt;br /&gt;
==Multiple Scripts==&lt;br /&gt;
&lt;br /&gt;
Non-trivial projects usually need more than one build script. AMBuild allows build scripts to nest; any script can run another script. Each script gets its own &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, known internally as a ''context''. All jobs are created within a context and associated with that context. This allows AMBuild to reparse a minimal number of build scripts when a build script changes.&lt;br /&gt;
&lt;br /&gt;
Contexts, by default, are associated with the folder they exist in relative to the source tree. For example, a build script in &amp;lt;tt&amp;gt;/source-tree/src/game/AMBuild&amp;lt;/tt&amp;gt; will have a context associated with &amp;lt;tt&amp;gt;src/game&amp;lt;/tt&amp;gt;. This folder structure is mirrored in the build folder, and all jobs occur within the context's local folder. For example, let's move our packaging into a separate script, &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# PackageScript&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
builder.SetBuildFolder('dist')&lt;br /&gt;
builder.AddCopy(os.path.join(builder.sourcePath, 'README.txt'), '.')&lt;br /&gt;
builder.AddCopy(Hello.binary, '.')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we modify our main &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
builder.DetectCxx()&lt;br /&gt;
&lt;br /&gt;
program = cxx.Program(&amp;quot;hello&amp;quot;)&lt;br /&gt;
program.sources = [&lt;br /&gt;
  'main.cpp',&lt;br /&gt;
  'helpers.cpp',&lt;br /&gt;
]&lt;br /&gt;
outputs = builder.Add(program)&lt;br /&gt;
&lt;br /&gt;
builder.Build(&lt;br /&gt;
  ['PackageScript'],&lt;br /&gt;
  { 'Hello': outputs }&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter is an array of script paths to run, and the second is a dictionary of global variables to give each script. Note that since our &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt; is in the root of the source tree, by default its build folder is &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, so we manually override its build folder.&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt; is parsed during the configure step, all of its jobs will automatically be configured to occur inside a &amp;lt;tt&amp;gt;dist&amp;lt;/tt&amp;gt; folder within the build folder, so &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt; actually refers to &amp;lt;tt&amp;gt;./dist/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you have only one script, you can use &amp;lt;tt&amp;gt;Build&amp;lt;/tt&amp;gt; instead. This also lets scripts return a value. For example:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
folders = builder.Build('MakeFolders')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# MakeFolders&lt;br /&gt;
folders = [&lt;br /&gt;
  builder.AddFolder('egg'),&lt;br /&gt;
  builder.AddFolder('yam'),&lt;br /&gt;
  builder.AddFolder('plant'),&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Magic variable; assigning to &amp;quot;rvalue&amp;quot; will propagate the value&lt;br /&gt;
# back up to Build().&lt;br /&gt;
rvalue = folders&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is possible to pass variables to other scripts (they appear as global variables), or they can be attached to the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object and they will automatically be propagated down. It's useful to propagate compiler objects this way, so they don't have to be re-detected and reconfigured in every subsequent script.&lt;br /&gt;
&lt;br /&gt;
==Custom Options==&lt;br /&gt;
&lt;br /&gt;
It is possible to add custom options to the configure step using Python's [http://docs.python.org/2/library/optparse.html optparse] module. Recall the default &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; that AMBuild generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys, ambuild2.run&lt;br /&gt;
&lt;br /&gt;
parser = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
parser.Configure()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;parser&amp;lt;/tt&amp;gt; object has an &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; attribute, which is an instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;. You can add to it, for example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys, ambuild2.run&lt;br /&gt;
&lt;br /&gt;
parser = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
parser.options.add_argument('--enable-debug', action='store_true', dest='debug', default=False,&lt;br /&gt;
                            help='Enable debugging symbols')&lt;br /&gt;
parser.options.add_argument('--enable-optimize', action='store_true', dest='opt', default=False,&lt;br /&gt;
                            help='Enable optimization')&lt;br /&gt;
parser.Configure()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These options can be accessed from any &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
if builder.options.debug:&lt;br /&gt;
  cxx.cflags += ['-O0', '-ggdb3']&lt;br /&gt;
  cxx.cdefines += ['DEBUG']&lt;br /&gt;
if builder.options.opt:&lt;br /&gt;
  cxx.cflags += ['-O3']&lt;br /&gt;
  cxx.cdefines += ['NDEBUG']&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Weak Dependencies==&lt;br /&gt;
&lt;br /&gt;
Sometimes it is useful to force build steps to occur in distinct phases. Normally, this would be the antithesis of what we want: the dependency graph should precisely and perfectly represent dependencies, and there should be no need to enforce order manually. That's true, but there are situations that warrant relaxing how we construct the graph.&lt;br /&gt;
&lt;br /&gt;
One example is generated headers in particular pose a problem. If we created dependencies on a &amp;quot;generate headers&amp;quot; task, then generating new headers would trigger recompiling every source file - even ones that never included those headers. Furthermore, if we created dependencies on each individual generated header, we'd have a huge dependency graph - 50 includes and 800 source files would mean 80,000 dependency links. AMBuild solves the first problem in the same way [http://gittup.org/tup/ tup] does. We do not yet attempt to solve the second problem, though it is planned for the future.&lt;br /&gt;
&lt;br /&gt;
First, we introduce the concept of a ''weak dependency''. A weak dependency is one that theoretically exists, and must exist for ordering, but does not propagate damage. For example, let's say that &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; has a weak dependency on &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; doesn't &amp;lt;tt&amp;gt;#include &amp;quot;generated.h&amp;quot;&amp;lt;/tt&amp;gt;, then no changes to &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt; should ever trigger a rebuild of &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt;. However, if &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; is changed to include &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt;, then the weak dependency ensures those jobs are executed in the right order. (It is illegal in AMBuild to depend on a generated file without having an explicit dependency.) The weak dependency can then be upgraded to a strong dependency, and possibly downgraded again later if the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; is removed.&lt;br /&gt;
&lt;br /&gt;
As an example, let's say we have two steps: generating headers and actual compilation. First, we add a shell command and save its outputs in a global variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
generated_headers = builder.AddCommand(&lt;br /&gt;
  argv = ['python', os.path.join(builder.buildPath, 'tools', 'buildbot', 'generate_headers.py')],&lt;br /&gt;
  inputs = [os.path.join(builder.sourcePath, '.hg', 'dirstate')],&lt;br /&gt;
  outputs = ['sourcemod_auto_version.h']&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In another build script, assuming we communicated the &amp;lt;tt&amp;gt;headers&amp;lt;/tt&amp;gt; object through, we could add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
library = cxx.Library('cstrike')&lt;br /&gt;
library.sources = ['cstrike.cpp', 'smsdk_ext.cpp']&lt;br /&gt;
library.sourcedeps += generated_headers&lt;br /&gt;
builder.Add(library)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now when our generated headers change, we are guaranteed that if our library's sources need to be recompiled, they will be compiled after the headers are generated.&lt;br /&gt;
&lt;br /&gt;
==Many Source Groups==&lt;br /&gt;
&lt;br /&gt;
Projects may have complex components that form a single, monolithic unit. For example, portions of code may need certain compile options that other areas do not need. This can be accomplished in AMBuild using modules. For example, the root of a project might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
program = cxx.Program('sample')&lt;br /&gt;
&lt;br /&gt;
builder.Build(['cairo/AMBuild', 'gtk/AMBuild'], {&lt;br /&gt;
  'program': program&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
builder.Add(program)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, &amp;lt;tt&amp;gt;cairo/AMBuild&amp;lt;/tt&amp;gt; can do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
module = program.Module(builder, 'cairo')&lt;br /&gt;
module.sources += [&lt;br /&gt;
  'file.cc',&lt;br /&gt;
]&lt;br /&gt;
module.cxxflags += ['-Wno-flag-needed-for-cairo']&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The module will build as part of the entire binary.&lt;br /&gt;
&lt;br /&gt;
==Reconfiguring==&lt;br /&gt;
&lt;br /&gt;
Reconfiguring can happen for two reasons. One is if you change some properties of the build, for example, configuring a debug build over an existing optimized build. Another is if a build script changes, AMBuild will automatically reconfigure the build using the previous configure options.&lt;br /&gt;
&lt;br /&gt;
===Output Cleaning===&lt;br /&gt;
When a reconfigure occurs, AMBuild will produce a new dependency graph alongside the old dependency graph, and these graphs are then merged. Any generated files in the old graph that are not present in the new graph are removed from the file system. This is necessary to ensure that builds do not become inconsistent or corrupt: every incremental build should be identical to a clean build.&lt;br /&gt;
&lt;br /&gt;
For example, our object folder for our original script might look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander  933 Nov 11 02:26 goodbye.o&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander 1232 Nov 11 02:26 helpers.o&lt;br /&gt;
-rwxrwxr-x 1 dvander dvander 8509 Nov 11 02:26 sample&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we comment out 'goodbye.cpp' from &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;, and build again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Reparsing build scripts.&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', '-fno-exceptions', '-fno-rtti', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Removing old output: sample/goodbye.o&lt;br /&gt;
Spawned taskmaster (pid: 41899)&lt;br /&gt;
Spawned worker (pid: 41900)&lt;br /&gt;
[41900] c++ helpers.o -o sample&lt;br /&gt;
Build succeeded.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And indeed, &amp;lt;tt&amp;gt;goodbye.o&amp;lt;/tt&amp;gt; is gone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander 1232 Nov 11 02:26 helpers.o&lt;br /&gt;
-rwxrwxr-x 1 dvander dvander 8473 Nov 11 02:28 sample&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Minimal Reparsing===&lt;br /&gt;
Unlike the normal dependency graph, AMBuild scripts can depend on each other. For example, a nested script may propagate a graph object back to the root script, which then propagates it down again. This creates an implicit cycle: if either script changes, the entire cycle must be reparsed. Avoiding this is extremely difficult as it is easy to construct situations in which a minimal reparse algorithm would fail. Thus, at the moment, AMBuild performs full reparses instead.&lt;br /&gt;
&lt;br /&gt;
If this becomes a performance bottleneck, which it might in a huge project with hundreds of build scripts, we would like to implement minimal reparsing. It would likely require transitioning to a more restricted API that disallows (or discourages) arbitrary dataflow between build scripts. To solve the problem mentioned earlier, we would need specific functions that allow AMBuild to track script inter-dependencies.&lt;br /&gt;
&lt;br /&gt;
Even with full reparsing however, AMBuild will only remove or rebuild individual jobs that have changed. If you add a single .cpp file to a source list, a full reparse will only result in that file being built and its binary relinked (and of course, any tasks depending on that binary).&lt;br /&gt;
&lt;br /&gt;
===Refactoring===&lt;br /&gt;
Sometimes, it is useful to see whether changing build scripts would actually change the dependency graph. For example, refactoring them, or tracking down excessive rebuild problems. In Tup, this can be done with a &amp;quot;refactoring&amp;quot; build, and AMBuild (sort of) supports this feature. It is still new and may not catch all problems.&lt;br /&gt;
&lt;br /&gt;
An example of a refactoring build where the dependency graph has changed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dvander@linux64:~/temp$ ambuild --refactor obj-linux-x86_64&lt;br /&gt;
Reparsing build scripts.&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', '-fno-exceptions', '-fno-rtti', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
New output introduced: sample&lt;br /&gt;
Failed to reparse build scripts.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_Tutorial&amp;diff=11091</id>
		<title>AMBuild Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_Tutorial&amp;diff=11091"/>
		<updated>2020-08-25T03:55:03Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Writing project files with AMBuild is fairly easy. This tutorial will guide you through making simple AMBuild scripts to compile and package a C++ project.&lt;br /&gt;
&lt;br /&gt;
For information on the full API, see [[AMBuild API]].&lt;br /&gt;
&lt;br /&gt;
==Simple Project==&lt;br /&gt;
To begin, let's say we have a sample project with the following files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
goodbye.cpp  helpers.cpp  README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To start, we need to generate a default AMBuild configure script. This is the script that will perform the &amp;quot;configure&amp;quot; step for your build. You can generate one with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --new-project&lt;br /&gt;
$ ls&lt;br /&gt;
AMBuildScript  configure.py  goodbye.cpp  helpers.cpp  README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The configure script simply invokes AMBuild. It can be modified (as we'll see later) to take extra command line options.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cat configure.py&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys&lt;br /&gt;
from ambuild2 import run&lt;br /&gt;
&lt;br /&gt;
prep = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
prep.Configure()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, we're ready to actually make a build script for our project. The master build script must be a file called &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;, and it must be written in [http://python.org/ Python] syntax. The full Python API on your system is available to AMBuild scripts, but the important aspect we'll deal with here is the AMBuild API.&lt;br /&gt;
&lt;br /&gt;
The first step is to tell AMBuild to detect the first available C or C++ compiler. This is done with the following line:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
cxx = builder.DetectCxx()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With just this line in your build script, you can now try to configure build. You should see something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ python ../configure.py&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you get an error - it's likely you don't have a compiler installed. Make sure gcc, clang, or Microsoft Visual Studio is available where appropriate.&lt;br /&gt;
&lt;br /&gt;
Now, we're ready to complete our AMBuildScript:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
program = cxx.Program(&amp;quot;hello&amp;quot;)&lt;br /&gt;
program.sources = [&lt;br /&gt;
  'main.cpp',&lt;br /&gt;
  'helpers.cpp',&lt;br /&gt;
]&lt;br /&gt;
builder.Add(program)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object is an instance of an AMBuild ''context'' - more about this is in the [[AMBuild API]] documentation. Every AMBuild script has access to a &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;builder.cxx&amp;lt;/tt&amp;gt; object has information about the C/C++ compiler for the configure session. The &amp;lt;tt&amp;gt;Program()&amp;lt;/tt&amp;gt; method will return an object used to create C++ compilation tasks. In this case, we're asking to build an executable that will be named 'hello' (or &amp;lt;tt&amp;gt;hello.exe&amp;lt;/tt&amp;gt; on Windows). You can also specified shared libraries with &amp;lt;tt&amp;gt;Library&amp;lt;/tt&amp;gt;, and static libraries with &amp;lt;tt&amp;gt;StaticLibrary&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can attach a list of source files to your Program via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute. Finally, use &amp;lt;tt&amp;gt;builder.Add&amp;lt;/tt&amp;gt; to take your C++ configuration and construct the necessary dependency graph and build steps.&lt;br /&gt;
&lt;br /&gt;
Now, we can actually attempt to build. First, let's make sure AMBuild computed our graph and dependencies correctly:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ python ../configure.py&lt;br /&gt;
$ ambuild --show-graph&lt;br /&gt;
 : mkdir &amp;quot;hello&amp;quot;&lt;br /&gt;
 - hello/hello&lt;br /&gt;
   - c++ main.o helpers.o -o hello&lt;br /&gt;
     - hello/main.o&lt;br /&gt;
       - [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
         - /home/dvander/projects/ambuild/ambuild2/main.cpp&lt;br /&gt;
     - hello/helpers.o&lt;br /&gt;
       - [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
         - /home/dvander/projects/ambuild/ambuild2/helpers.cpp&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
mkdir -p hello&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
  -&amp;gt; hello/main.o&lt;br /&gt;
task 1: [gcc] -&amp;gt; c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
  -&amp;gt; hello/helpers.o&lt;br /&gt;
task 2: c++ main.o helpers.o -o hello&lt;br /&gt;
  -&amp;gt; hello/hello&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It looks good! Now we can build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild&lt;br /&gt;
mkdir -p hello&lt;br /&gt;
Spawned task master (pid: 15563)&lt;br /&gt;
Spawned worker (pid: 15564)&lt;br /&gt;
Spawned worker (pid: 15565)&lt;br /&gt;
[15564] c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
[15565] c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
[15565] c++ main.o helpers.o -o hello&lt;br /&gt;
[15565] Child process terminating normally.&lt;br /&gt;
[15564] Child process terminating normally.&lt;br /&gt;
[15563] Child process terminating normally.&lt;br /&gt;
Build succeeded.&lt;br /&gt;
$ ./hello/hello&lt;br /&gt;
Hello!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that AMBuild gives each C++ binary its own folder. For example, if you build a static library called &amp;lt;tt&amp;gt;egg.a&amp;lt;/tt&amp;gt;, a shared library called &amp;lt;tt&amp;gt;egg.so&amp;lt;/tt&amp;gt;, and an executable called &amp;lt;tt&amp;gt;egg&amp;lt;/tt&amp;gt; all in the same folder, AMBuild will actually perform each of these builds in separate folders, and the binary paths will look like:&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg.a/egg.a&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg.so/egg.so&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;egg/egg&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is to allow complex build scenarios where the same files are rebuilt multiple times.&lt;br /&gt;
&lt;br /&gt;
==Packaging==&lt;br /&gt;
&lt;br /&gt;
Now that our project builds, let's add to our build script so that we can create a build package. We'd like to make a folder we can zip or tar for distribution, with the following files:&lt;br /&gt;
* &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt;, our readme&lt;br /&gt;
* &amp;lt;tt&amp;gt;hello&amp;lt;/tt&amp;gt;, our final binary&lt;br /&gt;
&lt;br /&gt;
First, we have to add a step to the build to create the distribution folder:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
dist_folder = builder.AddFolder('dist')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The return value from &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; is a dependency graph node, that we can use as an input to future steps.&lt;br /&gt;
&lt;br /&gt;
Now we can copy our files:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
outputs = builder.Add(program)&lt;br /&gt;
&lt;br /&gt;
folder = builder.AddFolder('dist')&lt;br /&gt;
builder.AddCopy(os.path.join(builder.sourcePath, 'README.txt'), folder)&lt;br /&gt;
builder.AddCopy(outputs.binary, folder)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; can be copied directly from the source tree. To copy the executable, we use the return value of &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;. We could construct its path ourselves, but having the dependency object already available is much more convenient.&lt;br /&gt;
&lt;br /&gt;
Now, when we build, we see:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
[5952] cp &amp;quot;/home/dvander/projects/ambuild/ambuild2/README.txt&amp;quot; &amp;quot;./dist/README.txt&amp;quot;&lt;br /&gt;
Spawned worker (pid: 5953)&lt;br /&gt;
[5952] c++ -H -c /home/dvander/projects/ambuild/ambuild2/helpers.cpp -o helpers.o&lt;br /&gt;
[5954] c++ -H -c /home/dvander/projects/ambuild/ambuild2/main.cpp -o main.o&lt;br /&gt;
[5954] c++ main.o helpers.o -o hello&lt;br /&gt;
[5954] cp &amp;quot;hello/hello&amp;quot; &amp;quot;./dist/hello&amp;quot;&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since copying &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; has no dependencies, it can execute in parallel with other jobs, even before compilation has finished. It won't be copied again unless &amp;lt;tt&amp;gt;README.txt&amp;lt;/tt&amp;gt; changes. However the copy of &amp;lt;tt&amp;gt;hello/hello&amp;lt;/tt&amp;gt; has to occur last. We can see that it succeeded with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -l dist/&lt;br /&gt;
total 12&lt;br /&gt;
-rwxr-xr-x 1 dvander dvander 7036 Oct 16 22:32 hello&lt;br /&gt;
-rw-r--r-- 1 dvander dvander   23 Oct 16 22:32 README.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is also possible to add a step to execute a command like &amp;quot;tar&amp;quot; or &amp;quot;zip&amp;quot;, but there's a complication. There must be a dependency to every file that would be included in the command, otherwise, the commands might occur out of order. We are still looking into easier ways to automate this.&lt;br /&gt;
&lt;br /&gt;
==Multiple Scripts==&lt;br /&gt;
&lt;br /&gt;
Non-trivial projects usually need more than one build script. AMBuild allows build scripts to nest; any script can run another script. Each script gets its own &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, known internally as a ''context''. All jobs are created within a context and associated with that context. This allows AMBuild to reparse a minimal number of build scripts when a build script changes.&lt;br /&gt;
&lt;br /&gt;
Contexts, by default, are associated with the folder they exist in relative to the source tree. For example, a build script in &amp;lt;tt&amp;gt;/source-tree/src/game/AMBuild&amp;lt;/tt&amp;gt; will have a context associated with &amp;lt;tt&amp;gt;src/game&amp;lt;/tt&amp;gt;. This folder structure is mirrored in the build folder, and all jobs occur within the context's local folder. For example, let's move our packaging into a separate script, &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# PackageScript&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
builder.SetBuildFolder('dist')&lt;br /&gt;
builder.AddCopy(os.path.join(builder.sourcePath, 'README.txt'), '.')&lt;br /&gt;
builder.AddCopy(Hello.binary, '.')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we modify our main &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
builder.DetectCxx()&lt;br /&gt;
&lt;br /&gt;
program = cxx.Program(&amp;quot;hello&amp;quot;)&lt;br /&gt;
program.sources = [&lt;br /&gt;
  'main.cpp',&lt;br /&gt;
  'helpers.cpp',&lt;br /&gt;
]&lt;br /&gt;
outputs = builder.Add(program)&lt;br /&gt;
&lt;br /&gt;
builder.Build(&lt;br /&gt;
  ['PackageScript'],&lt;br /&gt;
  { 'Hello': outputs }&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter is an array of script paths to run, and the second is a dictionary of global variables to give each script. Note that since our &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt; is in the root of the source tree, by default its build folder is &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, so we manually override its build folder.&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;tt&amp;gt;PackageScript&amp;lt;/tt&amp;gt; is parsed during the configure step, all of its jobs will automatically be configured to occur inside a &amp;lt;tt&amp;gt;dist&amp;lt;/tt&amp;gt; folder within the build folder, so &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt; actually refers to &amp;lt;tt&amp;gt;./dist/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you have only one script, you can use &amp;lt;tt&amp;gt;Build&amp;lt;/tt&amp;gt; instead. This also lets scripts return a value. For example:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# AMBuildScript&lt;br /&gt;
folders = builder.Build('MakeFolders')&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# MakeFolders&lt;br /&gt;
folders = [&lt;br /&gt;
  builder.AddFolder('egg'),&lt;br /&gt;
  builder.AddFolder('yam'),&lt;br /&gt;
  builder.AddFolder('plant'),&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Magic variable; assigning to &amp;quot;rvalue&amp;quot; will propagate the value&lt;br /&gt;
# back up to Build().&lt;br /&gt;
rvalue = folders&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Custom Options==&lt;br /&gt;
&lt;br /&gt;
It is possible to add custom options to the configure step using Python's [http://docs.python.org/2/library/optparse.html optparse] module. Recall the default &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; that AMBuild generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys, ambuild2.run&lt;br /&gt;
&lt;br /&gt;
parser = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
parser.Configure()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;parser&amp;lt;/tt&amp;gt; object has an &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; attribute, which is an instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;. You can add to it, for example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
# vim: set sts=2 ts=8 sw=2 tw=99 noet:&lt;br /&gt;
import sys, ambuild2.run&lt;br /&gt;
&lt;br /&gt;
parser = run.BuildParser(sys.path[0], api='2.2')&lt;br /&gt;
parser.options.add_argument('--enable-debug', action='store_true', dest='debug', default=False,&lt;br /&gt;
                            help='Enable debugging symbols')&lt;br /&gt;
parser.options.add_argument('--enable-optimize', action='store_true', dest='opt', default=False,&lt;br /&gt;
                            help='Enable optimization')&lt;br /&gt;
parser.Configure()&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These options can be accessed from any &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt; object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
if builder.options.debug:&lt;br /&gt;
  cxx.cflags += ['-O0', '-ggdb3']&lt;br /&gt;
  cxx.cdefines += ['DEBUG']&lt;br /&gt;
if builder.options.opt:&lt;br /&gt;
  cxx.cflags += ['-O3']&lt;br /&gt;
  cxx.cdefines += ['NDEBUG']&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Weak Dependencies==&lt;br /&gt;
&lt;br /&gt;
Sometimes it is useful to force build steps to occur in distinct phases. Normally, this would be the antithesis of what we want: the dependency graph should precisely and perfectly represent dependencies, and there should be no need to enforce order manually. That's true, but there are situations that warrant relaxing how we construct the graph.&lt;br /&gt;
&lt;br /&gt;
One example is generated headers in particular pose a problem. If we created dependencies on a &amp;quot;generate headers&amp;quot; task, then generating new headers would trigger recompiling every source file - even ones that never included those headers. Furthermore, if we created dependencies on each individual generated header, we'd have a huge dependency graph - 50 includes and 800 source files would mean 80,000 dependency links. AMBuild solves the first problem in the same way [http://gittup.org/tup/ tup] does. We do not yet attempt to solve the second problem, though it is planned for the future.&lt;br /&gt;
&lt;br /&gt;
First, we introduce the concept of a ''weak dependency''. A weak dependency is one that theoretically exists, and must exist for ordering, but does not propagate damage. For example, let's say that &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; has a weak dependency on &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; doesn't &amp;lt;tt&amp;gt;#include &amp;quot;generated.h&amp;quot;&amp;lt;/tt&amp;gt;, then no changes to &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt; should ever trigger a rebuild of &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt;. However, if &amp;lt;tt&amp;gt;hello.cpp&amp;lt;/tt&amp;gt; is changed to include &amp;lt;tt&amp;gt;generated.h&amp;lt;/tt&amp;gt;, then the weak dependency ensures those jobs are executed in the right order. (It is illegal in AMBuild to depend on a generated file without having an explicit dependency.) The weak dependency can then be upgraded to a strong dependency, and possibly downgraded again later if the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; is removed.&lt;br /&gt;
&lt;br /&gt;
As an example, let's say we have two steps: generating headers and actual compilation. First, we add a shell command and save its outputs in a global variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
generated_headers = builder.AddCommand(&lt;br /&gt;
  argv = ['python', os.path.join(builder.buildPath, 'tools', 'buildbot', 'generate_headers.py')],&lt;br /&gt;
  inputs = [os.path.join(builder.sourcePath, '.hg', 'dirstate')],&lt;br /&gt;
  outputs = ['sourcemod_auto_version.h']&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In another build script, assuming we communicated the &amp;lt;tt&amp;gt;headers&amp;lt;/tt&amp;gt; object through, we could add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
library = cxx.Library('cstrike')&lt;br /&gt;
library.sources = ['cstrike.cpp', 'smsdk_ext.cpp']&lt;br /&gt;
library.sourcedeps += generated_headers&lt;br /&gt;
builder.Add(library)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now when our generated headers change, we are guaranteed that if our library's sources need to be recompiled, they will be compiled after the headers are generated.&lt;br /&gt;
&lt;br /&gt;
==Many Source Groups==&lt;br /&gt;
&lt;br /&gt;
Projects may have complex components that form a single, monolithic unit. For example, portions of code may need certain compile options that other areas do not need. This can be accomplished in AMBuild using modules. For example, the root of a project might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
program = cxx.Program('sample')&lt;br /&gt;
&lt;br /&gt;
builder.Build(['cairo/AMBuild', 'gtk/AMBuild'], {&lt;br /&gt;
  'program': program&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
builder.Add(program)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, &amp;lt;tt&amp;gt;cairo/AMBuild&amp;lt;/tt&amp;gt; can do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
module = program.Module(builder, 'cairo')&lt;br /&gt;
module.sources += [&lt;br /&gt;
  'file.cc',&lt;br /&gt;
]&lt;br /&gt;
module.cxxflags += ['-Wno-flag-needed-for-cairo']&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The module will build as part of the entire binary.&lt;br /&gt;
&lt;br /&gt;
==Reconfiguring==&lt;br /&gt;
&lt;br /&gt;
Reconfiguring can happen for two reasons. One is if you change some properties of the build, for example, configuring a debug build over an existing optimized build. Another is if a build script changes, AMBuild will automatically reconfigure the build using the previous configure options.&lt;br /&gt;
&lt;br /&gt;
===Output Cleaning===&lt;br /&gt;
When a reconfigure occurs, AMBuild will produce a new dependency graph alongside the old dependency graph, and these graphs are then merged. Any generated files in the old graph that are not present in the new graph are removed from the file system. This is necessary to ensure that builds do not become inconsistent or corrupt: every incremental build should be identical to a clean build.&lt;br /&gt;
&lt;br /&gt;
For example, our object folder for our original script might look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander  933 Nov 11 02:26 goodbye.o&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander 1232 Nov 11 02:26 helpers.o&lt;br /&gt;
-rwxrwxr-x 1 dvander dvander 8509 Nov 11 02:26 sample&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we comment out 'goodbye.cpp' from &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;, and build again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Reparsing build scripts.&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', '-fno-exceptions', '-fno-rtti', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Removing old output: sample/goodbye.o&lt;br /&gt;
Spawned taskmaster (pid: 41899)&lt;br /&gt;
Spawned worker (pid: 41900)&lt;br /&gt;
[41900] c++ helpers.o -o sample&lt;br /&gt;
Build succeeded.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And indeed, &amp;lt;tt&amp;gt;goodbye.o&amp;lt;/tt&amp;gt; is gone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-rw-r-- 1 dvander dvander 1232 Nov 11 02:26 helpers.o&lt;br /&gt;
-rwxrwxr-x 1 dvander dvander 8473 Nov 11 02:28 sample&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Minimal Reparsing===&lt;br /&gt;
Unlike the normal dependency graph, AMBuild scripts can depend on each other. For example, a nested script may propagate a graph object back to the root script, which then propagates it down again. This creates an implicit cycle: if either script changes, the entire cycle must be reparsed. Avoiding this is extremely difficult as it is easy to construct situations in which a minimal reparse algorithm would fail. Thus, at the moment, AMBuild performs full reparses instead.&lt;br /&gt;
&lt;br /&gt;
If this becomes a performance bottleneck, which it might in a huge project with hundreds of build scripts, we would like to implement minimal reparsing. It would likely require transitioning to a more restricted API that disallows (or discourages) arbitrary dataflow between build scripts. To solve the problem mentioned earlier, we would need specific functions that allow AMBuild to track script inter-dependencies.&lt;br /&gt;
&lt;br /&gt;
Even with full reparsing however, AMBuild will only remove or rebuild individual jobs that have changed. If you add a single .cpp file to a source list, a full reparse will only result in that file being built and its binary relinked (and of course, any tasks depending on that binary).&lt;br /&gt;
&lt;br /&gt;
===Refactoring===&lt;br /&gt;
Sometimes, it is useful to see whether changing build scripts would actually change the dependency graph. For example, refactoring them, or tracking down excessive rebuild problems. In Tup, this can be done with a &amp;quot;refactoring&amp;quot; build, and AMBuild (sort of) supports this feature. It is still new and may not catch all problems.&lt;br /&gt;
&lt;br /&gt;
An example of a refactoring build where the dependency graph has changed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dvander@linux64:~/temp$ ambuild --refactor obj-linux-x86_64&lt;br /&gt;
Reparsing build scripts.&lt;br /&gt;
Checking CC compiler (vendor test gcc)... ['cc', 'test.c', '-o', 'test']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
Checking CXX compiler (vendor test gcc)... ['c++', '-fno-exceptions', '-fno-rtti', 'test.cpp', '-o', 'testp']&lt;br /&gt;
found gcc version 4.7&lt;br /&gt;
New output introduced: sample&lt;br /&gt;
Failed to reparse build scripts.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11090</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11090"/>
		<updated>2020-08-25T03:50:58Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback (see the bottom of this page) if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
AMBuild 2.2 is the latest release. It supports cross-compiling, multi-architecture builds, and precompiled headers.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 2.7 or higher is required. If using Python 3, then 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
Additionally, pip and setuptools (both Python components) are also required. If your distribution or Python installation does not provide for these, see [https://pip.pypa.io/en/stable/installing/ Installing Pip] for manual instructions.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: By default, pip will perform per-user installations. To install globally for all users, you will need to use &amp;quot;sudo&amp;quot; (or run as Administrator on Windows).&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. The author is not aware of an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;br /&gt;
&lt;br /&gt;
==Tup==&lt;br /&gt;
AMBuild is designed to be, essentially, a miniature clone of Tup written entirely in Python. In particular it closely follows concepts in [http://gittup.org/tup/build_system_rules_and_algorithms.pdf the Tup whitepaper]. However there are a few differences that may make one more desirable over the other:&lt;br /&gt;
* Tup has been around longer than AMBuild 2, and has been more thoroughly tested. &lt;br /&gt;
* Tup uses complex file system features to optimize updates. Algorithms that are O(n) in AMBuild tend to be O(1) in Tup.&lt;br /&gt;
* AMBuild only requires a default Python installation to work. Tup, due to being written in C and using very platform specific file system features, may not be as accessible.&lt;br /&gt;
* Tup has more features for speeding up very large projects. It can do minimal reparsing and it can reduce the number of links in large graphs.&lt;br /&gt;
* AMBuild is designed to be a front-end in addition to a back-end. It has a simple API and script syntax, and is designed to support multiple output formats. For example, it could conceivably generate Visual Studio or XCode project files.&lt;br /&gt;
&lt;br /&gt;
Since AMBuild is also a frontend, AMBuild may one day eliminate its backend in favor of emitting Tupfiles instead.&lt;br /&gt;
&lt;br /&gt;
AMBuild's IPC implementation is very low-level, and it has not yet been ported beyond Windows, Mac/BSD, or Linux. However it's not difficult to port to Unix-like systems, and if needed a generic (albeit suboptimal) cross-platform implementation could be provided.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11089</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11089"/>
		<updated>2020-08-25T03:32:52Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Changes from 2.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. The main use case was for tricking the linker into linking to a local symlink. This can be achieved by adding the file name as a linker flag, and including an &amp;lt;tt&amp;gt;AddSymlink&amp;lt;/tt&amp;gt; node in &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* AddCommand no longer returns a (node, (entry...)) tuple. Instead, it returns a list of entries.&lt;br /&gt;
* AddCopy and AddSymlink no longer return a (node, (entry...)) tuple. Instead, they both return a single entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11088</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11088"/>
		<updated>2020-08-25T03:14:30Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Changes from 2.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. In the obscure cases where it was needed, &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;entry&amp;lt;/tt&amp;gt; objects can be used instead.&lt;br /&gt;
* AddCommand, AddCopy, and AddSymlink no longer return command nodes. They return only entries, and the copy/symlink variants return only one entry.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11087</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11087"/>
		<updated>2020-08-25T03:13:48Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy. Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
**  Returns the &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for the new file.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. In the obscure cases where it was needed, &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;entry&amp;lt;/tt&amp;gt; objects can be used instead.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11086</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11086"/>
		<updated>2020-08-25T03:07:31Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Changes from 2.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. In the obscure cases where it was needed, &amp;lt;tt&amp;gt;weaklinkdeps&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;entry&amp;lt;/tt&amp;gt; objects can be used instead.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11085</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11085"/>
		<updated>2020-08-25T03:04:48Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Changes from 2.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed. In the obscure cases where it was needed, &amp;lt;tt&amp;gt;weaklinks&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;entry&amp;lt;/tt&amp;gt; objects can be used instead.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11084</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11084"/>
		<updated>2020-08-25T03:04:07Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&lt;br /&gt;
''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; API has been removed, since it is fully replaced (more conveniently, even) by other means.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11083</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11083"/>
		<updated>2020-08-25T02:41:42Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''include_hotlist'' - Array of important headers. This is unused by AMBuild, but when generating IDE project files, the named includes will show up in the project explorer.&lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11082</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11082"/>
		<updated>2020-08-24T23:28:10Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either 'msvc', 'gcc', 'clang', or 'emscripten'.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either 'msvc' or 'gcc'.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11081</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11081"/>
		<updated>2020-08-24T15:18:38Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Precompiled Headers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also note, a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder does not support modules or custom tools.&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11080</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11080"/>
		<updated>2020-08-24T04:26:01Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly. This is intended for small text files, since the data is stored directly in the internal database.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11079</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11079"/>
		<updated>2020-08-24T04:02:30Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''AddOutputFile(path, contents)'' - Adds a task that causes &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; to be written to &amp;lt;i&amp;gt;path&amp;lt;/i&amp;gt;. The file is always opened in binary mode, and the data given as &amp;lt;i&amp;gt;contents&amp;lt;/i&amp;gt; should be a &amp;lt;tt&amp;gt;bytes&amp;lt;/tt&amp;gt; object when using Python 3. Python 2 will accept a &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt;, but it's highly recommended that you call the &amp;lt;tt&amp;gt;encode&amp;lt;/tt&amp;gt; function to make sure it is encoded properly.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. See the [[#Precompiled Headers]] section for more information.&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', source_type = 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be either 'c' or 'c++', depending on what kind of files will be including it. GCC does not support mixing and matching and AMBuild will ignore it with a warning.&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11078</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11078"/>
		<updated>2020-08-24T03:40:40Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Precompiled Headers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The builder is configured to produce a precompiled header object for each source input. When added to a builder, it returns a &amp;lt;tt&amp;gt;PchNodes&amp;lt;/tt&amp;gt; object, which can be added to the &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;) of another &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. Make sure that when using precompiled headers, the exact same compiler and architecture flags are used, and that C source files never use C++ precompiled headers (and vice versa).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild provides a unified header that can be used as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11077</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11077"/>
		<updated>2020-08-24T03:39:56Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Precompiled Headers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The builder is configured to produce a precompiled header object for each source input. When added to a builder, it returns a &amp;lt;tt&amp;gt;PchNodes&amp;lt;/tt&amp;gt; object, which can be added to the &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;) of another &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. Make sure that when using precompiled headers, the exact same compiler and architecture flags are used, and that C source files never use C++ precompiled headers (and vice versa).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild attempts to bridge the common functionality together.&lt;br /&gt;
&lt;br /&gt;
When using a &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder, the source files should be header files (.h, .hpp, or .hxx). AMBuild will generate a unified header combining these together. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
pch_builder = cxx.PrecompiledHeaders('myheaders', 'c++')&lt;br /&gt;
pch_builder.sources += [&lt;br /&gt;
    'amtl/am-vector.h',&lt;br /&gt;
    'amtl/am-string.h',&lt;br /&gt;
]&lt;br /&gt;
pch = builder.Add(pch_builder)&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To use this in a subsequent C++ project, simply add it to &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
binary = cxx.Program('hello')&lt;br /&gt;
binary.cxxincludes += [pch]&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The position doesn't matter. AMBuild will automatically position precompiled header includes to the front of the final list.&lt;br /&gt;
&lt;br /&gt;
In your C++ source, precompiled header includes must come before any C/C++ tokens. AMBuild builds a wrapper header that can be included as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;myheaders.h&amp;gt;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the name &amp;quot;myheaders.h&amp;quot; is derived from the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; builder name.&lt;br /&gt;
&lt;br /&gt;
Precompiled headers are easy to misuse, and errors can be extremely difficult to detect. AMBuild makes no attempt to ensure they're being used correctly. In particular:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it. Exactly what must match is compiler dependent, so it's best to use the same settings everywhere.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler and will silently ignore the precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11076</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11076"/>
		<updated>2020-08-23T21:38:25Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The builder is configured to produce a precompiled header object for each source input. When added to a builder, it returns a &amp;lt;tt&amp;gt;PchNodes&amp;lt;/tt&amp;gt; object, which can be added to the &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;) of another &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. Make sure that when using precompiled headers, the exact same compiler and architecture flags are used, and that C source files never use C++ precompiled headers (and vice versa).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Precompiled Headers=&lt;br /&gt;
Clang, GCC, and MSVC all support some notion of precompiled headers, but the level of support and compatibility between them is wildly different. AMBuild supports this feature, but makes no attempts to ensure that you're using them correctly. To ensure that they will work, we recommend the following:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the compiler settings (especially, architecture, version, and flags) are identical between the &amp;lt;tt&amp;gt;PrecompiledHeaders&amp;lt;/tt&amp;gt; object and builders that depend on it.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Always use include guards in precompiled headers. Do not use &amp;lt;tt&amp;gt;#pragma once&amp;lt;/tt&amp;gt; because GCC has long-standing, unfixed bugs around using it with precompiled headers.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Make sure the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive for a precompiled header is the very first thing in your source files. Preceding C/C++ tokens will confuse the compiler.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11075</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11075"/>
		<updated>2020-08-23T19:16:36Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The builder is configured to produce a precompiled header object for each source input. When added to a builder, it returns a &amp;lt;tt&amp;gt;PchNodes&amp;lt;/tt&amp;gt; object, which can be added to the &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;) of another &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;source_type&amp;lt;/tt&amp;gt; argument must be 'c' or 'c++'. Make sure that when using precompiled headers, the exact same compiler and architecture flags are used, and that C source files never use C++ precompiled headers (and vice versa).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11074</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11074"/>
		<updated>2020-08-23T19:15:23Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;PrecompiledHeaders(name, source_type)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler's settings. The builder is configured to produce a precompiled header object for each source input. When added to a builder, it returns a &amp;lt;tt&amp;gt;PchNodes&amp;lt;/tt&amp;gt; object, which can be added to the &amp;lt;tt&amp;gt;includes&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;cxxincludes&amp;lt;/tt&amp;gt;) of another &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11073</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11073"/>
		<updated>2020-08-23T18:08:51Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* C++ Detection */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
On Linux, true cross-compilation (eg something like x86 to ARM) is automatically detected for Debian-derived distributions. For example, if the target is &amp;quot;linux-arm-gnueabihf&amp;quot;, AMBuild will automatically search for a compiler named &amp;quot;arm-linux-gnueabihf-gcc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11072</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11072"/>
		<updated>2020-08-23T07:54:31Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback (see the bottom of this page) if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 2.7 or higher is required. If using Python 3, then 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
Additionally, pip and setuptools (both Python components) are also required. If your distribution or Python installation does not provide for these, see [https://pip.pypa.io/en/stable/installing/ Installing Pip] for manual instructions.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: By default, pip will perform per-user installations. To install globally for all users, you will need to use &amp;quot;sudo&amp;quot; (or run as Administrator on Windows).&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. The author is not aware of an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;br /&gt;
&lt;br /&gt;
==Tup==&lt;br /&gt;
AMBuild is designed to be, essentially, a miniature clone of Tup written entirely in Python. In particular it closely follows concepts in [http://gittup.org/tup/build_system_rules_and_algorithms.pdf the Tup whitepaper]. However there are a few differences that may make one more desirable over the other:&lt;br /&gt;
* Tup has been around longer than AMBuild 2, and has been more thoroughly tested. &lt;br /&gt;
* Tup uses complex file system features to optimize updates. Algorithms that are O(n) in AMBuild tend to be O(1) in Tup.&lt;br /&gt;
* AMBuild only requires a default Python installation to work. Tup, due to being written in C and using very platform specific file system features, may not be as accessible.&lt;br /&gt;
* Tup has more features for speeding up very large projects. It can do minimal reparsing and it can reduce the number of links in large graphs.&lt;br /&gt;
* AMBuild is designed to be a front-end in addition to a back-end. It has a simple API and script syntax, and is designed to support multiple output formats. For example, it could conceivably generate Visual Studio or XCode project files.&lt;br /&gt;
&lt;br /&gt;
Since AMBuild is also a frontend, AMBuild may one day eliminate its backend in favor of emitting Tupfiles instead.&lt;br /&gt;
&lt;br /&gt;
AMBuild's IPC implementation is very low-level, and it has not yet been ported beyond Windows, Mac/BSD, or Linux. However it's not difficult to port to Unix-like systems, and if needed a generic (albeit suboptimal) cross-platform implementation could be provided.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11071</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11071"/>
		<updated>2020-08-23T07:53:52Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback (see the bottom of this page) if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 2.7 or higher is required. If using Python 3, then 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
Two Python components, pip and setuptools, are also required. If your distribution does not provide packages for these, see [https://pip.pypa.io/en/stable/installing/ Installing Pip] for manual instructions.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: By default, pip will perform per-user installations. To install globally for all users, you will need to use &amp;quot;sudo&amp;quot; (or run as Administrator on Windows).&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. The author is not aware of an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;br /&gt;
&lt;br /&gt;
==Tup==&lt;br /&gt;
AMBuild is designed to be, essentially, a miniature clone of Tup written entirely in Python. In particular it closely follows concepts in [http://gittup.org/tup/build_system_rules_and_algorithms.pdf the Tup whitepaper]. However there are a few differences that may make one more desirable over the other:&lt;br /&gt;
* Tup has been around longer than AMBuild 2, and has been more thoroughly tested. &lt;br /&gt;
* Tup uses complex file system features to optimize updates. Algorithms that are O(n) in AMBuild tend to be O(1) in Tup.&lt;br /&gt;
* AMBuild only requires a default Python installation to work. Tup, due to being written in C and using very platform specific file system features, may not be as accessible.&lt;br /&gt;
* Tup has more features for speeding up very large projects. It can do minimal reparsing and it can reduce the number of links in large graphs.&lt;br /&gt;
* AMBuild is designed to be a front-end in addition to a back-end. It has a simple API and script syntax, and is designed to support multiple output formats. For example, it could conceivably generate Visual Studio or XCode project files.&lt;br /&gt;
&lt;br /&gt;
Since AMBuild is also a frontend, AMBuild may one day eliminate its backend in favor of emitting Tupfiles instead.&lt;br /&gt;
&lt;br /&gt;
AMBuild's IPC implementation is very low-level, and it has not yet been ported beyond Windows, Mac/BSD, or Linux. However it's not difficult to port to Unix-like systems, and if needed a generic (albeit suboptimal) cross-platform implementation could be provided.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11070</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11070"/>
		<updated>2020-08-23T07:52:15Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback (see the bottom of this page) if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 2.7 or higher is required. If using Python 3, then 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
PIP and Setuptools are also required, these two packages are technically optional in the Python universe and '''''MAY''''' require manual installation. Some Linux (example: Ubuntu/Debian) platforms provide packages to install pip and setuptools while the Windows Python installer bundles a copy of PIP &amp;amp; Setuptools, otherwise, the generic way is via [https://bootstrap.pypa.io/get-pip.py get-pip.py] with no arguments.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: By default, pip will perform per-user installations. To install globally for all users, you will need to use &amp;quot;sudo&amp;quot; (or run as Administrator on Windows).&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. The author is not aware of an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;br /&gt;
&lt;br /&gt;
==Tup==&lt;br /&gt;
AMBuild is designed to be, essentially, a miniature clone of Tup written entirely in Python. In particular it closely follows concepts in [http://gittup.org/tup/build_system_rules_and_algorithms.pdf the Tup whitepaper]. However there are a few differences that may make one more desirable over the other:&lt;br /&gt;
* Tup has been around longer than AMBuild 2, and has been more thoroughly tested. &lt;br /&gt;
* Tup uses complex file system features to optimize updates. Algorithms that are O(n) in AMBuild tend to be O(1) in Tup.&lt;br /&gt;
* AMBuild only requires a default Python installation to work. Tup, due to being written in C and using very platform specific file system features, may not be as accessible.&lt;br /&gt;
* Tup has more features for speeding up very large projects. It can do minimal reparsing and it can reduce the number of links in large graphs.&lt;br /&gt;
* AMBuild is designed to be a front-end in addition to a back-end. It has a simple API and script syntax, and is designed to support multiple output formats. For example, it could conceivably generate Visual Studio or XCode project files.&lt;br /&gt;
&lt;br /&gt;
Since AMBuild is also a frontend, AMBuild may one day eliminate its backend in favor of emitting Tupfiles instead.&lt;br /&gt;
&lt;br /&gt;
AMBuild's IPC implementation is very low-level, and it has not yet been ported beyond Windows, Mac/BSD, or Linux. However it's not difficult to port to Unix-like systems, and if needed a generic (albeit suboptimal) cross-platform implementation could be provided.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11069</id>
		<title>AMBuild</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild&amp;diff=11069"/>
		<updated>2020-08-23T07:50:57Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMBuild is a tool for building software projects and creating release packages. It is targeted at C++ projects, though it can be used for anything. It has been tailored to solve three major problems that most build tools do not address:&lt;br /&gt;
*'''Accuracy'''. You should *never* need to clean a build. Clean rebuilds are unnecessary and a waste of your time. AMBuild always computes minimal rebuilds accurately - any failure to do so is considered a bug.&lt;br /&gt;
*'''Speed'''. Most build systems need to traverse the entire dependency graph for changes. AMBuild only needs to look at the set of changed files on the filesystem.&lt;br /&gt;
*'''Flexibility'''. Build scripts are written in Python, so they're very easy to write and provide full programmatic control.&lt;br /&gt;
&lt;br /&gt;
Keep in mind, AMBuild is neither widely used nor has it been used on a wide variety of systems. AlliedModders has used it successfully for small to medium-sized C++ projects on Linux, Mac, and Windows. Our largest project, SourceMod, has 700 C++ files and over 200,000 lines of code. We're happy to receive feedback (see the bottom of this page) if you use it in your own projects.&lt;br /&gt;
&lt;br /&gt;
=Motivation=&lt;br /&gt;
&lt;br /&gt;
AlliedModders C++ projects require a lot of customization. The set of flags passed to the compiler, their order, how things get linked, is all delicate and complicated. In addition, each Source game requires different linkage, so our C++ files usually get compiled multiple times, over and over again, into separate binaries. Lastly, our projects are large, and minimizing build time through correct dependency computation and parallelization is important. Very few build systems can handle any of these scenarios well, much less all of them, so we sought to make a new build system.&lt;br /&gt;
&lt;br /&gt;
The initial version of AMBuild only solved flexibility problems. By controlling the build pipeline through Python, we were able to generate 15+ different binaries from the same source files without any code duplication. Over time the AMBuild script syntax has become very simple; you no longer need a complex project to justify AMBuild.&lt;br /&gt;
&lt;br /&gt;
The modern version of AMBuild (also known as AMBuild 2), is modeled after [http://gittup.org/tup/ Tup]. Tup is a huge advance forward in build systems, and it is likely that one day AMBuild will simply use Tup as a backend. If you are looking at AMBuild as a build platform for your projects, you may want to see whether Tup meets your needs instead.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
Python 2.7 or higher is required. If using Python 3, then 3.3 or higher is required.&lt;br /&gt;
&lt;br /&gt;
PIP and Setuptools are also required, these two packages are technically optional in the Python universe and '''''MAY''''' require manual installation. Some Linux (example: Ubuntu/Debian) platforms provide packages to install pip and setuptools while the Windows Python installer bundles a copy of PIP &amp;amp; Setuptools, otherwise, the generic way is via [https://bootstrap.pypa.io/get-pip.py get-pip.py] with no arguments.&lt;br /&gt;
&lt;br /&gt;
AMBuild has been tested to work on the following platforms. Although builds of Python for specific architectures were tested, we expect that other architectures will work as well.&lt;br /&gt;
* Windows 7+ with x86, x86_64, arm, or arm64 targets.&lt;br /&gt;
* Linux with clang and GCC.&lt;br /&gt;
* OS X 10.9+ with x86 and x86_64 targets.&lt;br /&gt;
&lt;br /&gt;
It has also been tested to work with the following compilers:&lt;br /&gt;
* Visual Studio 2015+&lt;br /&gt;
* GCC 4+&lt;br /&gt;
* Clang 3+&lt;br /&gt;
* Emscripten 1.25+ (JS output mode only, lib deps do not work)&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
AMBuild can be downloaded via GitHub at [https://github.com/alliedmodders/ambuild https://github.com/alliedmodders/ambuild].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
$ pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Administrator privileges are required to install AMBuild for '''''ALL USERS''''', otherwise, pip will install AMBuild at the user level.&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild Tutorial]] for more information.&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
&lt;br /&gt;
See the [[AMBuild API]] article for more information.&lt;br /&gt;
&lt;br /&gt;
=Technical Overview=&lt;br /&gt;
&lt;br /&gt;
AMBuild is separated into a ''frontend'' and a ''backend''. The frontend is responsible for parsing build scripts (this is known as the ''configure'' step). The backend is responsible for actually performing builds. The frontend and backend are separate, and it is possible to use a different backend other than AMBuild. For example, there are plans for the configure step to be able to produce Visual Studio project files.&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Build scripts are written in Python, and they are parsed whenever you configure the build. If a build script changes, it will automatically re-trigger the configure process on the next build. When a configure takes place, any files left by an old build are removed if they are modified or removed in the new dependency graph.&lt;br /&gt;
&lt;br /&gt;
The details of the generated dependency graph are stored in an SQLite database, which is located in a hidden &amp;lt;tt&amp;gt;.ambuild2&amp;lt;/tt&amp;gt; folder inside the build path.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
The build process involves a few important steps that are executed every time you use the &amp;lt;tt&amp;gt;ambuild&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Damage Computation'''. Builds a list of all files that have changed since the last build. This is based on filesystem timestamps, and either a forward or backward time change is enough to be considered &amp;quot;damaged&amp;quot; (or dirty). For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-changed&lt;br /&gt;
/home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Partial DAG Construction'''. A partial dependency graph is built based on the list of damaged files. This is the entire set of nodes in the graph which need to be recomputed. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-damage&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-damage&lt;br /&gt;
 - package/addons/metamod/bin/server_i486.so&lt;br /&gt;
  - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
   - loader/server_i486/server_i486.so&lt;br /&gt;
    - c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server_i486.so&lt;br /&gt;
     - loader/server_i486/loader.o&lt;br /&gt;
      - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
       - /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Task Construction'''. The partial DAG is simplified into a tree of commands to run. The output of this step can be seen with &amp;lt;tt&amp;gt;--show-commands&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-commands&lt;br /&gt;
 - cp &amp;quot;../loader/server_i486/server_i486.so&amp;quot; &amp;quot;package/addons/metamod/bin/server_i486.so&amp;quot;&lt;br /&gt;
  - c++ loader.o gamedll.o serverplugin.o utility.o -shared -o server_i486.so&lt;br /&gt;
   - [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;'''Updating'''. Each task in the task tree is executed and the results are processed to either reject the build, or update the state of the dependency graph. At this phase, tasks are executed in parallel based on the number of CPU cores available. The task graph is also shared to maximize throughput. You can see the sequential build steps with &amp;lt;tt&amp;gt;--show-steps&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ambuild --show-steps&lt;br /&gt;
task 0: [gcc] -&amp;gt; c++ -Wall -Werror -H -c /home/dvander/alliedmodders/mmsource-central/loader/loader.cpp -o loader.o&lt;br /&gt;
  -&amp;gt; loader/server/loader.o&lt;br /&gt;
task 1: c++ loader.o gamedll.o serverplugin.o utility.o -m32 -static-libgcc -shared -o server.so&lt;br /&gt;
  -&amp;gt; loader/server/server.so&lt;br /&gt;
task 2: cp &amp;quot;../loader/server/server.so&amp;quot; &amp;quot;package/addons/metamod/bin/server.so&amp;quot;&lt;br /&gt;
  -&amp;gt; package/addons/metamod/bin/server.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Maximizing throughput in Python is tricky since it has limited capability for IPC and multithreading. AMBuild spawns worker processes based on the number of CPUs available, which run task jobs and return the results.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Comparisons=&lt;br /&gt;
==Make, Speed==&lt;br /&gt;
Make uses a recursive update scheme. Starting with the top-level rule, Make will recursively search all dependencies to find outdated rules, and it will update all rules as it unwinds. This usually involves touching way more rules than are necessary. Consider the following dependency graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:RecursiveDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
In this graph, &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has been modified. Even though it's the only rule that has been changed, Make must visit every single node in the graph to discover that it has changed. Furthermore, it has to visit it multiple times: once for &amp;lt;tt&amp;gt;main.o&amp;lt;/tt&amp;gt;, and another time for &amp;lt;tt&amp;gt;helpers.o&amp;lt;/tt&amp;gt;. In a large dependency graph, this is very expensive.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, the direction of the graph is reversed:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
With this graph, it is possible to visit every node once. Once we know that &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt; has changed, we can follow the edges upward and ignore everything in the graph that is unaffected:&lt;br /&gt;
&lt;br /&gt;
[[Image:AMPartialDepGraph.png]]&lt;br /&gt;
&lt;br /&gt;
==Make, Accuracy==&lt;br /&gt;
AMBuild strives to be accurate by design, in two ways:&lt;br /&gt;
* Computation of dependencies should be as minimally accurate as possible. Changing a build script should not result in a complete rebuild.&lt;br /&gt;
* An incremental build should be exactly the same as a fresh build.&lt;br /&gt;
&lt;br /&gt;
It is difficult to achieve very accurate rebuilds in Make. For example, consider a Makefile that lists source files and CFLAGS, and invokes the C++ compiler to build and link them:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Makefile&lt;br /&gt;
CFLAGS = -Wall&lt;br /&gt;
&lt;br /&gt;
helpers.o: helpers.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) helpers.cpp -c -o helpers.o&lt;br /&gt;
main.o: main.cpp&lt;br /&gt;
  $(CC) $(CFLAGS) main.cpp -c -o main.o&lt;br /&gt;
&lt;br /&gt;
main: main.o helpers.o&lt;br /&gt;
  $(CC) main.o helpers.o -o main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you change &amp;lt;tt&amp;gt;helpers.cpp&amp;lt;/tt&amp;gt;, you will get a minimal rebuild. If you add a new source file, you will likely get a minimal rebuild. However, if you ''remove the &amp;lt;tt&amp;gt;helpers&amp;lt;/tt&amp;gt; rule completely'', the build will be incorrect, because &amp;lt;tt&amp;gt;Make&amp;lt;/tt&amp;gt; cannot tell that &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; needs to be relinked.&lt;br /&gt;
&lt;br /&gt;
One way to solve this is to have certain rules, like the link rule, have a dependency on &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; itself. But then if you change &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;, it will trigger a relink, even though that rule does not depend on &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. You would need to break the Makefile down into many smaller Makefiles.&lt;br /&gt;
&lt;br /&gt;
AMBuild mitigates these problems by intelligently updating the dependency graph. If a reparse of the build scripts produces identical nodes, it will not consider those nodes as stale.&lt;br /&gt;
&lt;br /&gt;
Furthermore, when deleting rules, Make will leave their outputs behind. The author is not aware of an easy way to solve this. Leaving old outputs behind is undesirable for a number of reasons. Stale outputs might fool a user or developer tool into thinking the build has succeeded, when in fact it has failed. Stale outputs might be loaded accidentally, i.e. &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; picking up a library that should not exist. Tests that developers forgot to update might pass locally because of a stale output.&lt;br /&gt;
&lt;br /&gt;
In AMBuild, leaving stale files behind is an error, since they would not be produced by a fresh build.&lt;br /&gt;
&lt;br /&gt;
==Tup==&lt;br /&gt;
AMBuild is designed to be, essentially, a miniature clone of Tup written entirely in Python. In particular it closely follows concepts in [http://gittup.org/tup/build_system_rules_and_algorithms.pdf the Tup whitepaper]. However there are a few differences that may make one more desirable over the other:&lt;br /&gt;
* Tup has been around longer than AMBuild 2, and has been more thoroughly tested. &lt;br /&gt;
* Tup uses complex file system features to optimize updates. Algorithms that are O(n) in AMBuild tend to be O(1) in Tup.&lt;br /&gt;
* AMBuild only requires a default Python installation to work. Tup, due to being written in C and using very platform specific file system features, may not be as accessible.&lt;br /&gt;
* Tup has more features for speeding up very large projects. It can do minimal reparsing and it can reduce the number of links in large graphs.&lt;br /&gt;
* AMBuild is designed to be a front-end in addition to a back-end. It has a simple API and script syntax, and is designed to support multiple output formats. For example, it could conceivably generate Visual Studio or XCode project files.&lt;br /&gt;
&lt;br /&gt;
Since AMBuild is also a frontend, AMBuild may one day eliminate its backend in favor of emitting Tupfiles instead.&lt;br /&gt;
&lt;br /&gt;
AMBuild's IPC implementation is very low-level, and it has not yet been ported beyond Windows, Mac/BSD, or Linux. However it's not difficult to port to Unix-like systems, and if needed a generic (albeit suboptimal) cross-platform implementation could be provided.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11068</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11068"/>
		<updated>2020-08-23T07:46:17Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;b&amp;gt;This documentation is for the AMBuild 2.2 API.&amp;lt;/b&amp;gt; See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11066</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11066"/>
		<updated>2020-08-23T07:46:04Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: BAILOPAN moved page AMBuild API (2.2) to AMBuild API&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This documentation is for the AMBuild 2.2 API. See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API_(2.2)&amp;diff=11067</id>
		<title>AMBuild API (2.2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API_(2.2)&amp;diff=11067"/>
		<updated>2020-08-23T07:46:04Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: BAILOPAN moved page AMBuild API (2.2) to AMBuild API&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[AMBuild API]]&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API_(2.1)&amp;diff=11064</id>
		<title>AMBuild API (2.1)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API_(2.1)&amp;diff=11064"/>
		<updated>2020-08-23T07:45:42Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: BAILOPAN moved page AMBuild API to AMBuild API (2.1) over redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This documentation is for the AMBuild 2.1 API. [[AMBuild API (2.0)|Click here]] for the 2.0 API.&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''configure context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''ProjectBuilder''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and two-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;. Note that AMBuild can run on either Python 2 or Python 3, so it is best to use the subset which is common to both versions.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is a string constructed out of the platform and architecture, such as &amp;quot;obj-linux-i386&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
* &amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - If this project only supports a single target architecture, it may be specified here. Otherwise, the target architecture will be inherited from the host architecture, and can be further overridden by the &amp;lt;tt&amp;gt;--target-arch&amp;lt;/tt&amp;gt; command-line option.&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_arch&amp;lt;/tt&amp;gt; - By default, this is &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;. A project can set this to a default architecture if it prefers one. &amp;lt;tt&amp;gt;--target-arch&amp;lt;/tt&amp;gt; will still override it if specified.&lt;br /&gt;
&lt;br /&gt;
Note that architectures specified on the command line are currently not normalized - they are passed as given.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''cxx'' - An instance of a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object, or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; was never called. Calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; will set the &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; field for this and all future contexts. Each context gets a clone of its parent's compiler, so it is safe to modify compilers in inner scripts.&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''target'' - The System object corresponding to the desired target system (see [[#Platforms]]).&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(options = {})'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; dictionary, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object that is also accessible via the &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; attribute.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and ProjectBuilders return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
The target architecture represents what the build should attempt to configure itself for. AMBuild does not attempt to configure the compiler or environment for cross-compiling.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
There are two APIs for creating C++ binaries - &amp;lt;tt&amp;gt;ProjectBuilder&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;ProjectBuilder&amp;lt;/tt&amp;gt; makes it possible to group related tasks together. For example, if one binary has multiple build configurations, a &amp;lt;tt&amp;gt;Builder&amp;lt;/tt&amp;gt; will allow you to group them together with a common set of source files. For building, the results are exactly the same as creating individual &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;s.&lt;br /&gt;
&lt;br /&gt;
For generating IDE project files, the distinction can be important. When the same binary is built across multiple configurations, AMBuild generates a new project file for each configuration. Using &amp;lt;tt&amp;gt;ProjectBuilder&amp;lt;/tt&amp;gt; over &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; allows AMBuild to store each of the configurations in a single project file.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ProgramProject(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;ProjectBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;LibraryProject(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;ProjectBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibraryProject(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;ProjectBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original &amp;lt;tt&amp;gt;builder.cxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=ProjectBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;ProjectBuilder&amp;lt;/tt&amp;gt; assists in creating multiple configurations of a C++ compilation task. Set the source list via &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt;, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;ProjectBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original &amp;lt;tt&amp;gt;builder.compiler&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, and 'cl.exe' is not in PATH, then AMBuild&lt;br /&gt;
    looks in the registry for Visual Studio 2015. It will also look for&lt;br /&gt;
    the 'vswhere' tool, and if present, will detect installations of&lt;br /&gt;
    Visual Studio 2017 and 2019. The highest working version is used. If&lt;br /&gt;
    no working version is found, the logic in step 2 is used as a&lt;br /&gt;
    last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure newer Windows Kits properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand (eg, the environment set up, and CC/CXX set properly).&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.1.1, options may be specified in adictionary given to &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;. Any unused options will be left in the dictionary after the call returns, and any consumed options will be removed.&lt;br /&gt;
&lt;br /&gt;
Available options:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not that since the &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; argument is specific to AMBuild 2.1.1 and higher, projects wanting to maintain backwards compatibility can use this snippet to detect its availability:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    apiVersion = getattr(builder, 'apiVerison', None)&lt;br /&gt;
    if apiVersion and apiVersion &amp;gt;= '2.1.1':&lt;br /&gt;
    	cxx = builder.DetectCxx(cxx_options)&lt;br /&gt;
    else:&lt;br /&gt;
    	cxx = builder.DetectCxx()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; fields on Contexts have been replaced with the &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System objects. It is enough to replace &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;target.platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11063</id>
		<title>AMBuild API</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMBuild_API&amp;diff=11063"/>
		<updated>2020-08-23T07:44:59Z</updated>

		<summary type="html">&lt;p&gt;BAILOPAN: /* Options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This documentation is for the AMBuild 2.2 API. See older versions: [[AMBuild API (2.1)]] or [[AMBuild API (2.0)]].&lt;br /&gt;
&lt;br /&gt;
AMBuild scripts have access to the following object types:&lt;br /&gt;
* '''BuildParser''': This tells AMBuild how to begin parsing your &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt;. It is usually created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''Context''': Exposed as the &amp;lt;tt&amp;gt;builder&amp;lt;/tt&amp;gt;, this is the entry point for the API and is known as a ''build context''.&lt;br /&gt;
* '''Entry''': Represents a node in the dependency graph.&lt;br /&gt;
* '''Compiler''': An abstraction representing a C++ compiler environment.&lt;br /&gt;
* '''Project''' and '''BinaryBuilder''': Abstractions for building C++ compilation jobs.&lt;br /&gt;
&lt;br /&gt;
As a general rule, AMBuild uses the following conventions:&lt;br /&gt;
* Methods starting with an upper-case letter are considered public API.&lt;br /&gt;
* Methods starting with a lower-case letter are considered private and should not be used. There are a few exceptions for brevity or accessor-like functions.&lt;br /&gt;
* Properties and attributes ending with an underscore are considered private and should not be used.&lt;br /&gt;
* Spaces are used instead of tabs, and four-space indents are preferred.&lt;br /&gt;
&lt;br /&gt;
=BuildParsers=&lt;br /&gt;
&lt;br /&gt;
BuildParsers are created in &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, and the final step of &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt; is to call &amp;lt;tt&amp;gt;parser.Configure()&amp;lt;/tt&amp;gt;, which will begin parsing the root &amp;lt;tt&amp;gt;AMBuildScript&amp;lt;/tt&amp;gt; of the project. BuildParsers have extra properties worth exploring for more complicated projects:&lt;br /&gt;
* &amp;lt;tt&amp;gt;options&amp;lt;/tt&amp;gt; - An instance of &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; - The System object for the host system. (see [[#Platforms]])&lt;br /&gt;
* &amp;lt;tt&amp;gt;default_build_folder&amp;lt;/tt&amp;gt; - By default, the build folder for a project is &amp;quot;objdir&amp;quot;. This property can be set to change the default. It can be a string, or a function taking a &amp;lt;tt&amp;gt;BuildParser&amp;lt;/tt&amp;gt; object and returning a string.&lt;br /&gt;
&lt;br /&gt;
=Contexts=&lt;br /&gt;
&lt;br /&gt;
Contexts are implemented in &amp;lt;tt&amp;gt;ambuild2/frontend/base_gen.py&amp;lt;/tt&amp;gt;. They are the entry point for using AMBuild.&lt;br /&gt;
&lt;br /&gt;
When using path strings, it is important to note how AMBuild recognizes paths.&lt;br /&gt;
* ''source'' path strings may be any absolute path in the file system, as long as that path is not within the build folder. Source paths may also be expressed as relative to &amp;lt;tt&amp;gt;builder.currentSourcePath&amp;lt;/tt&amp;gt;, which is the source folder of the currently executing build script.&lt;br /&gt;
* ''output'' path strings are always relative to &amp;lt;tt&amp;gt;builder.buildFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''parent'' - The context that loaded the current context.&lt;br /&gt;
* ''script'' - The path, relative to &amp;lt;tt&amp;gt;sourcePath&amp;lt;/tt&amp;gt;, of the current build script.&lt;br /&gt;
* ''sourcePath'' - The absolute path to the source tree.&lt;br /&gt;
* ''options'' - The result of evaluating command-line options from &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;, via the &amp;lt;tt&amp;gt;optparse&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
* ''buildPath'' - The absolute path to the build folder.&lt;br /&gt;
* ''buildFolder'' - The working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;; &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; for the root of the build.&lt;br /&gt;
* ''currentSourcePath'' - The source folder that the current build script is in.&lt;br /&gt;
* ''host'' - The System object corresponding to the host system (see [[#Platforms]]).&lt;br /&gt;
* ''originalCwd'' - The working directory that was set when the user first configured the build. This is useful when constructing absolute paths from user inputs that contain relative paths.&lt;br /&gt;
&lt;br /&gt;
Custom attributes can be set on Build Contexts. When evaluating nested build scripts, these attributes will be automatically copied. If the object stored at the attribute inherits from &amp;lt;tt&amp;gt;ambuild2.frontend.cloneable.Cloneable&amp;lt;/tt&amp;gt;, then it will be deep copied. Compiler objects (described later on) are always cloned this way, so nested build scripts do not interfere with parent ones.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''SetBuildFolder(folder)'' - Sets the working directory of jobs in this context, relative to &amp;lt;tt&amp;gt;buildPath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''folder'' - A string representing the folder path. '.' and './' are allowed.&lt;br /&gt;
** Returns &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''DetectCxx(**kwargs)'' - Detects C and C++ compilers and raises an exception if neither are available or they do not match. The full rules for this, and the options available, are under [[#C++ Detection]].&lt;br /&gt;
** Returns a &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Add(taskbuilder)'' - Some jobs are too complex to use a single API call, and instead provide objects to assist in creation. These objects are finalized into the dependency graph with this function. Currently, the only complex jobs built-in are C/C++ compilation jobs.&lt;br /&gt;
** ''taskbuilder'' - The job builder instance.&lt;br /&gt;
** Returns a value based on the taskbuilder. For example, BinaryBuilders return a 'CppNode' described under the Compiler section, and Projects return a list of CppNodes.&lt;br /&gt;
* ''AddFolder(folder)'' - Ensures that a folder is created when performing a build. The folder is created relative to the context's local build folder.&lt;br /&gt;
** ''folder'' - A relative path specifying the folder. Folder chains can be created all at once; i.e. 'a/b/c' is a valid target even if 'a' or 'a/b' do not exist.&lt;br /&gt;
** Returns an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance describing the folder creation node.&lt;br /&gt;
* ''AddSymlink(source, output_path)'' - Adds a job to the build that will perform a symlink. On systems where symlinks are not available, it is implemented as a copy.&lt;br /&gt;
* ''AddCopy(source, output_path)'' - Adds a job to the build that will perform a file copy.&lt;br /&gt;
** ''source'' - Either a string containing a source file path, or a source node, or an output node, representing the file that will be the source of the operation.&lt;br /&gt;
** ''output_path'' - One of the following:&lt;br /&gt;
*** A string path ending in a path separator, or &amp;lt;tt&amp;gt;'.'&amp;lt;/tt&amp;gt;, specifying the folder to copy or symlink the file to. It is relative to the context's local build folder.&lt;br /&gt;
*** A string path ending in a filename, representing the destination file of the operation. It is relative to the context's local build folder.&lt;br /&gt;
*** A folder node created via &amp;lt;tt&amp;gt;AddFolder()&amp;lt;/tt&amp;gt;, representing the folder to copy or symlink the file to. In this case, the folder node's path is taken as-is and is not relative to the local build folder.&lt;br /&gt;
** See &amp;lt;tt&amp;gt;AddCommand&amp;lt;/tt&amp;gt; for return values.&lt;br /&gt;
* ''AddCommand(inputs, argv, outputs, folder?, dep_type?, weak_inputs?, shared_outputs?)'' - Adds a custom command that will be executed manually. The working directory of the command is the context's local build folder. As created, the command has no dependencies. If it has source dependencies they can be specified via &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''inputs'' - An iterable containing source file paths and/or &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; output-file nodes that are incoming dependencies.&lt;br /&gt;
** ''argv'' - The argument vector that will be passed to &amp;lt;tt&amp;gt;subprocess.Popen&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;argv[0]&amp;lt;/tt&amp;gt; should be the executable.&lt;br /&gt;
** ''outputs'' - An iterable containing files that are outputs of this command. Each file must be a relative path from the context's local build folder.&lt;br /&gt;
** ''folder'' - The working directory for the command. By default, this is &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt;. It can be &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; to specify the root of the build. Otherwise, it must be an &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; from calling &amp;lt;tt&amp;gt;AddFolder&amp;lt;/tt&amp;gt; or reading &amp;lt;tt&amp;gt;localFolder&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''dep_type'' - Specifies whether the output of the command contains a dependency list. The following three values are supported:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; - (default) This command does not support dependency discovery or does not have dynamic dependencies.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'msvc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Visual Studio C++ compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'gcc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the GNU C Compiler or Clang, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'sun'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the Sun Pro compiler, in &amp;lt;tt&amp;gt;stderr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*** &amp;lt;tt&amp;gt;'fxc'&amp;lt;/tt&amp;gt; - Dependencies are spewed in the exact manner of the FXC compiler, in &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** ''weak_inputs'' - Optional list of weak dependencies. Weak dependencies enforce an ordering between two commands, but an update only occurs if the command is discovered to actually use the dependency (see the Compiler.sourcedeps attribute).&lt;br /&gt;
** ''shared_outputs'' - Optional list of &amp;quot;shared&amp;quot; outputs. Shared outputs are files that are generated by multiple commands. This is a degenerate case in AMBuild, but some systems do this, and AMBuild needs to understand where the files came from. Shared outputs can not be used as an input; they do not participate in the dependency system, except that AMBuild knows when to remove them.&lt;br /&gt;
** Returns a 2-tuple, containing:&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instance representing the node for this command in the dependency graph.&lt;br /&gt;
*** A list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; instances, each instance corresponding to one of the output file paths specified.&lt;br /&gt;
* ''AddConfigureFile(path)'' - Adds a source path that will trigger automatic reconfiguring if the file changes. This is useful for files that are conceptually part of a build script, but are not actually loaded as a build script.&lt;br /&gt;
** ''path'' - A source path.&lt;br /&gt;
* ''HasFeature(name)'' - Returns whether the given named feature is available. This is not currently used, but exists so we can extend the API in a backwards-compatible way in the future.&lt;br /&gt;
* ''ProgramProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building executable programs. Projects are described later on.&lt;br /&gt;
* ''LibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building dynamically linked libraries. Projects are described later on.&lt;br /&gt;
* ''StaticLibraryProject(name)'' - Returns a &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; for building statically linked libraries. Projects are described later on.&lt;br /&gt;
* ''CloneableList(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;list&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make lists that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
* ''CloneableDict(*args, **kwargs)'' - Wrapper around &amp;lt;tt&amp;gt;OrderedDict&amp;lt;/tt&amp;gt; that implements &amp;lt;tt&amp;gt;Cloneable&amp;lt;/tt&amp;gt;. This can be used to make dictionaries that are deep-copied when assigned to an attribute in a build context.&lt;br /&gt;
&lt;br /&gt;
===Contexts and Scripts===&lt;br /&gt;
&lt;br /&gt;
AMBuild can run additional, user-provided scripts so the build process is not clumped into one giant file. When running sub-scripts, each script has a &amp;quot;context&amp;quot;. This context is a sub-builder that inherits various properties, and allows the script to not potentially interfere with variables and state in the global builder. These contexts can be created in one of three ways:&lt;br /&gt;
* '''Child''' contexts are relative to the context that created them. Their containing folder must be the parent folder or a folder somewhere underneath it, and their output folder is always the parent's output folder or a sub-folder of it.&lt;br /&gt;
* '''Top-Level''' contexts are child contexts that have no parent; they can change their output folder.&lt;br /&gt;
* '''Empty''' contexts have no input or output folder; they cannot perform build steps in their own context.&lt;br /&gt;
&lt;br /&gt;
With that in mind, AMBuild provides the following functions on build contexts to assist in running additional scripts. Each of these functions takes in an optional ''vars'' parameter; if not provided, it is initialized to an empty &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. Otherwise the newly run script's globals will be merged with ''vars'', along with the ''vars'' used to call the invoking script (if any).&lt;br /&gt;
&lt;br /&gt;
Additionally, each of these methods accepts a ''path'' (or in some cases, a list of paths). These paths must either be relative to the current source folder, or they may be specified as relative to the root of the source tree via a leading '/'. Paths may not be outside the source tree.&lt;br /&gt;
&lt;br /&gt;
* ''Import(path, vars?)'' - Runs ''path'' in an empty context, and returns the globals of the completed script as a &amp;lt;tt&amp;gt;dict&amp;lt;/tt&amp;gt;. If ''path'' is not a string, and is iterable, each path will be run in iteration order and &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; will be returned.&lt;br /&gt;
* ''Eval(path, vars?)'' - Helper function that runs ''path'' in an empty context, and returns the value of the global variable &amp;lt;tt&amp;gt;rvalue&amp;lt;/tt&amp;gt; in the completed script (or &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; if none was present).&lt;br /&gt;
* ''Build(path, vars?)'' - Runs ''path'' in a child context. ''path'' may alternately be an iterable of path strings, in which case each is evaluated in iteration order. If ''path'' is a single path string, and the executed script ends with a global variable called ''rvalue'', then the value of that variable is returned. Otherwise, &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; is returned.&lt;br /&gt;
&lt;br /&gt;
==Platforms==&lt;br /&gt;
AMBuild represents the host and target system via System objects. These objects have &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; properties. &amp;lt;tt&amp;gt;platform&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;windows&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;mac&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;linux&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;freebsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;openbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;netbsd&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;solaris&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;cygwin&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;arch&amp;lt;/tt&amp;gt; may be one of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86_64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;x86&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;arm64&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;armv*&amp;quot;&amp;lt;/tt&amp;gt; (where * is the ARM version and configuration, such as &amp;quot;armv5ejl&amp;quot;)&lt;br /&gt;
* ... Other architectures are untested, but will be added here as tested.&lt;br /&gt;
&lt;br /&gt;
Some patterns are normalized when passed as arguments. For example, &amp;quot;amd64&amp;quot; or &amp;quot;x64&amp;quot; will be normalized to &amp;quot;x86_64&amp;quot; for convenience.&lt;br /&gt;
&lt;br /&gt;
=Entry=&lt;br /&gt;
&amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects are considered mostly opaque. However, all frontends must define at least these attributes:&lt;br /&gt;
* ''path'' - A file system path that uniquely represents nodes that are present in the filesystem, such as source files, output files, or folders.&lt;br /&gt;
&lt;br /&gt;
=Compiler=&lt;br /&gt;
Compiler objects encapsulate information about invoking the C or C++ compiler. Most of its attributes are lists of options, so it is best to use += to extend these lists, to avoid replacing previously set options.&lt;br /&gt;
&lt;br /&gt;
Whenever options come in pairs - for example, C/C++ flags versus C++-only flags, C++ flags will automatically include all C flags during compilation time.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''includes'' - List of C and C++ include paths&lt;br /&gt;
* ''cxxincludes'' - List of C++ include paths.&lt;br /&gt;
* ''cflags'' - List of C and C++ compiler flags.&lt;br /&gt;
* ''cxxflags'' - List of C++ compiler flags.&lt;br /&gt;
* ''defines'' - List of C and C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''cxxdefines'' - List of C++ #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''rcdefines'' - List of RC (Resource Compiler) #defines, in the form of 'KEY' or 'KEY=VALUE'&lt;br /&gt;
* ''linkflags'' - Link flags (see below).&lt;br /&gt;
* ''postlink'' - Array of objects to link, added to the linker flags after linkflags. See below.&lt;br /&gt;
* ''sourcedeps'' - An array of output nodes which should be weak dependencies on each source compilation node.&lt;br /&gt;
* ''weaklinkdeps'' - Array of entries that will act as weak inputs to the linker. This is to ensure ordering; they do not affect the actual linker command. &lt;br /&gt;
* ''symbol_files'' - One of three values:&lt;br /&gt;
**&amp;lt;tt&amp;gt;'bundled'&amp;lt;/tt&amp;gt; - If possible, debug information will be generated into the binary. On some compilers this is not possible. For example, MSVC always generates .PDB files.&lt;br /&gt;
**&amp;lt;tt&amp;gt;'separate'&amp;lt;/tt&amp;gt; - Separates debug information into a separate file (a .pdb file, .sym file, or dSYM package depending on the platform).&lt;br /&gt;
* ''version'' - Returns an object representing the compiler version. It may be stringified with &amp;lt;tt&amp;gt;str()&amp;lt;/tt&amp;gt;. It can also be compared to either integers, other version objects, or strings. For example: &amp;lt;tt&amp;gt;compiler.version &amp;gt;= '4.7.4'&amp;lt;/tt&amp;gt; will return true if the compiler's version is at least &amp;lt;tt&amp;gt;4.7.3&amp;lt;/tt&amp;gt;. The exact meaning of the version is vendor-dependent; for example, MSVC versions look like large numbers (&amp;lt;tt&amp;gt;1800&amp;lt;/tt&amp;gt; corresponds to Visual Studio 2013).&lt;br /&gt;
* ''family'' - Returns the compiler family. This is either MSVC, GCC, Clang, or SunPro.&lt;br /&gt;
* ''behavior'' - Returns the compiler meta-family, or the most generic compiler this compiler tries to emulate. This is either MSVC, GCC, or SunPro.&lt;br /&gt;
* ''target'' - Returns the &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object representing the platform and architecture tuple. Currently, AMBuild has support for cross-compiling to different architectures, but not to different platforms, so the platform will always match &amp;lt;tt&amp;gt;builder.host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Entries to &amp;lt;tt&amp;gt;linkflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;postlink&amp;lt;/tt&amp;gt; can be:&lt;br /&gt;
* A string representing a linker flag.&lt;br /&gt;
* An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects are useful when precise control is needed over what text is given to the linker in order to link in a file. Essentially, they let you customize the link flag while still including a dependency. They also allow lazy computation of dependencies, since sometimes extra steps must be generated before linking to an object. &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; objects have two attributes:&lt;br /&gt;
** &amp;lt;tt&amp;gt;text&amp;lt;/tt&amp;gt;, the text that will be passed to the linker when constructing its argument list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;node&amp;lt;/tt&amp;gt;, an object which tells AMBuild how to build a dependency for the linker flag. It can be:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;, meaning that the text is a file path.&lt;br /&gt;
*** A file path.&lt;br /&gt;
*** An &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; or list of &amp;lt;tt&amp;gt;Entry&amp;lt;/tt&amp;gt; objects representing the output files of a command, or&lt;br /&gt;
*** A function which returns the above, and has the signature &amp;lt;tt&amp;gt;(builder, binary)&amp;lt;/tt&amp;gt;, receiving a &amp;lt;tt&amp;gt;Context&amp;lt;/tt&amp;gt; object and a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* ''Note:'' AMBuild does not currently support automatic dependency generation for &amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt; style linking.&lt;br /&gt;
&lt;br /&gt;
For example, to generate a linker invocation like &amp;quot;&amp;lt;tt&amp;gt;g++ main.o tier1.so -o main&amp;lt;/tt&amp;gt;&amp;quot;, where &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; is a generated file, you could do:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
binary.postlink += [binary.Dep('tier1.so', tier1_so_entry)]&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this requires symlinking &amp;lt;tt&amp;gt;tier1.so&amp;lt;/tt&amp;gt; to be in the local folder, you can get more complex, such as:&lt;br /&gt;
&amp;lt;Python&amp;gt;&lt;br /&gt;
def make_linker_dep(compiler, name, entry):&lt;br /&gt;
  def lazy_dep(builder, binary):&lt;br /&gt;
    cmd, (output,) = builder.AddSymlink(entry, '.')&lt;br /&gt;
    return output&lt;br /&gt;
  return compiler.Dep(name, lazy_dep)&lt;br /&gt;
&amp;lt;/Python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* &amp;lt;tt&amp;gt;Program(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate an executable (&amp;lt;tt&amp;gt;.exe&amp;lt;/tt&amp;gt; is automatically appended on Windows).&lt;br /&gt;
* &amp;lt;tt&amp;gt;Library(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a shared library. &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.dylib&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;StaticLibrary(name)&amp;lt;/tt&amp;gt; - Creates a new &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; instance, with a copy of the compiler settings. The builder is configured to generate a static library. &amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.lib&amp;lt;/tt&amp;gt; is automatically appended depending on the platform. Nothing is ever prepended to the name.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Dep(text, node)&amp;lt;/tt&amp;gt; - Creates a &amp;lt;tt&amp;gt;Dep&amp;lt;/tt&amp;gt; object instance (see above for more details).&lt;br /&gt;
* &amp;lt;tt&amp;gt;like(name)&amp;lt;/tt&amp;gt; - Returns whether the compiler is &amp;quot;like&amp;quot; another compiler. This is intended to represent the compatibility hierarchy of modern compilers. For example:&lt;br /&gt;
** Visual Studio is &amp;quot;like&amp;quot; 'msvc'.&lt;br /&gt;
** GCC is &amp;quot;like&amp;quot; 'gcc'.&lt;br /&gt;
** Clang is &amp;quot;like&amp;quot; 'gcc' and 'clang'.&lt;br /&gt;
** Note that GCC is not &amp;quot;like&amp;quot; Clang.&lt;br /&gt;
* &amp;lt;tt&amp;gt;pkg_config(pkg, link = 'dynamic')&amp;lt;/tt&amp;gt; - Runs the pkg-config program for the given package name, and adds relevant includes, cflags, and libraries to the compiler. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'dynamic' (default), shared libraries are used. If &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; is 'static', then static libraries are used instead.&lt;br /&gt;
&lt;br /&gt;
=BinaryBuilder=&lt;br /&gt;
&amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; assists in creating C/C++ compilation tasks. Once you've set all the information needed, they are integrated into the dependency graph by using &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''compiler'' - A full copy of the compiler settings used when instantiating this &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. Modifying this compiler will not modify the original.&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
* ''type'' - One of 'static', 'library', or 'program'.&lt;br /&gt;
* ''custom'' - A list of custom steps to include in the compilation process. See [[#Custom C++ Tools]].&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''Module(builder, name)'' - Creates and returns a new ''Module'' object that is attached to the BinaryBuilder it was invoked on. The module object has two properties: ''compiler'', a clone of the current compiler on the BinaryBuilder, and ''sources'', and empty list. Source files added to the module will be compiled as part of the BinaryBuilder that created it, however, they will use the module's compiler settings instead. Modules may be added from any context, and are intended for large monolithic projects that have many components that must be linked together.&lt;br /&gt;
&lt;br /&gt;
=Project=&lt;br /&gt;
Projects assist in creating multiple configurations of a C++ compilation task. It is essentially a factory for &amp;lt;tt&amp;gt;BinaryBuilders&amp;lt;/tt&amp;gt;. It's useful for tying multiple configurations of the same basic component together. The build output is identical to using &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. However, when used with Visual Studio project file generation, you will get one vcxproj file instead of many. Therefore, it's helpful for organization when using AMBuild's IDE tooling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; instances can be obtained through the build context, via &amp;lt;tt&amp;gt;ProgramProject&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LibraryProject&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;StaticLibraryProject&amp;lt;/tt&amp;gt;. You can set the source list via the &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; attribute, then use &amp;lt;tt&amp;gt;Configure()&amp;lt;/tt&amp;gt; to add a new configuration. After all configurations have been added, use &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; to add the project to the dependency graph.&lt;br /&gt;
&lt;br /&gt;
When calling &amp;lt;tt&amp;gt;builder.Add()&amp;lt;/tt&amp;gt; on a project, the return value is a list of &amp;lt;tt&amp;gt;CppNode&amp;lt;/tt&amp;gt;s, one for each configuration in the order they were added.&lt;br /&gt;
&lt;br /&gt;
==Attributes==&lt;br /&gt;
* ''sources'' - An (initially empty) list of C/C++ source file paths. They can be absolute paths, or paths relative to &amp;lt;tt&amp;gt;currentSourcePath&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''localFolder'' - The name of the folder this binary will be generated in, relative to the &amp;lt;tt&amp;gt;buildFolder&amp;lt;/tt&amp;gt; of the context that adds the tasks.&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
* ''Configure(compiler, name, tag)'' - Returns a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt; with the given name. The compiler must be an object returned by &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt;. The tag is used to describe the configuration for IDE project files.&lt;br /&gt;
* ''Dep(text, node)'' - A wrapper for &amp;lt;tt&amp;gt;compiler.Dep&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=C++ Detection=&lt;br /&gt;
When using the &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; API, AMBuild uses the following logic to find a C++ compiler:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If 'CC' and 'CXX' are defined in the environment, those most result&lt;br /&gt;
     in a valid compiler, and no other detection is performed. On&lt;br /&gt;
     Windows, tools like &amp;quot;rc&amp;quot; and &amp;quot;lib&amp;quot; must be in the environment.&lt;br /&gt;
     Defining CC but not CXX (or vice-versa) is an error.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If running on Windows, if 'cl.exe' is in PATH, then AMBuild assumes&lt;br /&gt;
     the environment has already been configured, and looks for, in this&lt;br /&gt;
     order: cl, clang, gcc, icc.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, if &amp;lt;tt&amp;gt;AMBUILD_VCVARS_&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; is defined in the environment,&lt;br /&gt;
     AMBuild will use the .bat file specified to create the Visual Studio environment.&lt;br /&gt;
     The &amp;lt;tt&amp;gt;&amp;amp;lt;arch&amp;amp;gt;&amp;lt;/tt&amp;gt; component can either be a normalized architecture name&lt;br /&gt;
     (such as &amp;lt;tt&amp;gt;X86_64&amp;lt;/tt&amp;gt;) or it can be &amp;lt;tt&amp;gt;ALL&amp;lt;/tt&amp;gt;, in which case, the VS architecture&lt;br /&gt;
     name will be passed to the batch file as an argument.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;On Windows, AMBuild then looks in the registry for Visual Studio 2015. It will&lt;br /&gt;
    also look for the 'vswhere' tool, and if present, will detect installations&lt;br /&gt;
    of Visual Studio 2017 and 2019. The highest working version is used. It will&lt;br /&gt;
    also detect Microsoft Visual C++ Build Tools (2015). If no working version&lt;br /&gt;
    of anything is found, the logic in step 2 is used as a last-ditch attempt.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Otherwise, AMBuild tries to run clang, gcc, or icc (in that order).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In all cases, if &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; and/or &amp;lt;tt&amp;gt;CXXFLAGS&amp;lt;/tt&amp;gt; are defined in the environment,&lt;br /&gt;
they will be propagated into the detected compiler.&lt;br /&gt;
&lt;br /&gt;
Note that on Windows, this logic is heavily dependent on vcvars being functional. For example,&lt;br /&gt;
Visual Studio 2015 may not configure Windows Kit 10 properly, and&lt;br /&gt;
AMBuild will not be able to automatically detect such an install. We recommend that for continuous integration, and reproducible, release-quality builds, that the environment be entirely configured beforehand via &amp;lt;tt&amp;gt;AMBUILD_VCVARS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Cross Compilation==&lt;br /&gt;
AMBuild tries to automatically detect cross-compilation, eg, compiling to non-native &amp;lt;i&amp;gt;triple&amp;lt;/i&amp;gt;.&lt;br /&gt;
A triple is a &amp;lt;i&amp;gt;platform-arch[subarch][-abi]&amp;lt;/i&amp;gt; sequence. For example, &amp;lt;i&amp;gt;windows-x86&amp;lt;/i&amp;gt; or&lt;br /&gt;
&amp;lt;i&amp;gt;linux-armv7-gnueabihf&amp;lt;/i&amp;gt;. On Mac and Windows targets, the ABI part of the triple is always&lt;br /&gt;
dropped since there is only one ABI.&lt;br /&gt;
&lt;br /&gt;
These triples directly correspond to &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
When specifying targets via a triple, AMBuild supports some shorthand sequences:&lt;br /&gt;
* &amp;lt;i&amp;gt;arch&amp;lt;/i&amp;gt; will only change the target architecture. Eg, &amp;quot;x86&amp;quot; on &amp;quot;linux-x86_64&amp;quot; will result in &amp;quot;linux-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;platform-arch&amp;lt;/i&amp;gt; works when the ABI can be elided. Eg, &amp;quot;windows-x86&amp;quot;.&lt;br /&gt;
* &amp;lt;i&amp;gt;arch-abi&amp;lt;/i&amp;gt; works when the host and target platform are the same. Eg, &amp;quot;arm-gnueabihf&amp;quot; on &amp;quot;linux-x86&amp;quot; will result in &amp;quot;linux-arm-gnueabihf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Options==&lt;br /&gt;
As of AMBuild 2.2, &amp;lt;tt&amp;gt;builder.DetectCxx()&amp;lt;/tt&amp;gt; supports the following options. Options not recognized are ignored.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; - A string to force the compiler's triple (or shorthand for a triple), as described above. Normally, AMBuild will use the first working compiler it can find, which could theoretically have any target configuration. This will force AMBuild to find a matching compiler, and if none exists, it will fail.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;target_arch&amp;lt;/tt&amp;gt; - A string to force only a change in architecture. This is useful for projects that do not support cross-platform, but do support cross-architecture, builds.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;force_msvc_version&amp;lt;/tt&amp;gt; - A string specifying which version of MSVC can be used during automatic detection. This only applies to searches for MSVC installations, not for &amp;quot;cl.exe&amp;quot; in the environment or when CC/CXX has been manually set. The string should be a version number (eg, &amp;quot;14.0&amp;quot;, &amp;quot;15.0&amp;quot;, or &amp;quot;16.0&amp;quot; etc).&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Custom C++ Tools=&lt;br /&gt;
BinaryBuilders have a &amp;quot;custom tool&amp;quot; list that allows build scripts to hook into the compilation process. Usually, custom entries will be fully provided by an AMBuild helper or a third party helper. However it is possible to write your own custom tools.&lt;br /&gt;
&lt;br /&gt;
FXC is a good example of when a custom tool is needed. FXC is a Microsoft tool for compiling HLSL shaders. It has a mode to generate C++ headers, but it's extremely cumbersome to work with, and AMBuild can hide that complexity while safely integrating it into the dependency graph.&lt;br /&gt;
&lt;br /&gt;
Custom tools are objects added to the &amp;lt;tt&amp;gt;custom&amp;lt;/tt&amp;gt; list on a &amp;lt;tt&amp;gt;BinaryBuilder&amp;lt;/tt&amp;gt;. This object must have a &amp;lt;tt&amp;gt;tool&amp;lt;/tt&amp;gt; attribute, containing an object with the following methods:&lt;br /&gt;
* ''evaluate(cmd)'' - Called when the BinaryBuilder is submitted to the build tool.&lt;br /&gt;
&lt;br /&gt;
The ''cmd'' parameter to ''evaluate'' is an object with the following properties:&lt;br /&gt;
* &amp;lt;tt&amp;gt;context&amp;lt;/tt&amp;gt; - The build context for the module that the tool will run against.&lt;br /&gt;
* &amp;lt;tt&amp;gt;localFolderNode&amp;lt;/tt&amp;gt; - A folder node, representing the output folder for the module's object files.&lt;br /&gt;
* &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; - The custom object given to the BinaryBuilder, that this tool should process.&lt;br /&gt;
* &amp;lt;tt&amp;gt;compiler&amp;lt;/tt&amp;gt; - The compiler object for the module this tool is running in.&lt;br /&gt;
&lt;br /&gt;
Additionally, the ''cmd'' object has properties which are considered outputs:&lt;br /&gt;
* &amp;lt;tt&amp;gt;sources&amp;lt;/tt&amp;gt; - An optional list of additional sources to compile. The tool may append new items.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; - An optional list of additional source dependencies. The module's &amp;lt;tt&amp;gt;sourcedeps&amp;lt;/tt&amp;gt; array will be extended to include anything the tool adds here.&lt;br /&gt;
&lt;br /&gt;
Finally, the ''cmd'' tool has helper methods:&lt;br /&gt;
* ''NameForObjectFile(path)'' - Computes a &amp;quot;safe&amp;quot; object file name for the given path. All characters that do not conform to C++ identifier name rules are replaced with an underscore.&lt;br /&gt;
* ''ComputeSourcePath(path)'' - Computes a command-line safe source path for an external tool. The output is either an absolute path, or a path relative to &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ''CustomSource(source, weak_deps=[])'' - Returns an object that acts as a source file for a source file list. However, it can be annotated with extra instructions to the build process.&lt;br /&gt;
** &amp;lt;tt&amp;gt;weak_deps&amp;lt;/tt&amp;gt; - An additional list of weak dependencies for this source file.&lt;br /&gt;
&lt;br /&gt;
When the binary is submitted to the build, the custom tool will have the chance to include any extra steps it wants. It should execute these steps, if possible, in the same folder as &amp;lt;tt&amp;gt;cmd.localFolderNode&amp;lt;/tt&amp;gt;. If these steps introduce new source files, they should be included in &amp;lt;tt&amp;gt;cmd.sources&amp;lt;/tt&amp;gt;. New weak dependencies should be included in &amp;lt;tt&amp;gt;cmd.sourcedeps&amp;lt;/tt&amp;gt;. If no dependencies at all are introduced, then you probably don't need a custom tool, as the C++ binary is not dependent on anything custom.&lt;br /&gt;
&lt;br /&gt;
=Predefined Custom C++ Tools=&lt;br /&gt;
&lt;br /&gt;
* See [[AMBuild FXC API]]&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.1=&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.cxx&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt; if you do not support multi-architecture builds.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
* Projects may no longer be created from &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; objects. They are created from contexts, and compilers are attached when a project binary is created.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Changes from 2.0=&lt;br /&gt;
If upgrading from the 2.0 API, the following changes should be noted:&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.DetectCompilers&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;Context.DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.compiler&amp;lt;/tt&amp;gt; has been removed. You can set it manually after calling &amp;lt;tt&amp;gt;DetectCxx&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;Context.RunScript&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RunBuildScripts&amp;lt;/tt&amp;gt; have been renamed to &amp;lt;tt&amp;gt;Context.Build&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Paths to &amp;lt;tt&amp;gt;RunBuildScript[s]&amp;lt;/tt&amp;gt; may now be specified as relative to the root of the source tree, by prefixing the path with '/'.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;vendor&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; is now undefined. It must not be accessed or compared. Use the new &amp;lt;tt&amp;gt;family&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;behavior&amp;lt;/tt&amp;gt; accessors, or use the &amp;lt;tt&amp;gt;like()&amp;lt;/tt&amp;gt; method.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;debuginfo&amp;lt;/tt&amp;gt; property on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; has been renamed to &amp;lt;tt&amp;gt;symbol_files&amp;lt;/tt&amp;gt;, and it no longer accepts &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;cc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;cxx&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;argv&amp;lt;/tt&amp;gt; properties on &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; have been removed.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; field on Contexts has been replaced with the &amp;lt;tt&amp;gt;host&amp;lt;/tt&amp;gt; System object. It is enough to replace &amp;lt;tt&amp;gt;host_platform&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;host.platform&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;target_platform&amp;lt;/tt&amp;gt; field on Contexts has been moved to the &amp;lt;tt&amp;gt;Compiler&amp;lt;/tt&amp;gt; object. It's now a &amp;lt;tt&amp;gt;System&amp;lt;/tt&amp;gt; object and has been renamed to &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* It is no longer possible to run a script from a context that is no longer the active context.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;BuildParser.options&amp;lt;/tt&amp;gt; field is now an &amp;lt;tt&amp;gt;argparse.ArgumentParser&amp;lt;/tt&amp;gt;, rather than an &amp;lt;tt&amp;gt;optparse.OptionParser&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>BAILOPAN</name></author>
		
	</entry>
</feed>