7.4. Using the toolpath for external Tools
Prev | Chapter 7. Environments | Next

## 7.4. Using the toolpath for external Tools

### 7.4.1. The default tool search path

Normally when using a tool from the construction environment, several different search locations are checked by default. This includes the `SCons/Tools/` directory that is part of the scons distribution and the directory `site_scons/site_tools` relative to the root `SConstruct` file.

    # Builtin tool or tool located within site_tools
    env = Environment(tools=['SomeTool'])
    env.SomeTool(targets, sources)

    # The search locations would include by default
    SCons/Tool/SomeTool.py
    SCons/Tool/SomeTool/__init__.py
    ./site_scons/site_tools/SomeTool.py
    ./site_scons/site_tools/SomeTool/__init__.py

### 7.4.2. Providing an external directory to toolpath

In some cases you may want to specify a different location to search for tools. The `Environment` function contains an option for this called `toolpath` This can be used to add additional search directories.

    # Tool located within the toolpath directory option
    env = Environment(
        tools=['SomeTool'],
        toolpath=['/opt/SomeToolPath', '/opt/SomeToolPath2']
    )
    env.SomeTool(targets, sources)

    # The search locations in this example would include:
    /opt/SomeToolPath/SomeTool.py
    /opt/SomeToolPath/SomeTool/__init__.py
    /opt/SomeToolPath2/SomeTool.py
    /opt/SomeToolPath2/SomeTool/__init__.py
    SCons/Tool/SomeTool.py
    SCons/Tool/SomeTool/__init__.py
    ./site_scons/site_tools/SomeTool.py
    ./site_scons/site_tools/SomeTool/__init__.py

### 7.4.3. Nested Tools within a toolpath

Since SCons 3.0, a Builder may be located within a sub-directory / sub-package of the toolpath. This is similar to namespacing within Python. With nested or namespaced tools we can use the dot notation to specify a sub-directory that the tool is located under.

    # namespaced target
    env = Environment(
        tools=['SubDir1.SubDir2.SomeTool'],
        toolpath=['/opt/SomeToolPath']
    )
    env.SomeTool(targets, sources)

    # With this example the search locations would include
    /opt/SomeToolPath/SubDir1/SubDir2/SomeTool.py
    /opt/SomeToolPath/SubDir1/SubDir2/SomeTool/__init__.py
    SCons/Tool/SubDir1/SubDir2/SomeTool.py
    SCons/Tool/SubDir1/SubDir2/SomeTool/__init__.py
    ./site_scons/site_tools/SubDir1/SubDir2/SomeTool.py
    ./site_scons/site_tools/SubDir1/SubDir2/SomeTool/__init__.py

### 7.4.4. Using sys.path within the toolpath

If we want to access tools external to scons which are findable via `sys.path` (for example, tools installed via Python's pip package manager), it is possible to use `sys.path` with the toolpath. One thing to watch out for with this approach is that `sys.path` can sometimes contains paths to `.egg` files instead of directories. So we need to filter those out with this approach.

    # namespaced target using sys.path within toolpath

    searchpaths = []
    for item in sys.path:
        if os.path.isdir(item):
            searchpaths.append(item)

    env = Environment(
        tools=['someinstalledpackage.SomeTool'],
        toolpath=searchpaths
    )
    env.SomeTool(targets, sources)

By using `sys.path` with the toolpath argument and by using the nested syntax we can have scons search packages installed via pip for Tools.

    # For Windows based on the python version and install directory, this may be something like
    C:\Python35\Lib\site-packages\someinstalledpackage\SomeTool.py
    C:\Python35\Lib\site-packages\someinstalledpackage\SomeTool\__init__.py

    # For Linux this could be something like:
    /usr/lib/python3/dist-packages/someinstalledpackage/SomeTool.py
    /usr/lib/python3/dist-packages/someinstalledpackage/SomeTool/__init__.py

### 7.4.5. Using the `PyPackageDir` function to add to the toolpath

In some cases you may want to use a tool located within a installed external pip package. This is possible by the use of `sys.path` with the toolpath. However in that situation you need to provide a prefix to the toolname to indicate where it is located within `sys.path`.

    searchpaths = []
    for item in sys.path:
        if os.path.isdir(item):
            searchpaths.append(item)
    env = Environment(
        tools=['tools_example.subdir1.subdir2.SomeTool'],
        toolpath=searchpaths
    )
    env.SomeTool(targets, sources)

To avoid the use of a prefix within the name of the tool or filtering `sys.path` for directories, we can use `PyPackageDir` function to locate the directory of the python package. `PyPackageDir` returns a Dir object which represents the path of the directory for the python package / module specified as a parameter.

    # namespaced target using sys.path
    env = Environment(
        tools=['SomeTool'],
        toolpath=[PyPackageDir('tools_example.subdir1.subdir2')]
    )
    env.SomeTool(targets, sources)

Prev | Up | Next
7.3. Controlling the Execution Environment for Issued Commands | Home | Chapter 8. Automatically Putting Command-line Options into their Construction Variables