1# Halide and CMake
2
3This is a comprehensive guide to the three main usage stories of the Halide
4CMake build.
5
61. Compiling or packaging Halide from source.
72. Building Halide programs using the official CMake package.
83. Contributing to Halide and updating the build files.
9
10The following sections cover each in detail.
11
12## Table of Contents
13
14- [Getting started](#getting-started)
15  - [Installing CMake](#installing-cmake)
16  - [Installing dependencies](#installing-dependencies)
17- [Building Halide with CMake](#building-halide-with-cmake)
18  - [Basic build](#basic-build)
19  - [Build options](#build-options)
20    - [Find module options](#find-module-options)
21- [Using Halide from your CMake build](#using-halide-from-your-cmake-build)
22  - [A basic CMake project](#a-basic-cmake-project)
23  - [JIT mode](#jit-mode)
24  - [AOT mode](#aot-mode)
25    - [Autoschedulers](#autoschedulers)
26    - [RunGenMain](#rungenmain)
27  - [Halide package documentation](#halide-package-documentation)
28    - [Components](#components)
29    - [Variables](#variables)
30    - [Imported targets](#imported-targets)
31    - [Functions](#functions)
32      - [`add_halide_library`](#add_halide_library)
33- [Contributing CMake code to Halide](#contributing-cmake-code-to-halide)
34  - [General guidelines and best practices](#general-guidelines-and-best-practices)
35    - [Prohibited commands list](#prohibited-commands-list)
36    - [Prohibited variables list](#prohibited-variables-list)
37  - [Adding tests](#adding-tests)
38  - [Adding apps](#adding-apps)
39
40# Getting started
41
42This section covers installing a recent version of CMake and the correct
43dependencies for building and using Halide. If you have not used CMake before,
44we strongly suggest reading through the [CMake documentation][cmake-docs] first.
45
46## Installing CMake
47
48Halide requires at least version 3.16, which was released in November 2019.
49Fortunately, getting a recent version of CMake couldn't be easier, and there are
50multiple good options on any system to do so. Generally, one should always have
51the most recent version of CMake installed system-wide. CMake is committed to
52backwards compatibility and even the most recent release can build projects over
53a decade old.
54
55### Cross-platform
56
57The Python package manager `pip3` has the newest version of CMake at all times.
58This might be the most convenient method since Python 3 is an optional
59dependency for Halide, anyway.
60
61```
62$ pip3 install --upgrade cmake
63```
64
65See the [PyPI website][pypi-cmake] for more details.
66
67### Windows
68
69On Windows, there are three primary methods for installing an up-to-date CMake:
70
711. If you have Visual Studio 2019 installed, you can get CMake 3.17 through the
72   Visual Studio installer. This is the recommended way of getting CMake if you
73   are able to use Visual Studio 2019. See Microsoft's
74   [documentation][vs2019-cmake-docs] for more details.
752. If you use [Chocolatey][chocolatey], its [CMake package][choco-cmake] is kept
76   up to date. It should be as simple as `choco install cmake`.
773. Otherwise, you should install CMake from [Kitware's website][cmake-download].
78
79### macOS
80
81On macOS, the [Homebrew][homebrew] [CMake package][brew-cmake] is kept up to
82date. Simply run:
83
84```
85$ brew update
86$ brew install cmake
87```
88
89to install the newest version of CMake. If your environment prevents you from
90installing Homebrew, the binary release on [Kitware's website][cmake-download]
91is also a viable option.
92
93### Ubuntu Linux
94
95There are a few good ways to install a modern CMake on Ubuntu:
96
971. If you're on Ubuntu Linux 20.04 (focal), then simply running
98   `sudo apt install cmake` will get you CMake 3.16.
992. If you are on an older Ubuntu release or would like to use the newest CMake,
100   try installing via the snap store: `snap install cmake`. Be sure you do not
101   already have `cmake` installed via APT. The snap package automatically stays
102   up to date.
1033. For older versions of Debian, Ubuntu, Mint, and derivatives, Kitware provides
104   an [APT repository][cmake-apt] with up-to-date releases. Note that this is
105   still useful for Ubuntu 20.04 because it will remain up to date.
1064. If all else fails, you might need to build CMake from source (eg. on old
107   Ubuntu versions running on ARM). In that case, follow the directions posted
108   on [Kitware's website][cmake-from-source].
109
110For other Linux distributions, check with your distribution's package manager or
111use pip as detailed above. Snap packages might also be available.
112
113**Note:** On WSL 1, the snap service is not available; in this case, prefer to
114use the APT repository. On WSL 2, all methods are available.
115
116## Installing dependencies
117
118We generally recommend using a package manager to fetch Halide's dependencies.
119Except where noted, we recommend using [vcpkg][vcpkg] on Windows,
120[Homebrew][homebrew] on macOS, and APT on Ubuntu 20.04 LTS.
121
122Only LLVM and Clang are _absolutely_ required to build Halide. Halide always
123supports three LLVM versions: the current major version, the previous major
124version, and trunk. The LLVM and Clang versions must match exactly. For most
125users, we recommend using a binary release of LLVM rather than building it
126yourself.
127
128However, to run all of the tests and apps, an extended set is needed. This
129includes [lld][lld], [Python 3][python], [libpng][libpng], [libjpeg][libjpeg],
130[Doxygen][doxygen], [OpenBLAS][openblas], [ATLAS][atlas], and [Eigen3][eigen].
131While not required to build any part of Halide, we find that [Ninja][ninja] is
132the best backend build tool across all platforms.
133
134Note that CMake has many special variables for overriding the locations of
135packages and executables. A partial list can be found in the
136["find module options"](#find-module-options) section below, and more can be
137found in the documentation for the CMake [find_package][find_package] command.
138Normally, you should prefer to make sure your environment is set up so that
139CMake can find dependencies automatically. For instance, if you want CMake to
140use a particular version of Python, create a [virtual environment][venv] and
141activate it _before_ configuring Halide.
142
143### Windows
144
145We assume you have vcpkg installed at `D:\vcpkg`. Follow the instructions in the
146[vcpkg README][vcpkg] to install. Start by installing LLVM.
147
148```
149D:\vcpkg> .\vcpkg install llvm[target-all,enable-assertions,clang-tools-extra]:x64-windows
150D:\vcpkg> .\vcpkg install llvm[target-all,enable-assertions,clang-tools-extra]:x86-windows
151```
152
153This will also install Clang and LLD. The `enable-assertions` option is not
154strictly necessary but will make debugging during development much smoother.
155These builds will take a long time and a lot of disk space. After they are
156built, it is safe to delete the intermediate build files and caches in
157`D:\vcpkg\buildtrees` and `%APPDATA%\local\vcpkg`.
158
159Then install the other libraries:
160
161```
162D:\vcpkg> .\vcpkg install libpng:x64-windows libjpeg-turbo:x64-windows openblas:x64-windows eigen3:x64-windows
163D:\vcpkg> .\vcpkg install libpng:x86-windows libjpeg-turbo:x86-windows openblas:x86-windows eigen3:x86-windows
164```
165
166To build the documentation, you will need to install [Doxygen][doxygen]. This
167can be done either through [Chocolatey][choco-doxygen] or from the [Doxygen
168website][doxygen-download].
169
170```
171> choco install doxygen
172```
173
174To build the Python bindings, you will need to install Python 3. This should be
175done by running the official installer from the [Python website][python]. Be
176sure to download the debugging symbols through the installer. This will require
177using the "Advanced Installation" workflow. Although it is not strictly
178necessary, it is convenient to install Python system-wide on Windows (ie.
179`C:\Program Files`). This makes it easy for CMake to find without needing to
180manually set the `PATH`.
181
182Once Python is installed, you can install the Python module dependencies either
183globally or in a [virtual environment][venv] by running
184
185```
186> pip3 install -r .\python_bindings\requirements.txt
187```
188
189from the root of the repository.
190
191If you would like to use [Ninja][ninja], note that it is installed alongside
192CMake when using the Visual Studio 2019 installer. Alternatively, you can
193install via [Chocolatey][choco-ninja] or place the [pre-built
194binary][ninja-download] from their website in the PATH.
195
196```
197> choco install ninja
198```
199
200### macOS
201
202On macOS, it is possible to install all dependencies via [Homebrew][homebrew]:
203
204```
205$ brew install llvm libpng libjpeg python@3.8 openblas doxygen ninja
206```
207
208The `llvm` package includes `clang`, `clang-format`, and `lld`, too. Don't
209forget to install the Python module dependencies:
210
211```
212$ pip3 install -r python_bindings/requirements.txt
213```
214
215### Ubuntu
216
217Finally, on Ubuntu 20.04 LTS, you should install the following packages (this
218includes the Python module dependencies):
219
220```
221dev@ubuntu:~$ sudo apt install \
222                  clang-tools lld llvm-dev libclang-dev liblld-10-dev \
223                  libpng-dev libjpeg-dev libgl-dev \
224                  python3-dev python3-numpy python3-scipy python3-imageio python3-pybind11 \
225                  libopenblas-dev libeigen3-dev libatlas-base-dev \
226                  doxygen ninja-build
227```
228
229# Building Halide with CMake
230
231## Basic build
232
233These instructions assume that your working directory is the Halide repo root.
234
235### Windows
236
237If you plan to use the Ninja generator, be sure to be in the developer command
238prompt corresponding to your intended environment. Note that whatever your
239intended target system (x86, x64, or arm), you must use the 64-bit _host tools_
240because the 32-bit tools run out of memory during the linking step with LLVM.
241More information is available from [Microsoft's documentation][msvc-cmd].
242
243You should either open the correct Developer Command Prompt directly or run the
244[`vcvarsall.bat`][vcvarsall] script with the correct argument, ie. one of the
245following:
246
247```
248D:\> "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
249D:\> "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64_x86
250D:\> "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64_arm
251```
252
253Then, assuming that vcpkg is installed to `D:\vcpkg`, simply run:
254
255```
256> cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=D:\vcpkg\scripts\buildsystems\vcpkg.cmake -S . -B build
257> cmake --build .\build
258```
259
260Valid values of [`CMAKE_BUILD_TYPE`][cmake_build_type] are `Debug`,
261`RelWithDebInfo`, `MinSizeRel`, and `Release`. When using a single-configuration
262generator (like Ninja) you must specify a build type when configuring Halide (or
263any other CMake project).
264
265Otherwise, if you wish to create a Visual Studio based build system, you can
266configure with:
267
268```
269> cmake -G "Visual Studio 16 2019" -Thost=x64 -A x64 ^
270        -DCMAKE_TOOLCHAIN_FILE=D:\vcpkg\scripts\buildsystems\vcpkg.cmake ^
271        -S . -B build
272> cmake --build .\build --config Release -j %NUMBER_OF_PROCESSORS%
273```
274
275Because the Visual Studio generator is a _multi-config generator_, you don't set
276`CMAKE_BUILD_TYPE` at configure-time, but instead pass the configuration to the
277build (and test/install) commands with the `--config` flag. More documentation
278is available in the [CMake User Interaction Guide][cmake-user-interaction].
279
280The process is similar for 32-bit:
281
282```
283> cmake -G "Visual Studio 16 2019" -Thost=x64 -A Win32 ^
284        -DCMAKE_TOOLCHAIN_FILE=D:\vcpkg\scripts\buildsystems\vcpkg.cmake ^
285        -S . -B build
286> cmake --build .\build --config Release -j %NUMBER_OF_PROCESSORS%
287```
288
289In both cases, the `-Thost=x64` flag ensures that the correct host tools are
290used.
291
292**Note:** due to limitations in MSBuild, incremental builds using the VS
293generators will not detect changes to headers in the `src/runtime` folder. We
294recommend using Ninja for day-to-day development and use Visual Studio only if
295you need it for packaging.
296
297### macOS and Linux
298
299The instructions here are straightforward. Assuming your environment is set up
300correctly, just run:
301
302```
303dev@host:~/Halide$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -S . -B build
304dev@host:~/Halide$ cmake --build ./build
305```
306
307If you omit `-G Ninja`, a Makefile-based generator will likely be used instead.
308In either case, [`CMAKE_BUILD_TYPE`][cmake_build_type] must be set to one of the
309standard types: `Debug`, `RelWithDebInfo`, `MinSizeRel`, or `Release`.
310
311## Installing
312
313Once built, Halide will need to be installed somewhere before using it in a
314separate project. On any platform, this means running the
315[`cmake --install`][cmake-install] command in one of two ways. For a
316single-configuration generator (like Ninja), run either:
317
318```
319dev@host:~/Halide$ cmake --install ./build --prefix /path/to/Halide-install
320> cmake --install .\build --prefix X:\path\to\Halide-install
321```
322
323For a multi-configuration generator (like Visual Studio) run:
324
325```
326dev@host:~/Halide$ cmake --install ./build --prefix /path/to/Halide-install --config Release
327> cmake --install .\build --prefix X:\path\to\Halide-install --config Release
328```
329
330Of course, make sure that you build the corresponding config before attempting
331to install it.
332
333## Build options
334
335Halide reads and understands several options that can configure the build. The
336following are the most consequential and control how Halide is actually
337compiled.
338
339| Option                                   | Default               | Description                                                                                                      |
340| ---------------------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------- |
341| [`BUILD_SHARED_LIBS`][build_shared_libs] | `ON`                  | Standard CMake variable that chooses whether to build as a static or shared library.                             |
342| `Halide_BUNDLE_LLVM`                     | `OFF`                 | When building Halide as a static library, unpack the LLVM static libraries and add those objects to libHalide.a. |
343| `Halide_SHARED_LLVM`                     | `OFF`                 | Link to the shared version of LLVM. Not available on Windows.                                                    |
344| `Halide_ENABLE_RTTI`                     | _inherited from LLVM_ | Enable RTTI when building Halide. Recommended to be set to `ON`                                                  |
345| `Halide_ENABLE_EXCEPTIONS`               | `ON`                  | Enable exceptions when building Halide                                                                           |
346| `Halide_USE_CODEMODEL_LARGE`             | `OFF`                 | Use the Large LLVM codemodel                                                                                     |
347| `Halide_TARGET`                          | _empty_               | The default target triple to use for `add_halide_library` (and the generator tests, by extension)                |
348
349The following options are only available when building Halide directly, ie. not
350through the [`add_subdirectory`][add_subdirectory] or
351[`FetchContent`][fetchcontent] mechanisms. They control whether non-essential
352targets (like tests and documentation) are built.
353
354| Option                 | Default              | Description                                                                              |
355| ---------------------- | -------------------- | ---------------------------------------------------------------------------------------- |
356| `WITH_TESTS`           | `ON`                 | Enable building unit and integration tests                                               |
357| `WITH_APPS`            | `ON`                 | Enable testing sample applications (run `ctest -L apps` to actually build and test them) |
358| `WITH_PYTHON_BINDINGS` | `ON` if Python found | Enable building Python 3.x bindings                                                      |
359| `WITH_DOCS`            | `OFF`                | Enable building the documentation via Doxygen                                            |
360| `WITH_UTILS`           | `ON`                 | Enable building various utilities including the trace visualizer                         |
361| `WITH_TUTORIALS`       | `ON`                 | Enable building the tutorials                                                            |
362
363The following options control whether to build certain test subsets. They only
364apply when `WITH_TESTS=ON`:
365
366| Option                    | Default | Description                       |
367| ------------------------- | ------- | --------------------------------- |
368| `WITH_TEST_AUTO_SCHEDULE` | `ON`    | enable the auto-scheduling tests  |
369| `WITH_TEST_CORRECTNESS`   | `ON`    | enable the correctness tests      |
370| `WITH_TEST_ERROR`         | `ON`    | enable the expected-error tests   |
371| `WITH_TEST_WARNING`       | `ON`    | enable the expected-warning tests |
372| `WITH_TEST_PERFORMANCE`   | `ON`    | enable performance testing        |
373| `WITH_TEST_OPENGL`        | `OFF`   | enable the OpenGL tests           |
374| `WITH_TEST_GENERATOR`     | `ON`    | enable the AOT generator tests    |
375
376The following options enable/disable various LLVM backends (they correspond to
377LLVM component names):
378
379| Option               | Default              | Description                                              |
380| -------------------- | -------------------- | -------------------------------------------------------- |
381| `TARGET_AARCH64`     | `ON`, _if available_ | Enable the AArch64 backend                               |
382| `TARGET_AMDGPU`      | `ON`, _if available_ | Enable the AMD GPU backend                               |
383| `TARGET_ARM`         | `ON`, _if available_ | Enable the ARM backend                                   |
384| `TARGET_HEXAGON`     | `ON`, _if available_ | Enable the Hexagon backend                               |
385| `TARGET_MIPS`        | `ON`, _if available_ | Enable the MIPS backend                                  |
386| `TARGET_NVPTX`       | `ON`, _if available_ | Enable the NVidia PTX backend                            |
387| `TARGET_POWERPC`     | `ON`, _if available_ | Enable the PowerPC backend                               |
388| `TARGET_RISCV`       | `ON`, _if available_ | Enable the RISC V backend                                |
389| `TARGET_WEBASSEMBLY` | `ON`, _if available_ | Enable the WebAssembly backend. Only valid for LLVM 11+. |
390| `TARGET_X86`         | `ON`, _if available_ | Enable the x86 (and x86_64) backend                      |
391
392The following options enable/disable various Halide-specific backends:
393
394| Option                | Default | Description                            |
395| --------------------- | ------- | -------------------------------------- |
396| `TARGET_OPENCL`       | `ON`    | Enable the OpenCL-C backend            |
397| `TARGET_OPENGL`       | `ON`    | Enable the OpenGL/GLSL backend         |
398| `TARGET_METAL`        | `ON`    | Enable the Metal backend               |
399| `TARGET_D3D12COMPUTE` | `ON`    | Enable the Direct3D 12 Compute backend |
400
401The following options are WebAssembly-specific. They only apply when
402`TARGET_WEBASSEMBLY=ON`:
403
404| Option            | Default | Description                                                |
405| ----------------- | ------- | ---------------------------------------------------------- |
406| `WITH_WABT`       | `ON`    | Include WABT Interpreter for WASM testing                  |
407| `WITH_WASM_SHELL` | `ON`    | Download a wasm shell (e.g. d8) for testing AOT wasm code. |
408
409### Find module options
410
411Halide uses the following find modules to search for certain dependencies. These
412modules accept certain variables containing hints for the search process. Before
413setting any of these variables, closely study the [`find_package`][find_package]
414documentation.
415
416All of these variables should be set at the CMake command line via the `-D`
417flag.
418
419First, Halide expects to find LLVM and Clang through the `CONFIG` mode of
420`find_package`. You can tell Halide where to find these dependencies by setting
421the corresponding `_DIR` variables:
422
423| Variable    | Description                                          |
424| ----------- | ---------------------------------------------------- |
425| `LLVM_DIR`  | Path to the directory containing `LLVMConfig.cmake`  |
426| `Clang_DIR` | Path to the directory containing `ClangConfig.cmake` |
427
428When using CMake 3.18 or above, some of Halide's tests will search for CUDA
429using the [`FindCUDAToolkit`][findcudatoolkit] module. If it doesn't find your
430CUDA installation automatically, you can point it to it by setting:
431
432| Variable           | Description                                       |
433| ------------------ | ------------------------------------------------- |
434| `CUDAToolkit_ROOT` | Path to the directory containing `bin/nvcc[.exe]` |
435| `CUDA_PATH`        | _Environment_ variable, same as above.            |
436
437If the CMake version is lower than 3.18, the deprecated [`FindCUDA`][findcuda]
438module will be used instead. It reads the variable `CUDA_TOOLKIT_ROOT_DIR`
439instead of `CUDAToolkit_ROOT` above.
440
441When targeting OpenGL, the [`FindOpenGL`][findopengl] and [`FindX11`][findx11]
442modules will be used to link AOT generated binaries. These modules can be
443overridden by setting the following variables:
444
445| Variable                | Description                      |
446| ----------------------- | -------------------------------- |
447| `OPENGL_egl_LIBRARY`    | Path to the EGL library.         |
448| `OPENGL_glu_LIBRARY`    | Path to the GLU library.         |
449| `OPENGL_glx_LIBRARY`    | Path to the GLVND GLX library.   |
450| `OPENGL_opengl_LIBRARY` | Path to the GLVND OpenGL library |
451| `OPENGL_gl_LIBRARY`     | Path to the OpenGL library.      |
452
453The OpenGL paths will need to be set if you intend to use OpenGL with X11 on
454macOS.
455
456Halide also searches for `libpng` and `libjpeg-turbo` through the
457[`FindPNG`][findpng] and [`FindJPEG`][findjpeg] modules, respectively. They can
458be overridden by setting the following variables.
459
460| Variable            | Description                                        |
461| ------------------- | -------------------------------------------------- |
462| `PNG_LIBRARIES`     | Paths to the libraries to link against to use PNG. |
463| `PNG_INCLUDE_DIRS`  | Path to `png.h`, etc.                              |
464| `JPEG_LIBRARIES`    | Paths to the libraries needed to use JPEG.         |
465| `JPEG_INCLUDE_DIRS` | Paths to `jpeglib.h`, etc.                         |
466
467When `WITH_DOCS` is set to `ON`, Halide searches for Doxygen using the
468[`FindDoxygen`][finddoxygen] module. It can be overridden by setting the
469following variable.
470
471| Variable             | Description                     |
472| -------------------- | ------------------------------- |
473| `DOXYGEN_EXECUTABLE` | Path to the Doxygen executable. |
474
475When compiling for an OpenCL target, Halide uses the [`FindOpenCL`][findopencl]
476target to locate the libraries and include paths. These can be overridden by
477setting the following variables:
478
479| Variable              | Description                                           |
480| --------------------- | ----------------------------------------------------- |
481| `OpenCL_LIBRARIES`    | Paths to the libraries to link against to use OpenCL. |
482| `OpenCL_INCLUDE_DIRS` | Include directories for OpenCL.                       |
483
484Lastly, Halide searches for Python 3 using the [`FindPython3`][findpython3]
485module, _not_ the deprecated `FindPythonInterp` and `FindPythonLibs` modules,
486like other projects you might have encountered. You can select which Python
487installation to use by setting the following variable.
488
489| Variable           | Description                                           |
490| ------------------ | ----------------------------------------------------- |
491| `Python3_ROOT_DIR` | Define the root directory of a Python 3 installation. |
492
493# Using Halide from your CMake build
494
495This section assumes some basic familiarity with CMake but tries to be explicit
496in all its examples. To learn more about CMake, consult the
497[documentation][cmake-docs] and engage with the community on the [CMake
498Discourse][cmake-discourse].
499
500Note: previous releases bundled a `halide.cmake` module that was meant to be
501[`include()`][include]-ed into your project. This has been removed. Please
502upgrade to the new package config module.
503
504## A basic CMake project
505
506There are two main ways to use Halide in your application: as a **JIT compiler**
507for dynamic pipelines or an **ahead-of-time (AOT) compiler** for static
508pipelines. CMake provides robust support for both use cases.
509
510No matter how you intend to use Halide, you will need some basic CMake
511boilerplate.
512
513```cmake
514cmake_minimum_required(VERSION 3.16)
515project(HalideExample)
516
517set(CMAKE_CXX_STANDARD 11)  # or newer
518set(CMAKE_CXX_STANDARD_REQUIRED YES)
519set(CMAKE_CXX_EXTENSIONS NO)
520
521find_package(Halide REQUIRED)
522```
523
524The [`cmake_minimum_required`][cmake_minimum_required] command is required to be
525the first command executed in a CMake program. It disables all of the deprecated
526behavior ("policies" in CMake lingo) from earlier versions. The
527[`project`][project] command sets the name of the project (and has arguments for
528versioning, language support, etc.) and is required by CMake to be called
529immediately after setting the minimum version.
530
531The next three variables set the project-wide C++ standard. The first,
532[`CMAKE_CXX_STANDARD`][cmake_cxx_standard], simply sets the standard version.
533Halide requires at least C++11. The second,
534[`CMAKE_CXX_STANDARD_REQUIRED`][cmake_cxx_standard_required], tells CMake to
535fail if the compiler cannot provide the requested standard version. Lastly,
536[`CMAKE_CXX_EXTENSIONS`][cmake_cxx_extensions] tells CMake to disable
537vendor-specific extensions to C++. This is not necessary to simply use Halide,
538but we require it when authoring new code in the Halide repo.
539
540Finally, we use [`find_package`][find_package] to locate Halide on your system.
541If Halide is not globally installed, you will need to add the root of the Halide
542installation directory to [`CMAKE_MODULE_PATH`][cmake_module_path] at the CMake
543command line.
544
545```
546dev@ubuntu:~/myproj$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_MODULE_PATH="/path/to/Halide-install" -S . -B build
547```
548
549## JIT mode
550
551To use Halide in JIT mode (like the [tutorials][halide-tutorials] do, for
552example), you can simply link to `Halide::Halide`.
553
554```cmake
555# ... same project setup as before ...
556add_executable(my_halide_app main.cpp)
557target_link_libraries(my_halide_app PRIVATE Halide::Halide)
558```
559
560Then `Halide.h` will be available to your code and everything should just work.
561That's it!
562
563## AOT mode
564
565Using Halide in AOT mode is more complicated so we'll walk through it step by
566step. Note that this only applies to Halide generators, so it might be useful to
567re-read the [tutorial][halide-generator-tutorial] on generators. Assume (like in
568the tutorial) that you have a source file named `my_generators.cpp` and that in
569it you have generator classes `MyFirstGenerator` and `MySecondGenerator` with
570registered names `my_first_generator` and `my_second_generator` respectively.
571
572Then the first step is to add a **generator executable** to your build:
573
574```cmake
575# ... same project setup as before ...
576add_executable(my_generators my_generators.cpp)
577target_link_libraries(my_generators PRIVATE Halide::Generator)
578```
579
580Using the generator executable, we can add a Halide library corresponding to
581`MyFirstGenerator`.
582
583```cmake
584# ... continuing from above
585add_halide_library(my_first_generator FROM my_generators)
586```
587
588This will create a static library target in CMake that corresponds to the output
589of running your generator. The second generator in the file requires generator
590parameters to be passed to it. These are also easy to handle:
591
592```cmake
593# ... continuing from above
594add_halide_library(my_second_generator FROM my_generators
595                   PARAMS parallel=false scale=3.0 rotation=ccw output.type=uint16)
596```
597
598Adding multiple configurations is easy, too:
599
600```cmake
601# ... continuing from above
602add_halide_library(my_second_generator_2 FROM my_generators
603                   GENERATOR my_second_generator
604                   PARAMS scale=9.0 rotation=ccw output.type=float32)
605
606add_halide_library(my_second_generator_3 FROM my_generators
607                   GENERATOR my_second_generator
608                   PARAMS parallel=false output.type=float64)
609```
610
611Here, we had to specify which generator to use (`my_second_generator`) since it
612uses the target name by default. The functions in these libraries will be named
613after the target names, `my_second_generator_2` and `my_second_generator_3`, by
614default, but it is possible to control this via the `FUNCTION_NAME` parameter.
615
616Each one of these targets, `<GEN>`, carries an associated `<GEN>.runtime`
617target, which is also a static library containing the Halide runtime. It is
618transitively linked through `<GEN>` to targets that link to `<GEN>`. On an
619operating system like Linux, where weak linking is available, this is not an
620issue. However, on Windows, this can fail due to symbol redefinitions. In these
621cases, you must declare that two Halide libraries share a runtime, like so:
622
623```cmake
624# ... updating above
625add_halide_library(my_second_generator_2 FROM my_generators
626                   GENERATOR my_second_generator
627                   USE_RUNTIME my_first_generator.runtime
628                   PARAMS scale=9.0 rotation=ccw output.type=float32)
629
630add_halide_library(my_second_generator_3 FROM my_generators
631                   GENERATOR my_second_generator
632                   USE_RUNTIME my_first_generator.runtime
633                   PARAMS parallel=false output.type=float64)
634```
635
636This will even work correctly when different combinations of targets are
637specified for each halide library. A "greatest common denominator" target will
638be chosen that is compatible with all of them (or the build will fail).
639
640### Autoschedulers
641
642When the autoschedulers are included in the release package, they are very
643simple to apply to your own generators. For example, we could update the
644definition of the `my_first_generator` library above to use the `Adams2019`
645autoscheduler:
646
647```cmake
648add_halide_library(my_second_generator FROM my_generators
649                   AUTOSCHEDULER Halide::Adams2019
650                   PARAMS auto_schedule=true)
651```
652
653### RunGenMain
654
655Halide provides a generic driver for generators to be used during development
656for benchmarking and debugging. Suppose you have a generator executable called
657`my_gen` and a generator within called `my_filter`. Then you can pass a variable
658name to the `REGISTRATION` parameter of `add_halide_library` which will contain
659the name of a generated C++ source that should be linked to `Halide::RunGenMain`
660and `my_filter`.
661
662For example:
663
664```cmake
665add_halide_library(my_filter FROM my_gen
666                   REGISTRATION filter_reg_cpp)
667add_executable(runner ${filter_reg_cpp})
668target_link_libraries(runner PRIVATE my_filter Halide::RunGenMain)
669```
670
671Then you can run, debug, and benchmark your generator through the `runner`
672executable.
673
674## Halide package documentation
675
676Halide provides a CMake _package configuration_ module. The intended way to use
677the CMake build is to run `find_package(Halide ...)` in your `CMakeLists.txt`
678file. Closely read the [`find_package` documentation][find_package] before
679proceeding.
680
681### Components
682
683The Halide package script understands a handful of optional components when
684loading the package.
685
686First, if you plan to use the Halide Image IO library, you will want to include
687the `png` and `jpeg` components when loading Halide.
688
689Second, Halide releases can contain a variety of configurations: static, shared,
690debug, release, etc. CMake handles Debug/Release configurations automatically,
691but generally only allows one type of library to be loaded.
692
693The package understands two components, `static` and `shared`, that specify
694which type of library you would like to load. For example, if you want to make
695sure that you link against shared Halide, you can write:
696
697```cmake
698find_package(Halide REQUIRED COMPONENTS shared)
699```
700
701If the shared libraries are not available, this will result in a failure.
702
703If no component is specified, then the `Halide_SHARED_LIBS` variable is checked.
704If it is defined and set to true, then the shared libraries will be loaded or
705the package loading will fail. Similarly, if it is defined and set to false, the
706static libraries will be loaded.
707
708If no component is specified and `Halide_SHARED_LIBS` is _not_ defined, then the
709[`BUILD_SHARED_LIBS`][build_shared_libs] variable will be inspected. If it is
710**not defined** or **defined and set to true**, then it will attempt to load the
711shared libs and fall back to the static libs if they are not available.
712Similarly, if `BUILD_SHARED_LIBS` is **defined and set to false**, then it will
713try the static libs first then fall back to the shared libs.
714
715### Variables
716
717Variables that control package loading:
718
719| Variable             | Description                                                                                                                                                                   |
720| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
721| `Halide_SHARED_LIBS` | override `BUILD_SHARED_LIBS` when loading the Halide package via `find_package`. Has no effect when using Halide via `add_subdirectory` as a Git or `FetchContent` submodule. |
722
723Variables set by the package:
724
725| Variable                   | Description                                                      |
726| -------------------------- | ---------------------------------------------------------------- |
727| `Halide_VERSION`           | The full version string of the loaded Halide package             |
728| `Halide_VERSION_MAJOR`     | The major version of the loaded Halide package                   |
729| `Halide_VERSION_MINOR`     | The minor version of the loaded Halide package                   |
730| `Halide_VERSION_PATCH`     | The patch version of the loaded Halide package                   |
731| `Halide_VERSION_TWEAK`     | The tweak version of the loaded Halide package                   |
732| `Halide_HOST_TARGET`       | The Halide target triple corresponding to "host" for this build. |
733| `Halide_ENABLE_EXCEPTIONS` | Whether Halide was compiled with exception support               |
734| `Halide_ENABLE_RTTI`       | Whether Halide was compiled with RTTI                            |
735
736### Imported targets
737
738Halide defines the following targets that are available to users:
739
740| Imported target      | Description                                                                                                                          |
741| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
742| `Halide::Halide`     | this is the JIT-mode library to use when using Halide from C++.                                                                      |
743| `Halide::Generator`  | this is the target to use when defining a generator executable. It supplies a `main()` function.                                     |
744| `Halide::Runtime`    | adds include paths to the Halide runtime headers                                                                                     |
745| `Halide::Tools`      | adds include paths to the Halide tools, including the benchmarking utility.                                                          |
746| `Halide::ImageIO`    | adds include paths to the Halide image IO utility and sets up dependencies to PNG / JPEG if they are available.                      |
747| `Halide::RunGenMain` | used with the `REGISTRATION` parameter of `add_halide_library` to create simple runners and benchmarking tools for Halide libraries. |
748
749The following targets are not guaranteed to be available:
750
751| Imported target   | Description                                                                                                                              |
752| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
753| `Halide::Python`  | this is a Python 3 module that can be referenced as `$<TARGET_FILE:Halide::Python>` when setting up Python tests or the like from CMake. |
754| `Halide::Adams19` | the Adams et.al. 2019 autoscheduler (no GPU support)                                                                                     |
755| `Halide::Li18`    | the Li et.al. 2018 gradient autoscheduler (limited GPU support)                                                                          |
756
757### Functions
758
759Currently, only one function is defined:
760
761#### `add_halide_library`
762
763This is the main function for managing generators in AOT compilation. The full
764signature follows:
765
766```
767add_halide_library(<target> FROM <generator-target>
768                   [GENERATOR generator-name]
769                   [FUNCTION_NAME function-name]
770                   [USE_RUNTIME hl-target]
771                   [PARAMS param1 [param2 ...]]
772                   [TARGETS target1 [target2 ...]]
773                   [FEATURES feature1 [feature2 ...]]
774                   [PLUGINS plugin1 [plugin2 ...]]
775                   [AUTOSCHEDULER scheduler-name]
776                   [GRADIENT_DESCENT]
777                   [C_BACKEND]
778                   [REGISTRATION OUTVAR]
779                   [<extra-output> OUTVAR])
780
781extra-output = ASSEMBLY | BITCODE | COMPILER_LOG | CPP_STUB
782             | FEATURIZATION | LLVM_ASSEMBLY | PYTHON_EXTENSION
783             | PYTORCH_WRAPPER | SCHEDULE | STMT | STMT_HTML
784```
785
786This function creates a called `<target>` corresponding to running the
787`<generator-target>` (an executable target which links to `Halide::Generator`)
788one time, using command line arguments derived from the other parameters.
789
790The arguments `GENERATOR` and `FUNCTION_NAME` default to `<target>`. They
791correspond to the `-g` and `-f` command line flags, respectively.
792
793If `USE_RUNTIME` is not specified, this function will create another target
794called `<target>.runtime` which corresponds to running the generator with `-r`
795and a compatible list of targets. This runtime target is an INTERFACE dependency
796of `<target>`. If multiple runtime targets need to be linked together, setting
797`USE_RUNTIME` to another Halide library, `<target2>` will prevent the generation
798of `<target>.runtime` and instead use `<target2>.runtime`.
799
800Parameters can be passed to a generator via the `PARAMS` argument. Parameters
801should be space-separated. Similarly, `TARGETS` is a space-separated list of
802targets for which to generate code in a single function. They must all share the
803same platform/bits/os triple (eg. `arm-32-linux`). Features that are in common
804among all targets, including device libraries (like `cuda`) should go in
805`FEATURES`.
806
807Every element of `TARGETS` must begin with the same `arch-bits-os` triple. This
808function understands two _meta-triples_, `host` and `cmake`. The meta-triple
809`host` is equal to the `arch-bits-os` triple used to compile Halide along with
810all of the supported instruction set extensions. On platforms that support
811running both 32 and 64-bit programs, this will not necessarily equal the
812platform the compiler is running on or that CMake is targeting.
813
814The meta-triple `cmake` is equal to the `arch-bits-os` of the current CMake
815target. This is useful if you want to make sure you are not unintentionally
816cross-compiling, which would result in an [`IMPORTED` target][imported-target]
817being created. When `TARGETS` is empty and the `host` target would not
818cross-compile, then `host` will be used. Otherwise, `cmake` will be used and an
819author warning will be issued.
820
821To set the default autoscheduler, set the `AUTOSCHEDULER` argument to a target
822named like `Namespace::Scheduler`, for example `Halide::Adams19`. This will set
823the `-s` flag on the generator command line to `Scheduler` and add the target to
824the list of plugins. Additional plugins can be loaded by setting the `PLUGINS`
825argument. If the argument to `AUTOSCHEDULER` does not contain `::` or it does
826not name a target, it will be passed to the `-s` flag verbatim.
827
828If `GRADIENT_DESCENT` is set, then the module will be built suitably for
829gradient descent calculation in TensorFlow or PyTorch. See
830`Generator::build_gradient_module()` for more documentation. This corresponds to
831passing `-d 1` at the generator command line.
832
833If the `C_BACKEND` option is set, this command will invoke the configured C++
834compiler on a generated source. Note that a `<target>.runtime` target is _not_
835created in this case, and the `USE_RUNTIME` option is ignored. Other options
836work as expected.
837
838If `REGISTRATION` is set, the path to the generated `.registration.cpp` file
839will be set in `OUTVAR`. This can be used to generate a runner for a Halide
840library that is useful for benchmarking and testing, as documented above. This
841is equivalent to setting `-e registration` at the generator command line.
842
843Lastly, each of the `extra-output` arguments directly correspond to an extra
844output (via `-e`) from the generator. The value `OUTVAR` names a variable into
845which a path (relative to
846[`CMAKE_CURRENT_BINARY_DIR`][cmake_current_binary_dir]) to the extra file will
847be written.
848
849## Cross compiling
850
851Cross-compiling in CMake can be tricky, since CMake doesn't easily support
852compiling for both the host platform and the cross-platform within the same
853build. Unfortunately, Halide generator executables are just about always
854designed to run on the host platform. Each project will be set up differently
855and have different requirements, but here are some suggestions for effective use
856of CMake in these scenarios.
857
858### Use a super-build
859
860A CMake super-build consists of breaking down a project into sub-projects that
861are isolated by [toolchain][cmake-toolchains]. The basic structure is to have an
862outermost project that only coordinates the sub-builds via the
863[`ExternalProject`][externalproject] module.
864
865One would then use Halide to build a generator executable in one self-contained
866project, then export that target to be used in a separate project. The second
867project would be configured with the target [toolchain][cmake-toolchains] and
868would call `add_halide_library` with no `TARGETS` option and set `FROM` equal to
869the name of the imported generator executable. Obviously, this is a significant
870increase in complexity over a typical CMake project.
871
872### Use `ExternalProject` directly
873
874A lighter weight alternative to the above is to use
875[`ExternalProject`][externalproject] directly in your parent build. Configure
876the parent build with the target [toolchain][cmake-toolchains], and configure
877the inner project to use the host toolchain. Then, manually create an
878[`IMPORTED` target][imported-executable] for your generator executable and call
879`add_halide_library` as described above.
880
881The main drawback of this approach is that creating accurate `IMPORTED` targets
882is difficult since predicting the names and locations of your binaries across
883all possible platform and CMake project generators is difficult. In particular,
884it is hard to predict executable extensions in cross-OS builds.
885
886### Use an emulator or run on device
887
888The [`CMAKE_CROSSCOMPILING_EMULATOR`][cmake_crosscompiling_emulator] variable
889allows one to specify a command _prefix_ to run a target-system binary on the
890host machine. One could set this to a custom shell script that uploads the
891generator executable, runs it on the device and copies back the results.
892
893### Bypass CMake
894
895The previous two options ensure that the targets generated by
896`add_halide_library` will be _normal_ static libraries. This approach does not
897use [`ExternalProject`][externalproject], but instead produces `IMPORTED`
898targets. The main drawback of `IMPORTED` targets is that they are considered
899second-class in CMake. In particular, they cannot be installed with the typical
900[`install(TARGETS)` command][install-targets]. Instead, they must be installed
901using [`install(FILES)`][install-files] and the
902[`$<TARGET_FILE:tgt>`][target-file] generator expression.
903
904# Contributing CMake code to Halide
905
906When contributing new CMake code to Halide, keep in mind that the minimum
907version is 3.16. Therefore, it is possible (and indeed required) to use modern
908CMake best practices.
909
910Like any large and complex system with a dedication to preserving backwards
911compatibility, CMake is difficult to learn and full of traps. While not
912comprehensive, the following serves as a guide for writing quality CMake code
913and outlines the code quality expectations we have as they apply to CMake.
914
915## General guidelines and best practices
916
917The following are some common mistakes that lead to subtly broken builds.
918
919- **Reading the build directory.** While setting up the build, the build
920  directory should be considered _write only_. Using the build directory as a
921  read/write temporary directory is acceptable as long as all temp files are
922  cleaned up by the end of configuration.
923- **Not using [generator expressions][cmake-genex].** Declarative is better than
924  imperative and this is no exception. Conditionally adding to a target property
925  can leak unwanted details about the build environment into packages. Some
926  information is not accurate or available except via generator expressions, eg.
927  the build configuration.
928- **Using the wrong variable.** `CMAKE_SOURCE_DIR` doesn't always point to the
929  Halide source root. When someone uses Halide via
930  [`FetchContent`][fetchcontent], it will point to _their_ source root instead.
931  The correct variable is [`Halide_SOURCE_DIR`][project-name_source_dir]. If you
932  want to know if the compiler is MSVC, check it directly with the
933  [`MSVC`][msvc] variable; don't use [`WIN32`][win32]. That will be wrong when
934  compiling with clang on Windows. In most cases, however, a generator
935  expression will be more appropriate.
936- **Using directory properties.** Directory properties have vexing behavior and
937  are essentially deprecated from CMake 3.0+. Propagating target properties is
938  the way of the future.
939- **Using the wrong visibility.** Target properties can be `PRIVATE`,
940  `INTERFACE`, or both (aka `PUBLIC`). Pick the most conservative one for each
941  scenario. Refer to the [transitive usage requirements][cmake-propagation] docs
942  for more information.
943
944### Prohibited commands list
945
946As mentioned above, using directory properties is brittle and they are therefore
947_not allowed_. The following functions may not appear in any new CMake code.
948
949| Command                             | Alternative                                                                                        |
950| ----------------------------------- | -------------------------------------------------------------------------------------------------- |
951| `add_compile_definitions`           | Use [`target_compile_definitions`][target_compile_definitions]                                     |
952| `add_compile_options`               | Use [`target_compile_options`][target_compile_options]                                             |
953| `add_definitions`                   | Use [`target_compile_definitions`][target_compile_definitions]                                     |
954| `add_link_options`                  | Use [`target_link_options`][target_link_options], but prefer not to use either                     |
955| `get_directory_property`            | Use cache variables or target properties                                                           |
956| `get_property(... DIRECTORY)`       | Use cache variables or target properties                                                           |
957| `include_directories`               | Use [`target_include_directories`][target_include_directories]                                     |
958| `link_directories`                  | Use [`target_link_libraries`][target_link_libraries]                                               |
959| `link_libraries`                    | Use [`target_link_libraries`][target_link_libraries]                                               |
960| `remove_definitions`                | [Generator expressions][cmake-genex] in [`target_compile_definitions`][target_compile_definitions] |
961| `set_directory_properties`          | Use cache variables or target properties                                                           |
962| `set_property(... DIRECTORY)`       | Use cache variables or target properties                                                           |
963| `target_link_libraries(target lib)` | Use [`target_link_libraries`][target_link_libraries] _with a visibility specifier_ (eg. `PRIVATE`) |
964
965As an example, it was once common practice to write code similar to this:
966
967```cmake
968# WRONG: do not do this
969include_directories(include)
970add_library(my_lib source1.cpp ..)
971```
972
973However, this has two major pitfalls. First, it applies to _all_ targets created
974in that directory, even those before the call to `include_directories` and those
975created in [`include()`][include]-ed CMake files. As CMake files get larger and
976more complex, this behavior gets harder to pinpoint. This is particularly vexing
977when using the `link_libraries` or `add_defintions` commands. Second, this form
978does not provide a way to _propagate_ the include directory to consumers of
979`my_lib`. The correct way to do this is:
980
981```cmake
982# CORRECT
983add_library(my_lib source1.cpp ...)
984target_include_directories(my_lib PUBLIC $<BUILD_INTERFACE:include>)
985```
986
987This is better in many ways. It only affects the target in question. It
988propagates the include path to the targets linking to it (via `PUBLIC`). It also
989does not incorrectly export the host-filesystem-specific include path when
990installing or packaging the target (via `$<BUILD_INTERFACE>`).
991
992If common properties need to be grouped together, use an INTERFACE target
993(better) or write a function (worse). There are also several functions that are
994disallowed for other reasons:
995
996| Command                         | Reason                                                                            | Alternative                                                                            |
997| ------------------------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
998| `aux_source_directory`          | Interacts poorly with incremental builds and Git                                  | List source files explicitly                                                           |
999| `build_command`                 | CTest internal function                                                           | Use CTest build-and-test mode via [`CMAKE_CTEST_COMMAND`][cmake_ctest_command]         |
1000| `cmake_host_system_information` | Usually misleading information.                                                   | Inspect [toolchain][cmake-toolchains] variables and use generator expressions.         |
1001| `cmake_policy(... OLD)`         | OLD policies are deprecated by definition.                                        | Instead, fix the code to work with the new policy.                                     |
1002| `create_test_sourcelist`        | We use our own unit testing solution                                              | See the [adding tests](#adding-tests) section.                                         |
1003| `define_property`               | Adds unnecessary complexity                                                       | Use a cache variable. Exceptions under special circumstances.                          |
1004| `enable_language`               | Halide is C/C++ only                                                              | [`FindCUDAToolkit`][findcudatoolkit] or [`FindCUDA`][findcuda], appropriately guarded. |
1005| `file(GLOB ...)`                | Interacts poorly with incremental builds and Git                                  | List source files explicitly. Allowed if not globbing for source files.                |
1006| `fltk_wrap_ui`                  | Halide does not use FLTK                                                          | None                                                                                   |
1007| `include_external_msproject`    | Halide must remain portable                                                       | Write a CMake package config file or find module.                                      |
1008| `include_guard`                 | Use of recursive inclusion is not allowed                                         | Write (recursive) functions.                                                           |
1009| `include_regular_expression`    | Changes default dependency checking behavior                                      | None                                                                                   |
1010| `load_cache`                    | Superseded by [`FetchContent`][fetchcontent]/[`ExternalProject`][externalproject] | Use aforementioned modules                                                             |
1011| `macro`                         | CMake macros are not hygienic and are therefore error-prone                       | Use functions instead.                                                                 |
1012| `site_name`                     | Privacy: do not want leak host name information                                   | Provide a cache variable, generate a unique name.                                      |
1013| `variable_watch`                | Debugging helper                                                                  | None. Not needed in production.                                                        |
1014
1015Lastly, do not introduce any dependencies via [`find_package`][find_package]
1016without broader approval. Confine dependencies to the `dependencies/` subtree.
1017
1018### Prohibited variables list
1019
1020Any variables that are specific to languages that are not enabled should, of
1021course, be avoided. But of greater concern are variables that are easy to misuse
1022or should not be overridden for our end-users. The following (non-exhaustive)
1023list of variables shall not be used in code merged into master.
1024
1025| Variable                        | Reason                                        | Alternative                                                                                             |
1026| ------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
1027| `CMAKE_ROOT`                    | Code smell                                    | Rely on `find_package` search options; include `HINTS` if necessary                                     |
1028| `CMAKE_DEBUG_TARGET_PROPERTIES` | Debugging helper                              | None                                                                                                    |
1029| `CMAKE_FIND_DEBUG_MODE`         | Debugging helper                              | None                                                                                                    |
1030| `CMAKE_RULE_MESSAGES`           | Debugging helper                              | None                                                                                                    |
1031| `CMAKE_VERBOSE_MAKEFILE`        | Debugging helper                              | None                                                                                                    |
1032| `CMAKE_BACKWARDS_COMPATIBILITY` | Deprecated                                    | None                                                                                                    |
1033| `CMAKE_BUILD_TOOL`              | Deprecated                                    | `${CMAKE_COMMAND} --build` or [`CMAKE_MAKE_PROGRAM`][cmake_make_program] (but see below)                |
1034| `CMAKE_CACHEFILE_DIR`           | Deprecated                                    | [`CMAKE_BINARY_DIR`][cmake_binary_dir], but see below                                                   |
1035| `CMAKE_CFG_INTDIR`              | Deprecated                                    | `$<CONFIG>`, `$<TARGET_FILE:..>`, target resolution of [`add_custom_command`][add_custom_command], etc. |
1036| `CMAKE_CL_64`                   | Deprecated                                    | [`CMAKE_SIZEOF_VOID_P`][cmake_sizeof_void_p]                                                            |
1037| `CMAKE_COMPILER_IS_*`           | Deprecated                                    | [`CMAKE_<LANG>_COMPILER_ID`][cmake_lang_compiler_id]                                                    |
1038| `CMAKE_HOME_DIRECTORY`          | Deprecated                                    | [`CMAKE_SOURCE_DIR`][cmake_source_dir], but see below                                                   |
1039| `CMAKE_DIRECTORY_LABELS`        | Directory property                            | None                                                                                                    |
1040| `CMAKE_BUILD_TYPE`              | Only applies to single-config generators.     | `$<CONFIG>`                                                                                             |
1041| `CMAKE_*_FLAGS*` (w/o `_INIT`)  | User-only                                     | Write a [toolchain][cmake-toolchains] file with the corresponding `_INIT` variable                      |
1042| `CMAKE_COLOR_MAKEFILE`          | User-only                                     | None                                                                                                    |
1043| `CMAKE_ERROR_DEPRECATED`        | User-only                                     | None                                                                                                    |
1044| `CMAKE_CONFIGURATION_TYPES`     | We only support the four standard build types | None                                                                                                    |
1045
1046Of course feel free to insert debugging helpers _while developing_ but please
1047remove them before review. Finally, the following variables are allowed, but
1048their use must be motivated:
1049
1050| Variable                                       | Reason                                              | Alternative                                                                                  |
1051| ---------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------- |
1052| [`CMAKE_SOURCE_DIR`][cmake_source_dir]         | Points to global source root, not Halide's.         | [`Halide_SOURCE_DIR`][project-name_source_dir] or [`PROJECT_SOURCE_DIR`][project_source_dir] |
1053| [`CMAKE_BINARY_DIR`][cmake_binary_dir]         | Points to global build root, not Halide's           | [`Halide_BINARY_DIR`][project-name_binary_dir] or [`PROJECT_BINARY_DIR`][project_binary_dir] |
1054| [`CMAKE_MAKE_PROGRAM`][cmake_make_program]     | CMake abstracts over differences in the build tool. | Prefer CTest's build and test mode or CMake's `--build` mode                                 |
1055| [`CMAKE_CROSSCOMPILING`][cmake_crosscompiling] | Often misleading.                                   | Inspect relevant variables directly, eg. [`CMAKE_SYSTEM_NAME`][cmake_system_name]            |
1056| [`BUILD_SHARED_LIBS`][build_shared_libs]       | Could override user setting                         | None, but be careful to restore value when overriding for a dependency                       |
1057
1058Any use of these functions and variables will block a PR.
1059
1060## Adding tests
1061
1062When adding a file to any of the folders under `test`, be aware that CI expects
1063that every `.c` and `.cpp` appears in the `CMakeLists.txt` file _on its own
1064line_, possibly as a comment. This is to avoid globbing and also to ensure that
1065added files are not missed.
1066
1067For most test types, it should be as simple as adding to the existing lists,
1068which must remain in alphabetical order. Generator tests are trickier, but
1069following the existing examples is a safe way to go.
1070
1071## Adding apps
1072
1073If you're contributing a new app to Halide: great! Thank you! There are a few
1074guidelines you should follow when writing a new app.
1075
1076- Write the app as if it were a top-level project. You should call
1077  `find_package(Halide)` and set the C++ version to 11.
1078- Call [`enable_testing()`][enable_testing] and add a small test that runs the
1079  app.
1080- Don't assume your app will have access to a GPU. Write your schedules to be
1081  robust to varying buildbot hardware.
1082- Don't assume your app will be run on a specific OS, architecture, or bitness.
1083  Write your apps to be robust (ideally efficient) on all supported platforms.
1084- If you rely on any additional packages, don't include them as `REQUIRED`,
1085  instead test to see if their targets are available and, if not, call
1086  `return()` before creating any targets. In this case, print a
1087  `message(STATUS "[SKIP] ...")`, too.
1088- Look at the existing apps for examples.
1089- Test your app with ctest before opening a PR. Apps are built as part of the
1090  test, rather than the main build.
1091
1092[add_custom_command]:
1093  https://cmake.org/cmake/help/latest/command/add_custom_command.html
1094[add_library]: https://cmake.org/cmake/help/latest/command/add_library.html
1095[add_subdirectory]:
1096  https://cmake.org/cmake/help/latest/command/add_subdirectory.html
1097[atlas]: http://math-atlas.sourceforge.net/
1098[brew-cmake]: https://formulae.brew.sh/cask/cmake#default
1099[build_shared_libs]:
1100  https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html
1101[choco-cmake]: https://chocolatey.org/packages/cmake/
1102[choco-doxygen]: https://chocolatey.org/packages/doxygen.install
1103[choco-ninja]: https://chocolatey.org/packages/ninja
1104[chocolatey]: https://chocolatey.org/
1105[cmake-apt]: https://apt.kitware.com/
1106[cmake-discourse]: https://discourse.cmake.org/
1107[cmake-docs]: https://cmake.org/cmake/help/latest/
1108[cmake-download]: https://cmake.org/download/
1109[cmake-from-source]: https://cmake.org/install/
1110[cmake-genex]:
1111  https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html
1112[cmake-install]:
1113  https://cmake.org/cmake/help/latest/manual/cmake.1.html#install-a-project
1114[cmake-propagation]:
1115  https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#transitive-usage-requirements
1116[cmake-toolchains]:
1117  https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html
1118[cmake-user-interaction]:
1119  https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#setting-build-variables
1120[cmake_binary_dir]:
1121  https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html
1122[cmake_build_type]:
1123  https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
1124[cmake_crosscompiling]:
1125  https://cmake.org/cmake/help/latest/variable/CMAKE_CROSSCOMPILING.html
1126[cmake_crosscompiling_emulator]:
1127  https://cmake.org/cmake/help/latest/variable/CMAKE_CROSSCOMPILING_EMULATOR.html
1128[cmake_ctest_command]:
1129  https://cmake.org/cmake/help/latest/variable/CMAKE_CTEST_COMMAND.html
1130[cmake_current_binary_dir]:
1131  https://cmake.org/cmake/help/latest/variable/CMAKE_CURRENT_BINARY_DIR.html
1132[cmake_cxx_extensions]:
1133  https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_EXTENSIONS.html
1134[cmake_cxx_standard]:
1135  https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_STANDARD.html
1136[cmake_cxx_standard_required]:
1137  https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_STANDARD_REQUIRED.html
1138[cmake_lang_compiler_id]:
1139  https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
1140[cmake_make_program]:
1141  https://cmake.org/cmake/help/latest/variable/CMAKE_MAKE_PROGRAM.html
1142[cmake_minimum_required]:
1143  https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html
1144[cmake_module_path]:
1145  https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_PATH.html
1146[cmake_sizeof_void_p]:
1147  https://cmake.org/cmake/help/latest/variable/CMAKE_SIZEOF_VOID_P.html
1148[cmake_source_dir]:
1149  https://cmake.org/cmake/help/latest/variable/CMAKE_SOURCE_DIR.html
1150[cmake_system_name]:
1151  https://cmake.org/cmake/help/latest/variable/CMAKE_SYSTEM_NAME.html
1152[doxygen-download]: https://www.doxygen.nl/download.html
1153[doxygen]: https://www.doxygen.nl/index.html
1154[eigen]: http://eigen.tuxfamily.org/index.php?title=Main_Page
1155[enable_testing]:
1156  https://cmake.org/cmake/help/latest/command/enable_testing.html
1157[externalproject]:
1158  https://cmake.org/cmake/help/latest/module/ExternalProject.html
1159[fetchcontent]: https://cmake.org/cmake/help/latest/module/FetchContent.html
1160[find_package]: https://cmake.org/cmake/help/latest/command/find_package.html
1161[findcuda]: https://cmake.org/cmake/help/latest/module/FindCUDA.html
1162[findcudatoolkit]:
1163  https://cmake.org/cmake/help/latest/module/FindCUDAToolkit.html
1164[finddoxygen]: https://cmake.org/cmake/help/latest/module/FindDoxygen.html
1165[findjpeg]: https://cmake.org/cmake/help/latest/module/FindJPEG.html
1166[findopencl]: https://cmake.org/cmake/help/latest/module/FindOpenCL.html
1167[findopengl]: https://cmake.org/cmake/help/latest/module/FindOpenGL.html
1168[findpng]: https://cmake.org/cmake/help/latest/module/FindPNG.html
1169[findpython3]: https://cmake.org/cmake/help/latest/module/FindPython3.html
1170[findx11]: https://cmake.org/cmake/help/latest/module/FindX11.html
1171[halide-generator-tutorial]:
1172  https://halide-lang.org/tutorials/tutorial_lesson_15_generators.html
1173[halide-tutorials]: https://halide-lang.org/tutorials/tutorial_introduction.html
1174[homebrew]: https://brew.sh
1175[imported-executable]:
1176  https://cmake.org/cmake/help/latest/command/add_executable.html#imported-executables
1177[imported-target]:
1178  https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#imported-targets
1179[include]: https://cmake.org/cmake/help/latest/command/include.html
1180[install-files]: https://cmake.org/cmake/help/latest/command/install.html#files
1181[install-targets]:
1182  https://cmake.org/cmake/help/latest/command/install.html#targets
1183[libjpeg]: https://www.libjpeg-turbo.org/
1184[libpng]: http://www.libpng.org/pub/png/libpng.html
1185[lld]: https://lld.llvm.org/
1186[msvc]: https://cmake.org/cmake/help/latest/variable/MSVC.html
1187[msvc-cmd]:
1188  https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019
1189[ninja-download]: https://github.com/ninja-build/ninja/releases
1190[ninja]: https://ninja-build.org/
1191[openblas]: https://www.openblas.net/
1192[project]: https://cmake.org/cmake/help/latest/command/project.html
1193[project-name_binary_dir]:
1194  https://cmake.org/cmake/help/latest/variable/PROJECT-NAME_BINARY_DIR.html
1195[project-name_source_dir]:
1196  https://cmake.org/cmake/help/latest/variable/PROJECT-NAME_SOURCE_DIR.html
1197[project_source_dir]:
1198  https://cmake.org/cmake/help/latest/variable/PROJECT_SOURCE_DIR.html
1199[project_binary_dir]:
1200  https://cmake.org/cmake/help/latest/variable/PROJECT_BINARY_DIR.html
1201[pypi-cmake]: https://pypi.org/project/cmake/
1202[python]: https://www.python.org/downloads/
1203[target-file]:
1204  https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#target-dependent-queries
1205[target_compile_definitions]:
1206  https://cmake.org/cmake/help/latest/command/target_compile_definitions.html
1207[target_compile_options]:
1208  https://cmake.org/cmake/help/latest/command/target_compile_options.html
1209[target_include_directories]:
1210  https://cmake.org/cmake/help/latest/command/target_include_directories.html
1211[target_link_libraries]:
1212  https://cmake.org/cmake/help/latest/command/target_link_libraries.html
1213[target_link_options]:
1214  https://cmake.org/cmake/help/latest/command/target_link_options.html
1215[vcpkg]: https://github.com/Microsoft/vcpkg
1216[vcvarsall]:
1217  https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#vcvarsall-syntax
1218[venv]: https://docs.python.org/3/tutorial/venv.html
1219[vs2019-cmake-docs]:
1220  https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=vs-2019
1221[win32]: https://cmake.org/cmake/help/latest/variable/WIN32.html
1222