Skip to content

Instantly share code, notes, and snippets.

@CandyMi
Last active March 14, 2024 08:25
Show Gist options
  • Save CandyMi/37e3069973730cd9a5a0e990658a8074 to your computer and use it in GitHub Desktop.
Save CandyMi/37e3069973730cd9a5a0e990658a8074 to your computer and use it in GitHub Desktop.
Build lua from cmake

介绍

LuaCMAKE 构建配置文件

支持

目前已测试的平台与支持的编译器

编译器

  • MSVC

  • gcc

  • clang

平台

  • Windows

  • Linux

  • MacOS

  • FreeBSD

使用

  • src目录下创建CMakeLists.txt文件, 并将下面内容复制进去.

  • 然后在src目录运行命令 cmake -B build && cmake --build build

优势

  • 可选的并行编译与缓存加速,可以更快构建并且降低调试成本.

  • 内部脚本自动检测平台, 减少手动配置带来的复杂性.

  • 简化开发者的构建成本, 将重心集中在语言与业务.

  • 更方便的为开发者支持C/CXX两种编译方式.

  • 更智能的警告和错误提示.

替换

如果您想使用C++进行编译又想按照C标准导入/导出符号,那么可以根据自己的平台在luadir/src目录选择下面的命令运行.

不过,需要注意的是: 运行下面的脚本之后必须使用C++编译器进行编译,否则会引起编译错误.

1. Windows

使用PowerShell来快速替换.

# 修改符号导出规则适应`C`与`C++`
if (-not (Test-Path "luaconf.h.old")) {
  Rename-Item "luaconf.h" "luaconf.h.old"
}

Get-Content luaconf.h.old | ForEach-Object { $_.replace('__declspec(dllexport)', 'extern "C" __declspec(dllexport)') } | Set-Content luaconf.h

Remove-Item "luaconf.h.old"

2. Posix Like

使用下面的命令替换即可.

#!/usr/bin/env bash 
perl -pi -e "s/#define LUA_API\t\textern$/#ifdef __cplusplus\n#define LUA_API extern \"C\"\n#else\n#define LUA_API extern\n#endif/g" luaconf.h

最后

  • 如果你的宿主程序使用C++编写, 推荐使用C++编译器进行编译. 否则可能无法保障RAII的完整性.

  • 您将LUAI_THROW替换为try/catch/throw后,在性能上会受到一定影响(具体数值以实际为准).

cmake_minimum_required(VERSION 2.8...3.12)
project(lua)
# Lua 头文件
set(LIBLUA_INCLUDE lua.h luaconf.h lualib.h lauxlib.h lua.hpp)
file(GLOB LUA_SOURCES lua.c)
file(GLOB LUAC_SOURCES luac.c)
file(GLOB LIBLUA_SOURCES l*.c)
list(REMOVE_ITEM LIBLUA_SOURCES ${LUA_SOURCES})
list(REMOVE_ITEM LIBLUA_SOURCES ${LUAC_SOURCES})
# 可选C++编译器
if (USE_CXX)
set_source_files_properties(${LUA_SOURCES} ${LUAC_SOURCES} ${LIBLUA_SOURCES} PROPERTIES LANGUAGE CXX)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Clang 编译器会有警告
add_compile_options(-Wno-deprecated)
endif()
endif()
# 增加 CCache 支持
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif()
# 生成 Liblua
add_library(liblua_object OBJECT ${LIBLUA_SOURCES})
add_library(liblua STATIC $<TARGET_OBJECTS:liblua_object>)
if (WIN32)
add_library(liblua-dll SHARED $<TARGET_OBJECTS:liblua_object>)
target_compile_definitions(liblua-dll PRIVATE LUA_BUILD_AS_DLL LUA_COMPAT_5_3 LUA_COMPAT_5_2)
else()
add_definitions(-DLUA_USE_POSIX -DLUA_USE_DLOPEN -DLUA_COMPAT_5_3 -DLUA_COMPAT_5_2)
target_compile_options(liblua PRIVATE -fPIC -pipe)
target_link_libraries(liblua PRIVATE dl PRIVATE m)
endif()
# Liblua 静态库
set_target_properties (liblua PROPERTIES PUBLIC_HEADER "${LIBLUA_INCLUDE}" OUTPUT_NAME "liblua" PREFIX "")
install (TARGETS liblua ARCHIVE DESTINATION lib PUBLIC_HEADER DESTINATION include)
# Liblua 共享库
if (WIN32)
set_target_properties(liblua-dll PROPERTIES OUTPUT_NAME "liblua" PREFIX "")
install(TARGETS liblua-dll LIBRARY DESTINATION lib)
endif()
# 生成 Lua 可执行文件
if (LUA_SOURCES)
add_executable(lua ${LUA_SOURCES})
if (NOT WIN32) # 自动检测是否存在`ReadLine`
find_path(READLINE_INC_FOUND NAMES readline/readline.h)
find_library(READLINE_LIB_FOUND NAMES readline)
endif()
if (READLINE_INC_FOUND AND READLINE_LIB_FOUND)
add_definitions(-DLUA_USE_READLINE)
target_link_libraries(lua PRIVATE liblua PRIVATE readline)
else()
target_link_libraries(lua PRIVATE liblua)
endif()
install(TARGETS lua RUNTIME DESTINATION bin)
else()
message("[Warning]: Unable to generate `lua.exe`, the `lua.c` file cannot be found.")
endif()
# 生成 Luac 可执行文件
if(LUAC_SOURCES)
add_executable(luac ${LUAC_SOURCES})
target_link_libraries(luac PRIVATE liblua)
install(TARGETS luac RUNTIME DESTINATION bin)
else()
message("[Warning]: Unable to generate `luac.exe`, the `luac.c` file cannot be found.")
endif()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment