Frequently Asked Questions
I'm getting "Duplicate name of actual target" error. What does it mean? The most likely case is that you're trying to compile the same file twice, with almost the same, but differing properties. For example: exe a : a.cpp : <include>/usr/local/include ; exe b : a.cpp ; The above snippet requires two different compilations of 'a.cpp', which differ only in 'include' property. Since the 'include' property is free, Boost.Build can't generate two ojects files into different directories. On the other hand, it's dangerous to compile the file only once -- maybe you really want to compile with different includes. To solve this issue, you need to decide if file should be compiled once or twice. Two compile file only once, make sure that properties are the same: exe a : a.cpp : <include>/usr/local/include ; exe b : a.cpp : <include>/usr/local/include ; If changing the properties is not desirable, for example if 'a' and 'b' target have other sources which need specific properties, separate 'a.cpp' into it's own target: obj a_obj : a.cpp : <include>/usr/local/include ; exe a : a_obj ; To compile file twice, you can make the object file local to the main target: exe a : [ obj a_obj : a.cpp ] : <include>/usr/local/include ; exe b : [ obj a_obj : a.cpp ] ; A good question is why Boost.Build can't use some of the above approaches automatically. The problem is that such magic would require additional implementation complexities and would only help in half of the cases, while in other half we'd be silently doing the wrong thing. It's simpler and safe to ask user to clarify his intention in such cases.
Accessing environment variables Many users would like to use environment variables in Jamfiles, for example, to control location of external libraries. In many cases you better declare those external libraries in the site-config.jam file, as documented in the recipes section. However, if the users already have the environment variables set up, it's not convenient to ask them to set up site-config.jam files as well, and using environment variables might be reasonable. In Boost.Build V2, each Jamfile is a separate namespace, and the variables defined in environment is imported into the global namespace. Therefore, to access environment variable from Jamfile, you'd need the following code: import modules ; local path = [ modules.peek : SOME_LIBRARY_PATH ] ; exe a : a.cpp : <include>$(SOME_LIBRARY_PATH) ;
How to control properties order? For internal reasons, Boost.Build sorts all the properties alphabetically. This means that if you write: exe a : a.cpp : <include>b <include>a ; then the command line with first mention the "a" include directory, and then "b", even though they are specified in the opposite order. In most cases, the user doesn't care. But sometimes the order of includes, or other properties, is important. For example, if one uses both the C++ Boost library and the "boost-sandbox" (libraries in development), then include path for boost-sandbox must come first, because some headers may override ones in C++ Boost. For such cases, a special syntax is provided: exe a : a.cpp : <include>a&&b ; The && symbols separate values of an property, and specify that the order of the values should be preserved. You are advised to use this feature only when the order of properties really matters, and not as a convenient shortcut. Using it everywhere might negatively affect performance.
How to control the library order on Unix? On the Unix-like operating systems, the order in which static libraries are specified when invoking the linker is important, because by default, the linker uses one pass though the libraries list. Passing the libraries in the incorrect order will lead to a link error. Further, this behaviour is often used to make one library override symbols from another. So, sometimes it's necessary to force specific order of libraries. Boost.Build tries to automatically compute the right order. The primary rule is that if library a "uses" library b, then library a will appear on the command line before library b. Library a is considered to use b is b is present either in the sources of a or in its requirements. To explicitly specify the use relationship one can use the <use> feature. For example, both of the following lines will cause a to appear before b on the command line: lib a : a.cpp b ; lib a : a.cpp : <use>b ; The same approach works for searched libraries, too: lib z ; lib png : : <use>z ; exe viewer : viewer png z ;
Can I get output of external program as a variable in a Jamfile? From time to time users ask how to run an external program and save the result in Jamfile variable, something like: local gtk_includes = [ RUN_COMMAND gtk-config ] ; Unfortunately, this is not possible at the moment. However, if the result of command invocation is to be used in a command to some tool, and you're working on Unix, the following workaround is possible. alias gtk+-2.0 : : : : <cflags>"`pkg-config --cflags gtk+-2.0`" <inkflags>"`pkg-config --libs gtk+-2.0`" ; If you use the "gtk+-2.0" target in sources, then the properties specified above will be added to the build properties and eventually will appear in the command line. Unix command line shell processes the backticks quoting by running the tool and using its output -- which is what's desired in that case. Thanks to Daniel James for sharing this approach.
How to get the project-root location? You might want to use the location of the project-root in your Jamfiles. To do it, you'd need to declare path constant in your project-root.jam: path-constant TOP : . ; After that, the TOP variable can be used in every Jamfile.
How to change compilation flags for one file? If one file must be compiled with special options, you need to explicitly declare an obj target for that file and then use that target in your exe or lib target: exe a : a.cpp b ; obj b : b.cpp : <optimization>off ; Of course you can use other properties, for example to specify specific compiler options: exe a : a.cpp b ; obj b : b.cpp : <cflags>-g ; You can also use conditional properties to a finer control: exe a : a.cpp b ; obj b : b.cpp : <variant>release:<optimization>off ;