在上一篇 环境搭建与 Hello
World 中,我们使用 gcc 命令行编译了 Echo
Server。但在实际工程中,我们通常使用构建系统来管理依赖和编译流程。
本篇将介绍如何在三种主流构建系统中集成 Libevent:Makefile (传统)、CMake (现代 C++ 标准) 和 Bazel (Google 风格大仓)。
1. Makefile (传统方式)
对于小型 C 项目,Makefile
依然是简单高效的选择。为了避免硬编码路径(如
/usr/local/include),推荐使用
pkg-config 工具。
1.1. 检查 pkg-config
安装 Libevent 后,它通常会提供 .pc
文件。检查是否能被识别:
pkg-config --cflags --libs libevent
# 输出示例: -I/usr/local/include -L/usr/local/lib -levent1.2. 编写 Makefile
CC = gcc
CFLAGS = -g -Wall $(shell pkg-config --cflags libevent)
LDFLAGS = $(shell pkg-config --libs libevent)
TARGET = echo_server
SRCS = echo_server.c
OBJS = $(SRCS:.c=.o)
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: all clean这样,无论 Libevent 安装在 /usr 还是
/usr/local,pkg-config
都会自动填充正确的路径。
2. CMake (现代 C++ 标配)
CMake 是目前 C/C++ 开源项目的事实标准。集成 Libevent
主要有两种方式:系统预装查找
(find_package) 和 源码自动下载
(FetchContent)。
2.1. 方式一:find_package (依赖系统库)
这种方式要求运行环境已经安装了 Libevent(通过 apt 或源码安装)。
CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(LibeventDemo C)
# 查找 Libevent 包
find_package(Libevent CONFIG REQUIRED)
add_executable(echo_server echo_server.c)
# 链接 Libevent::core 和 Libevent::extra
# 注意:Libevent 的 CMake 配置通常导出为 Libevent::Libevent 或 Libevent::core
if(TARGET Libevent::core)
target_link_libraries(echo_server PRIVATE Libevent::core)
else()
# 兼容旧版本或非标准安装
include_directories(${LIBEVENT_INCLUDE_DIRS})
target_link_libraries(echo_server PRIVATE ${LIBEVENT_LIBRARIES})
endif()提示: 如果 CMake 报错找不到,可以尝试使用
PkgConfig模块作为回退方案。
2.2. 方式二:FetchContent (源码集成)
这种方式无需预先安装 Libevent,CMake 会在构建时自动下载源码并编译。适合追求环境一致性的项目。
CMakeLists.txt:
cmake_minimum_required(VERSION 3.14)
project(LibeventDemo C)
include(FetchContent)
# 定义下载源
FetchContent_Declare(
libevent
URL https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz
)
# 禁用 Libevent 的测试和示例,加快构建
set(EVENT__DISABLE_OPENSSL ON CACHE BOOL "" FORCE)
set(EVENT__DISABLE_BENCHMARK ON CACHE BOOL "" FORCE)
set(EVENT__DISABLE_TESTS ON CACHE BOOL "" FORCE)
set(EVENT__DISABLE_SAMPLES ON CACHE BOOL "" FORCE)
# 下载并引入
FetchContent_MakeAvailable(libevent)
add_executable(echo_server echo_server.c)
# 链接 FetchContent 引入的目标
target_link_libraries(echo_server PRIVATE event_core event_extra)3. Bazel (大仓构建实践)
Bazel 是 Google 开源的构建系统,擅长处理多语言、大规模依赖。
3.1. WORKSPACE 配置
在项目根目录的 WORKSPACE
文件中定义外部依赖:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "com_github_libevent_libevent",
urls = ["https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz"],
strip_prefix = "libevent-2.1.12-stable",
build_file = "//third_party:libevent.BUILD", # 我们需要自己写 BUILD 文件
)3.2. 编写 BUILD 文件适配
由于 Libevent 官方源码包没有自带 Bazel 支持,我们需要在
third_party/libevent.BUILD
中描述如何编译它(这通常是最麻烦的一步,因为涉及
config.h 的生成)。
一个简化的 libevent.BUILD
示例(仅供参考,实际可能需要运行 configure
生成头文件):
cc_library(
name = "libevent",
srcs = glob([
"*.c",
"*.h",
"compat/*.h",
"include/*.h",
], exclude = [
"test/**",
"sample/**",
"win32/**",
]),
hdrs = glob(["include/event2/*.h"]),
includes = ["include"],
copts = [
"-DHAVE_CONFIG_H",
"-Iexternal/com_github_libevent_libevent/include",
],
visibility = ["//visibility:public"],
)注: 生产环境通常会先在 Docker 中运行
./configure生成好config.h,然后将其作为 patch 打入 Bazel 构建中,或者使用rules_foreign_cc规则集来调用make。
使用 rules_foreign_cc (推荐):
load("@rules_foreign_cc//foreign_cc:defs.bzl", "configure_make")
configure_make(
name = "libevent",
lib_source = "@com_github_libevent_libevent//:all_srcs",
out_static_libs = ["libevent.a"],
configure_options = [
"--disable-openssl",
"--disable-samples",
],
)3.3. 项目 BUILD 文件
cc_binary(
name = "echo_server",
srcs = ["echo_server.c"],
deps = ["@com_github_libevent_libevent//:libevent"],
)4. 总结
- Makefile: 适合简单、无额外依赖的小型 C 项目。
- CMake: 推荐使用
FetchContent模式,确保团队成员使用相同版本的 Libevent,且无需手动安装系统库。 - Bazel: 适合超大规模仓库,但对第三方 C
库的适配成本较高,建议配合
rules_foreign_cc使用。
掌握了构建系统的集成,我们就可以在复杂的工程中自如地使用
Libevent 了。下一篇,我们将深入 Libevent 的核心,剖析
event_base 和事件循环的内部机制。
上一篇: 00-intro/env-setup.md - 环境搭建与 Hello World 下一篇: 01-core/event-base-loop.md - Event Base 与 Event Loop