From: Igor Munkin via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: Sergey Kaplun <skaplun@tarantool.org>, Maxim Kokryashkin <m.kokryashkin@tarantool.org> Cc: tarantool-patches@dev.tarantool.org Subject: [Tarantool-patches] [PATCH] cmake: introduce CheckUnwindTables helper Date: Mon, 9 Jan 2023 18:28:21 +0300 [thread overview] Message-ID: <e717eaac5611b2ec46fbe8b400a1c6db796bdb1e.1673277902.git.imun@tarantool.org> (raw) In-Reply-To: <20221221143317.477323-1-m.kokryashkin@tarantool.org> After struggling with black voodoo magic oneliner provided by Mike Pall in scope of e131936133c58de4426c595db2341caf5a1665b5 ("Cleanup and enable external unwinding for more platforms.") to check whether the target toolchain always generates unwind tables, it was decided to implement it as a CMake function to encapsulate and comment this damn "grep" spell. Signed-off-by: Igor Munkin <imun@tarantool.org> --- Branch: https://github.com/tarantool/luajit/compare/imun/fix-build-for-non-bash CI is green(*): https://github.com/tarantool/luajit/commit/e717eaa (*) Max, could you please check this patch on the Alpine? cmake/CheckUnwindTables.cmake | 114 ++++++++++++++++++++++++++++++++++ cmake/SetTargetFlags.cmake | 18 ++---- 2 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 cmake/CheckUnwindTables.cmake diff --git a/cmake/CheckUnwindTables.cmake b/cmake/CheckUnwindTables.cmake new file mode 100644 index 00000000..903977ad --- /dev/null +++ b/cmake/CheckUnwindTables.cmake @@ -0,0 +1,114 @@ +# CheckUnwindTables provides a convenient way to define whether +# the target toolchain generates unwind tables. +# +# This function implements black voodoo magic provided by Mike +# Pall in scope of e131936133c58de4426c595db2341caf5a1665b5 +# ("Cleanup and enable external unwinding for more platforms.") +# via CMake. +# +# Example usage: +# +# # Find out whether the target toolchain always generates +# # unwind tables. +# CheckUnwindTables(HAVE_UNWIND_TABLES) +# if(HAVE_UNWIND_TABLES) +# AppendFlags(TARGET_C_FLAGS -DLUAJIT_UNWIND_EXTERNAL) +# endif() + +function(CheckUnwindTables status) + set(_CHECK_UNWIND_TABLES_RESULT FALSE) + + # 1. Build the command compiling the simple object file using + # the target toolchain. + # XXX: CMake helper <try_compile> can't be used, since there is + # no executable file as a result, but only an object file (in + # other words, there is no <main> function in C source file). + set(_TEST_UNWIND_OBJECT "${CMAKE_BINARY_DIR}/test-unwind-tables.o") + string(CONCAT _TEST_UNWIND_SOURCE + "extern void b(void);" + "int a(void) {" + "b();" + "return 0;" + "}" + ) + string(CONCAT _TEST_UNWIND_COMPILE + "echo '${_TEST_UNWIND_SOURCE}'" + "|" + "${CMAKE_C_COMPILER} -c -x c - -o ${_TEST_UNWIND_OBJECT}" + ) + + # 2. Use <grep> to find either .eh_frame (for ELF) or + # __unwind_info (for Mach-O) entries in the compiled object + # file. After the several attempts in scope of the following + # commits: + # * e131936133c58de4426c595db2341caf5a1665b5 ("Cleanup and + # enable external unwinding for more platforms.") + # * d4a554d6ee1507f7313641b26ed09bf1b518fa1f ("OSX: Fix build + # by hardcoding external frame unwinding.") + # * b9d523965b3f55b19345a1ed1ebc92e431747ce1 ("BSD: Fix build + # with BSD grep.") + # * 66563bdab0c7acf3cd61dc6cfcca36275951d084 ("Fix build with + # busybox grep.") + # Mike came up with the solution to use both alternatives: + # `grep -qa' as the major one and `grep -qU' as a fallback for + # BSD platforms. + set(_TEST_GREP_GNU "grep -qa") + set(_TEST_GREP_BSD "grep -qU") + set(_TEST_GREP_PATTERN "-e eh_frame -e __unwind_info") + string(CONCAT _TEST_UNWIND_CHECK + # XXX: Mind the space after the opening brace. The space is + # vital since { is a *reserved word* (i.e. the command built + # into the shell). For more info see the following link: + # https://www.gnu.org/software/bash/manual/html_node/Reserved-Words.html. + "{ " + "${_TEST_GREP_GNU} ${_TEST_GREP_PATTERN} ${_TEST_UNWIND_OBJECT}" + "||" + "${_TEST_GREP_BSD} ${_TEST_GREP_PATTERN} ${_TEST_UNWIND_OBJECT}" + # XXX: Mind the semicolon prior to the closing brace. The + # semicolon is vital due to we are executing the list of shell + # commands that has to be terminated by one of ';', '&', or a + # newline. Considering it will be executed synchronously via + # <execute_process>, only the first option fits here. For more + # info see the following link: + # https://www.gnu.org/software/bash/manual/html_node/Lists.html + # XXX: Considering the preceding semicolon, there is no need to + # separate } command with the additional whitespace. + ";}" + ) + + # 3. Use step 1 and step 2 to check whether target toolchain + # always generates unwind tables. + # XXX: There is no need in "echo E" command at the end, since + # we can check $? of the command by <RESULT_VARIABLE> value. + # Fun fact: there is $(.SHELLSTATUS) variable in GNU Make, but + # it can't be used in <ifeq>/<ifneq> conditions, so we can't get + # rid of "echo E" in the original Makefile machinery. + execute_process( + COMMAND /bin/sh -c "${_TEST_UNWIND_COMPILE} && ${_TEST_UNWIND_CHECK}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE _TEST_UNWIND_RC + ERROR_QUIET + OUTPUT_QUIET + ) + + if(_TEST_UNWIND_RC EQUAL 0) + set(_CHECK_UNWIND_TABLES_RESULT TRUE) + endif() + + # Remove generated object file. + file(REMOVE ${_TEST_UNWIND_OBJECT}) + + set(${status} ${_CHECK_UNWIND_TABLES_RESULT} PARENT_SCOPE) + # XXX: Unset the internal variable to not spoil CMake cache. + # Study the case in CheckIPOSupported.cmake, that affected this + # module: https://gitlab.kitware.com/cmake/cmake/-/commit/4b82977 + unset(_CHECK_UNWIND_TABLES_RESULT) + unset(_TEST_UNWIND_RC) + unset(_TEST_UNWIND_CHECK) + unset(_TEST_GREP_PATTERN) + unset(_TEST_GREP_BSD) + unset(_TEST_GREP_GNU) + unset(_TEST_UNWIND_COMPILE) + unset(_TEST_UNWIND_SOURCE) + unset(_TEST_UNWIND_OBJECT) +endfunction() diff --git a/cmake/SetTargetFlags.cmake b/cmake/SetTargetFlags.cmake index 1ca438f1..3b9e481d 100644 --- a/cmake/SetTargetFlags.cmake +++ b/cmake/SetTargetFlags.cmake @@ -6,6 +6,8 @@ # * TARGET_SHARED_FLAGS # * TARGET_LIBS +include(CheckUnwindTables) + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(BUILDVM_MODE machasm) else() # Linux and FreeBSD. @@ -21,18 +23,10 @@ else() string(FIND ${TARGET_C_FLAGS} "LJ_NO_UNWIND 1" UNWIND_POS) if(UNWIND_POS EQUAL -1) # Find out whether the target toolchain always generates - # unwindtables. - execute_process( - COMMAND bash -c "exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | ${CMAKE_C_COMPILER} -c -x c - -o tmpunwind.o && { grep -qa -e eh_frame -e __unwind_info tmpunwind.o || grep -qU -e eh_frame -e __unwind_info tmpunwind.o; } && echo E; rm -f tmpunwind.o" - WORKING_DIRECTORY ${LUAJIT_SOURCE_DIR} - OUTPUT_VARIABLE TESTUNWIND - RESULT_VARIABLE TESTUNWIND_RC - ) - if(TESTUNWIND_RC EQUAL 0) - string(FIND "${TESTUNWIND}" "E" UNW_TEST_POS) - if(NOT UNW_TEST_POS EQUAL -1) - AppendFlags(TARGET_C_FLAGS -DLUAJIT_UNWIND_EXTERNAL) - endif() + # unwind tables. + CheckUnwindTables(HAVE_UNWIND_TABLES) + if(HAVE_UNWIND_TABLES) + AppendFlags(TARGET_C_FLAGS -DLUAJIT_UNWIND_EXTERNAL) endif() endif() endif() -- 2.34.0
next prev parent reply other threads:[~2023-01-09 15:43 UTC|newest] Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-12-21 14:33 [Tarantool-patches] [PATCH luajit] cmake: fix build for non-bash shells Maxim Kokryashkin via Tarantool-patches 2023-01-09 15:28 ` Igor Munkin via Tarantool-patches [this message] 2023-01-10 10:05 ` [Tarantool-patches] [PATCH] cmake: introduce CheckUnwindTables helper Sergey Kaplun via Tarantool-patches 2023-01-10 11:12 ` Igor Munkin via Tarantool-patches 2023-01-10 17:36 ` Maxim Kokryashkin via Tarantool-patches 2023-01-10 19:18 ` Igor Munkin via Tarantool-patches 2023-01-12 14:55 ` Igor Munkin via Tarantool-patches 2023-01-09 15:32 ` [Tarantool-patches] [PATCH luajit] cmake: fix build for non-bash shells Igor Munkin via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=e717eaac5611b2ec46fbe8b400a1c6db796bdb1e.1673277902.git.imun@tarantool.org \ --to=tarantool-patches@dev.tarantool.org \ --cc=imun@tarantool.org \ --cc=m.kokryashkin@tarantool.org \ --cc=skaplun@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH] cmake: introduce CheckUnwindTables helper' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox