sylar环境配置与项目构建

分类: 365速度发国际大厅 时间: 2025-10-26 03:13:55 作者: admin 阅读: 5858

项目构建

sylar使用makefile + cmake进行项目构建

有关cmake的介绍参考:自动化构建系统生成工具CMake_cmake 构造工具-CSDN博客

关键文件

sylar/cmake/utils.cmake

该文件为CMakeLists.txt提供了一组通用的构建工具函数

1.force_redefine_file_macro_for_sources(targetname)

为某个CMake target(通常是可执行文件)中的所有源文件单独设置 __FILE__ 宏为相对于项目根目录的路径,而不是默认的绝对路径。可以让日志中打印出来的 __FILE__ 更简洁(如 src/module/a.cpp 而不是 /home/user/project/src/module/a.cpp),便于调试和跨平台输出一致。

function(force_redefine_file_macro_for_sources targetname)

# 获取构建目标 targetname 中显式指定的源文件列表

get_target_property(source_files "${targetname}" SOURCES)

foreach(sourcefile ${source_files})

# 获取每个源文件当前已有的编译宏定义列表(如 -DXXX)

get_property(defs SOURCE "${sourcefile}" PROPERTY COMPILE_DEFINITIONS)

# 获取源文件的绝对路径

get_filename_component(filepath "${sourcefile}" ABSOLUTE)

# 获取源文件相对项目根目录(PROJECT_SOURCE_DIR)的路径

string(REPLACE ${PROJECT_SOURCE_DIR}/ "" relpath ${filepath})

# 向编译宏中追加 __FILE__="相对路径"

# 目的是让日志输出中的 __FILE__ 宏显示为项目内的相对路径,而非系统绝对路径

list(APPEND defs "__FILE__=\"${relpath}\"")

# 将更新后的宏定义列表重新设置到该源文件上

set_property(SOURCE "${sourcefile}" PROPERTY COMPILE_DEFINITIONS ${defs})

endforeach()

endfunction()

2.ragelmaker(src_rl outputlist outputdir)

为 Ragel 状态机文件(.rl)创建自定义构建步骤,调用 ragel 工具生成 .cc 文件,并将生成的路径加入到指定的输出列表变量中。

function(ragelmaker src_rl outputlist outputdir)

# 获取源 ragel 文件(.rl)的不带后缀文件名(NAME_WE 表示去除扩展名)

get_filename_component(src_file ${src_rl} NAME_WE)

# 设置 ragel 生成的 .cpp 文件的完整路径,例如 outputdir/test.rl.cc

set(rl_out ${outputdir}/${src_file}.rl.cc)

# 将生成的目标文件路径加入输出文件列表(注意要用 PARENT_SCOPE 把变量传回外部作用域)

set(${outputlist} ${${outputlist}} ${rl_out} PARENT_SCOPE)

# 添加一个自定义构建命令:

# - 生成文件为 ${rl_out}

# - 使用 ragel 编译 ${src_rl} 生成 ${rl_out}

# - 执行前先进入 outputdir 目录

# - 设置依赖为 ${src_rl},即源文件变更会触发重新生成

add_custom_command(

OUTPUT ${rl_out}

COMMAND cd ${outputdir}

COMMAND ragel ${CMAKE_CURRENT_SOURCE_DIR}/${src_rl} -o ${rl_out} -l -C -G2 --error-format=msvc

DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${src_rl}

)

# 告诉 CMake 该文件是由构建步骤自动生成的

set_source_files_properties(${rl_out} PROPERTIES GENERATED TRUE)

endfunction(ragelmaker)

3.protobufmaker(src_proto outputlist outputdir)

为指定的 .proto 文件添加一个 CMake 自定义构建步骤,在构建过程中自动调用 protoc 编译器将该 .proto 文件生成对应的 .pb.cc 和 .pb.h 源码文件,并将生成的 .pb.cc 文件路径加入指定的变量中,供后续目标添加源文件使用。

function(protobufmaker src_proto outputlist outputdir)

# 从 proto 源文件路径中提取文件名(不带扩展名),用于输出文件命名

get_filename_component(src_file ${src_proto} NAME_WE)

# 提取 proto 文件所在的相对路径,便于构造输出目录结构

get_filename_component(src_path ${src_proto} PATH)

# 构造最终生成的 .pb.cc 文件的路径(注意路径中包含子目录结构)

set(protobuf_out ${outputdir}/${src_path}/${src_file}.pb.cc)

# 将生成的 .pb.cc 文件添加到调用者提供的变量中

# 注意:不能使用 list(APPEND),因为函数作用域不同,必须显式传回上层作用域

set(${outputlist} ${${outputlist}} ${protobuf_out} PARENT_SCOPE)

# 添加一个自定义构建命令:在编译时自动调用 protoc 编译器生成 .pb.cc 文件

add_custom_command(

OUTPUT ${protobuf_out} # 指定生成的目标文件

COMMAND protoc --cpp_out=${outputdir} -I${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${src_proto}

# 执行 protoc 命令,将 proto 文件生成对应的 .pb.cc/.pb.h 到指定目录

DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${src_proto} # 依赖 proto 文件本身

)

# 告诉 CMake:这个输出文件是构建过程中自动生成的,避免 IDE 提示或误删

set_source_files_properties(${protobuf_out} PROPERTIES GENERATED TRUE)

endfunction(protobufmaker)

4.sylar_add_executable(targetname srcs depends libs)

用于简洁高效地定义一个可执行文件的构建过程。它会创建一个可执行目标(add_executable)、指定它所依赖的其他目标(add_dependencies)、调用 force_redefine_file_macro_for_sources 函数为每个源文件设置 __FILE__ 宏路径(用于更好定位日志和错误信息),并链接指定的库(target_link_libraries)。

function(sylar_add_executable targetname srcs depends libs)

# 创建可执行文件 targetname,使用 srcs 作为源文件

add_executable(${targetname} ${srcs})

# 指定该可执行文件的构建依赖,必须在 depends 先构建完成之后才构建该目标

add_dependencies(${targetname} ${depends})

# 调用自定义函数 force_redefine_file_macro_for_sources,为每个源文件设置 __FILE__ 宏路径

force_redefine_file_macro_for_sources(${targetname})

# 指定目标要链接的库,如 pthread、protobuf、sylar 等

target_link_libraries(${targetname} ${libs})

endfunction()

sylar/CMakeLists.txt

基础配置

cmake_minimum_required(VERSION 3.5)

project(sylar C CXX)

set(CMAKE_CXX_STANDARD 17)

set(CMAKE_C_STANDARD 99)

set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -rdynamic -O3 -fPIC -ggdb -std=c++11 -Wall -Wno-deprecated -Wno-unused-function -Wno-builtin-macro-redefined -Wno-deprecated-declarations")

set(CMAKE_C_FLAGS "$ENV{CXXFLAGS} -rdynamic -O3 -fPIC -ggdb -std=c11 -Wall -Wno-deprecated -Wno-unused-function -Wno-builtin-macro-redefined -Wno-deprecated-declarations")

模块路径和工具函数引入

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

include(cmake/utils.cmake)

头文件与库路径配置

include_directories(. /apps/sylar/include)

link_directories(/apps/sylar/lib /apps/sylar/lib64)

外部依赖查找

find_package(Boost REQUIRED)

if(Boost_FOUND)

include_directories(${Boost_INCLUDE_DIRS})

endif()

find_package(MySQL REQUIRED)

if(MYSQL_FOUND)

include_directories(${MYSQL_INCLUDE_DIR})

endif()

find_package(Protobuf)

if(Protobuf_FOUND)

include_directories(${Protobuf_INCLUDE_DIRS})

endif()

find_package(OpenSSL REQUIRED)

if(OPENSSL_FOUND)

include_directories(${OPENSSL_INCLUDE_DIR})

endif()

find_package(ZLIB REQUIRED)

if(ZLIB_FOUND)

include_directories(${ZLIB_INCLUDE_DIR})

endif()

源文件收集与ragel/protobuf代码生成,生成的源文件也存入LIB_SRC中

set(LIB_SRC

sylar/address.cc

sylar/bytearray.cc

...

sylar/application.cc

sylar/zk_client.cc

)

ragelmaker(sylar/http/http11_parser.rl LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sylar/http)

ragelmaker(sylar/http/httpclient_parser.rl LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sylar/http)

ragelmaker(sylar/uri.rl LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sylar)

protobufmaker(sylar/ns/ns_protobuf.proto LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR})

构建共享库,将所有核心代码编译成一个共享库 libsylar.so,供测试程序和主程序链接使用。

add_library(sylar SHARED ${LIB_SRC})

force_redefine_file_macro_for_sources(sylar)

链接的三方库设置,汇总所有需要链接的第三方库,包括系统库、第三方静态库(如 hiredis、zookeeper)、数据库、加解密、内存分配等。

set(LIBS

sylar

dl

pthread

yaml-cpp

jsoncpp

${ZLIB_LIBRARIES}

${OPENSSL_LIBRARIES}

${PROTOBUF_LIBRARIES}

event

hiredis_vip

mysqlclient_r

zookeeper_mt

sqlite3

tinyxml2

jemalloc)

编译测试样例程序

sylar_add_executable(test_util "tests/test_util.cc" sylar "${LIBS}")

sylar_add_executable(test_hashmultimap "tests/test_hashmultimap.cc" sylar "${LIBS}")

...

sylar_add_executable(test_zkclient "tests/test_zookeeper.cc" sylar "${LIBS}")

sylar_add_executable(test_service_discovery "tests/test_service_discovery.cc" sylar "${LIBS}")

orm子模块构建

set(ORM_SRCS sylar/orm/table.cc sylar/orm/column.cc sylar/orm/index.cc sylar/orm/orm.cc sylar/orm/util.cc)

sylar_add_executable(orm "${ORM_SRCS}" sylar "${LIBS}")

把 tests/test_module.cc 这个源文件编译成一个共享库(动态链接库)test_module.so,它是作为插件模块来使用的。

add_library(test_module SHARED tests/test_module.cc)

构建最终主程序(执行入口),可执行文件命名为 sylar。

sylar_add_executable(bin_sylar "sylar/main.cc" sylar "${LIBS}")

set_target_properties(bin_sylar PROPERTIES OUTPUT_NAME "sylar")

设置所有生成的可执行文件输出到 bin/,共享库输出到 lib/,保持构建产物结构清晰。

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

sylar/Makefile

用于简化 CMake 项目的构建流程,它充当一个外部构建入口,用最少的命令让你快速编译整个项目或某个测试目标。

具体来说它通过定义默认目标和通配符目标,实现了一个自动化构建流程:当你在项目根目录下直接运行 make 时,它会检测是否存在 build/ 目录,如果存在就进入该目录并使用 make -j10 并行编译项目;如果不存在则会先创建 build/ 目录,然后再自动执行编译;当你运行 make xxx(如 make test_util)时,它会自动切换到 build/ 目录,构建指定的目标;如果 build/ 不存在,同样先配置再构建该目标。整个流程统一了构建过程,避免每次都手动输入 cmake 和 make 命令。

在初次构建项目时一般我们执行两次 make,即 make && make。第一次执行 make 会检测到当前没有 build/ 目录,于是会创建该目录并执行 cmake 配置过程,生成 Makefile 等构建文件;而这一步不会触发实际的编译操作。第二次执行 make 才会进入刚刚生成的 build/ 目录,并根据第一步生成的构建文件真正开始编译源码。因此,两次 make 分别对应 “生成构建系统” 和 “执行构建过程” 两个阶段。

.PHONY: xx

"":

if [ -d "build" ]; then \

cd build && make -j10; \

else \

mkdir build; \

cd build && cmake -DCMAKE_CXX_COMPILER:FILEPATH=$(shell which g++) -DCMAKE_C_COMPILER:FILEPATH=$(shell which gcc) ..; \

fi

# 通配目标,匹配 make xxx 时的情况

%:

if [ -d "build" ]; then \

cd build && make $@ -j10; \

else \

mkdir build; \

cd build && cmake -DCMAKE_CXX_COMPILER:FILEPATH=$(shell which g++) -DCMAKE_C_COMPILER:FILEPATH=$(shell which gcc) $@ ..; \

fi

项目环境的搭建

参考:captainwc/sylar

可以根据README.md中提供的sylar-build.pdf文件对项目依赖进行逐个安装,也可直接使用dockerfile进行sylar环境依赖的搭建

有关docker的介绍与使用可参考:docker介绍与常用命令汇总_docker简述-CSDN博客

提供的dockerfile做了以下事情

安装 Sylar 项目所需的依赖

编译并安装 hiredis-vip

解压并配置 ZooKeeper C 客户端

克隆 sylar 项目到 /workspace/sylar

最终进入 /workspace/sylar 并默认以 bash 进入容器

# Just ubuntu22.04 with some basic and useful tools, like g++ git bazel tmux uv etc

## You can get from https://raw.githubusercontent.com/captainwc/.dotfiles/refs/heads/main/scripts/docker/dockerfile-dev-base

FROM dev-base:latest

WORKDIR /workspace

RUN apt update \

&& apt install -y --no-install-recommends \

libjsoncpp-dev \

ragel \

libyaml-cpp-dev \

libmysqlclient-dev \

sqlite3 \

libsqlite3-dev \

redis-server \

libevent-dev \

libprotobuf-dev \

protobuf-compiler \

libssl-dev \

libtinyxml2-dev \

libjemalloc-dev \

libboost-dev \

&& git clone https://github.com/vipshop/hiredis-vip.git /tmp/hiredis-vip \

&& cd /tmp/hiredis-vip && make -j8 && make install && cd - \

&& sed -i '34i#include ' /usr/local/include/hiredis-vip/adapters/libevent.h \

&& wget -O /tmp/zookeeper.zip https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/pic_bed/2025_4/zookeeper-client-c-3.10.0-ubuntu22.zip \

&& cd /tmp && unzip zookeeper.zip && mv zookeeper/include /usr/local/include/zookeeper && mv zookeeper/lib/* /usr/local/lib/ && cd - \

&& ln -sf /usr/local/lib/libzookeeper_st.so.2.0.0 /usr/local/lib/libzookeeper_st.so \

&& ln -sf /usr/local/lib/libzookeeper_st.so.2.0.0 /usr/local/lib/libzookeeper_st.so.2 \

&& ln -sf /usr/local/lib/libzookeeper_mt.so.2.0.0 /usr/local/lib/libzookeeper_mt.so \

&& ln -sf /usr/local/lib/libzookeeper_mt.so.2.0.0 /usr/local/lib/libzookeeper_mt.so.2 \

&& ln -sf /usr/lib/x86_64-linux-gnu/libmysqlclient.so.21.2.41 /usr/lib/x86_64-linux-gnu/libmysqlclient_r.so \

&& ldconfig -v \

&& git clone https://github.com/captainwc/sylar.git \

&& apt clean && rm -rf /var/lib/apt/lists/* /tmp/*

WORKDIR /workspace/sylar

CMD [ "/bin/bash" ]

使用该dockerfile

1.下载提供的基础镜像

wget https://raw.githubusercontent.com/captainwc/.dotfiles/main/scripts/docker/dockerfile-dev-base -O Dockerfile.dev-base

2.构建基础镜像

构建成功后,你本地就有了一个名为 dev-base:latest 的基础镜像,供后续使用。

docker build -t dev-base:latest -f Dockerfile.dev-base .

3.基于基础镜像构建适用于sylar项目的镜像

docker build -t sylar-dev -f dockerfile .

4.启动一个临时容器

进入已构建好的容器sylar-dev的bash shell,工作目录已设为 /workspace/sylar,代码也已经克隆好。

docker run -it --rm sylar-dev

5.编译sylar项目

make && make

性能测试

sylar测试了HttpServer的性能,并与nginx进行了对比。

视频:[C++高级教程]sylar服务器框架性能测试(sylar)_哔哩哔哩_bilibili

sylar

HttpServer端:

http_server_test.cc

#include "sylar/http/http_server.h"

#include "sylar/log.h"

sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();

void run() {

g_logger->setLevel(sylar::LogLevel::INFO);

sylar::Address::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8020");

if (!addr) {

SYLAR_LOG_ERROR(g_logger) << "get address error";

return;

}

sylar::http::HttpServer::ptr http_server(new sylar::http::HttpServer);

while (!http_server->bind(addr)) {

SYLAR_LOG_ERROR(g_logger) << "bind " << *addr << " fail";

sleep(1);

}

http_server->start();

}

int main(int argc, char** argv) {

sylar::IOManager iom(3);

iom.schedule(run);

return 0;

}

sylar/CMakeLists.txt

sylar_add_executable(my_http_server "sample/http_server_test.cc" sylar "${LIBS}")

HttpClient端:

使用的是工具ab进行测试,ab是Apache HTTP服务器附带的压测工具,用于测试 HTTP 服务的并发处理能力、QPS、响应时间等指标。

ubuntu需要先安装apache2-utils

sudo apt update

sudo apt install apache2-utils

ab -V

Centos需要先安装httpd-tools

sudo yum install httpd-tools

ab的使用

ab [选项] [http://目标URL/]

ab -n 1000000 -c 500 http://127.0.0.1:8020/

ab -n 1000000 -c 500 -k http://127.0.0.1:8020/

ab常用选项

选项作用说明-n <请求数>总共发出多少个 HTTP 请求-c <并发数>并发多少个连接同时进行请求-t <时间>持续测试多少秒(替代 -n,限时压测)-k使用 HTTP Keep-Alive(长连接)

sylar的HttpServer测试结果

短链接:Requests per second: 15645.17 [#/sec] (mean)

长链接:Requests per second: 47000.43 [#/sec] (mean) 这是什么意思

nginx

ubuntu中安装并启动nginx

sudo apt update

sudo apt install -y nginx

启动 Nginx(默认监听 80 端口)

sudo systemctl start nginx

sudo systemctl enable nginx

确认是否启动成功

sudo netstat -tunlp | grep nginx

ab压测

ab -n 1000000 -c 200 "http://127.0.0.1:80/sylar"

ab -n 1000000 -c 200 -k "http://127.0.0.1:80/sylar"

nginx的HttpServer测试结果

短链接:Requests per second: 16864.61 [#/sec] (mean)长链接:Requests per second: 43122.75 [#/sec] (mean)

相关文章

be365备用网址

王者荣耀克制吕布真伤的装备

365速度发国际大厅

人工关节费用降到千元后,为何患者更担忧了?

365速度发国际大厅

京东 MALL 北京首店开业,设置 30 + 沉浸式主题体验区