# Installation

tacet is available for multiple languages. Choose your platform:

<Tabs syncKey="language">
<TabItem label="Rust" icon="seti:rust">

Add tacet as a dev dependency:

```bash
cargo add tacet --dev
cargo add rand --dev  # For random input generation
```

Or add to your `Cargo.toml`:

```toml
[dev-dependencies]
tacet = "0.1"
rand = "0.8"
```

### Feature flags

**Default features** (recommended):
- `parallel` - Rayon-based parallel bootstrap (4-8x speedup)
- `kperf` (macOS ARM64) - Cycle-accurate timing via kperf (opt-in, requires sudo)
- `perf` (Linux) - Cycle-accurate timing via perf_event (opt-in, requires sudo)

**Optional features:**
- `macros` - Proc macros (`timing_test!`, `timing_test_checked!`)

**Minimal build:**
```toml
[dev-dependencies]
tacet = { version = "0.1", default-features = false }
```

</TabItem>
<TabItem label="JavaScript" icon="seti:javascript">

<PackageManagers pkg="@tacet/js" pkgManagers={['bun', 'npm', 'pnpm', 'yarn']} />

Native bindings via NAPI-RS, supporting Node.js and Bun on:
- Linux (x86_64, aarch64)
- macOS (x86_64, aarch64)
- Windows (x86_64)

```javascript
const outcome = TimingOracle.forAttacker(AttackerModel.AdjacentNetwork)
  .test(
    () => new Uint8Array(32).fill(0),  // Baseline
    () => crypto.getRandomValues(new Uint8Array(32)),  // Sample
    (data) => myFunction(data)
  );
```

</TabItem>
<TabItem label="C" icon="seti:c">

### Quick Install (Recommended)

**Install Script (Linux/macOS):**
```bash
curl -fsSL https://raw.githubusercontent.com/agucova/tacet/main/install.sh | bash
```

Installs to `/usr/local` by default. For a custom location:
```bash
PREFIX=$HOME/.local bash -c "$(curl -fsSL https://raw.githubusercontent.com/agucova/tacet/main/install.sh)"
```

**Homebrew (macOS):**
```bash
HOMEBREW_DEVELOPER=1 brew install --formula \
  https://raw.githubusercontent.com/agucova/tacet/main/homebrew/Formula/tacet-c.rb
```

<Aside type="note">
The `HOMEBREW_DEVELOPER=1` flag is required because Homebrew no longer allows installing formulas directly from URLs without a tap. This is a safe workaround for formulas from trusted sources.
</Aside>

**Verify Installation:**
```bash
# Add Homebrew's pkgconfig to your path (add to ~/.zshrc or ~/.bashrc)
export PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"

pkg-config --modversion tacet
pkg-config --cflags --libs tacet
```

### Usage in Your Project

**With pkg-config (recommended):**
```bash
cc myfile.c $(pkg-config --cflags --libs tacet) -o myapp
```

**CMake:**
```cmake
find_package(PkgConfig REQUIRED)
pkg_check_modules(TACET REQUIRED tacet)

add_executable(my_test test.c)
target_include_directories(my_test PRIVATE ${TACET_INCLUDE_DIRS})
target_link_libraries(my_test PRIVATE ${TACET_LIBRARIES})
```

**Example usage:**
```c
#include <tacet/tacet.h>

ToConfig cfg = to_config_adjacent_network();
cfg.time_budget_secs = 30.0;  // Customize as needed
// ToConfig is a value type - no need to free
```

See [C API](https://tacet.sh/api/c) for full documentation.

### Build from Source (Advanced)

If you need to build from source:

```bash
git clone https://github.com/agucova/tacet
cd tacet
cargo build --release -p tacet-c

# Artifacts generated:
# - Header: crates/tacet-c/include/tacet.h
# - Library: target/release/libtacet_c.a
# - pkg-config: target/release/tacet.pc
```

</TabItem>
<TabItem label="C++" icon="seti:cpp">

### Quick Install (Recommended)

**Install Script (Linux/macOS):**
```bash
curl -fsSL https://raw.githubusercontent.com/agucova/tacet/main/install.sh | bash
```

Installs to `/usr/local` by default. For a custom location:
```bash
PREFIX=$HOME/.local bash -c "$(curl -fsSL https://raw.githubusercontent.com/agucova/tacet/main/install.sh)"
```

**Homebrew (macOS):**
```bash
HOMEBREW_DEVELOPER=1 brew install --formula \
  https://raw.githubusercontent.com/agucova/tacet/main/homebrew/Formula/tacet-c.rb
```

<Aside type="note">
The `HOMEBREW_DEVELOPER=1` flag is required because Homebrew no longer allows installing formulas directly from URLs without a tap. This is a safe workaround for formulas from trusted sources.
</Aside>

**Verify Installation:**
```bash
# Add Homebrew's pkgconfig to your path (add to ~/.zshrc or ~/.bashrc)
export PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"

pkg-config --modversion tacet
pkg-config --cflags --libs tacet
```

### Usage in Your Project

**With pkg-config (recommended):**
```bash
c++ -std=c++20 myfile.cpp $(pkg-config --cflags --libs tacet) -o myapp
```

**CMake (C++20 required):**
```cmake
find_package(PkgConfig REQUIRED)
pkg_check_modules(TACET REQUIRED tacet)

# C++20 required
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(my_test test.cpp)
target_include_directories(my_test PRIVATE ${TACET_INCLUDE_DIRS})
target_link_libraries(my_test PRIVATE ${TACET_LIBRARIES})
```

**Example usage:**
```cpp
#include <tacet/tacet.hpp>
using namespace std::chrono_literals;

auto oracle = tacet::Oracle::forAttacker(ToAttackerModel::AdjacentNetwork)
    .timeBudget(30s);
```

See [C++ API](https://tacet.sh/api/cpp) for full documentation.

### Build from Source (Advanced)

If you need to build from source:

```bash
git clone https://github.com/agucova/tacet
cd tacet
cargo build --release -p tacet-c

# Artifacts generated:
# - Header: bindings/cpp/tacet.hpp
# - Library: target/release/libtacet_c.a
# - pkg-config: target/release/tacet.pc
```

</TabItem>
<TabItem label="Go" icon="seti:go">

### Installation

```bash
go get github.com/agucova/tacet/crates/tacet-go
go run github.com/agucova/tacet/crates/tacet-go/cmd/tacet-install@latest
```

The install command downloads the pre-built native library (~12MB) for your platform and places it in the module cache where CGo can find it. This only needs to be run once.

**Requirements:** Go 1.22+ with CGo enabled

**Supported platforms:**
- macOS (ARM64 Apple Silicon, AMD64 Intel)
- Linux (ARM64, AMD64)

### Quick Start

```go
package main

import (
    "fmt"
    "log"
    "time"

    tacet "github.com/agucova/tacet/crates/tacet-go"
)

func main() {
    result, err := tacet.Test(
        tacet.NewZeroGenerator(0),
        tacet.FuncOperation(func(input []byte) {
            myCryptoFunction(input)
        }),
        32, // input size in bytes
        tacet.WithAttacker(tacet.AdjacentNetwork),
        tacet.WithTimeBudget(30*time.Second),
    )
    if err != nil {
        log.Fatal(err)
    }

    switch result.Outcome {
    case tacet.Pass:
        fmt.Printf("No leak (P=%.1f%%)\n", result.LeakProbability*100)
    case tacet.Fail:
        fmt.Printf("Leak detected: %s\n", result.Exploitability)
    }
}
```

### Troubleshooting

If you see linker errors about missing `tacet` symbols, run the install command:
```bash
go run github.com/agucova/tacet/crates/tacet-go/cmd/tacet-install@latest
```

To install a specific version:
```bash
go run github.com/agucova/tacet/crates/tacet-go/cmd/tacet-install@latest -version=v0.3.0
```

See [Go API documentation](https://tacet.sh/api/go) for complete reference.

</TabItem>
</Tabs>

## Platform support

| Platform | Timer | Resolution | Notes |
|----------|-------|------------|-------|
| Linux x86_64 | `rdtsc` | ~0.3ns | Best precision |
| Linux aarch64 | `cntvct_el0` | 1-10ns | Good precision |
| macOS x86_64 | `rdtsc` | ~0.3ns | Best precision |
| macOS ARM64 | `cntvct_el0` | ~42ns | Uses adaptive batching |
| Windows x86_64 | `rdtsc` | ~0.3ns | Best precision |

On platforms with coarse timer resolution (macOS ARM64), the library automatically uses adaptive batching to compensate.

## Enabling cycle-accurate timers

For cycle-accurate measurements on ARM64, use `TimerSpec::CyclePrecision`:

```rust
use tacet::{TimingOracle, AttackerModel, TimerSpec};

TimingOracle::for_attacker(AttackerModel::SharedHardware)
    .timer_spec(TimerSpec::CyclePrecision)  // Request cycle-accurate timer
```

This requires elevated privileges on ARM64:

<Tabs>
<TabItem label="macOS ARM64">
```bash
# kperf requires BOTH sudo AND single-threaded execution
sudo -E cargo test --test my_test -- --test-threads=1
```
</TabItem>
<TabItem label="Linux">
```bash
# Option 1: Run as root
sudo cargo test --test my_test -- --test-threads=1

# Option 2: Grant CAP_PERFMON (persistent)
sudo setcap cap_perfmon+ep target/debug/deps/my_test-*
cargo test --test my_test -- --test-threads=1
```
</TabItem>
</Tabs>

<Aside type="tip">
Using `CyclePrecision` explicitly will error if cycle-accurate timing isn't available, rather than silently falling back. This is safer for security-critical tests.
</Aside>

## Next steps

- [Quick Start](https://tacet.sh/getting-started/quick-start): Write your first timing test
- [The Two-Class Pattern](https://tacet.sh/core-concepts/two-class-pattern): Understanding input class selection
- [Attacker Models](https://tacet.sh/core-concepts/attacker-models): Choosing the right threat model