Skip to content
Snippets Groups Projects
Commit af2796c7 authored by Markus Böck's avatar Markus Böck
Browse files

[test] Add ability to get error messages from CMake for errc substitution

Visual Studios implementation of the C++ Standard Library does not use strerror to produce a message for std::error_code unlike other standard libraries such as libstdc++ or libc++ that might be used.

This patch adds a cmake script that through running a C++ program gets the error messages for the POSIX error codes and passes them onto lit through an optional config parameter.

If the config parameter is not set, or getting the messages failed, due to say a cross compiling configuration without an emulator, it will fall back to using pythons strerror functions.

Differential Revision: https://reviews.llvm.org/D98278
parent bcb3f0f8
No related branches found
No related tags found
No related merge requests found
......@@ -113,6 +113,7 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
include(TableGen)
include(HandleLLVMOptions)
include(VersionFromVCS)
include(GetErrcMessages)
include(LLVMDistributionSupport)
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
......@@ -177,6 +178,8 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
endif()
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
get_errc_messages(LLVM_LIT_ERRC_MESSAGES)
# On Win32 hosts, provide an option to specify the path to the GnuWin32 tools.
if( WIN32 AND NOT CYGWIN )
set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
......
......@@ -9,6 +9,7 @@ config.llvm_libs_dir = path(r"@LLVM_LIBS_DIR@")
config.llvm_shlib_dir = path(r"@SHLIBDIR@")
config.llvm_plugin_ext = "@LLVM_PLUGIN_EXT@"
config.lit_tools_dir = path(r"@LLVM_LIT_TOOLS_DIR@")
config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@"
config.clang_obj_root = path(r"@CLANG_BINARY_DIR@")
config.clang_src_dir = path(r"@CLANG_SOURCE_DIR@")
config.clang_tools_dir = path(r"@CLANG_TOOLS_DIR@")
......
......@@ -54,6 +54,7 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
include(AddLLVM)
include(TableGen)
include(HandleLLVMOptions)
include(GetErrcMessages)
include(CheckAtomic)
if(LLVM_INCLUDE_TESTS)
......@@ -98,6 +99,8 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif()
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
get_errc_messages(LLVM_LIT_ERRC_MESSAGES)
# On Win32 hosts, provide an option to specify the path to the GnuWin32 tools.
if(WIN32 AND NOT CYGWIN)
set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
......
......@@ -8,6 +8,7 @@ config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@"
config.lld_obj_root = "@LLD_BINARY_DIR@"
config.lld_libs_dir = "@LLD_LIBS_DIR@"
config.lld_tools_dir = "@LLD_TOOLS_DIR@"
......
......@@ -507,6 +507,9 @@ if (MSVC_IDE OR XCODE)
endif()
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
include(GetErrcMessages)
get_errc_messages(LLVM_LIT_ERRC_MESSAGES)
# On Win32 hosts, provide an option to specify the path to the GnuWin32 tools.
if( WIN32 AND NOT CYGWIN )
set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
......
# This function returns the messages of various POSIX error codes as they are returned by std::error_code.
# The purpose of this function is to supply those error messages to llvm-lit using the errc_messages config
# Currently supplied and needed error codes: ENOENT, EISDIR, EINVAL and EACCES
# Messages are semi colon separated
# Keep amount, order and tested error codes in sync with llvm/utils/lit/lit/llvm/config.py
function(get_errc_messages outvar)
set(errc_test_code ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/getErrc.cpp)
file(WRITE ${errc_test_code} "
#include <cerrno>
#include <iostream>
#include <string>
#include <system_error>
std::string getMessageFor(int err) {
return std::make_error_code(static_cast<std::errc>(err)).message();
}
int main() {
std::cout << getMessageFor(ENOENT) << ';' << getMessageFor(EISDIR);
std::cout << ';' << getMessageFor(EINVAL) << ';' << getMessageFor(EACCES);
}
")
try_run(errc_exit_code
errc_compiled
${CMAKE_BINARY_DIR}
${errc_test_code}
RUN_OUTPUT_VARIABLE errc_result
COMPILE_OUTPUT_VARIABLE errc_compile_errors)
if (errc_compiled)
set(${outvar} ${errc_result} PARENT_SCOPE)
else()
set(${outvar} "" PARENT_SCOPE)
message(STATUS "Failed to get errc messages")
endif ()
endfunction()
......@@ -12,6 +12,7 @@ config.llvm_shlib_dir = path(r"@SHLIBDIR@")
config.llvm_shlib_ext = "@SHLIBEXT@"
config.llvm_exe_ext = "@EXEEXT@"
config.lit_tools_dir = path(r"@LLVM_LIT_TOOLS_DIR@")
config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@"
config.python_executable = "@Python3_EXECUTABLE@"
config.gold_executable = "@GOLD_EXECUTABLE@"
config.ld64_executable = "@LD64_EXECUTABLE@"
......
......@@ -11,6 +11,7 @@ from lit.llvm.subst import FindTool
from lit.llvm.subst import ToolSubst
lit_path_displayed = False
python_errc_displayed = False
class LLVMConfig(object):
......@@ -356,19 +357,24 @@ class LLVMConfig(object):
return True
def add_err_msg_substitutions(self):
host_cxx = getattr(self.config, 'host_cxx', '')
# On Windows, python's os.strerror() does not emit the same spelling as
# the C++ std::error_code. As a workaround, hardcode the Windows error
# message.
if (sys.platform == 'win32' and 'MSYS' not in host_cxx):
# Python's strerror may not supply the same message
# as C++ std::error_code. One example of such a platform is
# Visual Studio. errc_messages may be supplied which contains the error
# messages for ENOENT, EISDIR, EINVAL and EACCES as a semi colon
# separated string. LLVM testsuites can use get_errc_messages in cmake
# to automatically get the messages and pass them into lit.
errc_messages = getattr(self.config, 'errc_messages', '')
if len(errc_messages) != 0:
(errc_enoent, errc_eisdir,
errc_einval, errc_eacces) = errc_messages.split(';')
self.config.substitutions.append(
('%errc_ENOENT', '\'no such file or directory\''))
('%errc_ENOENT', '\'' + errc_enoent + '\''))
self.config.substitutions.append(
('%errc_EISDIR', '\'is a directory\''))
('%errc_EISDIR', '\'' + errc_eisdir + '\''))
self.config.substitutions.append(
('%errc_EINVAL', '\'invalid argument\''))
('%errc_EINVAL', '\'' + errc_einval + '\''))
self.config.substitutions.append(
('%errc_EACCES', '\'permission denied\''))
('%errc_EACCES', '\'' + errc_eacces + '\''))
else:
self.config.substitutions.append(
('%errc_ENOENT', '\'' + os.strerror(errno.ENOENT) + '\''))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment