| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- #include "fastweb.h"
- #include "../../utils.h"
- #include <iostream>
- #include <fstream>
- namespace ngs {
- namespace fastweb {
- namespace {
- // Upstream layout for Fastweb runtime deps:
- // /opt/lua54, /opt/luarocks
- // cmake default prefix -> /usr/local (bin/lib/share)
- //
- // ylib / HPSocket are already installed by NGS build.sh — do not rebuild them.
- std::string build_root() {
- return "/tmp/ngs-fastweb-build";
- }
- std::string lua_prefix() {
- return "/opt/lua54";
- }
- std::string luarocks_prefix() {
- return "/opt/luarocks";
- }
- std::string system_prefix() {
- return "/usr/local";
- }
- std::string version_file() {
- return join_path(share_dir(), ".ngs_version");
- }
- std::string fastweb_bin() {
- return join_path(system_prefix(), "bin/fastweb");
- }
- std::string toolchain_env() {
- const std::string lua = lua_prefix();
- return "export LIBRARY_PATH=\"" + join_path(system_prefix(), "lib") +
- ":/usr/lib/x86_64-linux-gnu:${LIBRARY_PATH:-}\" && "
- "export LD_LIBRARY_PATH=\"" + join_path(system_prefix(), "lib") + ":" +
- join_path(lua, "lib") + ":${LD_LIBRARY_PATH:-}\" && "
- "export LDFLAGS=\"-L" + join_path(system_prefix(), "lib") +
- " -L/usr/lib/x86_64-linux-gnu ${LDFLAGS:-}\" && "
- "export CPPFLAGS=\"-I" + join_path(system_prefix(), "include") +
- " ${CPPFLAGS:-}\" && "
- "export CPATH=\"" + join_path(system_prefix(), "include") +
- ":${CPATH:-}\" && "
- "export CPLUS_INCLUDE_PATH=\"" + join_path(system_prefix(), "include") +
- ":${CPLUS_INCLUDE_PATH:-}\" && ";
- }
- bool write_version_file(const std::string& version, bool debug) {
- if (!ensure_dir(share_dir())) {
- return false;
- }
- std::ofstream out(version_file());
- if (!out) {
- return false;
- }
- out << version << (debug ? " (Debug)" : " (Release)");
- return true;
- }
- bool lua_installed() {
- return path_exists(join_path(lua_prefix(), "bin/lua"));
- }
- bool luarocks_installed() {
- return path_exists(join_path(luarocks_prefix(), "bin/luarocks"));
- }
- bool fastweb_bin_installed() {
- return path_exists(fastweb_bin());
- }
- bool ylib_present() {
- return path_exists("/usr/local/lib/libylib.a") ||
- path_exists("/usr/lib/x86_64-linux-gnu/libylib.a") ||
- path_exists("/usr/local/lib/libylib_d.a") ||
- path_exists("/usr/lib/x86_64-linux-gnu/libylib_d.a");
- }
- bool hpsocket_present() {
- return path_exists("/usr/local/lib/libhpsocket.a") ||
- path_exists("/usr/lib/x86_64-linux-gnu/libhpsocket.a") ||
- path_exists("/lib/x86_64-linux-gnu/libhpsocket.a");
- }
- bool install_apt_deps() {
- std::cout << "检查/安装系统依赖...\n";
- const char* check =
- "dpkg -s git unzip wget sqlite3 libsqlite3-dev make gcc g++ cmake "
- "libssl-dev openssl zlib1g-dev libmimalloc-dev >/dev/null 2>&1";
- if (run_cmd(check, false) == 0) {
- std::cout << "依赖已满足。\n";
- return true;
- }
- int rc = run_cmd(
- "sudo apt-get update -y && "
- "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "
- "git unzip wget sqlite3 libsqlite3-dev make gcc g++ cmake "
- "libssl-dev openssl zlib1g-dev libmimalloc-dev");
- return rc == 0;
- }
- bool install_lua(const std::string& work) {
- const std::string prefix = lua_prefix();
- std::cout << "安装 Lua 5.4.6 -> " << prefix << "\n";
- const std::string tarball = "lua-5.4.6.tar.gz";
- if (run_cmd("cd \"" + work + "\" && "
- "wget -q --show-progress "
- "https://download.fwlua.com/software/" + tarball + " && "
- "tar -zxf " + tarball) != 0) {
- return false;
- }
- ensure_dir(prefix);
- const std::string src = join_path(work, "lua-5.4.6");
- return run_cmd(
- "cd \"" + src + "\" && "
- "make linux MYCFLAGS=\"-fPIC\" "
- "MYLDFLAGS=\"-Wl,-rpath," + prefix + "/lib\" && "
- "make INSTALL_TOP=\"" + prefix + "\" install") == 0;
- }
- bool install_luarocks(const std::string& work) {
- const std::string prefix = luarocks_prefix();
- const std::string lua = lua_prefix();
- std::cout << "安装 LuaRocks 3.9.1 -> " << prefix << "\n";
- const std::string tarball = "luarocks-3.9.1.tar.gz";
- if (run_cmd("cd \"" + work + "\" && "
- "wget -q --show-progress "
- "https://download.fwlua.com/software/" + tarball + " && "
- "tar -zxf " + tarball) != 0) {
- return false;
- }
- ensure_dir(prefix);
- const std::string src = join_path(work, "luarocks-3.9.1");
- return run_cmd(
- "cd \"" + src + "\" && "
- "./configure --with-lua=\"" + lua + "\" "
- "--lua-suffix=5.4 --versioned-rocks-dir "
- "--prefix=\"" + prefix + "\" && "
- "make && make install") == 0;
- }
- // Upstream Linux CMakeLists hardcodes ylib_d; fix to match build type.
- bool patch_ylib_link(const std::string& repo, bool debug) {
- const std::string ylib_name = debug ? "ylib_d" : "ylib";
- std::cout << "修正 Linux 链接库: " << ylib_name << "\n";
- return run_cmd(
- "sed -i "
- "-e 's/^[[:blank:]]*ylib_d[[:blank:]]*$/\\t\\t\\t" + ylib_name + "/' "
- "-e 's/^[[:blank:]]*ylib[[:blank:]]*$/\\t\\t\\t" + ylib_name + "/' "
- "\"" + join_path(repo, "CMakeLists.txt") + "\"") == 0;
- }
- bool build_fastweb(bool debug) {
- const std::string root = build_root();
- const std::string repo = join_path(root, "fastweb");
- if (!is_dir(repo)) {
- std::cout << "克隆 fastweb...\n";
- if (run_cmd("cd \"" + root + "\" && "
- "git clone https://git.ddtalk.net/1585346868/fastweb.git") != 0) {
- return false;
- }
- }
- // Never run fastweb's own build.sh — it re-clones/rebuilds ylib.
- // NGS already provides system ylib + HPSocket; only build fastweb itself.
- if (!patch_ylib_link(repo, debug)) {
- std::cerr << "修正 ylib 链接失败。\n";
- return false;
- }
- remove_path(join_path(repo, "build"));
- const std::string build_type = debug ? "Debug" : "Release";
- std::cout << "编译安装 fastweb -> " << system_prefix()
- << " (" << build_type << ")...\n";
- std::cout << " (不执行 fastweb 自带 build.sh;直接 cmake/make/make install)\n";
- return run_cmd(
- toolchain_env() +
- "cd \"" + repo + "\" && "
- "mkdir -p build && cd build && "
- "cmake .. -DCMAKE_BUILD_TYPE=" + build_type + " && "
- "make -j\"$(nproc)\" && make install") == 0;
- }
- void remove_legacy_ngs_install() {
- remove_path(join_path(software_root(), "fastweb"));
- remove_path(join_path(software_root(), "3rdparty"));
- remove_path(join_path(software_root(), "lua54"));
- remove_path(join_path(software_root(), "luarocks"));
- remove_path(join_path(software_root(), ".build/fastweb"));
- }
- } // namespace
- std::string install_dir() {
- return system_prefix();
- }
- std::string bin_path() {
- return fastweb_bin();
- }
- std::string share_dir() {
- return join_path(system_prefix(), "share/fastweb");
- }
- bool is_installed() {
- return fastweb_bin_installed();
- }
- std::string installed_version() {
- const std::string path = version_file();
- if (path_exists(path)) {
- std::ifstream in(path);
- std::string ver;
- if (in && std::getline(in, ver) && !ver.empty()) {
- return ver;
- }
- }
- return is_installed() ? std::string(kDefaultVersion) : "";
- }
- void show_status() {
- std::cout << "安装前缀: " << install_dir() << "\n";
- std::cout << "构建目录: " << build_root() << "\n";
- std::cout << "可执行文件: " << fastweb_bin() << "\n";
- std::cout << "模板目录: " << share_dir() << "\n";
- std::cout << "Lua: " << lua_prefix()
- << (lua_installed() ? " [已安装]" : " [未安装]") << "\n";
- std::cout << "LuaRocks: " << luarocks_prefix()
- << (luarocks_installed() ? " [已安装]" : " [未安装]") << "\n";
- std::cout << "ylib: "
- << (ylib_present() ? "[系统已有]" : "[缺失,请先 ./build.sh]") << "\n";
- std::cout << "HPSocket: "
- << (hpsocket_present() ? "[系统已有]" : "[缺失,请先 ./build.sh]") << "\n";
- if (is_installed()) {
- std::cout << "状态: 已安装\n";
- std::cout << "版本: " << installed_version() << "\n";
- } else {
- std::cout << "状态: 未安装\n";
- }
- }
- bool install(bool debug) {
- if (lua_installed() && luarocks_installed() && is_installed()) {
- std::cout << "Fastweb 及相关组件已安装。\n";
- std::cout << "如需重装,请先卸载。\n";
- return false;
- }
- if (!ylib_present() || !hpsocket_present()) {
- std::cerr << "缺少系统依赖 ylib / HPSocket。\n"
- << "请先在 NGS 根目录执行 ./build.sh 完成初始化。\n";
- return false;
- }
- std::cout << "检测到系统已安装 ylib / HPSocket,跳过重复编译。\n";
- std::cout << "清理并创建构建目录: " << build_root() << "\n";
- remove_path(build_root());
- if (!ensure_dir(build_root())) {
- std::cerr << "无法创建构建目录。\n";
- return false;
- }
- if (!install_apt_deps()) {
- std::cerr << "系统依赖安装失败。\n";
- return false;
- }
- if (!lua_installed()) {
- if (!install_lua(build_root())) {
- std::cerr << "Lua 安装失败。\n";
- return false;
- }
- } else {
- std::cout << "Lua 已安装,跳过。\n";
- }
- if (!luarocks_installed()) {
- if (!install_luarocks(build_root())) {
- std::cerr << "LuaRocks 安装失败。\n";
- return false;
- }
- } else {
- std::cout << "LuaRocks 已安装,跳过。\n";
- }
- if (!build_fastweb(debug)) {
- std::cerr << "fastweb 编译安装失败。\n";
- return false;
- }
- write_version_file(kDefaultVersion, debug);
- remove_legacy_ngs_install();
- std::cout << "\nFastweb " << kDefaultVersion << " 安装成功。\n";
- log_info(std::string("fastweb installed version=") + kDefaultVersion +
- " debug=" + (debug ? "1" : "0") + " prefix=/usr/local");
- std::cout << "安装前缀: " << install_dir() << "\n";
- std::cout << "可执行文件: " << fastweb_bin() << "\n";
- std::cout << "模板目录: " << share_dir() << "\n";
- return true;
- }
- bool uninstall() {
- const bool has_fw = is_installed() || is_dir(share_dir());
- const bool has_lua = lua_installed() || is_dir(lua_prefix());
- const bool has_rocks = luarocks_installed() || is_dir(luarocks_prefix());
- const bool has_build = is_dir(build_root());
- const bool has_legacy = is_dir(join_path(software_root(), "fastweb")) ||
- is_dir(join_path(software_root(), "3rdparty"));
- if (!has_fw && !has_lua && !has_rocks && !has_build && !has_legacy) {
- std::cout << "Fastweb 未安装,无需卸载。\n";
- return true;
- }
- std::cout << "卸载 Fastweb(保留系统 ylib / HPSocket)...\n";
- remove_path(fastweb_bin());
- remove_path(join_path(system_prefix(), "lib/libfastwebcore.so"));
- remove_path(share_dir());
- remove_path(join_path(system_prefix(), "include/fastweb"));
- remove_path(join_path(system_prefix(), "include/sol"));
- remove_path(lua_prefix());
- remove_path(luarocks_prefix());
- remove_path(build_root());
- remove_legacy_ngs_install();
- std::cout << "Fastweb 已卸载。\n";
- log_info("fastweb uninstalled");
- return true;
- }
- void menu() {
- while (true) {
- print_header("软件管理 - Fastweb");
- show_status();
- std::cout << "\n";
- std::cout << " 1) 安装 Fastweb (Release)\n";
- std::cout << " 2) 安装 Fastweb (Debug)\n";
- std::cout << " 3) 卸载 Fastweb\n";
- std::cout << " 0) 返回上级\n\n";
- int choice = read_choice("请选择: ");
- switch (choice) {
- case 1:
- case 2: {
- const bool debug = (choice == 2);
- std::cout << "\n确认安装 Fastweb " << kDefaultVersion
- << "\n Lua/LuaRocks -> /opt"
- << "\n Fastweb -> /usr/local (cmake/make/make install)"
- << "\n ylib/HPSocket 使用 NGS 已安装的系统库"
- << " [" << (debug ? "Debug" : "Release") << "] ? [y/N]: ";
- std::string confirm;
- std::getline(std::cin, confirm);
- if (confirm == "y" || confirm == "Y") {
- install(debug);
- } else {
- std::cout << "已取消。\n";
- }
- pause();
- break;
- }
- case 3: {
- std::cout << "\n确认卸载 Fastweb(含 /opt/lua54、/opt/luarocks,"
- "不删除 ylib/HPSocket)? [y/N]: ";
- std::string confirm;
- std::getline(std::cin, confirm);
- if (confirm == "y" || confirm == "Y") {
- uninstall();
- } else {
- std::cout << "已取消。\n";
- }
- pause();
- break;
- }
- case 0:
- return;
- default:
- std::cout << "无效选项。\n";
- pause();
- break;
- }
- }
- }
- } // namespace fastweb
- } // namespace ngs
|