Browse Source

Merge topic 'external-project-launcher'

b2634b6 Detect CMake warnings and errors in build output.
012c986 ExternalProject: Add LOG_* options to hide step output
Brad King 15 years ago
parent
commit
a570ba6df7

+ 137 - 0
Modules/ExternalProject.cmake

@@ -43,6 +43,13 @@
 #    [TEST_BEFORE_INSTALL 1]     # Add test step executed before install step
 #    [TEST_AFTER_INSTALL 1]      # Add test step executed after install step
 #    [TEST_COMMAND cmd...]       # Command to drive test
+#   #--Output logging-------------
+#    [LOG_DOWNLOAD 1]            # Wrap download in script to log output
+#    [LOG_UPDATE 1]              # Wrap update in script to log output
+#    [LOG_CONFIGURE 1]           # Wrap configure in script to log output
+#    [LOG_BUILD 1]               # Wrap build in script to log output
+#    [LOG_TEST 1]                # Wrap test in script to log output
+#    [LOG_INSTALL 1]             # Wrap install in script to log output
 #    )
 # The *_DIR options specify directories for the project, with default
 # directories computed as follows.
@@ -86,6 +93,7 @@
 #    [DEPENDS files...]      # Files on which this step depends
 #    [ALWAYS 1]              # No stamp file, step always runs
 #    [WORKING_DIRECTORY dir] # Working directory for command
+#    [LOG 1]                 # Wrap step in script to log output
 #    )
 # The command line, comment, and working directory of every standard
 # and custom step is processed to replace tokens
@@ -606,6 +614,81 @@ function(_ep_get_build_command name step cmd_var)
   set(${cmd_var} "${cmd}" PARENT_SCOPE)
 endfunction(_ep_get_build_command)
 
+function(_ep_write_log_script name step cmd_var)
+  ExternalProject_Get_Property(${name} stamp_dir)
+  set(command "${${cmd_var}}")
+
+  set(make "")
+  if("${command}" MATCHES "^\\$\\(MAKE\\)")
+    # GNU make recognizes the string "$(MAKE)" as recursive make, so
+    # ensure that it appears directly in the makefile.
+    string(REGEX REPLACE "^\\$\\(MAKE\\)" "\${make}" command "${command}")
+    set(make "-Dmake=$(MAKE)")
+  endif()
+
+  set(config "")
+  if("${CMAKE_CFG_INTDIR}" MATCHES "^\\$")
+    string(REPLACE "${CMAKE_CFG_INTDIR}" "\${config}" command "${command}")
+    set(config "-Dconfig=${CMAKE_CFG_INTDIR}")
+  endif()
+
+  # Wrap multiple 'COMMAND' lines up into a second-level wrapper
+  # script so all output can be sent to one log file.
+  if("${command}" MATCHES ";COMMAND;")
+    set(code_execute_process "
+execute_process(COMMAND \${command} RESULT_VARIABLE result)
+if(result)
+  set(msg \"Command failed (\${result}):\\n\")
+  foreach(arg IN LISTS command)
+    set(msg \"\${msg} '\${arg}'\")
+  endforeach(arg)
+  message(FATAL_ERROR \"\${msg}\")
+endif()
+")
+    set(code "")
+    set(cmd "")
+    set(sep "")
+    foreach(arg IN LISTS command)
+      if("x${arg}" STREQUAL "xCOMMAND")
+        set(code "${code}set(command \"${cmd}\")${code_execute_process}")
+        set(cmd "")
+        set(sep "")
+      else()
+        set(cmd "${cmd}${sep}${arg}")
+        set(sep ";")
+      endif()
+    endforeach()
+    set(code "${code}set(command \"${cmd}\")${code_execute_process}")
+    file(WRITE ${stamp_dir}/${name}-${step}-impl.cmake "${code}")
+    set(command ${CMAKE_COMMAND} "-Dmake=\${make}" "-Dconfig=\${config}" -P ${stamp_dir}/${name}-${step}-impl.cmake)
+  endif()
+
+  # Wrap the command in a script to log output to files.
+  set(script ${stamp_dir}/${name}-${step}.cmake)
+  set(logbase ${stamp_dir}/${name}-${step})
+  file(WRITE ${script} "
+set(command \"${command}\")
+execute_process(
+  COMMAND \${command}
+  RESULT_VARIABLE result
+  OUTPUT_FILE \"${logbase}-out.log\"
+  ERROR_FILE \"${logbase}-err.log\"
+  )
+if(result)
+  set(msg \"Command failed: \${result}\\n\")
+  foreach(arg IN LISTS command)
+    set(msg \"\${msg} '\${arg}'\")
+  endforeach(arg)
+  set(msg \"\${msg}\\nSee also\\n  ${logbase}-*.log\\n\")
+  message(FATAL_ERROR \"\${msg}\")
+else()
+  set(msg \"${name} ${step} command succeeded.  See also ${logbase}-*.log\\n\")
+  message(STATUS \"\${msg}\")
+endif()
+")
+  set(command ${CMAKE_COMMAND} ${make} ${config} -P ${script})
+  set(${cmd_var} "${command}" PARENT_SCOPE)
+endfunction(_ep_write_log_script)
 
 # This module used to use "/${CMAKE_CFG_INTDIR}" directly and produced
 # makefiles with "/./" in paths for custom command dependencies. Which
@@ -695,6 +778,12 @@ function(ExternalProject_Add_Step name step)
     set(touch ${CMAKE_COMMAND} -E touch ${stamp_dir}${cfgdir}/${name}-${step})
   endif()
 
+  # Wrap with log script?
+  get_property(log TARGET ${name} PROPERTY _EP_${step}_LOG)
+  if(command AND log)
+    _ep_write_log_script(${name} ${step} command)
+  endif()
+
   add_custom_command(
     OUTPUT ${stamp_dir}${cfgdir}/${name}-${step}
     COMMENT ${comment}
@@ -905,12 +994,20 @@ function(_ep_add_download_command name)
     endif()
   endif()
 
+  get_property(log TARGET ${name} PROPERTY _EP_LOG_DOWNLOAD)
+  if(log)
+    set(log LOG 1)
+  else()
+    set(log "")
+  endif()
+
   ExternalProject_Add_Step(${name} download
     COMMENT ${comment}
     COMMAND ${cmd}
     WORKING_DIRECTORY ${work_dir}
     DEPENDS ${depends}
     DEPENDEES mkdir
+    ${log}
     )
 endfunction(_ep_add_download_command)
 
@@ -968,12 +1065,20 @@ function(_ep_add_update_command name)
     set(always 1)
   endif()
 
+  get_property(log TARGET ${name} PROPERTY _EP_LOG_UPDATE)
+  if(log)
+    set(log LOG 1)
+  else()
+    set(log "")
+  endif()
+
   ExternalProject_Add_Step(${name} update
     COMMENT ${comment}
     COMMAND ${cmd}
     ALWAYS ${always}
     WORKING_DIRECTORY ${work_dir}
     DEPENDEES download
+    ${log}
     )
 endfunction(_ep_add_update_command)
 
@@ -1044,11 +1149,19 @@ function(_ep_add_configure_command name)
   configure_file(${tmp_dir}/${name}-cfgcmd.txt.in ${tmp_dir}/${name}-cfgcmd.txt)
   list(APPEND file_deps ${tmp_dir}/${name}-cfgcmd.txt)
 
+  get_property(log TARGET ${name} PROPERTY _EP_LOG_CONFIGURE)
+  if(log)
+    set(log LOG 1)
+  else()
+    set(log "")
+  endif()
+
   ExternalProject_Add_Step(${name} configure
     COMMAND ${cmd}
     WORKING_DIRECTORY ${binary_dir}
     DEPENDEES update patch
     DEPENDS ${file_deps}
+    ${log}
     )
 endfunction(_ep_add_configure_command)
 
@@ -1063,10 +1176,18 @@ function(_ep_add_build_command name)
     _ep_get_build_command(${name} BUILD cmd)
   endif()
 
+  get_property(log TARGET ${name} PROPERTY _EP_LOG_BUILD)
+  if(log)
+    set(log LOG 1)
+  else()
+    set(log "")
+  endif()
+
   ExternalProject_Add_Step(${name} build
     COMMAND ${cmd}
     WORKING_DIRECTORY ${binary_dir}
     DEPENDEES configure
+    ${log}
     )
 endfunction(_ep_add_build_command)
 
@@ -1081,10 +1202,18 @@ function(_ep_add_install_command name)
     _ep_get_build_command(${name} INSTALL cmd)
   endif()
 
+  get_property(log TARGET ${name} PROPERTY _EP_LOG_INSTALL)
+  if(log)
+    set(log LOG 1)
+  else()
+    set(log "")
+  endif()
+
   ExternalProject_Add_Step(${name} install
     COMMAND ${cmd}
     WORKING_DIRECTORY ${binary_dir}
     DEPENDEES build
+    ${log}
     )
 endfunction(_ep_add_install_command)
 
@@ -1112,10 +1241,18 @@ function(_ep_add_test_command name)
       set(dep_args DEPENDEES install)
     endif()
 
+    get_property(log TARGET ${name} PROPERTY _EP_LOG_TEST)
+    if(log)
+      set(log LOG 1)
+    else()
+      set(log "")
+    endif()
+
     ExternalProject_Add_Step(${name} test
       COMMAND ${cmd}
       WORKING_DIRECTORY ${binary_dir}
       ${dep_args}
+      ${log}
       )
   endif()
 endfunction(_ep_add_test_command)

+ 20 - 5
Source/CTest/cmCTestBuildHandler.cxx

@@ -65,7 +65,7 @@ static const char* cmCTestErrorMatches[] = {
   "^Unresolved:",
   "Undefined symbols:",
   "^Undefined[ \\t]+first referenced",
-  "^CMake Error:",
+  "^CMake Error.*:",
   ":[ \\t]cannot find",
   ":[ \\t]can't find",
   ": \\*\\*\\* No rule to make target \\`.*\\'.  Stop",
@@ -129,6 +129,7 @@ static const char* cmCTestWarningMatches[] = {
   "\\([0-9]*\\): remark #[0-9]*",
   "\".*\", line [0-9]+: remark\\([0-9]*\\):",
   "cc-[0-9]* CC: REMARK File = .*, Line = [0-9]*",
+  "^CMake Warning.*:",
   0
 };
 
@@ -174,8 +175,8 @@ cmCTestWarningErrorFileLine[] = {
 //----------------------------------------------------------------------
 cmCTestBuildHandler::cmCTestBuildHandler()
 {
-  this->MaxPreContext = 6;
-  this->MaxPostContext = 6;
+  this->MaxPreContext = 10;
+  this->MaxPostContext = 10;
 
   this->MaxErrors = 50;
   this->MaxWarnings = 50;
@@ -214,8 +215,8 @@ void cmCTestBuildHandler::Initialize()
   this->ErrorsAndWarnings.clear();
   this->LastErrorOrWarning = this->ErrorsAndWarnings.end();
   this->PostContextCount = 0;
-  this->MaxPreContext = 6;
-  this->MaxPostContext = 6;
+  this->MaxPreContext = 10;
+  this->MaxPostContext = 10;
   this->PreContext.clear();
 
   this->TotalErrors = 0;
@@ -249,6 +250,20 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf)
                              "CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS",
                              this->MaxWarnings);
 
+  int n = -1;
+  this->CTest->PopulateCustomInteger(mf, "CTEST_CUSTOM_ERROR_PRE_CONTEXT", n);
+  if (n != -1)
+    {
+    this->MaxPreContext = static_cast<size_t>(n);
+    }
+
+  n = -1;
+  this->CTest->PopulateCustomInteger(mf, "CTEST_CUSTOM_ERROR_POST_CONTEXT", n);
+  if (n != -1)
+    {
+    this->MaxPostContext = static_cast<size_t>(n);
+    }
+
   // Record the user-specified custom warning rules.
   if(const char* customWarningMatchers =
      mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH"))

+ 6 - 0
Tests/ExternalProject/CMakeLists.txt

@@ -79,6 +79,7 @@ if(can_build_tutorial_step5)
     URL "${CMAKE_CURRENT_SOURCE_DIR}/../Tutorial/Step5"
     CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
     TEST_BEFORE_INSTALL 1
+    LOG_INSTALL 1
   )
   ExternalProject_Get_Property(${proj} install_dir)
   set(TutorialStep5_install_dir ${install_dir})
@@ -88,6 +89,7 @@ if(can_build_tutorial_step5)
     URL "${CMAKE_CURRENT_SOURCE_DIR}/../Tutorial/Step5"
     CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
     TEST_AFTER_INSTALL 1
+    LOG_TEST 1
   )
 endif()
 
@@ -104,6 +106,7 @@ ExternalProject_Add(${proj}
   CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
              -DTEST_LIST:STRING=A::B::C
   INSTALL_COMMAND ""
+  LOG_CONFIGURE 1
 )
 
 set(proj TutorialStep1-LocalNoDirTAR)
@@ -132,6 +135,7 @@ ExternalProject_Add(${proj}
   URL_MD5 38c648e817339c356f6be00eeed79bd0
   CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
   INSTALL_COMMAND ""
+  LOG_BUILD 1
 )
 
 set(proj TutorialStep1-LocalNoDirTGZ)
@@ -356,6 +360,7 @@ if(do_svn_tests)
     CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
     INSTALL_COMMAND ""
     DEPENDS "SetupLocalSVNRepository"
+    LOG_DOWNLOAD 1
   )
 endif()
 
@@ -430,6 +435,7 @@ if(do_git_tests)
     CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
     INSTALL_COMMAND ""
     DEPENDS "SetupLocalGITRepository"
+    LOG_UPDATE 1
   )
 endif()