Hi, (Pardon the length; skip to end to see what I am proposing to change. Below is justification why.)
I have found it annoyingly difficult to set up an environment for a build when using ExternalProject_Add. This seems to be needed when creating a superbuild that uses several different compilers. The common workaround seems to be to use a batch file that kicks off the build, as suggested by multiple posts I have seen on these mailing lists, StackOverflow, etc. An example of a nice & neat usage that doesn't need an environment set up. # For this discussion, suppose this is called from a # superbuild that has no languages set up, and no build # environment. ExternalProject_Add( <snip> # Conveniently, VS2010 generator doesn't need VCVarsAll.bat CMAKE_GENERATOR "Visual Studio 10 2010" CMAKE_CACHE_ARGS <long list of args>) But let's say I want to use Ninja to build both VS2010 32-bit/64-bit. Now things get really messy, especially if I want my logic in a reusable piece of code (effectively acting as a wrapper around ExternalProject_Add): # ${setEnv} must be path to a batch file that does this. # 1. Call VCVarsAll for desired VC version. # 2. Run command passed via arguments. <snip code to configure_file and write ${setEnv}> # ${someScriptFile} has to be made via file(GENERATE). # Essentially we have to reimplement the CMAKE_CACHE_ARGS option. # That is made difficult because _ep_command_line_to_initial_cache # is a private implementation detail of ExternalProject.cmake. <snip code to file(GENERATE) ${someScriptFile}> ExternalProject_Add( <snip> CONFIGURE_COMMAND ${setEnv} ${CMAKE_COMMAND} -GNinja -C${someScriptFile}) Basically I find myself copy/pasting _ep_command_line_to_initial_cache into my own project, amongst other annoyances. :( What would be nice is if I could directly pass VCVarsAll.bat to ExternalProject_Add and still be able to use CMAKE_GENERATOR and CMAKE_CACHE_ARGS. It would also be nice if this mechanism did not interfere with option CONFIGURE_COMMAND in case the external project is not CMake-based. Something like this might be perfect: ExternalProject_Add( <snip> CONFIGURE_ENVIRONMENT_COMMAND <path to VCVarsAll.bat> CMAKE_GENERATOR Ninja CMAKE_CACHE_ARGS <long list of args>) # Offer similar capability for other steps like building. This is made somewhat difficult by the fact that CMake currently provides no mechanism for a custom command to do this that I know of, and thus nothing for ExternalProject_Add to easily build off of. Therefore, I propose several possible options, and I'd like to know which one(s) I should think about pursuing: 1. add_custom_command (and friends) could be extended with a new keyword indicating that command is environment preparation for the next command. For example: add_custom_command(<snip> ENVIRONMENT_COMMAND <path to vcvarsall.bat> COMMAND ${CMAKE_PROGRAM} -GNinja <snip>) In this case, add_custom_command will run the ENVIRONMENT_COMMAND and COMMAND in the same shell. The ENVIRONMENT_COMMAND would have to be source'd / call'd as needed, depending on the shell. Implementation of #1: a. A new "cmake -E run_commands <command list file>" option could be added that runs each command on each line of the input file in a shared environment (source'ing and call'ing as needed depending on shell). E.g. by translating the list of input commands to a temporary batch/shell script and running it. Behind the scenes, add_custom_command and friends would assemble things into a "cmake -E" invocation that can be passed to the generators - handling EXE targets as needed. b. OR: Each CMake generator handles this directly without any special "cmake -E" option. (This sounds like more work?) 2. Instead of altering add_custom_command, just add the proposed "cmake -E run_commands" option as described above. ExternalProject_Add could then be modified to use this new "cmake -E" option directly. (Need to think about if the command is an EXE target...) 3. Instead of altering any C++ CMake code at all, modify ExternalProject_Add to implement my original workaround outlined at the top of this e-mail of generating a wrapper script. Downside: now ExternalProject.cmake has to learn platform-specific knowledge of the shell. Also need to think about if target is EXE target... 4. Do nothing; this is too complicated and so are not desired changes to make to CMake. Or: something else? The one possible wrench in the works would be if you used a Cygwin version of CMake (i.e. CMake expects /bin/sh shell) and wanted to prepare to use Visual C++ and run VCVarsAll.bat (i.e. but you need cmd.exe shell). That wouldn't work without a special option allowing you to explicitly set the shell. That's a rare enough case it's probably not worth worrying about in this initial version, I think. My personal preference would be option 1, and probably option 1a. In that case, steps would be: (1) implement "cmake -E run_commands", (2) extend add_custom_command, (3) extend ExternalProject_Add. What do you think? Best regards, James Johnston -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers