defmodule Linx.MixProject do
use Mix.Project
@version "0.2.0"
@source_url "https://github.com/oshlabs/linx"
def project do
[
app: :linx,
version: @version,
elixir: "~> 1.18",
start_permanent: Mix.env() == :prod,
# Custom compilers for the project's native code, run as part of
# `mix compile`:
# * :netlink_nif -- the netlink_socket NIF (Linx.Netlink)
# * :linx_process -- the linx_process Port binary (Linx.Process)
# * :linx_tty -- the linx_tty NIF (Linx.Tty)
# * :linx_mount -- the linx_mount NIF (Linx.Mount)
# * :linx_sysctl -- the linx_sysctl NIF (Linx.Sysctl)
# See lib/mix/tasks/compile.*.ex.
compilers:
Mix.compilers() ++
[:netlink_nif, :linx_process, :linx_tty, :linx_mount, :linx_sysctl],
deps: deps(),
name: "Linx",
description:
"Linux kernel interface primitives for Elixir: netlink/rtnetlink/nf_tables, " <>
"process & namespace lifecycle, PTY, cgroup v2, mounts, user namespaces, " <>
"capabilities, seccomp, and sysctl.",
source_url: @source_url,
package: package(),
docs: docs()
]
end
defp package do
[
licenses: ["MIT"],
links: %{
"GitHub" => @source_url,
"Changelog" => "#{@source_url}/blob/main/CHANGELOG.md"
},
# Ship the C sources (c_src) so the NIF/Port custom compilers can build
# them on the consumer's machine. priv/ artifacts are built per-machine
# and never shipped; the docs/ extras are dev-time `mix docs` material,
# omitted to keep the package lean.
files: ~w(lib c_src mix.exs README.md LICENSE),
maintainers: ["Leon de Rooij"]
]
end
def application do
[extra_applications: [:logger]]
end
defp deps do
[
{:ex_doc, "~> 0.34", only: :dev, runtime: false},
{:stream_data, "~> 1.0", only: :test, runtime: false}
]
end
# Injects mermaid.js so ```mermaid code blocks in the docs render as diagrams.
defp mermaid_script(:html) do
"""
<script type="module">
import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";
mermaid.initialize({startOnLoad: false});
let id = 0;
let rendering = false;
async function renderMermaid() {
if (rendering) return;
const blocks = document.querySelectorAll("pre code.mermaid");
if (blocks.length === 0) return;
rendering = true;
for (const code of blocks) {
const pre = code.parentElement;
const graph = code.textContent;
const {svg, bindFunctions} = await mermaid.render("mermaid-graph-" + id++, graph);
const div = document.createElement("div");
div.className = "mermaid";
div.innerHTML = svg;
if (bindFunctions) bindFunctions(div);
pre.replaceWith(div);
}
rendering = false;
}
// ex_doc navigates client-side (fetch + innerHTML swap + pushState), so the
// one-shot render only covers the first full load. Re-render after each
// content swap; renderMermaid() is a cheap no-op when nothing is pending.
renderMermaid();
new MutationObserver(renderMermaid).observe(document.body, {childList: true, subtree: true});
</script>
"""
end
defp mermaid_script(_), do: ""
defp docs do
[
main: "readme",
# Generated HTML lands under _build/, alongside other build artefacts,
# so the top-level `doc/` slot stays free for the `docs/` source tree.
output: "_build/docs",
# Render ```mermaid fenced blocks as diagrams (GitHub does this natively;
# ex_doc needs this script injected).
before_closing_body_tag: &mermaid_script/1,
extras: [
"README.md",
"CHANGELOG.md",
"docs/netlink/netlink-overview.md",
"docs/netlink/netlink-examples.md",
"docs/netlink/netlink-references.md",
"docs/process/process-overview.md",
"docs/process/process-examples.md",
"docs/process/process-references.md",
"docs/tty/tty-overview.md",
"docs/tty/tty-examples.md",
"docs/tty/tty-references.md",
"docs/cgroup/cgroup-overview.md",
"docs/cgroup/cgroup-examples.md",
"docs/cgroup/cgroup-references.md",
"docs/mount/mount-overview.md",
"docs/mount/mount-examples.md",
"docs/mount/mount-references.md",
"docs/user/user-overview.md",
"docs/user/user-examples.md",
"docs/user/user-references.md",
"docs/capabilities/capabilities-overview.md",
"docs/capabilities/capabilities-examples.md",
"docs/capabilities/capabilities-references.md",
"docs/seccomp/seccomp-overview.md",
"docs/seccomp/seccomp-examples.md",
"docs/seccomp/seccomp-references.md",
"docs/sysctl/sysctl-overview.md",
"docs/sysctl/sysctl-examples.md",
"docs/sysctl/sysctl-references.md",
"docs/netfilter/netfilter-overview.md",
"docs/netfilter/netfilter-examples.md",
"docs/netfilter/netfilter-references.md",
"docs/reconcile/reconcile-overview.md",
"docs/reconcile/reconcile-examples.md",
{:LICENSE, [title: "License"]}
],
source_ref: "v#{@version}",
# Per-subsystem pages, each a unique basename (ex_doc resolves cross-doc
# links by basename): <sub>-overview (the group landing), <sub>-examples
# (recipes), and <sub>-references (citations).
groups_for_extras: [
Netlink: [
"docs/netlink/netlink-overview.md",
"docs/netlink/netlink-examples.md",
"docs/netlink/netlink-references.md"
],
Process: [
"docs/process/process-overview.md",
"docs/process/process-examples.md",
"docs/process/process-references.md"
],
Tty: [
"docs/tty/tty-overview.md",
"docs/tty/tty-examples.md",
"docs/tty/tty-references.md"
],
Cgroup: [
"docs/cgroup/cgroup-overview.md",
"docs/cgroup/cgroup-examples.md",
"docs/cgroup/cgroup-references.md"
],
Mount: [
"docs/mount/mount-overview.md",
"docs/mount/mount-examples.md",
"docs/mount/mount-references.md"
],
User: [
"docs/user/user-overview.md",
"docs/user/user-examples.md",
"docs/user/user-references.md"
],
Capabilities: [
"docs/capabilities/capabilities-overview.md",
"docs/capabilities/capabilities-examples.md",
"docs/capabilities/capabilities-references.md"
],
Seccomp: [
"docs/seccomp/seccomp-overview.md",
"docs/seccomp/seccomp-examples.md",
"docs/seccomp/seccomp-references.md"
],
Sysctl: [
"docs/sysctl/sysctl-overview.md",
"docs/sysctl/sysctl-examples.md",
"docs/sysctl/sysctl-references.md"
],
Netfilter: [
"docs/netfilter/netfilter-overview.md",
"docs/netfilter/netfilter-examples.md",
"docs/netfilter/netfilter-references.md"
],
Reconcile: [
"docs/reconcile/reconcile-overview.md",
"docs/reconcile/reconcile-examples.md"
]
],
groups_for_modules: [
"Public types": [
Linx.IP,
Linx.IP.Subnet,
Linx.MAC
],
Process: [
Linx.Process,
Linx.Process.Error,
Linx.Process.Info
],
Tty: [
Linx.Tty,
Linx.Tty.Error,
Linx.Tty.Saved,
Linx.Tty.WindowSize,
Linx.Tty.Native
],
Cgroup: [
Linx.Cgroup,
Linx.Cgroup.Error,
Linx.Cgroup.Stats
],
Mount: [
Linx.Mount,
Linx.Mount.Entry,
Linx.Mount.Error,
Linx.Mount.Native
],
User: [
Linx.User,
Linx.User.Error,
Linx.User.Map
],
Capabilities: [
Linx.Capabilities,
Linx.Capabilities.Error,
Linx.Capabilities.State
],
Seccomp: [
Linx.Seccomp,
Linx.Seccomp.Builder,
Linx.Seccomp.Error,
Linx.Seccomp.Filter
],
Sysctl: [
Linx.Sysctl,
Linx.Sysctl.Entry,
Linx.Sysctl.Error,
Linx.Sysctl.Native
],
Netfilter: [
Linx.Netfilter,
Linx.Netfilter.Error,
Linx.Netfilter.Ruleset,
Linx.Netfilter.Table,
Linx.Netfilter.Chain,
Linx.Netfilter.Rule,
Linx.Netfilter.Expr,
Linx.Netfilter.Verdict,
Linx.Netfilter.Set,
Linx.Netfilter.Map,
Linx.Netfilter.Vmap,
Linx.Netfilter.Object,
Linx.Netfilter.Flowtable,
Linx.Netfilter.Patch,
Linx.Netfilter.Diff,
Linx.Netfilter.Event,
Linx.Netfilter.Monitor,
Linx.Netfilter.Log,
Linx.Netfilter.Log.Event,
Linx.Netfilter.Encoder,
Linx.Netfilter.Decoder,
Linx.Netfilter.Wire
],
"Netfilter — ~NFT sigil": [
Linx.NFT,
Linx.NFT.ParseError,
Linx.NFT.Tokenizer,
Linx.NFT.Parser,
Linx.NFT.Compiler,
Linx.NFT.RuntimeCompiler,
Linx.NFT.Runtime,
Linx.NFT.Formatter
],
"Netlink core": [
Linx.Netlink,
Linx.Netlink.Socket,
Linx.Netlink.Socket.Native,
Linx.Netlink.Attr,
Linx.Netlink.Message,
Linx.Netlink.Request,
Linx.Netlink.Constants,
Linx.Netlink.Codec,
Linx.Netlink.Error
],
nfnetlink: [
Linx.Netlink.Nfnl,
Linx.Netlink.Nfnl.Codec
],
rtnetlink: [
Linx.Netlink.Rtnl,
Linx.Netlink.Rtnl.Link,
Linx.Netlink.Rtnl.LinkInfo,
Linx.Netlink.Rtnl.LinkInfo.Macvlan,
Linx.Netlink.Rtnl.LinkInfo.Ipvlan,
Linx.Netlink.Rtnl.LinkInfo.Vlan,
Linx.Netlink.Rtnl.LinkInfo.Veth,
Linx.Netlink.Rtnl.Address,
Linx.Netlink.Rtnl.Route,
Linx.Netlink.Rtnl.Neighbour,
Linx.Netlink.Rtnl.Rule,
Linx.Netlink.Rtnl.Stats,
Linx.Netlink.Rtnl.Stats.Link64
]
]
]
end
end