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

相关推荐
CC__xy1 小时前
demo 通讯录 + 城市选择器 (字母索引左右联动 ListItemGroup+AlphabetIndexer)笔记
windows
LZQqqqqo9 小时前
C# 中 ArrayList动态数组、List<T>列表与 Dictionary<T Key, T Value>字典的深度对比
windows·c#·list
季春二九9 小时前
Windows 11 首次开机引导(OOBE 阶段)跳过登录微软账户,创建本地账户
windows·microsoft
芥子沫10 小时前
Jenkins常见问题及解决方法
windows·https·jenkins
cpsvps_net1 天前
美国服务器环境下Windows容器工作负载智能弹性伸缩
windows
甄超锋1 天前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
cpsvps1 天前
美国服务器环境下Windows容器工作负载基于指标的自动扩缩
windows
网硕互联的小客服1 天前
Apache 如何支持SHTML(SSI)的配置方法
运维·服务器·网络·windows·php
etcix1 天前
implement copy file content to clipboard on Windows
windows·stm32·单片机
许泽宇的技术分享1 天前
Windows MCP.Net:基于.NET的Windows桌面自动化MCP服务器深度解析
windows·自动化·.net