Windows環境下基于CMake構建Lua

慈雲數據 7個月前 (05-09) 技術支持 42 0

Windows環境下基于CMake構建Lua

  • 環境
    • `!!!注意: lua-5.4.6.tar.gz壓縮包中,并未提供luac.c文件,無法構建luac.exe,可以從lua-5.4.5.tar.gz壓縮包中拷貝使用`
    • 一、搭建基于CMake構建的Lua環境
    • 二、構建步驟
      • 2.1 命令
      • 2.2 驗證

        環境

        Lua

        Windows環境下基于CMake構建Lua
        (圖片來源網絡,侵删)

        下載地址

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

        Windows環境下基于CMake構建Lua
        (圖片來源網絡,侵删)

        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環境

        目錄結構

        Python
        5.4.6
        ├── build_vs2022_x64/ : 構建目錄
        ├── dist/: 安裝目錄
        ├── src/: 源碼目錄
        └── CMakeLists.txt
        

        CMakeLists.txt

        !!!相關配置根據源碼包中的makefile文件和luaconf.h頭文件确定

        Python
        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)
        # 判斷當前使用的編譯環境
        # 基于生成器表達式
        # $: 當項目所用編程語言匹配language,
        #   且項目所用編譯器匹配compiler_ids時,此表達式返回1,否則返回0
        set(gcc_like_c "$")
        set(msvc_like_c "$")
        # 爲接口庫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編譯選項說明:
        #   -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 
            "$"
            "$"
        )
        # target_compile_definitions: 專注于定義編譯器中的宏,這些宏可以在源代碼中使用。
        # -Dxxx表示宏定義
        # 配置都是來自makefile
        target_compile_definitions(project_c_compiler_flags INTERFACE
            "$"
        )
        # 編譯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 
                "$"
            )    
            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 $)
        target_include_directories(${LUA_EXE} PUBLIC $)
        target_include_directories(${LUAC_EXE} PUBLIC $)
        # 鏈接上述綁定的接口庫
        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 $
            ARCHIVE DESTINATION $
            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 $
        )
        install(TARGETS ${LUAC_EXE}
            EXPORT ${LUAC_EXE}-Targets
            RUNTIME DESTINATION $
        )
        

        二、構建步驟

        2.1 命令

        Python
        > 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 驗證

        Python
        > cd @lua-cmake-install目錄
        > lua -v
        > Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
        

微信掃一掃加客服

微信掃一掃加客服

點擊啓動AI問答
Draggable Icon