Skip to content

Commit c16ca06

Browse files
committed
Initial commit
0 parents  commit c16ca06

File tree

7 files changed

+3005
-0
lines changed

7 files changed

+3005
-0
lines changed

.github/workflows/release.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
release:
9+
types: [published]
10+
workflow_dispatch:
11+
12+
jobs:
13+
build:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Install Zig 0.15.2
21+
run: |
22+
curl -L "https://ziglang.org/download/0.15.2/zig-x86_64-linux-0.15.2.tar.xz" -o zig.tar.xz
23+
tar -xf zig.tar.xz
24+
echo "$PWD/zig-x86_64-linux-0.15.2" >> "$GITHUB_PATH"
25+
zig version
26+
27+
- name: Install Cosmocc 4.0.2
28+
run: |
29+
curl -L "https://cosmo.zip/pub/cosmocc/cosmocc-4.0.2.zip" -o cosmocc.zip
30+
unzip -q cosmocc.zip
31+
echo "$PWD/cosmocc/bin" >> "$GITHUB_PATH"
32+
cosmocc --version || true
33+
34+
- name: Build matrix binaries (including cosmo)
35+
run: zig build matrix -Doptimize=ReleaseFast
36+
37+
- name: Pack per-target archives
38+
run: |
39+
mkdir -p dist
40+
41+
pack() {
42+
local src_file="$1"
43+
local archive_name="$2"
44+
tar -C "$(dirname "$src_file")" -czf "dist/${archive_name}.tar.gz" "$(basename "$src_file")"
45+
}
46+
47+
pack "release/bin/webdav_linux_x86_64" "webdav_x86_64-linux-musl"
48+
pack "release/bin/webdav_linux_x86" "webdav_x86-linux-musl"
49+
pack "release/bin/webdav_linux_armv6" "webdav_arm-linux-musleabihf-arm1176jzf_s"
50+
pack "release/bin/webdav_linux_armv7" "webdav_arm-linux-musleabihf-cortex_a7"
51+
pack "release/bin/webdav_linux_arm64" "webdav_aarch64-linux-musl"
52+
pack "release/bin/webdav_linux_riscv64" "webdav_riscv64-linux-musl"
53+
pack "release/bin/webdav_linux_mips" "webdav_mips-linux-musleabi"
54+
pack "release/bin/webdav_linux_mipsel" "webdav_mipsel-linux-musleabi"
55+
pack "release/bin/webdav_linux_mips_hf" "webdav_mips-linux-musleabihf"
56+
pack "release/bin/webdav_linux_mipsel_hf" "webdav_mipsel-linux-musleabihf"
57+
pack "release/bin/webdav_linux_mips64" "webdav_mips64-linux-muslabi64"
58+
pack "release/bin/webdav_linux_mips64el" "webdav_mips64el-linux-muslabi64"
59+
pack "release/bin/webdav_linux_mips64n32" "webdav_mips64-linux-muslabin32"
60+
pack "release/bin/webdav_linux_mips64eln32" "webdav_mips64el-linux-muslabin32"
61+
pack "release/bin/webdav_macos_x86_64" "webdav_x86_64-macos"
62+
pack "release/bin/webdav_macos_arm64" "webdav_aarch64-macos"
63+
pack "release/bin/webdav_windows_x86.exe" "webdav_x86-windows-gnu"
64+
pack "release/bin/webdav_windows_amd64.exe" "webdav_x86_64-windows-gnu"
65+
pack "release/bin/webdav_windows_arm64.exe" "webdav_aarch64-windows-gnu"
66+
pack "release/bin/webdav_freebsd_x86_64" "webdav_x86_64-freebsd"
67+
pack "release/bin/webdav_freebsd_arm64" "webdav_aarch64-freebsd"
68+
pack "release/bin/webdav_x86_64-unknown-cosmo.com" "webdav_x86_64-unknown-cosmo"
69+
70+
- name: Upload workflow artifact
71+
uses: actions/upload-artifact@v4
72+
with:
73+
name: webdav-target-archives-${{ github.sha }}
74+
path: dist/*.tar.gz
75+
if-no-files-found: error
76+
77+
- name: Publish artifact in GitHub Release
78+
if: github.event_name == 'release'
79+
uses: softprops/action-gh-release@v2
80+
with:
81+
files: dist/*.tar.gz
82+
env:
83+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.zig-cache/
2+
zig-out/
3+
release/

README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# WebDAV Server
2+
3+
Servidor WebDAV em C++ com foco em portabilidade, compilado com Zig Build e Cosmopolitan.
4+
5+
## Recursos
6+
7+
- Servidor HTTP/WebDAV com operações comuns (`GET`, `PUT`, `DELETE`, `MKCOL`, `PROPFIND`, `MOVE`, `COPY`, `LOCK`, `UNLOCK`)
8+
- Interface de listagem de diretórios no navegador
9+
- Autenticação Basic opcional
10+
- Limite de taxa por IP
11+
- Build nativo e matriz de cross-compilation via `build.zig`
12+
13+
## Requisitos
14+
15+
- Zig 0.15.2
16+
- Cosmocc 4.0.2
17+
18+
Download usado neste projeto:
19+
20+
- `https://ziglang.org/download/0.15.2/zig-x86_64-linux-0.15.2.tar.xz`
21+
- `https://cosmo.zip/pub/cosmocc/cosmocc-4.0.2.zip`
22+
23+
## Build
24+
25+
Build nativo:
26+
27+
```bash
28+
zig build native -Doptimize=ReleaseFast
29+
```
30+
31+
Build da matriz completa de targets:
32+
33+
```bash
34+
zig build matrix -Doptimize=ReleaseFast
35+
```
36+
37+
Os binários são gerados em `release/bin`.
38+
39+
## Uso
40+
41+
```bash
42+
./release/bin/webdav -r . -p 8080
43+
```
44+
45+
Opções disponíveis:
46+
47+
- `-r <root>` diretório raiz (padrão: `.`)
48+
- `-p <porta>` porta do servidor (padrão: `8080`)
49+
- `-u <usuario>` usuário para Basic Auth
50+
- `-w <senha>` senha para Basic Auth
51+
- `-t <segundos>` timeout de conexão (padrão: `30`)
52+
- `-m <max_req>` máximo de requisições por minuto por IP (padrão: `1000`)
53+
- `-v` modo verboso
54+
- `-h` ajuda
55+
56+
Exemplo com autenticação:
57+
58+
```bash
59+
./release/bin/webdav -r /srv/webdav -p 8080 -u admin -w senhaforte -v
60+
```
61+
62+
## GitHub Actions
63+
64+
O workflow em `.github/workflows/release.yml`:
65+
66+
- baixa e instala Zig 0.15.2 diretamente da URL oficial
67+
- baixa e instala `cosmocc` 4.0.2
68+
- executa `zig build matrix` (inclui o build do `webdav_x86_64-unknown-cosmo.com` via `build.zig`)
69+
- compacta cada binário individualmente em `.tar.gz` com nome por triple/target (ex.: `webdav_x86_64-linux-musl.tar.gz`)
70+
- publica todos os `.tar.gz` no artifact do workflow
71+
- quando houver evento de release (`published`), publica todos os `.tar.gz` como assets da Release
72+
73+
## Interface
74+
75+
![Interface WebDAV](webdav.png)

build.zig

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
const std = @import("std");
2+
3+
const TargetSpec = struct {
4+
const CpuModelOverride = enum {
5+
arm1176jzf_s,
6+
cortex_a7,
7+
};
8+
9+
step_name: []const u8,
10+
out_name: []const u8,
11+
triple: []const u8,
12+
c_flags: []const []const u8,
13+
cpu_model: ?CpuModelOverride = null,
14+
windows: bool = false,
15+
};
16+
17+
fn resolveQuery(
18+
b: *std.Build,
19+
triple: []const u8,
20+
cpu_model: ?TargetSpec.CpuModelOverride,
21+
) std.Build.ResolvedTarget {
22+
var q = std.Target.Query.parse(.{ .arch_os_abi = triple }) catch |err| {
23+
std.debug.panic("invalid target triple '{s}': {s}", .{ triple, @errorName(err) });
24+
};
25+
if (cpu_model) |cpu| {
26+
q.cpu_model = switch (cpu) {
27+
.arm1176jzf_s => .{ .explicit = &std.Target.arm.cpu.arm1176jzf_s },
28+
.cortex_a7 => .{ .explicit = &std.Target.arm.cpu.cortex_a7 },
29+
};
30+
}
31+
return b.resolveTargetQuery(q);
32+
}
33+
34+
fn addWebdavExe(
35+
b: *std.Build,
36+
target: std.Build.ResolvedTarget,
37+
optimize: std.builtin.OptimizeMode,
38+
name: []const u8,
39+
c_flags: []const []const u8,
40+
is_windows: bool,
41+
) *std.Build.Step.Compile {
42+
const mod = b.createModule(.{
43+
.target = target,
44+
.optimize = optimize,
45+
.link_libc = true,
46+
.link_libcpp = true,
47+
});
48+
mod.addCSourceFile(.{
49+
.file = b.path("webdav.cpp"),
50+
.flags = c_flags,
51+
.language = .cpp,
52+
});
53+
54+
const exe = b.addExecutable(.{
55+
.name = name,
56+
.root_module = mod,
57+
});
58+
59+
if (is_windows) {
60+
exe.linkSystemLibrary("ws2_32");
61+
}
62+
63+
return exe;
64+
}
65+
66+
pub fn build(b: *std.Build) void {
67+
// Keep all installed artifacts in ./release instead of ./zig-out.
68+
b.resolveInstallPrefix("release", .{});
69+
70+
const optimize = b.option(
71+
std.builtin.OptimizeMode,
72+
"optimize",
73+
"Optimization mode (default: ReleaseFast)",
74+
) orelse .ReleaseFast;
75+
const keep_pdb = optimize == .Debug;
76+
const default_triple = b.option([]const u8, "default-triple", "Default triple for `zig build` and `zig build native`") orelse "x86_64-linux-musl";
77+
const default_target = resolveQuery(b, default_triple, null);
78+
79+
const base_flags = &.{
80+
"-std=c++17",
81+
"-Wall",
82+
"-Wextra",
83+
};
84+
85+
// Fast local build (current target)
86+
const native_exe = addWebdavExe(b, default_target, optimize, "webdav", base_flags, default_target.result.os.tag == .windows);
87+
const native_install = b.addInstallArtifact(native_exe, .{
88+
.pdb_dir = if (keep_pdb) .default else .disabled,
89+
});
90+
const native_step = b.step("native", "Build webdav for the selected/host target");
91+
native_step.dependOn(&native_install.step);
92+
93+
// Cross-build matrix
94+
const matrix_step = b.step("matrix", "Build the full cross-platform/cross-arch matrix");
95+
96+
// Cosmopolitan build via cosmoc++.
97+
const cosmo_out = b.getInstallPath(.bin, "webdav_x86_64-unknown-cosmo.com");
98+
const mkdir_release_bin = b.addSystemCommand(&.{ "mkdir", "-p", b.exe_dir });
99+
const cosmo_cmd = b.addSystemCommand(&.{
100+
"cosmoc++",
101+
"-O2",
102+
"-std=c++17",
103+
"-pthread",
104+
"-o",
105+
cosmo_out,
106+
"webdav.cpp",
107+
});
108+
cosmo_cmd.step.dependOn(&mkdir_release_bin.step);
109+
const cosmo_step = b.step("cosmo", "Build x86_64-unknown-cosmo with cosmoc++");
110+
if (optimize == .Debug) {
111+
cosmo_step.dependOn(&cosmo_cmd.step);
112+
} else {
113+
const cosmo_dbg = b.fmt("{s}.dbg", .{cosmo_out});
114+
const rm_cosmo_dbg = b.addSystemCommand(&.{ "rm", "-f", cosmo_dbg });
115+
rm_cosmo_dbg.step.dependOn(&cosmo_cmd.step);
116+
cosmo_step.dependOn(&rm_cosmo_dbg.step);
117+
}
118+
matrix_step.dependOn(cosmo_step);
119+
120+
const specs = [_]TargetSpec{
121+
.{ .step_name = "linux-x86_64", .out_name = "webdav_linux_x86_64", .triple = "x86_64-linux-musl", .c_flags = base_flags },
122+
.{ .step_name = "linux-x86", .out_name = "webdav_linux_x86", .triple = "x86-linux-musl", .c_flags = base_flags },
123+
.{ .step_name = "linux-armv6", .out_name = "webdav_linux_armv6", .triple = "arm-linux-musleabihf", .c_flags = base_flags, .cpu_model = .arm1176jzf_s },
124+
.{ .step_name = "linux-armv7", .out_name = "webdav_linux_armv7", .triple = "arm-linux-musleabihf", .c_flags = base_flags, .cpu_model = .cortex_a7 },
125+
.{ .step_name = "linux-armv8", .out_name = "webdav_linux_arm64", .triple = "aarch64-linux-musl", .c_flags = base_flags },
126+
.{ .step_name = "linux-riscv64", .out_name = "webdav_linux_riscv64", .triple = "riscv64-linux-musl", .c_flags = base_flags },
127+
.{ .step_name = "linux-mips", .out_name = "webdav_linux_mips", .triple = "mips-linux-musleabi", .c_flags = base_flags },
128+
.{ .step_name = "linux-mipsel", .out_name = "webdav_linux_mipsel", .triple = "mipsel-linux-musleabi", .c_flags = base_flags },
129+
.{ .step_name = "linux-mips-hf", .out_name = "webdav_linux_mips_hf", .triple = "mips-linux-musleabihf", .c_flags = base_flags },
130+
.{ .step_name = "linux-mipsel-hf", .out_name = "webdav_linux_mipsel_hf", .triple = "mipsel-linux-musleabihf", .c_flags = base_flags },
131+
.{ .step_name = "linux-mips64", .out_name = "webdav_linux_mips64", .triple = "mips64-linux-muslabi64", .c_flags = base_flags },
132+
.{ .step_name = "linux-mips64el", .out_name = "webdav_linux_mips64el", .triple = "mips64el-linux-muslabi64", .c_flags = base_flags },
133+
.{ .step_name = "linux-mips64n32", .out_name = "webdav_linux_mips64n32", .triple = "mips64-linux-muslabin32", .c_flags = base_flags },
134+
.{ .step_name = "linux-mips64eln32", .out_name = "webdav_linux_mips64eln32", .triple = "mips64el-linux-muslabin32", .c_flags = base_flags },
135+
.{ .step_name = "macos-x86_64", .out_name = "webdav_macos_x86_64", .triple = "x86_64-macos", .c_flags = base_flags },
136+
.{ .step_name = "macos-arm64", .out_name = "webdav_macos_arm64", .triple = "aarch64-macos", .c_flags = base_flags },
137+
.{ .step_name = "windows-x86", .out_name = "webdav_windows_x86.exe", .triple = "x86-windows-gnu", .c_flags = base_flags, .windows = true },
138+
.{ .step_name = "windows-amd64", .out_name = "webdav_windows_amd64.exe", .triple = "x86_64-windows-gnu", .c_flags = base_flags, .windows = true },
139+
.{ .step_name = "windows-arm64", .out_name = "webdav_windows_arm64.exe", .triple = "aarch64-windows-gnu", .c_flags = base_flags, .windows = true },
140+
.{ .step_name = "freebsd-x86_64", .out_name = "webdav_freebsd_x86_64", .triple = "x86_64-freebsd", .c_flags = base_flags },
141+
.{ .step_name = "freebsd-arm64", .out_name = "webdav_freebsd_arm64", .triple = "aarch64-freebsd", .c_flags = base_flags },
142+
};
143+
144+
inline for (specs) |spec| {
145+
const resolved = resolveQuery(b, spec.triple, spec.cpu_model);
146+
const exe = addWebdavExe(b, resolved, optimize, spec.step_name, spec.c_flags, spec.windows);
147+
const install_artifact = b.addInstallArtifact(exe, .{
148+
.dest_sub_path = spec.out_name,
149+
.pdb_dir = if (keep_pdb) .default else .disabled,
150+
});
151+
152+
const per_target_step = b.step(spec.step_name, b.fmt("Build target {s}", .{spec.triple}));
153+
per_target_step.dependOn(&install_artifact.step);
154+
matrix_step.dependOn(&install_artifact.step);
155+
}
156+
157+
// Keep default `zig build` fast/local.
158+
b.default_step = native_step;
159+
}

0 commit comments

Comments
 (0)