Search code examples
pythonboostboost-pythonbjam

Using bjam's pythonpath feature


I have a Jamfile that I am using with Boost.Python to wrap some C++ classes. I have the Jamfile automatically running a python script and loading the extension as a post-compile step:

rule run-test ( test-name : sources + )
{
    import testing ;
    testing.make-test run-pyd : $(sources) : : $(test-name) ;
}

Then:

PROJECT_NAME = example ;
run-test $(PROJECT_NAME) : $(PROJECT_NAME)_ext test_$(PROJECT_NAME)_ext.py ;

This would build example_ext.so, then run test_example_ext.py which does a simple "import example_ext" and then some basic testing.

The problem is that I need test_example_ext.py to be able to import some Python modules from other packages, so I need to set PYTHONPATH. From the command-line, this isn't a problem, but bjam doesn't appear to carry this through to its spawned Python process, even if exported.

In this case I'm looking for the equivalent of:

$ export PYTHONPATH=..

I.e. setting the Python search path one level above where I am running bjam.

The closest I've managed to get is to work out that this does what I want:

$ bjam pythonpath=..

This actually works. But I want to set this in the Jamfile, not rely on the command line. I've read the bjam manual which says that this is a property and I can use <pythonpath>.. somewhere. But it doesn't say where.

So my problem is that I can't work out how to specify this property in a Jamfile. Where does it go? What's the syntax? Is it part of "import python ;", or "using python ..." in user-config.jam, or part of the run-pyd or even the python-extension rule? I've tried all these randomly without understanding or success.

In boost_1_50_0/tools/build/v2/tools/python.jam I found:

# The pythonpath feature specifies additional elements for the PYTHONPATH
# environment variable, set by run-pyd. For example, pythonpath can be used to
# access Python modules that are part of the product being built, but are not
# installed in the development system's default paths.
feature.feature pythonpath : : free optional path ;

That appears to be declaring the 'pythonpath' property (aka feature), but for what context? Where and how can it be used?

And this page demonstrates how to define a property along those lines, but not really how or where to use it.


Solution

  • I believe I may have found an answer to my own question.

    The solution appears to be the project rule below, with the requirements keyword, although I haven't yet understood why it works, or the implications of specifying this.

    Here's my Jamfile:

    PROJECT_NAME = example ;
    
    import python ;
    
    # sets PYTHONPATH when executing run-test
    project : requirements <pythonpath>.. ;
    
    python-extension $(PROJECT_NAME)_ext :
      $(PROJECT_NAME).cpp
      $(PROJECT_NAME)_ext.cpp
    :
    ;
    
    # Declare test targets
    run-test $(PROJECT_NAME) : $(PROJECT_NAME)_ext test_$(PROJECT_NAME)_ext.py ;
    

    For completeness, I actually have this picking up a Jamroot file one directory up, that looks like this:

    import python ;
    
    # Specify the path to the Boost project.  If you move this project,
    # adjust this path to refer to the Boost root directory.
    use-project boost
      : ./boost ;
    
    # Set up the project-wide requirements that everything uses the
    # boost_python library from the project whose global ID is
    # /boost/python.
    project
      : requirements <library>/boost/python//boost_python ;
    
    # A little "rule" (function) to clean up the syntax of declaring tests
    # of these extension modules.
    rule run-test ( test-name : sources + )
    {
        import testing ;
        testing.make-test run-pyd : $(sources) : : $(test-name) ;
    }