diff --git a/v2/doc/src/extending.xml b/v2/doc/src/extending.xml index da81513ca..641041379 100644 --- a/v2/doc/src/extending.xml +++ b/v2/doc/src/extending.xml @@ -9,10 +9,10 @@ Introduction This document explains how to extend Boost.Build to accomodate - your local requirements. Let's start with quite simple, but + your local requirements. Let's start with a simple but realistic example. - Say you're writing an application which generates C++ code. If + Say you're writing an application that generates C++ code. If you ever did this, you know that it's not nice. Embedding large portions of C++ code in string literals is very awkward. A much better solution is: @@ -21,7 +21,7 @@ Write the template of the code to be generated, leaving - placeholders at the points which will change + placeholders at the points that will change @@ -37,45 +37,50 @@ - It's quite easy to achieve. You write special verbatim files, - which are just C++, except that the very first line of the file - gives a name of variable that should be generated. A simple tool - is created which takes verbatim file and creates a cpp file with - a single char* variable, which name is taken from the first line - of verbatim file, and which value is properly quoted content of - the verbatim file. + It's quite easy to achieve. You write special verbatim files + that are just C++, except that the very first line of the file + contains the name of a variable that should be generated. A simple tool + is created that takes a verbatim file and creates a cpp file with + a single char* variable whose name is taken from the first line + of the verbatim file and whose value is the file's properly quoted content. Let's see what Boost.Build can do. First off, Boost.Build has no idea about "verbatim files". So, - you must register a new type. The following code does it: + you must register a new target type. The following code does + it: import type ; -type.register VERBATIM : verbatim ; +type.register VERBATIM : vrb ; - The first parameter to 'type.register' gives the name of - declared type. By convention, it's uppercase. The second - parameter is suffix for this type. So, if Boost.Build sees - "code.verbatim" in the list of sources, it knows that it's of - type VERBATIM. + - Lastly, you need a tool to convert verbatim files to C++. Say - you've sketched such a tool in Python. Then, you have to inform - Boost.Build about the tool. The Boost.Build concept which - represents a tool is generator. + The first parameter to + type.register gives the name of the + declared type. By convention, it's uppercase. The second parameter + is the suffix for files of this type. So, if Boost.Build sees + code.vrb in a list of sources, it knows that it's of type + VERBATIM. - First, you say that generator 'inline-file' is able to convert - VERBATIM type into C++: + Next, you tell Boost.Build that the verbatim files can be + transformed into C++ files in one build step. A + generator is a template for a build step that + transforms targets of one type (or set of types) into another. Our + generator will be called verbatim.inline-file; it + transforms VERBATIM files into CPP files: import generators ; generators.register-standard verbatim.inline-file : VERBATIM : CPP ; + - Second, you must specify the commands to be run to actually - perform convertion: + Lastly, you have to inform Boost.Build about the shell + commands used to make that transformation. That's done with an + actions declaration. actions inline-file @@ -83,14 +88,21 @@ actions inline-file "./inline-file.py" $(<) $(>) } + + + + Now, we're ready to tie it all together. Put all the code - above in file "verbatim.jam", add "import verbatim ;" to - "project-root.jam", and it's possible to write the following in - Jamfile: + above in file verbatim.jam, add import verbatim ; + to project-root.jam, and it's possible to write + the following in Jamfile: exe codegen : codegen.cpp class_template.verbatim usage.verbatim ; @@ -182,7 +194,7 @@ class verbatim-scanner : common-scanner } All the complex logic is in the common-scanner class, - and you only need to override the method which returns the regular + and you only need to override the method that returns the regular expression to be used for scanning. The paranthethis in the regular expression indicate which part of the string is the name of the included file. @@ -194,7 +206,7 @@ scanner.register verbatim-scanner : include ; The value of the second parameter, in this case include, specifies which properties contain the list - of paths which should be searched for the included files. + of paths that should be searched for the included files. Finally, we assign the new scaner to the VERBATIM @@ -217,10 +229,10 @@ type.set-scanner VERBATIM : verbatim-scanner ; For each additional tool, a Boost.Build object called generator - must be created. That object has specific types of targets which it + must be created. That object has specific types of targets that it accepts an produces. Using that information, Boost.Build is able to automatically invoke the generator. For example, if you declare a - generator which takes a target of the type D and + generator that takes a target of the type D and produces a target of the type OBJ, when placing a file with extention .d in a list of sources will cause Boost.Build to invoke your generator, and then to link the @@ -246,7 +258,7 @@ actions inline-file We declare a standard generator, specifying its id, the source type and the target type. When invoked, the generator will create a target - of type CPP which will have the source target of + of type CPP that will have the source target of type VERBATIM as the only source. But what command will be used to actually generate the file? In bjam, actions are specified using named "actions" blocks and the name of the action @@ -347,7 +359,7 @@ generators.register [ new itrace-generator nm.itrace : EXE : ITRACE ] ; The generated-targets rule will be called with a single source target of type EXE. The call to the virtual-target.traverse will return all targets the - executable depends on, and we further find files which are not + executable depends on, and we further find files that are not produced from anything. The found targets are added to the sources. @@ -356,7 +368,7 @@ generators.register [ new itrace-generator nm.itrace : EXE : ITRACE ] ; sources to the desired types can be completely customized. Here's another real example. Tests for the Boost Python library usually consist of two parts: a Python program and a C++ file. The C++ file is - compiled to Python extension which is loaded by the Python + compiled to Python extension that is loaded by the Python program. But in the likely case that both files have the same name, the created Python extension must be renamed. Otherwise, Python program will import itself, not the extension. Here's how it can be @@ -451,11 +463,11 @@ actions inline-file with. The user does not have to adjust the values for a exact tool. For example, <optimization>speed has the same meaning for all C++ compilers and the user does not have to worry about the exact - options which are passed to the compiler's command line. + options passed to the compiler's command line. - Besides such portable features there are special 'raw' features which + Besides such portable features there are special 'raw' features that allow the user to pass any value to the command line parameters for a particular tool, if so desired. For example, the <cxxflags> feature allows to pass any command line @@ -533,7 +545,7 @@ actions inline-file Another example Here's an another example. - Let's see how we can make a feature which refers to a target. For example, + Let's see how we can make a feature that refers to a target. For example, when linking dynamic libraries on windows, one sometimes needs to specify "DEF file", telling what functions should be exported. It would be nice to use this file like this: @@ -551,7 +563,7 @@ feature def-file : : free dependency ; - One of the toolsets which cares about DEF files is + One of the toolsets that cares about DEF files is msvc. The following line should be added to it. @@ -597,7 +609,7 @@ rule link Sometimes you want to create a shorcut for some set of features. For example, release is a value of the variant and is a shortcut for a set of features. - . + It is possible to define your build variants. For example: @@ -614,7 +626,7 @@ variant super_release : release : <define>USE_ASM ; You are not restricted to using the variant feature - only. Here's example which defines a brand new feature: + only. Here's example that defines a brand new feature: feature parallelism : mpi fake none : composite link-incompatible ; feature.compose <parallelism>mpi : <library>/mpi//mpi/<parallelism>none ; @@ -654,7 +666,7 @@ generators.register-standard obfuscate.file : CPP : OBFUSCATED_CPP ; in Jamfiles, which will convert source to the OBFUSCATED_CPP type. - The second way is to write a wrapper rule, which will redirect to + The second way is to write a wrapper rule that will redirect to any of the existing rules. For example, you have only one library per directory and want all cpp files in the directory to be compiled. You can achieve this effect with: @@ -691,7 +703,7 @@ glib codegen ; Toolset modules If your extensions will be used only on one project, they can be - placed in a separate .jam file which will be + placed in a separate .jam file that will be imported by your project-root.jam. If the extensions will be used on many projects, the users will thank you for a finishing touch. @@ -700,12 +712,12 @@ glib codegen ; The standard way to use a tool in Boost.Build is the using rule. To make it work, you module should provide an init rule. The rule will be called with the same parameters - which were passed to the using rule. The set of allowed + that were passed to the using rule. The set of allowed parameters is determined by you. For example, you can allow the user to specify paths, tool version, or tool options. - Here are some guidelines which help to make Boost.Build more + Here are some guidelines that help to make Boost.Build more consistent: The init rule should never fail. Even if