[cmake-developers] Modules/GetPrequisites.cmake issues
Bill Somerville
bill at classdesign.com
Tue Jul 28 18:02:07 EDT 2015
Hi All,
attached is a patch that addresses some issues recently discussed on the
users list.
I'm no CMake expert so I don't know if I have done things in the best
way. One area I do not fully understand is how to detect MinGW, If I
could then objdump could be chosen as the preferred library dependency
walker over MS dumpbin.exe. See the patch description for details.
Regards
Bill Somerville.
-------------- next part --------------
From 203848c099026c23b5f70d395d0469887f099d23 Mon Sep 17 00:00:00 2001
From: Bill Somerville <bill at classdesign.com>
Date: Tue, 28 Jul 2015 22:40:36 +0100
Subject: [PATCH] For MinGW pre-filter objdump output for performance
As dumpbin.exe is no longer reliable for gcc libraries on MinGW
because it crashes on many common libraries like libgcc_s and
libgfortran it is now necessary too resort to using objdump for DLL
dependency walking. Using objdump has a secondary problem in that it
generates a lot of output for large libraries and causes
fixup_bundle() to take many minutes to process what took fractions of
a second with dumpbin.exe /dependents.
This patch includes a grep pre-filter in the execute_process() command
pipeline to reduce this output to a minimum for a several orders of
magnitude speed up. If grep isn't available the full output is used.
As there doesn't seem to be a reliable way of detecting MinGW callers
of fixup_bundle() may have to set the variable gp_tool to "objdump" if
dumpbin.exe is installed on the build machine to stop it using
dumpbin.exe for library dependency walking.
This patch also adds command status checking to the various
execute_process() invocations in GetPrerequisites.cmake so that they
don't fail silently producing invalid install packages.
---
Modules/GetPrerequisites.cmake | 53 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 49 insertions(+), 4 deletions(-)
diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake
index 23d486e..bbc1232 100644
--- a/Modules/GetPrerequisites.cmake
+++ b/Modules/GetPrerequisites.cmake
@@ -229,9 +229,14 @@ function(is_file_executable file result_var)
if(file_cmd)
execute_process(COMMAND "${file_cmd}" "${file_full}"
+ RESULT_VARIABLE file_rv
OUTPUT_VARIABLE file_ov
+ ERROR_VARIABLE file_ev
OUTPUT_STRIP_TRAILING_WHITESPACE
)
+ if(NOT file_rv STREQUAL "0")
+ message(FATAL_ERROR "${file_cmd} failed: ${file_rv}\n${file_ev}")
+ endif()
# Replace the name of the file in the output with a placeholder token
# (the string " _file_full_ ") so that just in case the path name of
@@ -543,11 +548,21 @@ function(gp_resolved_file_type original_file file exepath dirs type_var)
if(CYGPATH_EXECUTABLE)
execute_process(COMMAND ${CYGPATH_EXECUTABLE} -W
+ RESULT_VARIABLE env_rv
OUTPUT_VARIABLE env_windir
+ ERROR_VARIABLE env_ev
OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(NOT env_rv STREQUAL "0")
+ message(FATAL_ERROR "${CYGPATH_EXECUTABLE} -W failed: ${env_rv}\n${env_ev}")
+ endif()
execute_process(COMMAND ${CYGPATH_EXECUTABLE} -S
+ RESULT_VARIABLE env_rv
OUTPUT_VARIABLE env_sysdir
+ ERROR_VARIABLE env_ev
OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(NOT env_rv STREQUAL "0")
+ message(FATAL_ERROR "${CYGPATH_EXECUTABLE} -S failed: ${env_rv}\n${env_ev}")
+ endif()
string(TOLOWER "${env_windir}" windir)
string(TOLOWER "${env_sysdir}" sysroot)
@@ -709,6 +724,11 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa
set(gp_regex_error "")
set(gp_regex_fallback "")
set(gp_regex_cmp_count 1)
+ # objdump generaates copious output so we create a grep filter to pre-filter results
+ find_program(gp_grep_cmd grep)
+ if(gp_grep_cmd)
+ set(gp_cmd_filter "^[[:blank:]]*DLL Name: ")
+ endif()
else()
message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
@@ -763,10 +783,30 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa
# Run gp_cmd on the target:
#
- execute_process(
- COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
- OUTPUT_VARIABLE gp_cmd_ov
- )
+ if(gp_cmd_filter) # filter is for performance
+ execute_process(
+ COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
+ COMMAND ${gp_grep_cmd} ${gp_cmd_filter}
+ RESULT_VARIABLE gp_rv
+ OUTPUT_VARIABLE gp_cmd_ov
+ ERROR_VARIABLE gp_ev
+ )
+ else()
+ execute_process(
+ COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
+ RESULT_VARIABLE gp_rv
+ OUTPUT_VARIABLE gp_cmd_ov
+ ERROR_VARIABLE gp_ev
+ )
+ endif()
+ if(NOT gp_rv STREQUAL "0")
+ if(gp_tool STREQUAL "dumpbin")
+ # dumpbin error messages seem to go to stdout
+ message(FATAL_ERROR "${gp_cmd} failed: ${gp_rv}\n${gp_ev}\n${gp_cmd_ov}")
+ else()
+ message(FATAL_ERROR "${gp_cmd} failed: ${gp_rv}\n${gp_ev}")
+ endif()
+ endif()
if(gp_tool STREQUAL "ldd")
set(ENV{LD_LIBRARY_PATH} "${old_ld_env}")
@@ -791,8 +831,13 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa
if(gp_tool STREQUAL "otool")
execute_process(
COMMAND otool -D ${target}
+ RESULT_VARIABLE otool_rv
OUTPUT_VARIABLE gp_install_id_ov
+ ERROR_VARIABLE otool_ev
)
+ if(NOT otool_rv STREQUAL "0")
+ message(FATAL_ERROR "otool -D failed: ${otool_rv}\n${otool_ev}")
+ endif()
# second line is install name
string(REGEX REPLACE ".*:\n" "" gp_install_id "${gp_install_id_ov}")
if(gp_install_id)
--
1.9.5.msysgit.0
More information about the cmake-developers
mailing list