Windows环境下基于CMake构建Lua

Windows环境下基于CMake构建Lua

  • 环境
    • [`!!!注意: lua-5.4.6.tar.gz压缩包中,并未提供luac.c文件,无法构建luac.exe,可以从lua-5.4.5.tar.gz压缩包中拷贝使用`](#!!!注意: lua-5.4.6.tar.gz压缩包中,并未提供luac.c文件,无法构建luac.exe,可以从lua-5.4.5.tar.gz压缩包中拷贝使用)
  • 一、搭建基于CMake构建的Lua环境
  • 二、构建步骤
    • [2.1 命令](#2.1 命令)
    • [2.2 验证](#2.2 验证)

环境

Lua

下载地址

lua-5.4.6.tar.gz:https://www.lua.org/ftp/lua-5.4.6.tar.gz

lua-5.4.5.tar.gz:https://www.lua.org/ftp/lua-5.4.5.tar.gz

CMake

下载地址

官方:https://cmake.org/download/


!!!注意: lua-5.4.6.tar.gz压缩包中,并未提供luac.c文件,无法构建luac.exe,可以从lua-5.4.5.tar.gz压缩包中拷贝使用

一、搭建基于CMake构建的Lua环境

目录结构

shell 复制代码
5.4.6
├── build_vs2022_x64/ : 构建目录
├── dist/: 安装目录
├── src/: 源码目录
└── CMakeLists.txt

CMakeLists.txt
!!!相关配置根据源码包中的makefile文件和luaconf.h头文件确定

shell 复制代码
cmake_minimum_required(VERSION 3.20)

# 解决方案名字:lua
# 版本规则:主版本.子版本.修订版本.日期-阶段版本
# 构建语言:C/C++
# 构建目录:默认值为${PROJECT_BINARY_DIR}
project(
    lua
    VERSION 0.0.0.20240430
    LANGUAGES C CXX
)

# 使用C99标准 参照源码中的makefile选项:-std=c99
# 设为True:如果编译器不支持C99标准 构建过程报错停止
# 方式一:利用set指定 the C++ standard
#set(CMAKE_C_STANDARD_REQUIRED True)
#set(CMAKE_C_STANDARD 99)
# 方式二:利用接口库的形式
# https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_C_KNOWN_FEATURES.html
add_library(project_c_compiler_flags INTERFACE)
target_compile_features(project_c_compiler_flags INTERFACE c_std_99)

# 设置debug模式的标记
set(CMAKE_DEBUG_POSTFIX d)

# 判断当前使用的编译环境
# 基于生成器表达式
# $<COMPILE_LANG_AND_ID:language,compiler_ids>: 当项目所用编程语言匹配language,
#   且项目所用编译器匹配compiler_ids时,此表达式返回1,否则返回0
set(gcc_like_c "$<COMPILE_LANG_AND_ID:C,ARMClang,AppleClang,Clang,GNU,LCC>")
set(msvc_like_c "$<COMPILE_LANG_AND_ID:C,MSVC>")

# 为接口库project_c_compiler_flags 增加编译警告选项
# INTERFACE作用域表示project_c_compiler_flags 本身不需要,但是project_c_compiler_flags调用方需要使用
# 我们只想在编译阶段使用警告选项,而不会在安装阶段使用,可以利用BUILD_INTERFACE限制
# GCC警告说明:
# - 适用于C和C++的警告标志
#    -Wall: 启用大多数警告
#    -Wfatal-errors: 将所有警告视为错误,导致编译失败
#    -Wextra: 启用额外的警告,包括未使用的参数、未使用的函数返回值等
#    -Wshadow: 警告声明变量时隐藏了外层作用域中的变量
#    -Wundef: 警告使用未定义的宏
#    -Wwrite-strings: 警告将字符串常量赋值给非const char指针
#    -Wredundant-decls: 警告冗余的声明
#    -Wdisabled-optimization: 警告禁用的优化
#    -Wdouble-promotion: 警告双精度提升
#    -Wmissing-declarations: 警告未声明的函数
#    -Wformat=2:则启用了与格式化字符串相关的严格警告
#    -Wunused:警告未使用的代码元素
# - 不适用于C++的警告标志
#    -Wdeclaration-after-statement: 警告在语句之后声明变量
#    -Wmissing-prototypes: 警告缺少函数原型
#    -Wnested-externs: 警告嵌套的extern声明
#    -Wstrict-prototypes: 警告函数原型不符合严格的C标准
#    -Wc++-compat: 警告C++风格的兼容性问题
#    -Wold-style-definition: 警告使用旧的函数定义风格
# MSVC警告说明:
#   基于等级的警告系统:/W1, /W2, /W3, /W4
#   - /W4 通常被认为是最严格的警告级别,类似于GCC的 -Wall 和 -Wextra 的组合
#   -Wfatal-errors (GCC/Clang) 类似对应:/WX
set(GCC_C_WARNING_FLAGS "-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused")
set(MSVC_C_WARNING_FLAGS "/W4")
target_compile_options(project_c_compiler_flags INTERFACE 
    "$<${gcc_like_c}:$<BUILD_INTERFACE:${GCC_C_WARNING_FLAGS}>>"
    "$<${msvc_like_c}:$<BUILD_INTERFACE:${MSVC_C_WARNING_FLAGS}>>"
)

# 设置编译器标志
# GCC编译选项说明:
#   -std=c99:GCC按照C99标准编译代码
#   -O2: 编译器优化选项,表示使用第二级优化
#   -fno-stack-protector:指示编译器禁用堆栈保护器。当这个选项被设置时,编译器不会为函数生成堆栈保护代码,这可能会提高代码的执行效率,但也会降低对堆栈溢出攻击的防护能力。
#   -fno-common:指示编译器不要使用 common 段来存储未初始化的全局变量。通常,未初始化的全局变量会被放置在 common 段中,并在链接时合并。
#                禁用这个特性会导致每个未初始化的全局变量都有自己的存储空间,这可能会增加最终二进制文件的大小。这个选项有助于确保代码的行为更加确定,特别是在涉及多个编译单元和未初始化全局变量时。
#   -march=native:编译器针对当前运行的机器生成优化的机器代码。它会利用当前机器的特定指令集和功能来生成代码,从而可能提高程序的执行速度。
#                  然而,这也会降低代码在其他硬件上的可移植性,因为生成的代码可能依赖于当前机器的特定功能。
# MSVC编译选项说明:
#   -std=c99 (GCC/Clang) 类似对应:/std:c99
#   -O2 (GCC/Clang) 类似对应:/O2
#   /Ox:启用最大优化,这通常是 /O2 和其他优化选项的组合
#   /Od:禁用所有优化
#   /Zc:inline:强制内联函数的内联
#   /Zi: 生成调试信息 
#   /Gm-:禁用最小重新生成
#   /EHsc: 选择 C++ 异常处理模型
#   /RTC1: 启用运行时检查
#   /arch:SSE2、/arch:AVX:MSVC需要手动指定目标处理器架构和指令集,不会像GCC的-march=native自动检测。
# GCC
# 在当前的 GCC_C_COMPILER_FLAGS 值的基础上追加 -std=c99 编译选项,然后更新 GCC_C_COMPILER_FLAGS 变量的值
set(GCC_C_COMPILER_FLAGS "${CMAKE_C_FLAGS}")
# 编译选项 参照源码中的makefile选项
set(GCC_C_COMPILER_FLAGS "${GCC_C_COMPILER_FLAGS} -std=c99;-O2;-fno-stack-protector;-fno-common;-march=native")
# MSVC
# 在当前的 MSVC_C_COMPILER_FLAGS 值的基础上追加 /std:c99 编译选项,然后更新 MSVC_C_COMPILER_FLAGS 变量的值
set(MSVC_C_COMPILER_FLAGS "${CMAKE_C_FLAGS}")
set(MSVC_C_COMPILER_FLAGS "${MSVC_C_COMPILER_FLAGS} /std:c99")
# target_compile_options: 专注于设置编译器的行为或特性,比如优化级别、警告级别、语言标准等。
target_compile_options(project_c_compiler_flags INTERFACE 
    "$<${gcc_like_c}:$<BUILD_INTERFACE:${GCC_C_COMPILER_FLAGS}>>"
    "$<${msvc_like_c}:$<BUILD_INTERFACE:${MSVC_C_COMPILER_FLAGS}>>"
)
# target_compile_definitions: 专注于定义编译器中的宏,这些宏可以在源代码中使用。
# -Dxxx表示宏定义
# 配置都是来自makefile
target_compile_definitions(project_c_compiler_flags INTERFACE
    "$<${gcc_like_c}:$<BUILD_INTERFACE:-DLUA_USE_LINUX;-DLUA_USE_READLINE>>"
)

# 编译dll选项:
# LUA_BUILD_AS_DLL 默认为ON 生成windows的dll
option(LUA_BUILD_AS_DLL "Build for Windows dll." OFF)
if(LUA_BUILD_AS_DLL)
    # 源码文件luaconf.h中,定义宏LUA_BUILD_AS_DLL用来确定Windows dll的生成定义
    target_compile_definitions(project_c_compiler_flags INTERFACE 
        "$<${msvc_like_c}:$<BUILD_INTERFACE:-DLUA_BUILD_AS_DLL>>"
    )    
    message(STATUS "LUA_BUILD_AS_DLL=ON")
endif()

# 源码目录
file(GLOB LUA_LIB_SRC ${PROJECT_SOURCE_DIR}/src/*.h ${PROJECT_SOURCE_DIR}/src/*.c)
set(LUA_EXE_SRC ${LUA_LIB_SRC})
set(LUAC_EXE_SRC ${LUA_LIB_SRC})
set(LUA_EXE_MAIN ${PROJECT_SOURCE_DIR}/src/lua.c)
set(LUAC_EXE_MAIN ${PROJECT_SOURCE_DIR}/src/luac.c)
set(ONE_LUA_MAIN ${PROJECT_SOURCE_DIR}/src/onelua.c)
# liblua 不包含 luac.c luac.c
list(REMOVE_ITEM LUA_LIB_SRC ${LUA_EXE_MAIN} ${LUAC_EXE_MAIN} ${ONE_LUA_MAIN})
# lua.exe 不包含 luac.c
list(REMOVE_ITEM LUA_EXE_SRC ${LUAC_EXE_MAIN} ${ONE_LUA_MAIN})
# luac.exe 不包含 lua.c
list(REMOVE_ITEM LUAC_EXE_SRC ${LUA_EXE_MAIN} ${ONE_LUA_MAIN})
#message(STATUS "【${LUAC_EXE_SRC}】")

# 版本 
set(LUA_VERSION 050406)
#set(LUA_LIB lib${PROJECT_NAME}${LUA_VERSION})
#set(LUA_EXE ${PROJECT_NAME}${LUA_VERSION})
#set(LUAC_EXE ${PROJECT_NAME}c${LUA_VERSION})
set(LUA_LIB lib${PROJECT_NAME})
set(LUA_EXE ${PROJECT_NAME})
set(LUAC_EXE ${PROJECT_NAME}c)

message(STATUS "Lua Library Name:" ${LUA_LIB})
message(STATUS "Lua Executable Name:" ${LUA_EXE})
message(STATUS "Luac Executable Name:" ${LUAC_EXE})
message(STATUS "Lua Project Dir:" ${PROJECT_SOURCE_DIR})

# 创建目标
add_library(${LUA_LIB} ${LUA_LIB_SRC})
add_executable(${LUA_EXE} ${LUA_EXE_SRC})
add_executable(${LUAC_EXE} ${LUAC_EXE_SRC})

# 链接
# 包含添加目录
# ${PROJECT_SOURCE_DIR}: 表示项目主CMakeLists.txt文件所在目录
target_include_directories(${LUA_LIB} PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)
target_include_directories(${LUA_EXE} PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)
target_include_directories(${LUAC_EXE} PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)

# 链接上述绑定的接口库
target_link_libraries(${LUA_LIB} PRIVATE project_c_compiler_flags)
target_link_libraries(${LUA_EXE} PUBLIC project_c_compiler_flags)
target_link_libraries(${LUAC_EXE} PUBLIC project_c_compiler_flags)

# 生成结果后 需要安装
# 配置默认安装路径
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/dist)
endif()

# EXPORT可以导出其他CMake项目直接使用此项目的信息
# 导出后可以将信息输出到xxx.cmake文件,方便其它项目find_package调用
# ${CMAKE_INSTALL_INCLUDEDIR}: include
# make cache variables for install destinations
include(GNUInstallDirs)
message(STATUS "Lua install dir:" ${CMAKE_INSTALL_PREFIX})
message(STATUS "Lua install include dir:" "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}")

set(LIBLUA_INTSALL_TARGET ${LUA_LIB}-Targets)
# INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}"
install(TARGETS ${LUA_LIB}
    EXPORT ${LIBLUA_INTSALL_TARGET}
    LIBRARY DESTINATION $<IF:$<CONFIG:Debug>,libd,lib>
    ARCHIVE DESTINATION $<IF:$<CONFIG:Debug>,libd,lib>
    INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}"
)
# 安装include
install(FILES ${PROJECT_SOURCE_DIR}/src/lauxlib.h ${PROJECT_SOURCE_DIR}/src/lua.h ${PROJECT_SOURCE_DIR}/src/luaconf.h ${PROJECT_SOURCE_DIR}/src/lualib.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}")

# 关于exe install
install(TARGETS ${LUA_EXE}
    EXPORT ${LUA_EXE}-Targets
    RUNTIME DESTINATION $<IF:$<CONFIG:Debug>,bind,bin>
)
install(TARGETS ${LUAC_EXE}
    EXPORT ${LUAC_EXE}-Targets
    RUNTIME DESTINATION $<IF:$<CONFIG:Debug>,bind,bin>
)

二、构建步骤

2.1 命令

shell 复制代码
> cd @lua-5.4.6.tar.gz解压目录
> cmake -S . -B .\build_vs2022_x64\ -G "Visual Studio 17 2022"
> cmake --build .\build_vs2022_x64\ --config Debug -v --clean-first
> cmake --install .\build_vs2022_x64\ --prefix .\dist --config Debug -v

2.2 验证

shell 复制代码
> cd @lua-cmake-install目录
> lua -v
> Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio

相关推荐
程序员徐师兄2 小时前
Windows JDK11 下载安装教程,适合新手
java·windows·jdk11 下载安装·jdk11 下载教程
编码者卢布5 小时前
【App Service】Java应用上传文件功能部署在App Service Windows上报错 413 Payload Too Large
java·开发语言·windows
多来哈米7 小时前
openclaw在Windows部署
windows·openclaw
视觉AI7 小时前
【踩坑实录】Windows ICS 共享网络下,国产化盒子 SSH 连接异常的完整分析
网络·windows·ssh
小王不爱笑13210 小时前
Postman 使用教程
测试工具·lua·postman
qq_2466461911 小时前
openclaw快速安装-windows版
windows·stm32·单片机
sonrisa_12 小时前
Python同一类不同方法中变量值的传递
开发语言·windows·python
玖釉-12 小时前
探索连续细节层次(Continuous LOD):深入解析 NVIDIA 的 nv_cluster_lod_builder
c++·windows·图形渲染
MyY_DO12 小时前
第九课ida与花指令
windows·od
多多*13 小时前
Mysql数据库相关 事务 MVCC与锁的爱恨情仇 锁的层次架构 InnoDB锁分析
java·数据库·windows·sql·oracle·面试·哈希算法