# External Project module

**Note**: the functionality of this module is governed by [Meson's
  rules on mixing build systems](Mixing-build-systems.md).

*This is an experimental module, API could change.*

*Added 0.56.0*

This module allows building code that uses build systems other than
Meson. This module is intended to be used to build Autotools
subprojects as fallback if the dependency couldn't be found on the
system (e.g. too old distro version).

The project will be compiled out-of-tree inside Meson's build
directory. The project will also be installed inside Meson's build
directory using make's
[`DESTDIR`](https://www.gnu.org/prep/standards/html_node/DESTDIR.html)
feature. During project installation step, that DESTDIR will be copied
verbatim into the desired location.

External subprojects can use libraries built by Meson (main project,
or other subprojects) using pkg-config, thanks to `*-uninstalled.pc`
files generated by [`pkg.generate()`](Pkgconfig-module.md).

External build system requirements:

- Must support out-of-tree build. The configure script will be invoked with the
  current workdir inside Meson's build directory and not subproject's top source
  directory.
- Configure script must generate a `Makefile` in the current workdir.
- Configure script must take common directories like prefix, libdir, etc, as
  command line arguments.
- Configure script must support common environment variable like CFLAGS, CC, etc.
- Compilation step must detect when a reconfigure is needed, and do it
  transparently.

Known limitations:

- Executables from external projects cannot be used uninstalled, because they
  would need its libraries to be installed in the final location. This is why
  there is no `find_program()` method.
- The configure script must generate a `Makefile`, other build systems are not
  yet supported.
- When cross compiling, if `PKG_CONFIG_SYSROOT_DIR` is set in environment or
  `sys_root` in the cross file properties, the external subproject will not be
  able to find dependencies built by Meson using pkg-config. The reason is
  pkg-config and pkgconf both prepend the sysroot path to `-I` and `-L` arguments
  from `-uninstalled.pc` files. This is arguably a bug that could be fixed in
  future version of pkg-config/pkgconf.

*Since 1.7.0* [Meson devenv][Commands.md#devenv] setup `PATH` and
`LD_LIBRARY_PATH` to be able to run programs.

## Functions

### `add_project()`

This function should be called at the root directory of a project
using another build system. Usually in a `meson.build` file placed in
the top directory of a subproject, but could be also in any subdir.

Its first positional argument is the name of the configure script to
be executed (e.g. `configure`), that file must be in the current
directory and executable. Note that if a bootstrap script is required
(e.g. `autogen.sh` when building from git instead of tarball), it can
be done using `run_command()` before calling `add_project()` method.

*Since 0.60.0* If the first positional argument is `'waf'`, special treatment
is done for the [waf](https://waf.io/) build system. The waf executable must be
found either in the current directory, or in system `PATH`.

Keyword arguments:

- `configure_options`: An array of strings to be passed as arguments to the
  configure script. Some special tags will be replaced by Meson before passing
  them to the configure script: `@PREFIX@`, `@LIBDIR@` and `@INCLUDEDIR@`.
  Note that `libdir` and `includedir` paths are relative to `prefix` in Meson
  but some configure scripts requires absolute path, in that case they can be
  passed as `'--libdir=@PREFIX@/@LIBDIR@'`. *Since 0.57.0* default arguments are
  added in case some tags are not found in `configure_options`:
  `'--prefix=@PREFIX@'`, `'--libdir=@PREFIX@/@LIBDIR@'`, and
  `'--includedir=@PREFIX@/@INCLUDEDIR@'`. It was previously considered a fatal
  error to not specify them. *Since 1.7.0* `@BINDIR@` and `'--bindir=@PREFIX@/@BINDIR@'`
  default argument have been added.
- `cross_configure_options`: Extra options appended to `configure_options` only
  when cross compiling. special tag `@HOST@` will be replaced by
  `'{}-{}-{}'.format(host_machine.cpu_family(), build_machine.system(), host_machine.system()`.
  If omitted it defaults to `['--host=@HOST@']`.
- `verbose`: If set to `true` the output of sub-commands ran to configure, build
  and install the project will be printed onto Meson's stdout.
- `env` : environment variables to set, such as `['NAME1=value1', 'NAME2=value2']`,
  a dictionary, or an [[@env]] object.
- `depends` : *Since 0.63.0* Specifies that this project depends on the specified
  target(s) that must be built before running `make` to build this external
  project. This should be used for example when the external project links to a
  Meson `library()` that the `configure` script will find using the
  `-uninstalled.pc` pkg-config file generated by Meson.

Returns an [`ExternalProject`](#ExternalProject_object) object

## `ExternalProject` object

### Methods

#### `dependency(libname)`

Return a dependency object that can be used to build targets against a library
from the external project.

Keyword arguments:
- `subdir` path relative to `includedir` to be added to the header search path.

## Example `meson.build` file for a subproject

```meson
project('My Autotools Project', 'c',
  meson_version : '>=0.56.0',
)

mod = import('unstable-external_project')

p = mod.add_project('configure',
  configure_options : ['--prefix=@PREFIX@',
                       '--libdir=@LIBDIR@',
                       '--incdir=@INCLUDEDIR@',
                       '--enable-foo',
                      ],
)

mylib_dep = p.dependency('mylib')
meson.override_dependency('mylib', mylib_dep)
```

## Using wrap file

Most of the time the project will be built as a subproject, and
fetched using a `.wrap` file. In that case the simple `meson.build`
file needed to build the subproject can be provided by adding
`patch_directory=mysubproject` line in the wrap file, and place the
build definition file at
`subprojects/packagefiles/mysubproject/meson.build`.
