# CMake module

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

This module provides helper tools for generating cmake package files.
It also supports the usage of CMake based subprojects, similar to
the normal [meson subprojects](Subprojects.md).


## Usage

To use this module, just do: **`cmake = import('cmake')`**. The
following functions will then be available as methods on the object
with the name `cmake`. You can, of course, replace the name `cmake`
with anything else.

It is generally recommended to use the latest Meson version and
CMake >=3.17 for best compatibility. CMake subprojects will
usually also work with older CMake versions. However, this can
lead to unexpected issues in rare cases.

## CMake subprojects

Using CMake subprojects is similar to using the "normal" meson
subprojects. They also have to be located in the `subprojects`
directory.

Example:

```cmake
add_library(cm_lib SHARED ${SOURCES})
```

```meson
cmake = import('cmake')

# Configure the CMake project
sub_proj = cmake.subproject('libsimple_cmake')

# Fetch the dependency object
cm_lib = sub_proj.dependency('cm_lib')

executable(exe1, ['sources'], dependencies: [cm_lib])
```

The `subproject` method is almost identical to the normal meson
`subproject` function. The only difference is that a CMake project
instead of a meson project is configured.

The returned `sub_proj` supports the same options as a "normal" subproject.
Meson automatically detects CMake build targets, which can be accessed with
the methods listed [below](#subproject-object).

It is usually enough to just use the dependency object returned by the
`dependency()` method in the build targets. This is almost identical to
using `declare_dependency()` object from a normal meson subproject.

It is also possible to use executables defined in the CMake project as code
generators with the `target()` method:

```cmake
add_executable(cm_exe ${EXE_SRC})
```

```meson
cmake = import('cmake')

# Subproject with the "code generator"
sub_pro = cmake.subproject('cmCodeGen')

# Fetch the code generator exe
sub_exe = sub_pro.target('cm_exe')

# Use the code generator
generated = custom_target(
  'cmake-generated',
  input: [],
  output: ['test.cpp'],
  command: [sub_exe, '@OUTPUT@']
)
```

It should be noted that not all projects are guaranteed to work. The
safest approach would still be to create a `meson.build` for the
subprojects in question.

### Configuration options

*New in meson 0.55.0*

Meson also supports passing configuration options to CMake and overriding
certain build details extracted from the CMake subproject.

```meson
cmake   = import('cmake')
opt_var = cmake.subproject_options()

# Call CMake with `-DSOME_OTHER_VAR=ON`
opt_var.add_cmake_defines({'SOME_OTHER_VAR': true})

# Globally override the C++ standard to c++11
opt_var.set_override_option('cpp_std', 'c++11')

# Override the previous global C++ standard
# with c++14 only for the CMake target someLib
opt_var.set_override_option('cpp_std', 'c++14', target: 'someLib')

sub_pro = cmake.subproject('someLibProject', options: opt_var)

# Further changes to opt_var have no effect
```

See [the CMake options object](#cmake-options-object) for a complete reference
of all supported functions.

The CMake configuration options object is very similar to the
[configuration data object](Reference-manual.md#configuration-data-object) object
returned by [`configuration_data`](Reference-manual.md#configuration_data). It
is generated by the `subproject_options` function

All configuration options have to be set *before* the subproject is configured
and must be passed to the `subproject` method via the `options` key. Altering
the configuration object won't have any effect on previous `cmake.subproject`
calls.

In earlier meson versions CMake command-line parameters could be set with the
`cmake_options` kwarg. However, this feature is deprecated since 0.55.0 and only
kept for compatibility. It will not work together with the `options` kwarg.

### `subproject` object

This object is returned by the `subproject` function described above
and supports the following methods:

 - `dependency(target)` returns a dependency object for any CMake target.
 - `include_directories(target)` returns a meson `include_directories()`
   object for the specified target. Using this function is not necessary
   if the dependency object is used.
 - `target(target)` returns the raw build target.
 - `target_type(target)` returns the type of the target as a string
 - `target_list()` returns a list of all target *names*.
 - `get_variable(name)` fetches the specified variable from inside
   the subproject. Usually `dependency()` or `target()` should be
   preferred to extract build targets.
 - `found` returns true if the subproject is available, otherwise false
   *new in meson 0.53.2*

### `cmake options` object

This object is returned by the `subproject_options()` function and consumed by
the `options` kwarg of the `subproject` function. The following methods are
supported:

 - `add_cmake_defines({'opt1': val1, ...})` add additional CMake commandline defines
 - `set_override_option(opt, val)` set specific [build options](Build-options.md)
   for targets. This will effectively add `opt=val` to the `override_options`
   array of the [build target](Reference-manual.md#executable)
 - `set_install(bool)` override wether targets should be installed or not
 - `append_compile_args(lang, arg1, ...)` append compile flags for a specific
   language to the targets
 - `append_link_args(arg1, ...)` append linger args to the targets
 - `clear()` reset all data in the `cmake options` object

The methods `set_override_option`, `set_install`, `append_compile_args` and
`append_link_args` support the optional `target` kwarg. If specified, the set
options affect the specific target. The effect of the option is global for the
subproject otherwise.

If, for instance, `opt_var.set_install(false)` is called, no target will be
installed regardless of what is set by CMake. However, it is still possible to
install specific targets (here `foo`) by setting the `target` kwarg:
`opt_var.set_install(true, target: 'foo')`

Options that are not set won't affect the generated subproject. So, if for
instance, `set_install` was not called then the values extracted from CMake will
be used.

## CMake configuration files

### cmake.write_basic_package_version_file()

This function is the equivalent of the corresponding [CMake function](https://cmake.org/cmake/help/v3.11/module/CMakePackageConfigHelpers.html#generating-a-package-version-file),
it generates a `name` package version file.

* `name`: the name of the package.
* `version`: the version of the generated package file.
* `compatibility`: a string indicating the kind of compatibility, the accepted values are
`AnyNewerVersion`, `SameMajorVersion`, `SameMinorVersion` or `ExactVersion`.
It defaults to `AnyNewerVersion`. Depending on your cmake installation some kind of
compatibility may not be available.
* `install_dir`: optional installation directory, it defaults to `$(libdir)/cmake/$(name)`


Example:

```meson
cmake = import('cmake')

cmake.write_basic_package_version_file(name: 'myProject', version: '1.0.0')
```

### cmake.configure_package_config_file()

This function is the equivalent of the corresponding [CMake function](https://cmake.org/cmake/help/v3.11/module/CMakePackageConfigHelpers.html#generating-a-package-configuration-file),
it generates a `name` package configuration file from the `input` template file. Just like the cmake function
in this file the `@PACKAGE_INIT@` statement will be replaced by the appropriate piece of cmake code.
The equivalent `PATH_VARS` argument is given through the `configuration` parameter.

* `name`: the name of the package.
* `input`: the template file where that will be treated for variable substitutions contained in `configuration`.
* `install_dir`: optional installation directory, it defaults to `$(libdir)/cmake/$(name)`.
* `configuration`: a `configuration_data` object that will be used for variable substitution in the template file.


Example:

meson.build:

```meson
cmake = import('cmake')

conf = configuration_data()
conf.set_quoted('VAR', 'variable value')

cmake.configure_package_config_file(
    name: 'myProject',
    input: 'myProject.cmake.in',
    configuration: conf
)
```

myProject.cmake.in:

```text
@PACKAGE_INIT@

set(MYVAR VAR)
```
