# How To: Build Tectonic
This document lays out the options available for building the Tectonic [Rust
crate][rust-crate] and/or [executable] from source code. Because Tectonic relies
on a large number of system libraries and tightly-integrated C/C++ code, it can
be more challenging to compile than most Rust code.
[rust-crate]: https://doc.rust-lang.org/rust-by-example/crates.html
[executable]: https://en.wikipedia.org/wiki/Executable
For this reason, if you just want to *run* Tectonic, we recommend that you start
by [installing][install] a pre-built version if possible. Using a pre-compiled
binary will save you time and, possibly, headaches.
[install]: ../installation/index.md
## Basic Prerequisites
To build Tectonic you will need Rust, C, and C++ compilers installed. It is
beyond the scope of this document to give instructions on this topic, besides
pointing you to the [Rust installation
page](https://www.rust-lang.org/tools/install).
You do *not* necessarily need to download a copy of the Tectonic source code, if
the [cargo install] command will meet your needs.
[cargo install]: https://doc.rust-lang.org/cargo/commands/cargo-install.html
## Third-Party Dependencies
Tectonic relies on a number of well-established third-party libraries that deal
with fonts, Unicode, text shaping, and so on. Specifically:
- [fontconfig](https://fontconfig.org/) for discovering system fonts (except on
macOS)
- [freetype2](https://www.freetype.org/) for parsing font files
- [graphite2](https://graphite.sil.org/) for shaping certain unusual scripts
- [Harfbuzz](https://harfbuzz.github.io/) for text shaping
- [ICU4C](http://site.icu-project.org/home) for Unicode data and algorithms
- [libpng](http://www.libpng.org/) for parsing PNG images
- [OpenSSL](https://www.openssl.org/) for HTTPS if you’re not on a Mac or
Windows machine (or whichever SSL library is required for your system by the
[rust-native-tls] crate)
- [zlib](https://zlib.net/) for compression algorithms
[Harfbuzz]: https://harfbuzz.github.io/
[rust-native-tls]: https://github.com/sfackler/rust-native-tls/#readme
To build Tectonic, your first task is to decide where you want these library
dependencies to come from.
- Tectonic can provide some dependencies **internally** ("vendor" them). This is
the default for [Harfbuzz]. You can use [Cargo features][cargo-features],
described below, to control when this happens. For some third-party libraries
needed by Tectonic, vendoring is not possible.
- You can install the dependencies **externally**, with a system such as your
OS’s package manager, and tell the Tectonic build system how to access them.
Read [how to install Tectonic’s dependencies externally][external-dep-install]
for quick recipes as to how to do that.
- As an intermediate approach, you can **use cargo-vcpkg** to compile the
dependencies for Tectonic’s use with [vcpkg]. Read [this
page][cargo-vcpkg-dep-install] to learn how to do that.
[external-dep-install]: ./external-dep-install.md
[vcpkg]: https://vcpkg.readthedocs.io
[cargo-vcpkg-dep-install]: ./cargo-vcpkg-dep-install.md
You’ll have to set up one of two ways for the Tectonic build system to gather
the appropriate information about how to compile against the external
dependencies:
- **[pkg-config]**, the default system, is the appropriate choice in most cases.
Generally all you need to do is make sure that the `pkg-config` program is
installed using the same framework as you used to install the library
dependencies. You can force the Tectonic build system to use pkg-config for
dependency discovery by setting the environment variable
`TECTONIC_DEP_BACKEND` to the value `pkg-config`.
- **[vcpkg]** is the choice to use if you installed your dependencies this way,
either [using cargo-vcpkg][cargo-vcpkg-dep-install] or separately. Activate
this mode by setting the environment variable `TECTONIC_DEP_BACKEND` to the
value `vcpkg`.
[pkg-config]: https://www.freedesktop.org/wiki/Software/pkg-config/
If using [pkg-config], setting the environment variable
`TECTONIC_PKGCONFIG_FORCE_SEMI_STATIC` will cause the build system to attempt to
link with external libraries statically rather than dynamically. System
libraries, such as `libc` and `libm` on Unix systems, will still be linked
dynamically. This mode is planned to be superseded by better support for
"vendoring" dependent libraries.
## Choose Cargo Features
The Cargo build framework offers the concept of [features][cargo-features] to
control build options. Tectonic offers the following features:
[cargo-features]: https://doc.rust-lang.org/cargo/reference/features.html
- **`external-harfbuzz`**. By default, the Tectonic crates will build and link
to a "vendored" (static, internal) version of the [Harfbuzz] text shaping
library. If you would like to link to an externally-supplied version instead,
enable this feature.
- **`geturl-curl`**. Uses the [curl] crate to get URLs. In order for this to
take effect, you must use `--no-default-features`, because `geturl-reqwest` is
a default feature and takes precedence.
- **`geturl-reqwest`** (enabled by default). Uses the [reqwest] crate to get
URLs. This is a good portable default.
- **`native-tls-vendored`**. If using [reqwest], activate the `vendored` option
in the [native-tls] crate, causing OpenSSL to be vendored. This can be useful
when cross-compiling or building static binaries, but is discouraged because
that means that the resulting binaries won’t benefit from security fixes to
system TLS libraries.
[curl]: https://docs.rs/curl/
[reqwest]: https://docs.rs/reqwest/
[native-tls]: https://github.com/sfackler/rust-native-tls
Some lesser-used features are:
- **`serialization`** (enabled by default). Disabling this feature turns off all
Tectonic features that require the [serde] crate. This option is provided
because Tectonic’s use of serde requires [procedural macro][proc-macro]
support, which is not available by default on static-only compilation
environments. However, it is likely that serialization support will become
mandatory in the future, and one can still produce static `tectonic`
executables using a cross-compilation approach. Therefore we do not recommend
that you rely on this feature.
- **`profile`**. Compile Tectonic code in such a way as to make it profileable.
In particular, this forces the C/C++ compiler to include frame pointer
information unless it is known that such information is not needed for
profiling on the target platform.
[serde]: https://crates.io/crates/serde
[proc-macro]: https://doc.rust-lang.org/reference/procedural-macros.html
To avoid activating a feature that is enabled by default, you must pass the
`--no-default-features` flag to the `cargo` command that you run. Features are
enabled with a flag such as `--features "serialization profile"`.
## Compile the Code
To build the latest released version of Tectonic without needing to download its
source code, first *ensure that your build environment variables are set up
properly* and determine what feature flags you need. Then run:
```sh
cargo install tectonic
```
inserting any feature flags after the `install`. To install the latest version
from Git, do the same but use:
```sh
cargo install --git https://github.com/tectonic-typesetting/tectonic.git
```
Many other variations are possible. See the [cargo install] documentation for
more.
If you have downloaded its source code (perhaps because you wish to make your
own improvements), make sure that you’re inside the Tectonic source tree and run:
```sh
cargo build
```
once again adding any feature flags and ensuring that any necessary build
environment variables are set up properly. Read [The Cargo Book][cargo-book] for
vastly more information about where you can go from there.
[cargo-book]: https://doc.rust-lang.org/cargo/index.html