[CMake] Configuring external projects with cmake for a nonexistent install directory which is not configure-time writable
Michael Wild
themiwi at gmail.com
Mon Mar 14 10:58:20 EDT 2011
On 03/14/2011 03:37 PM, The Wanderer wrote:
> (I apologize for setting the Reply-To header, but I know of no other way
> to prevent my being sent an additional off-list copy of any reply even
> when there is no specific need to draw my attention to that reply.)
>
>
>
> I am running cmake 2.8.2, installed via Debian testing. No more recent
> version appears to be available via Debian.
>
> I am attempting to compile a project which has recently switched to
> cmake after a long time spent on autotools.
>
> The project uses, and includes the source to, at least two other
> projects, which it treats as external projects.
>
> The project explicitly requires (and enforces) an out-of-tree build.
>
> I habitually install each new version of this particular project under
> its own brand-new prefix, to more easily retain previous versions for
> fallback if necessary. As a consequence, the target install prefix does
> not exist at the beginning of the build process.
>
> I configure and compile as an ordinary user, which does not have write
> access to the install location. It has long been my understanding that
> this is ordinarily considered good practice.
>
> I am attempting to configure with the command line
>
> ----
> cmake /path/to/source -DDEBUG=1 -DPREFIX=/path/to/nonexistent/install/dir
> ----
>
> With this command, the configure process fails. The error message is:
>
> ----
> CMake Error at /usr/share/cmake-2.8/Modules/ExternalProject.cmake:504
> (file):
> file problem creating directory: /path/to/nonexistent/install/dir
> Call Stack (most recent call first):
> /usr/share/cmake-2.8/Modules/ExternalProject.cmake:1132
> (_ep_set_directories)
> dep/tbb/CMakeLists.txt:69 (ExternalProject_Add)
>
>
> CMake Error at /usr/share/cmake-2.8/Modules/ExternalProject.cmake:506
> (message):
> dir '/path/to/nonexistent/install/dir' does not exist after
> file(MAKE_DIRECTORY)
> Call Stack (most recent call first):
> /usr/share/cmake-2.8/Modules/ExternalProject.cmake:1132
> (_ep_set_directories)
> dep/tbb/CMakeLists.txt:69 (ExternalProject_Add)
> ----
>
> Since the user running the cmake command does not have write access to
> the install location, it is of course not surprising that the
> MAKE_DIRECTORY attempt would fail. What is surprising is that cmake
> would even attempt to create the install directory at configure time.
>
>
> This attempt is made by the following code snippet, in
> _ep_set_directories from
> /usr/share/cmake-2.8/Modules/ExternalProject.cmake:
>
> ----
> # Make the directories at CMake configure time *and* add a custom command
> # to make them at build time. They need to exist at makefile generation
> # time for Borland make and wmake so that CMake may generate makefiles
> # with "cd C:\short\paths\with\no\spaces" commands in them.
> #
> # Additionally, the add_custom_command is still used in case somebody
> # removes one of the necessary directories and tries to rebuild without
> # re-running cmake.
> foreach(var ${places})
> string(TOUPPER "${var}" VAR)
> get_property(dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
> file(MAKE_DIRECTORY "${dir}")
> if(NOT EXISTS "${dir}")
> message(FATAL_ERROR "dir '${dir}' does not exist after
> file(MAKE_DIRECTORY)")
> endif()
> endforeach()
> ----
>
> (At a glance, the 'add_custom_command' referenced in the comment does
> not seem to be present, but that's a separate issue.)
>
> The 'places' variable appears to be set via the line
>
> ----
> set(places stamp download source binary install tmp)
> ----
>
> As a result, cmake unconditionally attempts to create at configure time
> any directories it expects to need for external projects at install
> time, for the sake of (as best I can tell) DOS-based build
> compatibility. Without write access to the install location at configure
> time, this will inherently fail, and the build therefore cannot succeed
> unless the directories already exist.
>
> I have not been able to find any way to override this behavior. Looking
> at the code snippet involved, I don't see any obvious way for there to
> even currently be one.
>
> I am not compiling in a DOS-related environment, and I am not using
> either Borland make or wmake, nor do I ever expect to do either for this
> project. (Insofar as I am aware, this project does not even use cmake
> for its Windows port.) I therefore doubt that I will ever need the short
> paths in question.
>
>
> I know of only three ways to potentially get this project to build under
> these circumstances:
>
> * Run the configure process as a user with write access to the install
> location, such as the user which will run the install. This is a bad
> idea, for some of the same reasons you don't ordinarily want to
> compile as root.
>
> * Manually create the install directory in advance. This is the sort of
> thing which should be automated, and should not need to be done by
> hand.
>
> * Comment out, delete, or otherwise disable the relevant FATAL_ERROR
> and possibly MAKE_DIRECTORY lines from the system-wide
> ExternalProject.cmake file, just for the sake of this one project's
> build. This does not seem appropriate, even though I can't think of a
> reason why it should ever lead to problems (with any project) in my
> "GNU make and Linux"-only setup. At a minimum, it would probably have
> to be re-fixed every time I install an updated version of cmake, since
> this file would probably get overwritten.
>
> None of these three approaches seem acceptable.
>
>
> Given that I know this directory creation attempt is not necessary for
> the build and will fail, is there a way to override it, so that cmake
> can proceed without manual intervention?
>
> If so, how?
>
> If not, I consider that a bug. Is there any chance of getting it fixed,
> so that either the process can succeed fully automatically, or at least
> I can explicitly tell cmake to skip attempting to create directories at
> configure time?
>
This is a bug in the project, not in CMake. It uses the
ExternalProject.cmake module in a bogus way, probably by setting the
INSTALL_DIR option of ExternalProject_Add() to somewhere in the
CMAKE_INSTALL_PREFIX. This is wrong, it should be somewhere in the build
tree, and then the client project should install the necessary files itself.
Michael
More information about the CMake
mailing list