Tarantool development patches archive
 help / color / mirror / Atom feed
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


  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