<?xml version="1.0" standalone="yes"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
     "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">

  <chapter id="bbv2.faq">
    <title>Frequently Asked Questions</title>

    <section>
      <title>
        How do I get the current value of feature in Jamfile?
      </title>

      <para>
        This is not possible, since Jamfile does not have "current" value of any 
        feature, be it toolset, build variant or anything else. For a single invocation of
        <filename>bjam</filename>, any given main target can be built with several property sets.
        For example, user can request two build variants on the command line. Or one library
        is built as shared when used from one application, and as static when used from another.
        Obviously, Jamfile is read only once, so generally, there's no single value of a feature
        you can access in Jamfile.               
      </para>

      <para>A feature has a specific value only when building a target, and there are two ways how you
      can use that value:</para>
      <itemizedlist>
        <listitem><simpara>Use conditional requirements or indirect conditional requirements. See 
        <xref linkend="bbv2.advanced.targets.requirements.conditional"/>.</simpara>
        </listitem>
        <listitem>Define a custom generator and a custom main target type. The custom generator can do arbitrary processing
        or properties. See the <xref linkend="bbv2.extender">extender manual</xref>.
        </listitem>                
      </itemizedlist>

    </section>

    <section>
      <title>
        I'm getting "Duplicate name of actual target" error. What
        does it mean?
      </title>

    <para>    
    The most likely case is that you're trying to
    compile the same file twice, with almost the same,
    but differing properties. For example:

<programlisting>
exe a : a.cpp : &lt;include&gt;/opt/local/include ;
exe b : a.cpp ;
</programlisting>    

    </para>

    <para>
    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 objects 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.
    </para>

    <para>
    To solve this issue, you need to decide if file should
    be compiled once or twice.</para>

    <orderedlist>
    <listitem>
    <para>Two compile file only once, make sure that properties
      are the same:

<programlisting>
exe a : a.cpp : &lt;include&gt;/opt/local/include ;
exe b : a.cpp : &lt;include&gt;/opt/local/include ;
</programlisting></para></listitem>

    <listitem><para>
      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:

<programlisting>
obj a_obj : a.cpp : &lt;include&gt;/opt/local/include ;
exe a : a_obj ;
</programlisting></para></listitem>
   
      <listitem><para>
      To compile file twice, you can make the object file local
      to the main target:

<programlisting>
      exe a : [ obj a_obj : a.cpp ] : &lt;include&gt;/opt/local/include ;
      exe b : [ obj a_obj : a.cpp ] ;
</programlisting></para></listitem>

   </orderedlist>

   <para>
   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.
   </para>

    </section>

    <section id="bbv2.faq.envar">
      <title>
      Accessing environment variables
      </title>

    <para>    
      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 <link linkend="bbv2.recipies.site-config">recipes
      section</link>. 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.
    </para>

    <para>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:
<programlisting>
import os ;
local SOME_LIBRARY_PATH = [ os.environ SOME_LIBRARY_PATH ] ;
exe a : a.cpp : &lt;include&gt;$(SOME_LIBRARY_PATH) ;
</programlisting>
    </para>
</section>

    <section>
      <title>
        How to control properties order?
      </title>

    <para>For internal reasons, Boost.Build sorts all the properties
    alphabetically. This means that if you write:
<programlisting>
exe a : a.cpp : &lt;include&gt;b &lt;include&gt;a ;
</programlisting>
      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:
<programlisting>
exe a : a.cpp : &lt;include&gt;a&amp;&amp;b ;        
</programlisting>
    </para>

    <para>The <code>&amp;&amp;</code> 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.
    </para>

  </section>

  <section>
    <title>
      How to control the library order on Unix?
    </title>

    <para>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.    
    </para>

    <para>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
      &lt;use&gt; feature. For example, both of the following lines will cause
      a to appear before b on the command line:
<programlisting>
lib a : a.cpp b ;
lib a : a.cpp : &lt;use&gt;b ;
</programlisting>
    </para>

    <para>
      The same approach works for searched libraries, too:
<programlisting>
lib z ;
lib png : : &lt;use&gt;z ;
exe viewer : viewer png z ;
</programlisting>
    </para>

  </section>

  <section id="bbv2.faq.external">
    <title>Can I get output of external program as a variable in a Jamfile?
    </title>

    <para>The <code>SHELL</code> builtin can be used for the purpose:
<programlisting>
local gtk_includes = [ SHELL "gtk-config --cflags" ] ;
</programlisting>
    </para>
  </section>

  <section>
    <title>How to get the project-root location?
    </title>

    <para>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:
<programlisting>
path-constant TOP : . ;
</programlisting>
      After that, the <code>TOP</code> variable can be used in every Jamfile.
    </para>
  </section>

  <section>
    <title>How to change compilation flags for one file?
    </title>

    <para>If one file must be compiled with special options, you need to
      explicitly declare an <code>obj</code> target for that file and then use
      that target in your <code>exe</code> or <code>lib</code> target:
<programlisting>
exe a : a.cpp b ;
obj b : b.cpp : &lt;optimization&gt;off ;
</programlisting>
      Of course you can use other properties, for example to specify specific
      compiler options:
<programlisting>
exe a : a.cpp b ;
obj b : b.cpp : &lt;cflags&gt;-g ;
</programlisting>
      You can also use <link linkend="bbv2.tutorial.conditions">conditional
      properties</link> for finer control:
<programlisting>
exe a : a.cpp b ;
obj b : b.cpp : &lt;variant&gt;release:&lt;optimization&gt;off ;
</programlisting>

    </para>
  </section>

  <section id="bbv2.faq.dll-path">
    <title>Why are the <code>dll-path</code> and
    <code>hardcode-dll-paths</code> properties useful?
    </title>

    <para>(This entry is specific to Unix system.)Before answering the
      questions, let's recall a few points about shared libraries. Shared
      libraries can be used by several applications, or other libraries,
      without phisycally including the library in the application. This can
      greatly decrease the total size of applications. It's also possible to
      upgrade a shared library when the application is already
      installed. Finally, shared linking can be faster.
    </para>

    <para>However, the shared library must be found when the application is
      started. The dynamic linker will search in a system-defined list of
      paths, load the library and resolve the symbols. Which means that you
      should either change the system-defined list, given by the
      <envar>LD_LIBRARY_PATH</envar> environment variable, or install the
      libraries to a system location. This can be inconvenient when
      developing, since the libraries are not yet ready to be installed, and
      cluttering system paths is undesirable. Luckily, on Unix there's another
      way.
    </para>

    <para>An executable can include a list of additional library paths, which
      will be searched before system paths. This is excellent for development,
      because the build system knows the paths to all libraries and can include
      them in executables. That's done when the <code>hardcode-dll-paths</code>
      feature has the <literal>true</literal> value, which is the
      default. When the executables should be installed, the story is
      different.
    </para>

    <para>
      Obviously, installed executable should not hardcode paths to your
      development tree. (The <code>stage</code> rule explicitly disables the
      <code>hardcode-dll-paths</code> feature for that reason.) However, you
      can use the <code>dll-path</code> feature to add explicit paths
      manually. For example:
<programlisting>
stage installed : application : &lt;dll-path&gt;/usr/lib/snake
                                &lt;location&gt;/usr/bin ;          
</programlisting>
      will allow the application to find libraries placed to
      <filename>/usr/lib/snake</filename>.
    </para>

    <para>If you install libraries to a nonstandard location and add an
      explicit path, you get more control over libraries which will be used. A
      library of the same name in a system location will not be inadvertently
      used.  If you install libraries to a system location and do not add any
      paths, the system administrator will have more control. Each library can
      be individually upgraded, and all applications will use the new library.
    </para>

    <para>Which approach is best depends on your situation. If the libraries
      are relatively standalone and can be used by third party applications,
      they should be installed in the system location. If you have lots of
      libraries which can be used only by your application, it makes sense to
      install it to a nonstandard directory and add an explicit path, like the
      example above shows. Please also note that guidelines for different
      systems differ in this respect. The Debian guidelines prohibit any
      additional search paths, and Solaris guidelines suggest that they should
      always be used.
    </para>
      
  </section>

  <section id="bbv2.recipies.site-config">
    <title>Targets in site-config.jam</title>

    <para>It is desirable to declare standard libraries available on a
      given system. Putting target declaration in Jamfile is not really
      good, since locations of the libraries can vary. The solution is
      to declare the targets in site-config.jam:</para>    
<programlisting>
project site-config ;
lib zlib : : &lt;name&gt;z ;
</programlisting>

    <para>Recall that both <filename>site-config.jam</filename> and
    <filename>user-config.jam</filename> are projects, and everything
    you can do in a Jamfile you can do in those files. So, you declare
    a project id and a target. Now, one can write:
<programlisting>
exe hello : hello.cpp /site-config//zlib ;
</programlisting>
      in any Jamfile.</para>

  </section>

  <section id="bbv2.faq.header-only-libraries">
    <title>Header-only libraries</title>

    <para>In modern C++, libraries often consist of just header files, without
    any source files to compile. To use such libraries, you need to add proper
    includes and, maybe, defines, to your project. But with large number of
    external libraries it becomes problematic to remember which libraries are
    header only, and which are "real" ones. However, with Boost.Build a 
    header-only library can be declared as Boost.Build target and all 
    dependents can use such library without remebering if it's header-only or not.
    </para>

    <para>Header-only libraries are declared using the <code>alias</code> rule,
    that specifies only usage requirements, for example:
<programlisting>
alias mylib 
    : # no sources
    : # no build requirements
    : # no default build
    : &lt;include&gt;whatever
    ;
</programlisting>
    The includes specified in usage requirements of <code>mylib</code> are
    automatically added to build properties of all dependents. The dependents
    need not care if <code>mylib</code> is header-only or not, and it's possible
    to later make <code>mylib</code> into a regular compiled library.
    </para>

    <para>
      If you already have proper usage requirements declared for project where
      header-only library is defined, you don't need to duplicate them for
      the <code>alias</code> target:
<programlisting>
project my : usage-requirements &lt;include&gt;whatever ;
alias mylib ;
</programlisting>      
    </para>

  </section>

    
  </chapter>
<!--
     Local Variables:
     mode: nxml
     sgml-indent-data: t     
     sgml-parent-document: ("userman.xml" "chapter")
     sgml-set-face: t
     End:
-->
