diff options
31 files changed, 607 insertions, 114 deletions
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 3bfaa54..8ef4d7d 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -156,6 +156,7 @@ All Modules /module/FindMPEG2 /module/FindMPEG /module/FindMPI + /module/FindODBC /module/FindOpenACC /module/FindOpenAL /module/FindOpenCL diff --git a/Help/module/FindODBC.rst b/Help/module/FindODBC.rst new file mode 100644 index 0000000..8558334 --- /dev/null +++ b/Help/module/FindODBC.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindODBC.cmake diff --git a/Help/release/dev/FindODBC-module.rst b/Help/release/dev/FindODBC-module.rst new file mode 100644 index 0000000..f270e8e --- /dev/null +++ b/Help/release/dev/FindODBC-module.rst @@ -0,0 +1,5 @@ +FindODBC-module +--------------- + +* A :module:`FindODBC` module was added to find an Open Database Connectivity + (ODBC) library. diff --git a/Modules/FindBZip2.cmake b/Modules/FindBZip2.cmake index 0375b09..4d7123d 100644 --- a/Modules/FindBZip2.cmake +++ b/Modules/FindBZip2.cmake @@ -18,13 +18,24 @@ # # This module defines the following variables: # -# :: +# ``BZIP2_FOUND`` +# system has BZip2 +# ``BZIP2_INCLUDE_DIRS`` +# the BZip2 include directories +# ``BZIP2_LIBRARIES`` +# Link these to use BZip2 +# ``BZIP2_NEED_PREFIX`` +# this is set if the functions are prefixed with ``BZ2_`` +# ``BZIP2_VERSION_STRING`` +# the version of BZip2 found # -# BZIP2_FOUND - system has BZip2 -# BZIP2_INCLUDE_DIR - the BZip2 include directory -# BZIP2_LIBRARIES - Link these to use BZip2 -# BZIP2_NEED_PREFIX - this is set if the functions are prefixed with BZ2_ -# BZIP2_VERSION_STRING - the version of BZip2 found (since CMake 2.8.8) +# Cache variables +# ^^^^^^^^^^^^^^^ +# +# The following cache variables may also be set: +# +# ``BZIP2_INCLUDE_DIR`` +# the BZip2 include directory set(_BZIP2_PATHS PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Bzip2;InstallPath]" @@ -53,6 +64,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(BZip2 VERSION_VAR BZIP2_VERSION_STRING) if (BZIP2_FOUND) + set(BZIP2_INCLUDE_DIRS ${BZIP2_INCLUDE_DIR}) include(${CMAKE_CURRENT_LIST_DIR}/CheckSymbolExists.cmake) include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake) cmake_push_check_state() diff --git a/Modules/FindLua.cmake b/Modules/FindLua.cmake index 7eba206..8f35fc7 100644 --- a/Modules/FindLua.cmake +++ b/Modules/FindLua.cmake @@ -39,9 +39,16 @@ unset(_lua_include_subdirs) unset(_lua_library_names) unset(_lua_append_versions) +set(_lua_additional_paths + ~/Library/Frameworks + /Library/Frameworks + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt) # this is a function only to have all the variables inside go away automatically -function(_lua_set_version_vars) +function(_lua_get_versions) set(LUA_VERSIONS5 5.3 5.2 5.1 5.0) if (Lua_FIND_VERSION_EXACT) @@ -59,6 +66,10 @@ function(_lua_set_version_vars) list(APPEND _lua_append_versions ${subver}) endif () endforeach () + # New version -> Search for it (heuristic only! Defines in include might have changed) + if (NOT _lua_append_versions) + set(_lua_append_versions ${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}) + endif() endif () endif () else () @@ -66,22 +77,42 @@ function(_lua_set_version_vars) set(_lua_append_versions ${LUA_VERSIONS5}) endif () - list(APPEND _lua_include_subdirs "include/lua" "include") + if (LUA_Debug) + message(STATUS "Considering following Lua versions: ${_lua_append_versions}") + endif() + + set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE) +endfunction() + +function(_lua_set_version_vars) + set(_lua_include_subdirs_raw "lua") foreach (ver IN LISTS _lua_append_versions) string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _ver "${ver}") - list(APPEND _lua_include_subdirs - include/lua${CMAKE_MATCH_1}${CMAKE_MATCH_2} - include/lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2} - include/lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2} + list(APPEND _lua_include_subdirs_raw + lua${CMAKE_MATCH_1}${CMAKE_MATCH_2} + lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2} + lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2} ) endforeach () + # Prepend "include/" to each path directly after the path + set(_lua_include_subdirs "include") + foreach (dir IN LISTS _lua_include_subdirs_raw) + list(APPEND _lua_include_subdirs "${dir}" "include/${dir}") + endforeach () + set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE) - set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE) endfunction(_lua_set_version_vars) -function(_lua_check_header_version _hdr_file) +function(_lua_get_header_version) + unset(LUA_VERSION_STRING PARENT_SCOPE) + set(_hdr_file "${LUA_INCLUDE_DIR}/lua.h") + + if (NOT EXISTS "${_hdr_file}") + return() + endif () + # At least 5.[012] have different ways to express the version # so all of them need to be tested. Lua 5.2 defines LUA_VERSION # and LUA_RELEASE as joined by the C preprocessor, so avoid those. @@ -111,39 +142,54 @@ function(_lua_check_header_version _hdr_file) return() endif () endforeach () -endfunction(_lua_check_header_version) - -_lua_set_version_vars() - -if (LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h") - _lua_check_header_version("${LUA_INCLUDE_DIR}/lua.h") -endif () - -if (NOT LUA_VERSION_STRING) - foreach (subdir IN LISTS _lua_include_subdirs) - unset(LUA_INCLUDE_PREFIX CACHE) - unset(LUA_INCLUDE_PREFIX) - find_path(LUA_INCLUDE_PREFIX ${subdir}/lua.h - HINTS - ENV LUA_DIR - PATHS - ~/Library/Frameworks - /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt - ) - if (LUA_INCLUDE_PREFIX) - _lua_check_header_version("${LUA_INCLUDE_PREFIX}/${subdir}/lua.h") - if (LUA_VERSION_STRING) - set(LUA_INCLUDE_DIR "${LUA_INCLUDE_PREFIX}/${subdir}") +endfunction(_lua_get_header_version) + +function(_lua_find_header) + _lua_set_version_vars() + + # Initialize as local variable + set(CMAKE_IGNORE_PATH ${CMAKE_IGNORE_PATH}) + while (TRUE) + # Find the next header to test. Check each possible subdir in order + # This prefers e.g. higher versions as they are earlier in the list + # It is also consistent with previous versions of FindLua + foreach (subdir IN LISTS _lua_include_subdirs) + find_path(LUA_INCLUDE_DIR lua.h + HINTS + ENV LUA_DIR + PATH_SUFFIXES ${subdir} + PATHS ${_lua_additional_paths} + ) + if (LUA_INCLUDE_DIR) break() - endif () - endif () - endforeach () -endif () -unset(_lua_include_subdirs) + endif() + endforeach() + # Did not found header -> Fail + if (NOT LUA_INCLUDE_DIR) + return() + endif() + _lua_get_header_version() + # Found accepted version -> Ok + if (LUA_VERSION_STRING) + if (LUA_Debug) + message(STATUS "Found suitable version ${LUA_VERSION_STRING} in ${LUA_INCLUDE_DIR}/lua.h") + endif() + return() + endif() + # Found wrong version -> Ignore this path and retry + if (LUA_Debug) + message(STATUS "Ignoring unsuitable version in ${LUA_INCLUDE_DIR}") + endif() + list(APPEND CMAKE_IGNORE_PATH "${LUA_INCLUDE_DIR}") + unset(LUA_INCLUDE_DIR CACHE) + unset(LUA_INCLUDE_DIR) + unset(LUA_INCLUDE_DIR PARENT_SCOPE) + endwhile () +endfunction() + +_lua_get_versions() +_lua_find_header() +_lua_get_header_version() unset(_lua_append_versions) if (LUA_VERSION_STRING) @@ -160,13 +206,7 @@ find_library(LUA_LIBRARY HINTS ENV LUA_DIR PATH_SUFFIXES lib - PATHS - ~/Library/Frameworks - /Library/Frameworks - /sw - /opt/local - /opt/csw - /opt + PATHS ${_lua_additional_paths} ) unset(_lua_library_names) diff --git a/Modules/FindODBC.cmake b/Modules/FindODBC.cmake new file mode 100644 index 0000000..c8ca477 --- /dev/null +++ b/Modules/FindODBC.cmake @@ -0,0 +1,227 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindODBC +-------- + +Find an Open Database Connectivity (ODBC) include directory and library. + +On Windows, when building with Visual Studio, this module assumes the ODBC +library is provided by the available Windows SDK. + +On Unix, this module allows to search for ODBC library provided by +unixODBC or iODBC implementations of ODBC API. +This module reads hint about location of the config program: + +.. variable:: ODBC_CONFIG + + Location of odbc_config or iodbc-config program + +Otherwise, this module tries to find the config program, +first from unixODBC, then from iODBC. +If no config program found, this module searches for ODBC header +and library in list of known locations. + +Imported targets +^^^^^^^^^^^^^^^^ + +This module defines the following :prop_tgt:`IMPORTED` targets: + +.. variable:: ODBC::ODBC + + Imported target for using the ODBC library, if found. + +Result variables +^^^^^^^^^^^^^^^^ + +.. variable:: ODBC_FOUND + + Set to true if ODBC library found, otherwise false or undefined. + +.. variable:: ODBC_INCLUDE_DIRS + + Paths to include directories listed in one variable for use by ODBC client. + May be empty on Windows, where the include directory corresponding to the + expected Windows SDK is already available in the compilation environment. + +.. variable:: ODBC_LIBRARIES + + Paths to libraries to linked against to use ODBC. + May just a library name on Windows, where the library directory corresponding + to the expected Windows SDK is already available in the compilation environment. + +.. variable:: ODBC_CONFIG + + Path to unixODBC or iODBC config program, if found or specified. + +Cache variables +^^^^^^^^^^^^^^^ + +For users who wish to edit and control the module behavior, this module +reads hints about search locations from the following variables: + +.. variable:: ODBC_INCLUDE_DIR + + Path to ODBC include directory with ``sql.h`` header. + +.. variable:: ODBC_LIBRARY + + Path to ODBC library to be linked. + +These variables should not be used directly by project code. + +Limitations +^^^^^^^^^^^ + +On Windows, this module does not search for iODBC. +On Unix, there is no way to prefer unixODBC over iODBC, or vice versa, +other than providing the config program location using the ``ODBC_CONFIG``. +This module does not allow to search for a specific ODBC driver. + +#]=======================================================================] + +# Define lists used internally +set(_odbc_include_paths) +set(_odbc_lib_paths) +set(_odbc_lib_names) +set(_odbc_required_libs_names) + +### Try Windows Kits ########################################################## +if(WIN32) + # List names of ODBC libraries on Windows + set(ODBC_LIBRARY odbc32.lib) + set(_odbc_lib_names odbc32;) + + # List additional libraries required to use ODBC library + if(MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") + set(_odbc_required_libs_names odbccp32;ws2_32) + elseif(MINGW) + set(_odbc_required_libs_names odbccp32) + endif() +endif() + +### Try unixODBC or iODBC config program ###################################### +if (UNIX) + find_program(ODBC_CONFIG + NAMES odbc_config iodbc-config + DOC "Path to unixODBC or iODBC config program") + mark_as_advanced(ODBC_CONFIG) +endif() + +if (UNIX AND ODBC_CONFIG) + # unixODBC and iODBC accept unified command line options + execute_process(COMMAND ${ODBC_CONFIG} --cflags + OUTPUT_VARIABLE _cflags OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${ODBC_CONFIG} --libs + OUTPUT_VARIABLE _libs OUTPUT_STRIP_TRAILING_WHITESPACE) + + # Collect paths of include directories from CFLAGS + separate_arguments(_cflags NATIVE_COMMAND "${_cflags}") + foreach(arg IN LISTS _cflags) + if("${arg}" MATCHES "^-I(.*)$") + list(APPEND _odbc_include_paths "${CMAKE_MATCH_1}") + endif() + endforeach() + unset(_cflags) + + # Collect paths of library names and directories from LIBS + separate_arguments(_libs NATIVE_COMMAND "${_libs}") + foreach(arg IN LISTS _libs) + if("${arg}" MATCHES "^-L(.*)$") + list(APPEND _odbc_lib_paths "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(.*)$") + set(_lib_name ${CMAKE_MATCH_1}) + string(REGEX MATCH "odbc" _is_odbc ${_lib_name}) + if(_is_odbc) + list(APPEND _odbc_lib_names ${_lib_name}) + else() + list(APPEND _odbc_required_libs_names ${_lib_name}) + endif() + unset(_lib_name) + endif() + endforeach() + unset(_libs) +endif() + +### Try unixODBC or iODBC in include/lib filesystems ########################## +if (UNIX AND NOT ODBC_CONFIG) + # List names of both ODBC libraries, unixODBC and iODBC + set(_odbc_lib_names odbc;iodbc;unixodbc;) +endif() + +### Find include directories ################################################## +find_path(ODBC_INCLUDE_DIR + NAMES sql.h + PATHS ${_odbc_include_paths}) + +if(NOT ODBC_INCLUDE_DIR AND WIN32) + set(ODBC_INCLUDE_DIR "") +endif() + +### Find libraries ############################################################ +if(NOT ODBC_LIBRARY) + find_library(ODBC_LIBRARY + NAMES ${_odbc_lib_names} + PATHS ${_odbc_lib_paths} + PATH_SUFFIXES odbc) + + foreach(_lib IN LISTS _odbc_required_libs_names) + find_library(_lib_path + NAMES ${_lib} + PATHS ${_odbc_lib_paths} # system parths or collected from ODBC_CONFIG + PATH_SUFFIXES odbc) + if(_lib_path) + list(APPEND _odbc_required_libs_paths ${_lib_path}) + endif() + unset(_lib_path CACHE) + endforeach() +endif() + +# Unset internal lists as no longer used +unset(_odbc_include_paths) +unset(_odbc_lib_paths) +unset(_odbc_lib_names) +unset(_odbc_required_libs_names) + +### Set result variables ###################################################### +set(_odbc_required_vars ODBC_LIBRARY) +if(NOT WIN32) + list(APPEND _odbc_required_vars ODBC_INCLUDE_DIR) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(ODBC DEFAULT_MSG ${_odbc_required_vars}) + +unset(_odbc_required_vars) + +mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR) + +set(ODBC_INCLUDE_DIRS ${ODBC_INCLUDE_DIR}) +list(APPEND ODBC_LIBRARIES ${ODBC_LIBRARY}) +list(APPEND ODBC_LIBRARIES ${_odbc_required_libs_paths}) + +### Import targets ############################################################ +if(ODBC_FOUND) + if(NOT TARGET ODBC::ODBC) + if(IS_ABSOLUTE "${ODBC_LIBRARY}") + add_library(ODBC::ODBC UNKNOWN IMPORTED) + set_target_properties(ODBC::ODBC PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${ODBC_LIBRARY}") + else() + add_library(ODBC::ODBC INTERFACE IMPORTED) + set_target_properties(ODBC::ODBC PROPERTIES + IMPORTED_LIBNAME "${ODBC_LIBRARY}") + endif() + set_target_properties(ODBC::ODBC PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${ODBC_INCLUDE_DIR}") + + if(_odbc_required_libs_paths) + set_property(TARGET ODBC::ODBC APPEND PROPERTY + INTERFACE_LINK_LIBRARIES "${_odbc_required_libs_paths}") + endif() + endif() +endif() + +unset(_odbc_required_libs_paths) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 70ff631..36f8c7e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 11) -set(CMake_VERSION_PATCH 20180524) +set(CMake_VERSION_PATCH 20180525) #set(CMake_VERSION_RC 1) diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index df288bd..9ff967c 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -29,10 +29,10 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus& inStatus) { - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "foreach")) { + if (lff.Name.Lower == "foreach") { // record the number of nested foreach commands this->Depth++; - } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) { + } else if (lff.Name.Lower == "endforeach") { // if this is the endofreach for this statement if (!this->Depth) { // Remove the function blocker for this scope or bail. @@ -97,7 +97,7 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) { - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) { + if (lff.Name.Lower == "endforeach") { std::vector<std::string> expandedArguments; mf.ExpandArguments(lff.Arguments, expandedArguments); // if the endforeach has arguments then make sure diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 774df84..67c9e9a 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -9,7 +9,6 @@ #include "cmMakefile.h" #include "cmPolicies.h" #include "cmState.h" -#include "cmSystemTools.h" // define the class for function commands class cmFunctionHelperCommand : public cmCommand @@ -128,9 +127,9 @@ bool cmFunctionFunctionBlocker::IsFunctionBlocked( { // record commands until we hit the ENDFUNCTION // at the ENDFUNCTION call we shift gears and start looking for invocations - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "function")) { + if (lff.Name.Lower == "function") { this->Depth++; - } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) { + } else if (lff.Name.Lower == "endfunction") { // if this is the endfunction for this function then execute if (!this->Depth) { // create a new command and add it to cmake @@ -157,7 +156,7 @@ bool cmFunctionFunctionBlocker::IsFunctionBlocked( bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) { - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) { + if (lff.Name.Lower == "endfunction") { std::vector<std::string> expandedArguments; mf.ExpandArguments(lff.Arguments, expandedArguments, this->GetStartingContext().FilePath.c_str()); diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 4926f22..ae4041d 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -30,9 +30,9 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus& inStatus) { // we start by recording all the functions - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "if")) { + if (lff.Name.Lower == "if") { this->ScopeDepth++; - } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endif")) { + } else if (lff.Name.Lower == "endif") { this->ScopeDepth--; // if this is the endif for this if statement, then start executing if (!this->ScopeDepth) { @@ -48,15 +48,14 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, int scopeDepth = 0; for (cmListFileFunction const& func : this->Functions) { // keep track of scope depth - if (!cmSystemTools::Strucmp(func.Name.c_str(), "if")) { + if (func.Name.Lower == "if") { scopeDepth++; } - if (!cmSystemTools::Strucmp(func.Name.c_str(), "endif")) { + if (func.Name.Lower == "endif") { scopeDepth--; } // watch for our state change - if (scopeDepth == 0 && - !cmSystemTools::Strucmp(func.Name.c_str(), "else")) { + if (scopeDepth == 0 && func.Name.Lower == "else") { if (this->ElseSeen) { cmListFileBacktrace bt = mf.GetBacktrace(func); @@ -76,8 +75,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) { mf.PrintCommandTrace(func); } - } else if (scopeDepth == 0 && - !cmSystemTools::Strucmp(func.Name.c_str(), "elseif")) { + } else if (scopeDepth == 0 && func.Name.Lower == "elseif") { if (this->ElseSeen) { cmListFileBacktrace bt = mf.GetBacktrace(func); mf.GetCMakeInstance()->IssueMessage( @@ -163,7 +161,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, cmMakefile&) { - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endif")) { + if (lff.Name.Lower == "endif") { // if the endif has arguments, then make sure // they match the arguments of the matching if if (lff.Arguments.empty() || lff.Arguments == this->Args) { diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 64e634f..b468257 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -13,6 +13,14 @@ #include <assert.h> #include <sstream> +cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=( + std::string const& name) +{ + this->Original = name; + this->Lower = cmSystemTools::LowerCase(name); + return *this; +} + struct cmListFileParser { cmListFileParser(cmListFile* lf, cmListFileBacktrace const& lfbt, diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 1f9e374..70f7166 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -23,11 +23,22 @@ class cmMessenger; struct cmCommandContext { - std::string Name; + struct cmCommandName + { + std::string Lower; + std::string Original; + cmCommandName() {} + cmCommandName(std::string const& name) { *this = name; } + cmCommandName& operator=(std::string const& name); + } Name; long Line; cmCommandContext() - : Name() - , Line(0) + : Line(0) + { + } + cmCommandContext(const char* name, int line) + : Name(name) + , Line(line) { } }; @@ -81,7 +92,7 @@ public: cmListFileContext lfc; lfc.FilePath = fileName; lfc.Line = lfcc.Line; - lfc.Name = lfcc.Name; + lfc.Name = lfcc.Name.Original; return lfc; } }; diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 6f4b930..23d93a3 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -161,9 +161,9 @@ bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, { // record commands until we hit the ENDMACRO // at the ENDMACRO call we shift gears and start looking for invocations - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "macro")) { + if (lff.Name.Lower == "macro") { this->Depth++; - } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) { + } else if (lff.Name.Lower == "endmacro") { // if this is the endmacro for this macro then execute if (!this->Depth) { mf.AppendProperty("MACROS", this->Args[0].c_str()); @@ -191,7 +191,7 @@ bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) { - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) { + if (lff.Name.Lower == "endmacro") { std::vector<std::string> expandedArguments; mf.ExpandArguments(lff.Arguments, expandedArguments, this->GetStartingContext().FilePath.c_str()); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 33e76b2..0d0ba42 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -224,7 +224,7 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const cmListFileBacktrace cmMakefile::GetBacktrace(cmCommandContext const& cc) const { cmListFileContext lfc; - lfc.Name = cc.Name; + lfc.Name = cc.Name.Original; lfc.Line = cc.Line; lfc.FilePath = this->StateSnapshot.GetExecutionListFile(); return this->Backtrace.Push(lfc); @@ -265,7 +265,7 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const std::ostringstream msg; msg << full_path << "(" << lff.Line << "): "; - msg << lff.Name << "("; + msg << lff.Name.Original << "("; bool expand = this->GetCMakeInstance()->GetTraceExpand(); std::string temp; for (cmListFileArgument const& arg : lff.Arguments) { @@ -317,14 +317,13 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, return result; } - std::string name = lff.Name; - // Place this call on the call stack. cmMakefileCall stack_manager(this, lff, status); static_cast<void>(stack_manager); // Lookup the command prototype. - if (cmCommand* proto = this->GetState()->GetCommand(name)) { + if (cmCommand* proto = + this->GetState()->GetCommandByExactName(lff.Name.Lower)) { // Clone the prototype. std::unique_ptr<cmCommand> pcmd(proto->Clone()); pcmd->SetMakefile(this); @@ -341,7 +340,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, if (!invokeSucceeded || hadNestedError) { if (!hadNestedError) { // The command invocation requested that we report an error. - std::string const error = name + " " + pcmd->GetError(); + std::string const error = + std::string(lff.Name.Original) + " " + pcmd->GetError(); this->IssueMessage(cmake::FATAL_ERROR, error); } result = false; @@ -356,7 +356,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, } else { if (!cmSystemTools::GetFatalErrorOccured()) { std::string error = "Unknown CMake command \""; - error += lff.Name; + error += lff.Name.Original; error += "\"."; this->IssueMessage(cmake::FATAL_ERROR, error); result = false; @@ -1454,7 +1454,7 @@ void cmMakefile::Configure() bool hasVersion = false; // search for the right policy command for (cmListFileFunction const& func : listFile.Functions) { - if (cmSystemTools::LowerCase(func.Name) == "cmake_minimum_required") { + if (func.Name.Lower == "cmake_minimum_required") { hasVersion = true; break; } @@ -1481,8 +1481,7 @@ void cmMakefile::Configure() allowedCommands.insert("message"); isProblem = false; for (cmListFileFunction const& func : listFile.Functions) { - std::string name = cmSystemTools::LowerCase(func.Name); - if (allowedCommands.find(name) == allowedCommands.end()) { + if (allowedCommands.find(func.Name.Lower) == allowedCommands.end()) { isProblem = true; break; } @@ -1501,7 +1500,7 @@ void cmMakefile::Configure() bool hasProject = false; // search for a project command for (cmListFileFunction const& func : listFile.Functions) { - if (cmSystemTools::LowerCase(func.Name) == "project") { + if (func.Name.Lower == "project") { hasProject = true; break; } @@ -1509,7 +1508,7 @@ void cmMakefile::Configure() // if no project command is found, add one if (!hasProject) { cmListFileFunction project; - project.Name = "PROJECT"; + project.Name.Lower = "project"; project.Arguments.emplace_back("Project", cmListFileArgument::Unquoted, 0); listFile.Functions.insert(listFile.Functions.begin(), project); diff --git a/Source/cmState.cxx b/Source/cmState.cxx index a93fb11..a57be4d 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -462,13 +462,17 @@ void cmState::AddScriptedCommand(std::string const& name, cmCommand* command) cmCommand* cmState::GetCommand(std::string const& name) const { - std::string sName = cmSystemTools::LowerCase(name); + return GetCommandByExactName(cmSystemTools::LowerCase(name)); +} + +cmCommand* cmState::GetCommandByExactName(std::string const& name) const +{ std::map<std::string, cmCommand*>::const_iterator pos; - pos = this->ScriptedCommands.find(sName); + pos = this->ScriptedCommands.find(name); if (pos != this->ScriptedCommands.end()) { return pos->second; } - pos = this->BuiltinCommands.find(sName); + pos = this->BuiltinCommands.find(name); if (pos != this->BuiltinCommands.end()) { return pos->second; } diff --git a/Source/cmState.h b/Source/cmState.h index 4c6fc69..38bdfec 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -125,7 +125,11 @@ public: bool GetIsGeneratorMultiConfig() const; void SetIsGeneratorMultiConfig(bool b); + // Returns a command from its name, case insensitive, or nullptr cmCommand* GetCommand(std::string const& name) const; + // Returns a command from its name, or nullptr + cmCommand* GetCommandByExactName(std::string const& name) const; + void AddBuiltinCommand(std::string const& name, cmCommand* command); void AddDisallowedCommand(std::string const& name, cmCommand* command, cmPolicies::PolicyID policy, const char* message); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 99b8998..fa6c8ad 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -96,6 +96,11 @@ struct cmVisualStudio10TargetGenerator::Elem } void EndElement() { + // Do not emit element which has not been started + if (Tag.empty()) { + return; + } + if (HasElements) { this->WriteString("</") << this->Tag << ">"; if (this->Indent > 0) { @@ -1280,12 +1285,16 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( } cmLocalVisualStudio7Generator* lg = this->LocalGenerator; - Elem e1(e0, "ItemGroup"); - Elem e2(e1); + std::unique_ptr<Elem> spe1; + std::unique_ptr<Elem> spe2; if (this->ProjectType != csproj) { - this->WriteSource(e2, "CustomBuild", source); - e2.SetHasElements(); + spe1 = cm::make_unique<Elem>(e0, "ItemGroup"); + spe2 = cm::make_unique<Elem>(*spe1); + this->WriteSource(*spe2, "CustomBuild", source); + spe2->SetHasElements(); } else { + Elem e1(e0, "ItemGroup"); + Elem e2(e1); std::string link; this->GetCSharpSourceLink(source, link); this->WriteSource(e2, "None", source); @@ -1326,13 +1335,13 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( this->WriteCustomRuleCSharp(e0, c, name, script, inputs.str(), outputs.str(), comment); } else { - this->WriteCustomRuleCpp(e2, c, script, inputs.str(), outputs.str(), + this->WriteCustomRuleCpp(*spe2, c, script, inputs.str(), outputs.str(), comment); } } if (this->ProjectType != csproj) { - e2.EndElement(); - e1.EndElement(); + spe2->EndElement(); + spe1->EndElement(); } } @@ -3887,7 +3896,6 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0) iotExtensionsVersion) { if (!hasWrittenItemGroup) { e1.StartElement("ItemGroup"); - hasWrittenItemGroup = true; } if (desktopExtensionsVersion) { this->WriteSingleSDKReference(e1, "WindowsDesktop", @@ -3903,9 +3911,7 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0) } } - if (hasWrittenItemGroup) { - e1.EndElement(); - } + e1.EndElement(); } void cmVisualStudio10TargetGenerator::WriteSingleSDKReference( @@ -4207,10 +4213,12 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1) std::string sourceFile = this->ConvertPath(manifestFile, false); ConvertToWindowsSlash(sourceFile); - Elem e2(e1, "Xml"); - e2.Attribute("Include", sourceFile); - e2.Element("SubType", "Designer"); - e2.EndElement(); + { + Elem e2(e1, "Xml"); + e2.Attribute("Include", sourceFile); + e2.Element("SubType", "Designer"); + e2.EndElement(); + } this->AddedFiles.push_back(sourceFile); std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png"; @@ -4482,10 +4490,12 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles( std::string sourceFile = this->ConvertPath(manifestFile, false); ConvertToWindowsSlash(sourceFile); - Elem e2(e1, "AppxManifest"); - e2.Attribute("Include", sourceFile); - e2.Element("SubType", "Designer"); - e2.EndElement(); + { + Elem e2(e1, "AppxManifest"); + e2.Attribute("Include", sourceFile); + e2.Element("SubType", "Designer"); + e2.EndElement(); + } this->AddedFiles.push_back(sourceFile); std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png"; diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index a080034..d5bcfc2 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -28,10 +28,10 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus& inStatus) { // at end of for each execute recorded commands - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "while")) { + if (lff.Name.Lower == "while") { // record the number of while commands past this one this->Depth++; - } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) { + } else if (lff.Name.Lower == "endwhile") { // if this is the endwhile for this while loop then execute if (!this->Depth) { // Remove the function blocker for this scope or bail. @@ -117,7 +117,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, cmMakefile&) { - if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) { + if (lff.Name.Lower == "endwhile") { // if the endwhile has arguments, then make sure // they match the arguments of the matching while if (lff.Arguments.empty() || lff.Arguments == this->Args) { diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index fe8f2cc..0e94388 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1438,6 +1438,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release add_subdirectory(FindLTTngUST) endif() + if(CMake_TEST_FindODBC) + add_subdirectory(FindODBC) + endif() + if(CMake_TEST_FindOpenCL) add_subdirectory(FindOpenCL) endif() diff --git a/Tests/FindODBC/CMakeLists.txt b/Tests/FindODBC/CMakeLists.txt new file mode 100644 index 0000000..6a81090 --- /dev/null +++ b/Tests/FindODBC/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindODBC.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindODBC/Test" + "${CMake_BINARY_DIR}/Tests/FindODBC/Test" + ${build_generator_args} + --build-project TestFindODBC + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindODBC/Test/CMakeLists.txt b/Tests/FindODBC/Test/CMakeLists.txt new file mode 100644 index 0000000..a20c0f7 --- /dev/null +++ b/Tests/FindODBC/Test/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.1) +project(TestFindODBC C) +include(CTest) + +find_package(ODBC) + +add_executable(test_odbc_tgt main.c) +target_link_libraries(test_odbc_tgt ODBC::ODBC) +add_test(NAME test_odbc_tgt COMMAND test_odbc_tgt) + +add_executable(test_odbc_var main.c) +target_include_directories(test_odbc_var PRIVATE ${ODBC_INCLUDE_DIRS}) +target_link_libraries(test_odbc_var PRIVATE ${ODBC_LIBRARIES}) +add_test(NAME test_odbc_var COMMAND test_odbc_var) diff --git a/Tests/FindODBC/Test/main.c b/Tests/FindODBC/Test/main.c new file mode 100644 index 0000000..917167b --- /dev/null +++ b/Tests/FindODBC/Test/main.c @@ -0,0 +1,12 @@ +#ifdef WIN32 +#include <windows.h> +#endif +#include <sql.h> + +int main() +{ + SQLHENV env; + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + SQLFreeHandle(SQL_HANDLE_ENV, env); + return 0; +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 690c5b4..bb46144 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -152,6 +152,7 @@ add_RunCMake_test(ExternalData) add_RunCMake_test(FeatureSummary) add_RunCMake_test(FPHSA) add_RunCMake_test(FindBoost) +add_RunCMake_test(FindLua) add_RunCMake_test(FindOpenGL) if(NOT CMAKE_C_COMPILER_ID MATCHES "Watcom") add_RunCMake_test(GenerateExportHeader) diff --git a/Tests/RunCMake/FindLua/CMakeLists.txt b/Tests/RunCMake/FindLua/CMakeLists.txt new file mode 100644 index 0000000..a2c4d98 --- /dev/null +++ b/Tests/RunCMake/FindLua/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.4) +project(${RunCMake_TEST} C) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/FindLua/FindLuaTest.cmake b/Tests/RunCMake/FindLua/FindLuaTest.cmake new file mode 100644 index 0000000..610d544 --- /dev/null +++ b/Tests/RunCMake/FindLua/FindLuaTest.cmake @@ -0,0 +1,87 @@ +unset(VERSION) + +# Ignore all default paths for this test to avoid finding system Lua +set(CMAKE_INCLUDE_PATH ) +set(CMAKE_PREFIX_PATH ) +set(CMAKE_FRAMEWORK_PATH ) + +set(ENV{CMAKE_INCLUDE_PATH} ) +set(ENV{CMAKE_PREFIX_PATH} ) +set(ENV{CMAKE_FRAMEWORK_PATH} ) + +set(ENV{PATH} ) +set(ENV{INCLUDE} ) + +set(CMAKE_SYSTEM_INCLUDE_PATH ) +set(CMAKE_SYSTEM_PREFIX_PATH ) +set(CMAKE_SYSTEM_FRAMEWORK_PATH ) + +function(require_found path version) + find_package(Lua ${VERSION} QUIET) + if(NOT "${LUA_INCLUDE_DIR}" STREQUAL "${path}") + message(FATAL_ERROR "LUA_INCLUDE_PATH != path: '${LUA_INCLUDE_DIR}' != '${path}'") + endif() + if(NOT LUA_VERSION_STRING MATCHES "^${version}\.[0-9]$") + message(FATAL_ERROR "Wrong versionfound in '${LUA_INCLUDE_DIR}': ${LUA_VERSION_STRING} != ${version}") + endif() +endfunction() + +# Use functions for scoping and better error messages +function(require_find path version) + unset(LUA_INCLUDE_DIR CACHE) + require_found(${lua_path} ${version}) +endfunction() + +function(test_prefix_path path lua_path version) + set(CMAKE_PREFIX_PATH ${path}) + require_find(lua_path ${version}) +endfunction() + +function(test_include_path path lua_path version) + set(CMAKE_INCLUDE_PATH ${path}) + require_find(lua_path ${version}) +endfunction() + +function(test_env_path path lua_path version) + set(ENV{LUA_DIR} ${path}) + require_find(lua_path ${version}) + unset(ENV{LUA_DIR}) +endfunction() + +function(test_path prefix_path lua_path version) + # Shortcut: Make paths relative to current list dir + set(prefix_path ${CMAKE_CURRENT_LIST_DIR}/${prefix_path}) + set(lua_path ${CMAKE_CURRENT_LIST_DIR}/${lua_path}) + + test_prefix_path(${prefix_path} ${lua_path} ${version}) + test_include_path(${prefix_path}/include ${lua_path} ${version}) + test_env_path(${prefix_path} ${lua_path} ${version}) +endfunction() + +# Simple test +test_path(prefix1 prefix1/include 5.3) +# Find highest version +test_path(prefix2 prefix2/include/lua5.3 5.3) +foreach(ver 5.3 5.2 5.1) + # At least X or X.0 -> Highest + set(VERSION "${ver}") + test_path(prefix2 prefix2/include/lua5.3 5.3) + set(VERSION "${ver}.0") + test_path(prefix2 prefix2/include/lua5.3 5.3) + # Exactly X/X.0 + set(VERSION "${ver}" EXACT) + test_path(prefix2 prefix2/include/lua${ver} ${ver}) + set(VERSION "${ver}.0" EXACT) + test_path(prefix2 prefix2/include/lua${ver} ${ver}) +endforeach() + +# Find unknown version +set(VERSION "5.9") +test_path(prefix2 prefix2/include/lua5.9 5.9) +set(VERSION "5.9" EXACT) +test_path(prefix2 prefix2/include/lua5.9 5.9) + +# Set LUA_INCLUDE_DIR (non-cache) to unsuitable version +set(LUA_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/prefix2/include/lua5.2) +set(VERSION "5.1" EXACT) +test_path(prefix2 prefix2/include/lua5.1 5.1) diff --git a/Tests/RunCMake/FindLua/RunCMakeTest.cmake b/Tests/RunCMake/FindLua/RunCMakeTest.cmake new file mode 100644 index 0000000..3f18033 --- /dev/null +++ b/Tests/RunCMake/FindLua/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(FindLuaTest) diff --git a/Tests/RunCMake/FindLua/prefix1/include/lua.h b/Tests/RunCMake/FindLua/prefix1/include/lua.h new file mode 100644 index 0000000..d33434a --- /dev/null +++ b/Tests/RunCMake/FindLua/prefix1/include/lua.h @@ -0,0 +1,8 @@ + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "3" +#define LUA_VERSION_NUM 503 +#define LUA_VERSION_RELEASE "4" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE diff --git a/Tests/RunCMake/FindLua/prefix2/include/lua5.1/lua.h b/Tests/RunCMake/FindLua/prefix2/include/lua5.1/lua.h new file mode 100644 index 0000000..661e62c --- /dev/null +++ b/Tests/RunCMake/FindLua/prefix2/include/lua5.1/lua.h @@ -0,0 +1,8 @@ + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "1" +#define LUA_VERSION_NUM 501 +#define LUA_VERSION_RELEASE "4" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE diff --git a/Tests/RunCMake/FindLua/prefix2/include/lua5.2/lua.h b/Tests/RunCMake/FindLua/prefix2/include/lua5.2/lua.h new file mode 100644 index 0000000..d53f326 --- /dev/null +++ b/Tests/RunCMake/FindLua/prefix2/include/lua5.2/lua.h @@ -0,0 +1,8 @@ + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "2" +#define LUA_VERSION_NUM 502 +#define LUA_VERSION_RELEASE "4" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE diff --git a/Tests/RunCMake/FindLua/prefix2/include/lua5.3/lua.h b/Tests/RunCMake/FindLua/prefix2/include/lua5.3/lua.h new file mode 100644 index 0000000..d33434a --- /dev/null +++ b/Tests/RunCMake/FindLua/prefix2/include/lua5.3/lua.h @@ -0,0 +1,8 @@ + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "3" +#define LUA_VERSION_NUM 503 +#define LUA_VERSION_RELEASE "4" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE diff --git a/Tests/RunCMake/FindLua/prefix2/include/lua5.9/lua.h b/Tests/RunCMake/FindLua/prefix2/include/lua5.9/lua.h new file mode 100644 index 0000000..730f7cc --- /dev/null +++ b/Tests/RunCMake/FindLua/prefix2/include/lua5.9/lua.h @@ -0,0 +1,8 @@ + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "9" +#define LUA_VERSION_NUM 509 +#define LUA_VERSION_RELEASE "4" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE |
