# How FTL language runtimes work
## Building
After the below steps are complete FTL has enough information to deploy the module and the language-specific build stages are complete.
### Extract dependencies
The first thing FTL does is a fast pass to [extract imports](https://github.com/TBD54566975/ftl/blob/main/buildengine/deps.go) from the source code. The modules are then built in topological order based on the imports. This process is built into FTL itself.
### Generate dependencies
Before building a module, any dependencies must be code-generated somewhere that the language toolchain can load. For example, in Go we generate modules into `${gitroot}/.ftl/go/modules` and use a `go.work` file to pull these into the module's build. The generated code includes all of the public types, functions, and resources for a given module, and is created from the module's schema.
The FTL build engine will ensure that the schema protobuf for each module is provided to the language-specific build.
### Extract the schema / build the binary
These can be separate steps, but typically they're quite tightly coupled.
The FTL tooling expects at least two artefacts to exist after the language-specific tooling has completed its build:
1. A `schema.pb` file containing the encoded [xyz.block.ftl.v1.schema.Module](https://github.com/TBD54566975/ftl/blob/main/backend/protos/xyz/block/ftl/v1/schema/schema.proto) protobuf representing the extracted FTL schema for the module.
2. One or more files needed to execute the module on a Runner. In Go this is a single binary, `main`.
FTL defines sane defaults for each language, but they can be overridden in the module's [ftl.toml](https://github.com/TBD54566975/ftl/blob/main/common/moduleconfig/moduleconfig.go) file.
#### Schema types
FTL has a relatively rich type system, which needs to be fully supported. The full set of types is listed [here](https://tbd54566975.github.io/ftl/docs/reference/types/).
#### Schema symbol naming
To ensure consistent naming of symbols across languages, FTL normalises casing to the following:
1. Types are `UpperCamelCase`
2. Functions are `lowerCamelCase`
Acronyms/initialisms are never all-caps, eg. `Dns` not `DNS`.
The algorithm for normalising case is defined in code [here](https://github.com/TBD54566975/ftl/blob/main/backend/schema/strcase/case.go), but is basically:
Split before the start of any upper case run, or underscore, dropping underscores.
eg.
| Symbol | Tokens | Normalised |
| ---------------- | -------------------------- | ----------------- |
| `"TwoWords"` | `["Two", "Words"]` | `"twoWords"`
| `"two_words"` | `["two", "words"]` | `"twoWords"`
| `"twoWORDSMore"` | `["two", "WORDS", "More"]` | `"twoWordsMore"`
> [!Note]
> Similarly, when _generating_ code, FTL will use the idiomatic casing of the language.
As an end-to-end example, given the Python function `my_awesome_verb()`, the FTL verb name would be `myAwesomeVerb` and the Go function name would be `MyAwesomeVerb`.
## Runtime
In order to integrate with FTL, each language also needs a runtime. At a minimum, the runtime needs to implement inbound and outbound verb calls:
1. The gRPC endpoint [VerbService.Call()](https://github.com/TBD54566975/ftl/blob/main/backend/protos/xyz/block/ftl/v1/ftl.proto#L99) in order to receive calls.
2. A function in an FTL package or on an FTL-specific context object, that allows the runtime to call other verbs via a `VerbService.Call()` client.
The RPC client should connect to the VerbService running at the URL passed through the environment variable `$FTL_ENDPOINT` (eg. `FTL_ENDPOINT=http://127.0.0.1:8892`). The FTL Runner will ensure this environment variable is set.
### Payload encoding
FTL currently encodes all request/response payloads as JSON.