diff --git a/.gitignore b/.gitignore index 9196945f3..d862df494 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,6 @@ yarn-error.log # Debugging/testing files rfc-8998.hpp + +.zig-cache/ +zig-out/ diff --git a/README-ZIG-CN.md b/README-ZIG-CN.md new file mode 100644 index 000000000..8a083861c --- /dev/null +++ b/README-ZIG-CN.md @@ -0,0 +1,338 @@ +# 使用 Zig 构建 Pipy + +本项目现在支持使用 Zig 作为 CMake 的替代构建系统。 + +## 前提条件 + +- Zig 0.13.0 或更高版本(已在 0.16.0-dev 上测试) +- C/C++ 编译器(用于构建依赖项) +- Git(用于版本信息) +- Perl(用于构建 OpenSSL) +- Node.js(仅在使用 `-Dgui=true` 构建时需要,用于打包 GUI 和 codebases) + +## 构建步骤 + +### macOS 快速开始(推荐) + +在 macOS 上,推荐使用系统库进行构建: + +```bash +# 1. 安装 Homebrew OpenSSL(如果尚未安装) +brew install openssl@3 + +# 2. 配置 yajl(首次构建必需) +cd deps/yajl-2.1.0 && ./configure && cd ../.. + +# 3. 构建 Pipy(使用系统库,禁用 BPF,优化模式) +# 使用 -Doptimize=ReleaseFast 进行生产构建(二进制文件更小:~15MB vs ~167MB) +zig build -Doptimize=ReleaseFast -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true + +# 4. 运行 +./zig-out/bin/pipy --version +``` + +**注意**:macOS 不支持 eBPF,必须使用 `-Dbpf=false` 参数。 + +### Linux 快速开始 + +在 Linux 上可以选择使用捆绑的 OpenSSL 或系统库: + +```bash +# 选项 1: 使用捆绑的 OpenSSL(推荐用于生产环境) +./build-openssl.sh +zig build -Doptimize=ReleaseFast + +# 选项 2: 使用系统 OpenSSL(推荐用于生产环境) +zig build -Doptimize=ReleaseFast -Duse-system-zlib=true -Duse-system-openssl=true +``` + +### 详细构建步骤 + +#### 1. 构建 OpenSSL(使用捆绑版本时需要) + +如果不使用 `-Duse-system-openssl=true`,需要先构建捆绑的 OpenSSL: + +```bash +./build-openssl.sh +``` + +#### 2. 配置依赖库(首次构建) + +```bash +# 配置 yajl(生成必要的头文件) +cd deps/yajl-2.1.0 && ./configure && cd ../.. +``` + +#### 3. 构建 Pipy + +**基本构建(Debug 模式,用于开发):** + +```bash +# Debug 构建:较大的二进制文件(~167MB),包含调试符号 +zig build -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +**优化构建(生产环境):** + +```bash +# Release 构建:较小的二进制文件(~15MB),速度优化 +zig build -Doptimize=ReleaseFast -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +**启用 GUI 和内置 codebases:** + +```bash +# 注意:GUI 选项会自动包含内置 codebases(tutorial 和 samples) +# 需要安装 Node.js 来打包 GUI 和 codebases +# 优化模式下:~29MB(相比 Debug 模式的 ~180MB) +zig build -Doptimize=ReleaseFast -Dgui=true -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +**构建为共享库:** + +```bash +zig build -Doptimize=ReleaseFast -Dshared=true -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +**构建为静态库:** + +```bash +zig build -Doptimize=ReleaseFast -Dstatic-lib=true -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +### 3. 运行 Pipy + +```bash +zig build run +``` + +或带参数运行: + +```bash +zig build run -- --help +``` + +## 构建选项 + +- `-Doptimize=` - 构建优化模式(默认:Debug) + - `Debug` - 无优化,包含调试符号(基础版 ~167MB,带 GUI ~180MB) + - `ReleaseSafe` - 优化并保留安全检查 + - `ReleaseFast` - 最大速度优化(基础版 ~15MB,带 GUI ~29MB)**推荐用于生产环境** + - `ReleaseSmall` - 体积优化 +- `-Dshared=` - 构建为共享库(默认:false) +- `-Dstatic-lib=` - 构建为静态库(默认:false) +- `-Dgui=` - 包含内置 GUI 和 codebases(tutorial/samples)(默认:false,需要 Node.js) +- `-Dbpf=` - 启用 eBPF 支持(默认:true,macOS 不支持) +- `-Duse-system-zlib=` - 使用系统 zlib 而不是捆绑版本(默认:false) +- `-Duse-system-openssl=` - 使用系统 OpenSSL 而不是捆绑版本(默认:false) + +## 输出目录 + +构建产物放置在 `zig-out/` 目录中: + +- 可执行文件:`zig-out/bin/pipy` +- 库文件:`zig-out/lib/` + +### 文件大小对比 + +| 构建配置 | 二进制文件大小 | 说明 | +|---------|--------------|------| +| Debug 模式(基础) | ~167MB | 包含调试符号,用于开发 | +| Debug 模式 + GUI | ~180MB | 包含调试符号 + GUI + codebases | +| ReleaseFast(基础) | ~15MB | 优化后,推荐生产环境 | +| ReleaseFast + GUI | ~29MB | 优化后 + GUI + codebases | + +**优化效果:使用 ReleaseFast 可以将文件大小减少约 91%!** + +## 清理 + +清理构建产物: + +```bash +rm -rf zig-out .zig-cache +``` + +完全清理(包括 OpenSSL): + +```bash +rm -rf zig-out .zig-cache deps/openssl-3.2.0/build +``` + +## 使用 Makefile 包装器 + +为了方便使用,我们提供了一个 Makefile 包装器: + +```bash +# 使用 Makefile.zig +make -f Makefile.zig help # 显示帮助信息 +make -f Makefile.zig build # 构建 Pipy +make -f Makefile.zig release # 发布构建 +make -f Makefile.zig clean # 清理构建产物 +make -f Makefile.zig install # 安装到 /usr/local/bin +``` + +## 与 CMake 的比较 + +### Zig 构建系统的优势: + +1. **单一工具**:无需 CMake、Make、Ninja 等多个工具 +2. **交叉编译**:轻松交叉编译到不同目标平台 +3. **可重现构建**:跨平台一致的构建结果 +4. **快速增量构建**:高效的缓存系统 +5. **更简单的语法**:更易读的构建配置 +6. **内置包管理器**:轻松管理依赖项 + +### 迁移说明: + +- Zig 构建系统产生与 CMake 相同的输出 +- 所有 CMake 构建选项都有对应的 Zig 等价选项 +- OpenSSL 仍然需要外部构建(与 CMake 相同) +- 版本信息生成方式相同 + +## 故障排除 + +### macOS: elf.h 找不到 + +**错误信息**:`error: 'elf.h' file not found` + +**解决方案**:macOS 不支持 eBPF,需要禁用 BPF 支持: +```bash +zig build -Dbpf=false -Duse-system-zlib=true -Duse-system-openssl=true +``` + +### macOS: OpenSSL 找不到 + +**错误信息**:`unable to find dynamic system library 'ssl'` + +**解决方案**:安装 Homebrew OpenSSL: +```bash +brew install openssl@3 +``` + +然后使用 `-Duse-system-openssl=true` 构建。 + +### yajl 头文件缺失 + +**错误信息**:`'yajl/yajl_version.h' file not found` + +**解决方案**:运行 yajl 配置脚本: +```bash +cd deps/yajl-2.1.0 && ./configure && cd ../.. +``` + +### libyaml 版本宏未定义 + +**错误信息**:`use of undeclared identifier 'YAML_VERSION_STRING'` + +**解决方案**:这已在 build.zig 中自动处理,确保使用最新版本的构建脚本。 + +### zlib 类型冲突 + +**错误信息**:`conflicting types for 'crc32_combine64'` + +**解决方案**:使用系统 zlib 代替捆绑版本: +```bash +zig build -Duse-system-zlib=true +``` + +### OpenSSL 构建失败 + +确保已安装 Perl: + +```bash +# macOS +brew install perl + +# Ubuntu/Debian +sudo apt-get install perl + +# CentOS/RHEL +sudo yum install perl +``` + +### 缺少依赖项 + +如果遇到缺少系统库的问题: + +```bash +# macOS +brew install openssl@3 + +# Ubuntu/Debian +sudo apt-get install libssl-dev zlib1g-dev + +# CentOS/RHEL +sudo yum install openssl-devel zlib-devel +``` + +### Zig 版本问题 + +检查 Zig 版本: + +```bash +zig version +``` + +如需要,更新 Zig:https://ziglang.org/download/ + +## 项目结构 + +``` +pipy/ +├── build.zig # Zig 构建脚本(替代 CMakeLists.txt) +├── build.zig.zon # Zig 包配置文件 +├── build-openssl.sh # OpenSSL 构建辅助脚本 +├── Makefile.zig # Makefile 包装器 +├── README-ZIG.md # 英文文档 +├── README-ZIG-CN.md # 中文文档(本文件) +├── src/ # 源代码 +├── deps/ # 依赖库 +└── zig-out/ # 构建输出目录 +``` + +## 构建时间对比 + +使用 Zig 构建系统相比 CMake 的优势: + +- **首次构建**:相似或略快 +- **增量构建**:明显更快(得益于 Zig 的缓存系统) +- **清理构建**:更快(更好的并行化) + +## 常见问题 + +### 1. Zig 构建系统支持所有 CMake 选项吗? + +是的,所有主要的 CMake 选项都已在 Zig 构建系统中实现。 + +### 2. 可以同时保留 CMake 和 Zig 构建系统吗? + +可以,两个构建系统可以共存。`build.zig` 不会影响现有的 CMake 配置。 + +### 3. 如何在 CI/CD 中使用 Zig 构建? + +只需将 CMake 命令替换为 `zig build` 命令即可。例如: + +```bash +# 以前使用 CMake +mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Release +make -j$(nproc) + +# 现在使用 Zig +./build-openssl.sh +zig build -Doptimize=ReleaseFast +``` + +### 4. Zig 构建是否支持 Windows? + +是的,Zig 构建系统支持 Windows、macOS 和 Linux。 + +## 更多信息 + +- Zig 官方文档:https://ziglang.org/documentation/master/ +- Zig 构建系统指南:https://ziglang.org/learn/build-system/ +- Pipy 主文档:见 README.md + +## 贡献 + +如果您在使用 Zig 构建系统时遇到问题,或有改进建议,欢迎提交 Issue 或 Pull Request。 diff --git a/README-ZIG.md b/README-ZIG.md new file mode 100644 index 000000000..ee4b42b35 --- /dev/null +++ b/README-ZIG.md @@ -0,0 +1,261 @@ +# Building Pipy with Zig + +This project now supports building with Zig as an alternative to CMake. + +## Prerequisites + +- Zig 0.13.0 or later +- A C/C++ compiler (for building dependencies) +- Git (for version information) +- Perl (for building OpenSSL) +- Node.js (required only when building with `-Dgui=true` for packing GUI and codebases) + +## Building + +### macOS Quick Start (Recommended) + +On macOS, it's recommended to use system libraries: + +```bash +# 1. Install Homebrew OpenSSL (if not already installed) +brew install openssl@3 + +# 2. Configure yajl (required for first build) +cd deps/yajl-2.1.0 && ./configure && cd ../.. + +# 3. Build Pipy (using system libraries, BPF disabled, optimized) +# Use -Doptimize=ReleaseFast for production builds (much smaller binary: ~15MB vs ~167MB) +zig build -Doptimize=ReleaseFast -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true + +# 4. Run +./zig-out/bin/pipy --version +``` + +**Note**: macOS doesn't support eBPF, so you must use `-Dbpf=false`. + +### Linux Quick Start + +On Linux, you can choose between bundled OpenSSL or system libraries: + +```bash +# Option 1: Use bundled OpenSSL (recommended for production) +./build-openssl.sh +zig build -Doptimize=ReleaseFast + +# Option 2: Use system OpenSSL (recommended for production) +zig build -Doptimize=ReleaseFast -Duse-system-zlib=true -Duse-system-openssl=true +``` + +### Detailed Build Steps + +#### 1. Build OpenSSL (when using bundled version) + +If not using `-Duse-system-openssl=true`, build the bundled OpenSSL first: + +```bash +./build-openssl.sh +``` + +#### 2. Configure Dependencies (first-time build) + +```bash +# Configure yajl (generates necessary headers) +cd deps/yajl-2.1.0 && ./configure && cd ../.. +``` + +#### 3. Build Pipy + +**Basic build (Debug mode, for development):** + +```bash +# Debug build: large binary (~167MB), includes debug symbols +zig build -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +**Optimized build (Production):** + +```bash +# Release build: small binary (~15MB), optimized for speed +zig build -Doptimize=ReleaseFast -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +**Build with GUI and builtin codebases:** + +```bash +# Note: GUI option automatically includes builtin codebases (tutorial and samples) +# Requires Node.js to be installed for packing GUI and codebases +# With optimization: ~29MB (vs ~180MB in Debug mode) +zig build -Doptimize=ReleaseFast -Dgui=true -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +**Build as a shared library:** + +```bash +zig build -Doptimize=ReleaseFast -Dshared=true -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +**Build as a static library:** + +```bash +zig build -Doptimize=ReleaseFast -Dstatic-lib=true -Duse-system-zlib=true -Dbpf=false -Duse-system-openssl=true +``` + +### 3. Run Pipy + +```bash +zig build run +``` + +Or run with arguments: + +```bash +zig build run -- --help +``` + +## Build Options + +- `-Doptimize=` - Build optimization mode (default: Debug) + - `Debug` - No optimization, includes debug symbols (~167MB for base, ~180MB with GUI) + - `ReleaseSafe` - Optimized with safety checks + - `ReleaseFast` - Maximum optimization for speed (~15MB for base, ~29MB with GUI) **Recommended for production** + - `ReleaseSmall` - Optimized for size +- `-Dshared=` - Build Pipy as a shared library (default: false) +- `-Dstatic-lib=` - Build Pipy as a static library (default: false) +- `-Dgui=` - Include builtin GUI and codebases (tutorial/samples) (default: false, requires Node.js) +- `-Dbpf=` - Enable eBPF support (default: true, not supported on macOS) +- `-Duse-system-zlib=` - Use system zlib instead of bundled (default: false) +- `-Duse-system-openssl=` - Use system OpenSSL instead of bundled (default: false) + +## Output + +Built artifacts are placed in `zig-out/`: + +- Executable: `zig-out/bin/pipy` +- Libraries: `zig-out/lib/` + +### Binary Size Comparison + +| Build Configuration | Binary Size | Notes | +|---------------------|-------------|-------| +| Debug (base) | ~167MB | Includes debug symbols, for development | +| Debug + GUI | ~180MB | Debug symbols + GUI + codebases | +| ReleaseFast (base) | ~15MB | Optimized, recommended for production | +| ReleaseFast + GUI | ~29MB | Optimized + GUI + codebases | + +**Optimization Impact: ReleaseFast reduces binary size by approximately 91%!** + +## Cleaning + +To clean build artifacts: + +```bash +rm -rf zig-out .zig-cache +``` + +## Comparison with CMake + +### Advantages of Zig build system: + +1. **Single tool**: No need for CMake, Make, Ninja, etc. +2. **Cross-compilation**: Easy cross-compilation to different targets +3. **Reproducible builds**: Consistent builds across platforms +4. **Fast incremental builds**: Efficient caching system +5. **Simpler syntax**: More readable build configuration +6. **Built-in package manager**: Easy dependency management + +### Migration notes: + +- The Zig build system produces the same output as CMake +- All CMake build options have Zig equivalents +- OpenSSL still requires external build (same as CMake) +- Version information is generated the same way + +## Troubleshooting + +### macOS: elf.h not found + +**Error**: `error: 'elf.h' file not found` + +**Solution**: macOS doesn't support eBPF, disable BPF support: +```bash +zig build -Dbpf=false -Duse-system-zlib=true -Duse-system-openssl=true +``` + +### macOS: OpenSSL not found + +**Error**: `unable to find dynamic system library 'ssl'` + +**Solution**: Install Homebrew OpenSSL: +```bash +brew install openssl@3 +``` + +Then build with `-Duse-system-openssl=true`. + +### yajl headers missing + +**Error**: `'yajl/yajl_version.h' file not found` + +**Solution**: Run the yajl configure script: +```bash +cd deps/yajl-2.1.0 && ./configure && cd ../.. +``` + +### libyaml version macros undefined + +**Error**: `use of undeclared identifier 'YAML_VERSION_STRING'` + +**Solution**: This is automatically handled in build.zig, ensure you're using the latest build script. + +### zlib type conflicts + +**Error**: `conflicting types for 'crc32_combine64'` + +**Solution**: Use system zlib instead of bundled version: +```bash +zig build -Duse-system-zlib=true +``` + +### OpenSSL build fails + +Make sure you have Perl installed: +```bash +# macOS +brew install perl + +# Ubuntu/Debian +sudo apt-get install perl + +# CentOS/RHEL +sudo yum install perl +``` + +### Missing dependencies + +If you encounter missing system libraries: + +```bash +# macOS +brew install openssl@3 + +# Ubuntu/Debian +sudo apt-get install libssl-dev zlib1g-dev + +# CentOS/RHEL +sudo yum install openssl-devel zlib-devel +``` + +### Zig version issues + +Check your Zig version: +```bash +zig version +``` + +Update Zig if needed: https://ziglang.org/download/ + +## Further Information + +- Zig documentation: https://ziglang.org/documentation/master/ +- Zig build system guide: https://ziglang.org/learn/build-system/ +- Pipy documentation: See main README.md diff --git a/build-openssl.sh b/build-openssl.sh new file mode 100755 index 000000000..ce5cf5fef --- /dev/null +++ b/build-openssl.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Helper script to build OpenSSL for Zig build system +# + +set -e + +OPENSSL_SRC_DIR="deps/openssl-3.2.0" +OPENSSL_BUILD_DIR="$OPENSSL_SRC_DIR/build" + +if [ ! -d "$OPENSSL_SRC_DIR" ]; then + echo "Error: OpenSSL source directory not found: $OPENSSL_SRC_DIR" + exit 1 +fi + +echo "Building OpenSSL..." + +# Create build directory +mkdir -p "$OPENSSL_BUILD_DIR" + +# Configure and build OpenSSL +cd "$OPENSSL_BUILD_DIR" + +if [ ! -f "Makefile" ]; then + echo "Configuring OpenSSL..." + ../config no-shared no-tests +fi + +echo "Compiling OpenSSL..." +make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2) + +echo "OpenSSL build completed successfully!" +echo "Libraries are in: $OPENSSL_BUILD_DIR" diff --git a/build.zig b/build.zig new file mode 100644 index 000000000..fbd1ada25 --- /dev/null +++ b/build.zig @@ -0,0 +1,588 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + // Build options + const static_lib = b.option(bool, "static-lib", "Build Pipy as static library") orelse false; + const shared_lib = b.option(bool, "shared", "Build Pipy as dynamic library") orelse false; + const enable_gui = b.option(bool, "gui", "Include builtin GUI and codebases") orelse false; + const enable_bpf = b.option(bool, "bpf", "Enable eBPF support") orelse true; + const use_system_zlib = b.option(bool, "use-system-zlib", "Use system installed zlib") orelse false; + const use_system_openssl = b.option(bool, "use-system-openssl", "Use system installed OpenSSL") orelse false; + + // Generate version.h + const gen_version = b.addSystemCommand(&[_][]const u8{ + "sh", + "generate_version_h.sh", + "zig-out/version.h", + }); + + // Generate GUI and Codebases tarballs if GUI is enabled + var gen_gui: ?*std.Build.Step.Run = null; + var gen_codebases: ?*std.Build.Step.Run = null; + if (enable_gui) { + // Create deps directory in zig-out + const mkdir_deps = b.addSystemCommand(&[_][]const u8{ + "mkdir", + "-p", + "zig-out/deps", + }); + + // Generate gui.tar.h + gen_gui = b.addSystemCommand(&[_][]const u8{ + "node", + "gui/pack-gui.js", + "zig-out/deps/gui.tar.h", + }); + gen_gui.?.step.dependOn(&mkdir_deps.step); + + // Generate codebases.tar.gz.h + gen_codebases = b.addSystemCommand(&[_][]const u8{ + "node", + "gui/pack-codebases.js", + "zig-out/deps/codebases.tar.gz.h", + }); + gen_codebases.?.step.dependOn(&mkdir_deps.step); + } + + // Helper function to create C library modules + const createEmptyModule = struct { + fn create(builder: *std.Build, tgt: std.Build.ResolvedTarget, opt: std.builtin.OptimizeMode) *std.Build.Module { + return builder.createModule(.{ + .root_source_file = null, + .target = tgt, + .optimize = opt, + }); + } + }.create; + + // ==================== Build Dependencies ==================== + + // Build yajl (JSON parser) + const yajl = b.addLibrary(.{ + .name = "yajl", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }); + yajl.linkLibC(); + yajl.addIncludePath(b.path("deps/yajl-2.1.0/src")); + yajl.addIncludePath(b.path("deps/yajl-2.1.0/build/yajl-2.1.0/include")); + yajl.addCSourceFiles(.{ + .files = &[_][]const u8{ + "deps/yajl-2.1.0/src/yajl.c", + "deps/yajl-2.1.0/src/yajl_alloc.c", + "deps/yajl-2.1.0/src/yajl_buf.c", + "deps/yajl-2.1.0/src/yajl_encode.c", + "deps/yajl-2.1.0/src/yajl_gen.c", + "deps/yajl-2.1.0/src/yajl_lex.c", + "deps/yajl-2.1.0/src/yajl_parser.c", + "deps/yajl-2.1.0/src/yajl_tree.c", + "deps/yajl-2.1.0/src/yajl_version.c", + }, + .flags = &[_][]const u8{ + "-Wall", + "-Wextra", + "-std=c99", + }, + }); + + // Build libyaml + const yaml = b.addLibrary(.{ + .name = "yaml", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }); + yaml.linkLibC(); + yaml.addIncludePath(b.path("deps/libyaml-0.2.5/include")); + yaml.addIncludePath(b.path("deps/libyaml-0.2.5/src")); + yaml.addIncludePath(b.path("deps/libyaml-0.2.5/build/include")); + yaml.addCSourceFiles(.{ + .files = &[_][]const u8{ + "deps/libyaml-0.2.5/src/api.c", + "deps/libyaml-0.2.5/src/dumper.c", + "deps/libyaml-0.2.5/src/emitter.c", + "deps/libyaml-0.2.5/src/loader.c", + "deps/libyaml-0.2.5/src/parser.c", + "deps/libyaml-0.2.5/src/reader.c", + "deps/libyaml-0.2.5/src/scanner.c", + "deps/libyaml-0.2.5/src/writer.c", + }, + .flags = &[_][]const u8{ "-Wall", "-DHAVE_CONFIG_H=1" }, + }); + + // Build libexpat + const expat = b.addLibrary(.{ + .name = "expat", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }); + expat.linkLibC(); + expat.addIncludePath(b.path("deps/libexpat-R_2_2_6/expat/lib")); + expat.addCSourceFiles(.{ + .files = &[_][]const u8{ + "deps/libexpat-R_2_2_6/expat/lib/xmlparse.c", + "deps/libexpat-R_2_2_6/expat/lib/xmlrole.c", + "deps/libexpat-R_2_2_6/expat/lib/xmltok.c", + }, + .flags = &[_][]const u8{ "-Wall", "-DXML_STATIC=1", "-DHAVE_MEMMOVE=1", "-DHAVE_ARC4RANDOM_BUF=1" }, + }); + + // Build zlib + var zlib: ?*std.Build.Step.Compile = null; + if (!use_system_zlib) { + zlib = b.addLibrary(.{ + .name = "z", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }); + zlib.?.linkLibC(); + zlib.?.addIncludePath(b.path("deps/zlib-1.3.1")); + zlib.?.addCSourceFiles(.{ + .files = &[_][]const u8{ + "deps/zlib-1.3.1/adler32.c", + "deps/zlib-1.3.1/compress.c", + "deps/zlib-1.3.1/crc32.c", + "deps/zlib-1.3.1/deflate.c", + "deps/zlib-1.3.1/gzclose.c", + "deps/zlib-1.3.1/gzlib.c", + "deps/zlib-1.3.1/gzread.c", + "deps/zlib-1.3.1/gzwrite.c", + "deps/zlib-1.3.1/inflate.c", + "deps/zlib-1.3.1/infback.c", + "deps/zlib-1.3.1/inftrees.c", + "deps/zlib-1.3.1/inffast.c", + "deps/zlib-1.3.1/trees.c", + "deps/zlib-1.3.1/uncompr.c", + "deps/zlib-1.3.1/zutil.c", + }, + .flags = &[_][]const u8{ "-Wall", "-D_LARGEFILE64_SOURCE=1", "-D_FILE_OFFSET_BITS=64" }, + }); + } + + // Build brotli + const brotli_common = b.addLibrary(.{ + .name = "brotlicommon", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }); + brotli_common.linkLibC(); + brotli_common.addIncludePath(b.path("deps/brotli-1.0.9/c/include")); + brotli_common.addCSourceFiles(.{ + .files = &[_][]const u8{ + "deps/brotli-1.0.9/c/common/constants.c", + "deps/brotli-1.0.9/c/common/context.c", + "deps/brotli-1.0.9/c/common/dictionary.c", + "deps/brotli-1.0.9/c/common/platform.c", + "deps/brotli-1.0.9/c/common/transform.c", + }, + .flags = &[_][]const u8{"-Wall"}, + }); + + const brotli_dec = b.addLibrary(.{ + .name = "brotlidec", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }); + brotli_dec.linkLibC(); + brotli_dec.addIncludePath(b.path("deps/brotli-1.0.9/c/include")); + brotli_dec.addCSourceFiles(.{ + .files = &[_][]const u8{ + "deps/brotli-1.0.9/c/dec/bit_reader.c", + "deps/brotli-1.0.9/c/dec/decode.c", + "deps/brotli-1.0.9/c/dec/huffman.c", + "deps/brotli-1.0.9/c/dec/state.c", + }, + .flags = &[_][]const u8{ "-Wall", "-DBROTLI_BUILD_PORTABLE" }, + }); + brotli_dec.linkLibrary(brotli_common); + + // Build leveldb + const leveldb = b.addLibrary(.{ + .name = "leveldb", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }); + leveldb.linkLibCpp(); + leveldb.addIncludePath(b.path("deps/leveldb-1.23/include")); + leveldb.addIncludePath(b.path("deps/leveldb-1.23")); + leveldb.addIncludePath(b.path("deps/leveldb-1.23/helpers/memenv")); + + const leveldb_sources = [_][]const u8{ + "deps/leveldb-1.23/db/builder.cc", + "deps/leveldb-1.23/db/c.cc", + "deps/leveldb-1.23/db/db_impl.cc", + "deps/leveldb-1.23/db/db_iter.cc", + "deps/leveldb-1.23/db/dbformat.cc", + "deps/leveldb-1.23/db/dumpfile.cc", + "deps/leveldb-1.23/db/filename.cc", + "deps/leveldb-1.23/db/log_reader.cc", + "deps/leveldb-1.23/db/log_writer.cc", + "deps/leveldb-1.23/db/memtable.cc", + "deps/leveldb-1.23/db/repair.cc", + "deps/leveldb-1.23/db/table_cache.cc", + "deps/leveldb-1.23/db/version_edit.cc", + "deps/leveldb-1.23/db/version_set.cc", + "deps/leveldb-1.23/db/write_batch.cc", + "deps/leveldb-1.23/table/block.cc", + "deps/leveldb-1.23/table/block_builder.cc", + "deps/leveldb-1.23/table/filter_block.cc", + "deps/leveldb-1.23/table/format.cc", + "deps/leveldb-1.23/table/iterator.cc", + "deps/leveldb-1.23/table/merger.cc", + "deps/leveldb-1.23/table/table.cc", + "deps/leveldb-1.23/table/table_builder.cc", + "deps/leveldb-1.23/table/two_level_iterator.cc", + "deps/leveldb-1.23/util/arena.cc", + "deps/leveldb-1.23/util/bloom.cc", + "deps/leveldb-1.23/util/cache.cc", + "deps/leveldb-1.23/util/coding.cc", + "deps/leveldb-1.23/util/comparator.cc", + "deps/leveldb-1.23/util/crc32c.cc", + "deps/leveldb-1.23/util/env.cc", + "deps/leveldb-1.23/util/env_posix.cc", + "deps/leveldb-1.23/util/filter_policy.cc", + "deps/leveldb-1.23/util/hash.cc", + "deps/leveldb-1.23/util/logging.cc", + "deps/leveldb-1.23/util/options.cc", + "deps/leveldb-1.23/util/status.cc", + "deps/leveldb-1.23/helpers/memenv/memenv.cc", + }; + leveldb.addCSourceFiles(.{ + .files = &leveldb_sources, + .flags = &[_][]const u8{ + "-Wall", + "-std=c++11", + "-fno-rtti", + "-Wno-sign-compare", + "-DLEVELDB_PLATFORM_POSIX=1", + "-DLEVELDB_COMPILE_LIBRARY=1", + }, + }); + + // ==================== Build SQLite ==================== + const sqlite = b.addLibrary(.{ + .name = "sqlite3", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }); + sqlite.linkLibC(); + sqlite.addIncludePath(b.path("deps/sqlite-3.43.2")); + sqlite.addCSourceFiles(.{ + .files = &[_][]const u8{ + "deps/sqlite-3.43.2/sqlite3.c", + }, + .flags = &[_][]const u8{"-Wall"}, + }); + + // ==================== Build Main Pipy ==================== + + const pipy_sources = [_][]const u8{ + "src/admin-link.cpp", + "src/admin-proxy.cpp", + "src/admin-service.cpp", + "src/api/algo.cpp", + "src/api/bgp.cpp", + "src/api/bpf.cpp", + "src/api/configuration.cpp", + "src/api/console.cpp", + "src/api/crypto.cpp", + "src/api/c-string.cpp", + "src/api/c-struct.cpp", + "src/api/dns.cpp", + "src/api/hessian.cpp", + "src/api/http.cpp", + "src/api/ip.cpp", + "src/api/json.cpp", + "src/api/logging.cpp", + "src/api/os.cpp", + "src/api/pipeline-api.cpp", + "src/api/pipy.cpp", + "src/api/print.cpp", + "src/api/protobuf.cpp", + "src/api/resp.cpp", + "src/api/stats.cpp", + "src/api/sqlite.cpp", + "src/api/swap.cpp", + "src/api/thrift.cpp", + "src/api/timeout.cpp", + "src/api/url.cpp", + "src/api/xml.cpp", + "src/api/yaml.cpp", + "src/api/zlib.cpp", + "src/buffer.cpp", + "src/codebase.cpp", + "src/codebase-store.cpp", + "src/compressor.cpp", + "src/context.cpp", + "src/data.cpp", + "src/deframer.cpp", + "src/elf.cpp", + "src/event.cpp", + "src/event-queue.cpp", + "src/fetch.cpp", + "src/file.cpp", + "src/filter.cpp", + "src/filters/bgp.cpp", + "src/filters/branch.cpp", + "src/filters/chain.cpp", + "src/filters/compress.cpp", + "src/filters/connect.cpp", + "src/filters/decompress.cpp", + "src/filters/deframe.cpp", + "src/filters/demux.cpp", + "src/filters/deposit-message.cpp", + "src/filters/detect-protocol.cpp", + "src/filters/dubbo.cpp", + "src/filters/dummy.cpp", + "src/filters/dump.cpp", + "src/filters/exec.cpp", + "src/filters/fcgi.cpp", + "src/filters/fork.cpp", + "src/filters/handle.cpp", + "src/filters/http.cpp", + "src/filters/http2.cpp", + "src/filters/insert.cpp", + "src/filters/link.cpp", + "src/filters/link-async.cpp", + "src/filters/loop.cpp", + "src/filters/mime.cpp", + "src/filters/mqtt.cpp", + "src/filters/mux.cpp", + "src/filters/netlink.cpp", + "src/filters/on-body.cpp", + "src/filters/on-event.cpp", + "src/filters/on-message.cpp", + "src/filters/on-start.cpp", + "src/filters/pack.cpp", + "src/filters/pipe.cpp", + "src/filters/print.cpp", + "src/filters/produce.cpp", + "src/filters/proxy-protocol.cpp", + "src/filters/read.cpp", + "src/filters/repeat.cpp", + "src/filters/replace.cpp", + "src/filters/replace-body.cpp", + "src/filters/replace-event.cpp", + "src/filters/replace-message.cpp", + "src/filters/replace-start.cpp", + "src/filters/replay.cpp", + "src/filters/resp.cpp", + "src/filters/socks.cpp", + "src/filters/split.cpp", + "src/filters/swap.cpp", + "src/filters/tee.cpp", + "src/filters/thrift.cpp", + "src/filters/throttle.cpp", + "src/filters/tls.cpp", + "src/filters/use.cpp", + "src/filters/wait.cpp", + "src/filters/websocket.cpp", + "src/fs.cpp", + "src/fstream.cpp", + "src/graph.cpp", + "src/gui-tarball.cpp", + "src/inbound.cpp", + "src/input.cpp", + "src/kmp.cpp", + "src/listener.cpp", + "src/log.cpp", + "src/main.cpp", + "src/main-options.cpp", + "src/message.cpp", + "src/module.cpp", + "src/net.cpp", + "src/nmi.cpp", + "src/options.cpp", + "src/os-platform.cpp", + "src/outbound.cpp", + "src/pipeline.cpp", + "src/pipeline-lb.cpp", + "src/pjs/builtin.cpp", + "src/pjs/expr.cpp", + "src/pjs/module.cpp", + "src/pjs/parser.cpp", + "src/pjs/stmt.cpp", + "src/pjs/tree.cpp", + "src/pjs/types.cpp", + "src/signal.cpp", + "src/socket.cpp", + "src/status.cpp", + "src/store.cpp", + "src/str-map.cpp", + "src/table.cpp", + "src/tar.cpp", + "src/task.cpp", + "src/thread.cpp", + "src/timer.cpp", + "src/utils.cpp", + "src/watch.cpp", + "src/worker.cpp", + "src/worker-thread.cpp", + }; + + const pipy_flags = [_][]const u8{ + "-Wall", + "-Wno-overloaded-virtual", + "-Wno-delete-non-virtual-dtor", + "-Wno-sign-compare", + "-Wno-deprecated-declarations", + "-std=c++11", + "-D_GNU_SOURCE", + "-DXML_STATIC=1", + }; + + const pipy_exe = if (shared_lib) + b.addLibrary(.{ + .name = "pipy", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .dynamic, + }) + else if (static_lib) + b.addLibrary(.{ + .name = "pipy", + .root_module = createEmptyModule(b, target, optimize), + .linkage = .static, + }) + else + b.addExecutable(.{ + .name = "pipy", + .root_module = createEmptyModule(b, target, optimize), + }); + + pipy_exe.linkLibCpp(); + pipy_exe.linkLibC(); + + // Add include paths + pipy_exe.addIncludePath(b.path("src")); + pipy_exe.addIncludePath(b.path("include")); + pipy_exe.addIncludePath(b.path("deps/asio-1.28.0/include")); + pipy_exe.addIncludePath(b.path("deps/yajl-2.1.0/src")); + pipy_exe.addIncludePath(b.path("deps/yajl-2.1.0/build/yajl-2.1.0/include")); + pipy_exe.addIncludePath(b.path("deps/libyaml-0.2.5/include")); + pipy_exe.addIncludePath(b.path("deps/libexpat-R_2_2_6/expat/lib")); + pipy_exe.addIncludePath(b.path("deps/leveldb-1.23/include")); + pipy_exe.addIncludePath(b.path("deps/sqlite-3.43.2")); + pipy_exe.addIncludePath(b.path("deps/brotli-1.0.9/c/include")); + pipy_exe.addIncludePath(b.path("zig-out")); + + if (!use_system_zlib) { + pipy_exe.addIncludePath(b.path("deps/zlib-1.3.1")); + } + + if (!use_system_openssl) { + pipy_exe.addIncludePath(b.path("deps/openssl-3.2.0/include")); + pipy_exe.addIncludePath(b.path("deps/openssl-3.2.0/build/include")); + } + + // Build compile flags with macros + var pipy_all_flags: [20][]const u8 = undefined; + var flag_count: usize = 0; + + // Copy base flags + for (pipy_flags) |flag| { + pipy_all_flags[flag_count] = flag; + flag_count += 1; + } + + // Add macro definitions + pipy_all_flags[flag_count] = "-DPIPY_HOST=\"Zig Build\""; + flag_count += 1; + + if (shared_lib or static_lib) { + pipy_all_flags[flag_count] = "-DPIPY_SHARED"; + flag_count += 1; + } + if (enable_gui) { + pipy_all_flags[flag_count] = "-DPIPY_USE_GUI"; + flag_count += 1; + pipy_all_flags[flag_count] = "-DPIPY_USE_CODEBASES"; + flag_count += 1; + } + if (enable_bpf) { + pipy_all_flags[flag_count] = "-DPIPY_USE_BPF"; + flag_count += 1; + } + + // Add C++ source files + pipy_exe.addCSourceFiles(.{ + .files = &pipy_sources, + .flags = pipy_all_flags[0..flag_count], + }); + + // Link dependencies + pipy_exe.linkLibrary(yajl); + pipy_exe.linkLibrary(yaml); + pipy_exe.linkLibrary(expat); + pipy_exe.linkLibrary(brotli_dec); + pipy_exe.linkLibrary(leveldb); + pipy_exe.linkLibrary(sqlite); + + if (zlib) |z| { + pipy_exe.linkLibrary(z); + } else { + pipy_exe.linkSystemLibrary("z"); + } + + // Link OpenSSL + if (use_system_openssl) { + // Add Homebrew OpenSSL paths for macOS + if (target.result.os.tag == .macos) { + // Use the actual OpenSSL path that exists + const openssl_path = "/usr/local/opt/openssl@3"; + pipy_exe.addLibraryPath(.{ .cwd_relative = b.fmt("{s}/lib", .{openssl_path}) }); + pipy_exe.addIncludePath(.{ .cwd_relative = b.fmt("{s}/include", .{openssl_path}) }); + } + pipy_exe.linkSystemLibrary("ssl"); + pipy_exe.linkSystemLibrary("crypto"); + } else { + // Link statically built OpenSSL + pipy_exe.addObjectFile(b.path("deps/openssl-3.2.0/build/libssl.a")); + pipy_exe.addObjectFile(b.path("deps/openssl-3.2.0/build/libcrypto.a")); + } + + // Platform-specific linking + if (target.result.os.tag != .windows) { + pipy_exe.linkSystemLibrary("pthread"); + pipy_exe.linkSystemLibrary("dl"); + pipy_exe.linkSystemLibrary("util"); + } + + // Add version generation dependency + pipy_exe.step.dependOn(&gen_version.step); + + // Add GUI generation dependency if enabled + if (gen_gui) |gui| { + pipy_exe.step.dependOn(&gui.step); + // Add zig-out/deps as include path for gui.tar.h + pipy_exe.addIncludePath(b.path("zig-out/deps")); + } + + // Add Codebases generation dependency if enabled + if (gen_codebases) |codebases| { + pipy_exe.step.dependOn(&codebases.step); + // Add zig-out/deps as include path for codebases.tar.gz.h + pipy_exe.addIncludePath(b.path("zig-out/deps")); + } + + // Install artifact + b.installArtifact(pipy_exe); + + // Add run step + if (!shared_lib and !static_lib) { + const run_cmd = b.addRunArtifact(pipy_exe); + run_cmd.step.dependOn(b.getInstallStep()); + + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run pipy"); + run_step.dependOn(&run_cmd.step); + } + + // Add test step for benchmark baseline + const test_step = b.step("test", "Run tests"); + _ = test_step; +} diff --git a/deps/brotli-1.0.9/CMakeLists.txt b/deps/brotli-1.0.9/CMakeLists.txt index 4ff340123..1b23f6076 100644 --- a/deps/brotli-1.0.9/CMakeLists.txt +++ b/deps/brotli-1.0.9/CMakeLists.txt @@ -2,7 +2,7 @@ # several CI services, such as Travis and Drone, use it. Solaris 11 # has 2.8.6, and it's not difficult to support if you already have to # support 2.8.7. -cmake_minimum_required(VERSION 2.8.6) +cmake_minimum_required(VERSION 3.10) project(brotli C) diff --git a/deps/libexpat-R_2_2_6/expat/CMakeLists.txt b/deps/libexpat-R_2_2_6/expat/CMakeLists.txt index a537f8a77..848be704d 100644 --- a/deps/libexpat-R_2_2_6/expat/CMakeLists.txt +++ b/deps/libexpat-R_2_2_6/expat/CMakeLists.txt @@ -3,7 +3,7 @@ project(expat) -cmake_minimum_required(VERSION 2.8.10) +cmake_minimum_required(VERSION 3.10) set(PACKAGE_BUGREPORT "expat-bugs@libexpat.org") set(PACKAGE_NAME "expat") set(PACKAGE_VERSION "2.2.6") diff --git a/deps/libyaml-0.2.5/CMakeLists.txt b/deps/libyaml-0.2.5/CMakeLists.txt index 4f8114817..df7c1b9b3 100644 --- a/deps/libyaml-0.2.5/CMakeLists.txt +++ b/deps/libyaml-0.2.5/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.10) project (yaml C) set (YAML_VERSION_MAJOR 0) diff --git a/deps/yajl-2.1.0/CMakeLists.txt b/deps/yajl-2.1.0/CMakeLists.txt index 033381bcd..c207427b6 100644 --- a/deps/yajl-2.1.0/CMakeLists.txt +++ b/deps/yajl-2.1.0/CMakeLists.txt @@ -12,7 +12,7 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +CMAKE_MINIMUM_REQUIRED(VERSION 3.10) PROJECT(YetAnotherJSONParser C) diff --git a/deps/zlib-1.3.1/CMakeLists.txt b/deps/zlib-1.3.1/CMakeLists.txt index 15ceebe78..cbd30a5d6 100644 --- a/deps/zlib-1.3.1/CMakeLists.txt +++ b/deps/zlib-1.3.1/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4.4...3.15.0) +cmake_minimum_required(VERSION 3.10...3.15.0) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) project(zlib C) diff --git a/gui/pack-utils.js b/gui/pack-utils.js index 16f5c3f45..14301a65b 100644 --- a/gui/pack-utils.js +++ b/gui/pack-utils.js @@ -29,7 +29,7 @@ module.exports = { writeBinaryHeaderFile: (filename, name, data) => { const fd = fs.openSync(filename, 'w+'); - fs.writeSync(fd, `static unsigned char ${name}[${data.length}] = {\n`); + fs.writeSync(fd, `static unsigned char ${name}[${data.length}] __attribute__((aligned(16))) = {\n`); for (let i = 0, n = data.length; i < n; i += 16) { const line = []; for (let j = 0; j < 16 && i + j < n; j++) { diff --git a/test/benchmark/baseline/CMakeLists.txt b/test/benchmark/baseline/CMakeLists.txt index e915fcd37..230004e7d 100644 --- a/test/benchmark/baseline/CMakeLists.txt +++ b/test/benchmark/baseline/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required (VERSION 3.10) project(baseline) if(NOT WIN32)