I'm trying to build Lua 5.4.3 (the latest release as of writing this) using the following CMakeLists.txt (and CMake 3.21) (ignore the fact that the target is called lua_static despite it being a shared lib):
cmake_minimum_required(VERSION 3.16)
project(Lua LANGUAGES CXX)
# make cache variables for install destinations
include(GNUInstallDirs)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(LUA_LIB_SRCS
"src/ldblib.c"
"src/ldebug.c"
"src/ldo.c"
"src/ldump.c"
"src/lfunc.c"
"src/lgc.c"
"src/linit.c"
"src/liolib.c"
"src/lopcodes.c"
"src/llex.c"
"src/lmathlib.c"
"src/lmem.c"
"src/loadlib.c"
"src/lobject.c"
"src/loslib.c"
"src/lparser.c"
"src/lstate.c"
"src/lstring.c"
"src/lstrlib.c"
"src/ltable.c"
"src/ltablib.c"
"src/ltm.c"
"src/lundump.c"
"src/lutf8lib.c"
"src/lvm.c"
"src/lzio.c"
"src/lapi.c"
"src/lauxlib.c"
"src/lbaselib.c"
"src/lcode.c"
"src/lcorolib.c"
"src/lctype.c"
)
set(LUA_HEADERS_INSTALL
"src/lua.h"
"src/luaconf.h"
"src/lualib.h"
"src/lauxlib.h"
"src/lua.hpp"
)
# Compile directly as C++.
set_source_files_properties(${LUA_LIB_SRCS} PROPERTIES LANGUAGE CXX )
add_library(lua_static SHARED ${LUA_LIB_SRCS})
set_target_properties(lua_static PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(lua_static PROPERTIES DEBUG_POSTFIX d)
# make sure __cplusplus is defined when using msvc
if (MSVC)
target_compile_options(lua_static PRIVATE /TP # /TP doesn't is somehow stripped or ignored?
/Zc:__cplusplus)
endif ()
target_include_directories(lua_static
PUBLIC
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
install(TARGETS lua_static
EXPORT lua_static_targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(FILES ${LUA_HEADERS_INSTALL} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(EXPORT lua_static_targets
FILE LuaStaticTargets.cmake
NAMESPACE lua::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lua
)
include(CMakePackageConfigHelpers)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/LuaConfig.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lua
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/LuaConfig.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lua
)
When building with MSVC, __cplusplus is defined and therefore I presume everything up until this point is working as intended. Then after installing, I link against the library like so
cmake_minimum_required(VERSION 3.16)
project(TestProject)
add_executable(Test Main.cpp)
# Lua
find_package(lua REQUIRED PATHS ${CMAKE_CURRENT_LIST_DIR}/lua)
set_target_properties(lua::lua_static PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(Test lua::lua_static)
The reason why I want to compile Lua as C++ is to enable exceptions (rather than longjmp). So to test if exceptions would be thrown, I tried invoking one in this test program
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <iostream>
constexpr char* Test_Lua = R"(
function f (x, y)
unknown()
return 1/0
en
)";
lua_State* state;
int main(int argc, char* argv[])
{
state = luaL_newstate();
luaL_openlibs(state);
try
{
int error = luaL_loadbuffer(state, Test_Lua, strlen(Test_Lua), "Test");
lua_call(state, 0, LUA_MULTRET); // Should thow, because of the syntax error
}
catch (...)
{
std::cout << "Exception!" << std::endl;
goto end;
}
end:
lua_close(state);
return 0;
}
When stepping into lua_call with the debugger, I at some point end up in ldo.c where Visual Studio indicates that LUAI_THROW is not defined via C++ exeption handling. This is because __cplusplus is not defined. Jumping to that source file in my Lua project files created earlier, LUAI_THROW was defined as desired. The fact that I can include the Lua headers suggests to me that the library has been compiled as a C++ library. In fact if I try to add extern "C" { ... }, I get linker errors.
Can someone shed some light on the cause of the problem?
Edit:
After looking more into the issue, I realized all compilation as C++ does, is that Lua internally handles functions that return error codes (such as luaL_loadbuffer) via exceptions. That doesn't mean I get to catch and handle them (which I originally thought). Functions like lua_call run in unprotected mode and thus call the panic function (see @bremen_matt's post).