Work around CMake bug that mangles install dir

CMake has a long-standing bug/feature (see [here](https://cmake.org/pipermail/cmake/2015-March/060204.html) and reply [here](https://cmake.org/pipermail/cmake/2015-March/060209.html)) which can mangle certain path variables by attempting to make them into relative paths if you try to set them with CACHE PATH.

Say you have your OpenCV download at `/path/on/my/computer/to/opencv/`. What actually happens is that if you try to set this variable by invoking CMAKE with `-DCMAKE_INSTALL_PREFIX=/my/desired/install/path`, what you end up is *not* `/usr/local/` and *not* `my/desired/install/path`, but instead, this monstrosity: `/path/on/my/computer/to/opencv/src/OpenCV-build//my/desired/install/path`.

That is, CMake attempts, for some reason, to turn the path that you passed into a path relative to `${CMAKE_BINARY_DIR}`. See the links I posted above: this is a known (and apparently unfixable) issue with CMake.

In OpenCV's case, among other potential issues, this leads to broken paths in `opencv_tests_config.hpp`, which can break the build or cause bizarre behaviour.

The fix for this issue, as stated in my links above, is to test that the variable hasn't been set yet with an `if(NOT DEFINED ...)` before attempting to set it. This is what I've implemented here. I admit I don't know enough about OpenCV's internals to know whether you *really* need to force the install to be in `/usr/local`, but as it stands right now you get *neither* a clean `/usr/local` path *nor* a customized `/my/desired/install/path`, but a broken mess. This change at least allows the user to customize their install directory.

In the meantime, there's a workaround for this, by explicitly defining the variable as a path with `-DCMAKE_INSTALL_PREFIX:PATH=my/desired/install/path`. But if this change can save anyone else the hours of headaches that I had today, I'll be happy.
pull/8186/head
Gabriel B. Nunes 8 years ago committed by GitHub
parent 642e4d97a4
commit 88e54ca1c0
  1. 26
      CMakeLists.txt

@ -25,19 +25,21 @@ endif()
# Following block can broke build in case of cross-compilng # Following block can broke build in case of cross-compilng
# but CMAKE_CROSSCOMPILING variable will be set only on project(OpenCV) command # but CMAKE_CROSSCOMPILING variable will be set only on project(OpenCV) command
# so we will try to detect crosscompiling by presense of CMAKE_TOOLCHAIN_FILE # so we will try to detect crosscompiling by presense of CMAKE_TOOLCHAIN_FILE
if(NOT CMAKE_TOOLCHAIN_FILE) if(NOT DEFINED CMAKE_INSTALL_PREFIX)
# it _must_ go before project(OpenCV) in order to work if(NOT CMAKE_TOOLCHAIN_FILE)
if(WIN32) # it _must_ go before project(OpenCV) in order to work
if(WIN32)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory")
else()
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation Directory")
endif()
else(NOT CMAKE_TOOLCHAIN_FILE)
#Android: set output folder to ${CMAKE_BINARY_DIR}
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are compiled to" )
# any crosscompiling
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory") set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory")
else() endif(NOT CMAKE_TOOLCHAIN_FILE)
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation Directory") endif()
endif()
else(NOT CMAKE_TOOLCHAIN_FILE)
#Android: set output folder to ${CMAKE_BINARY_DIR}
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are compiled to" )
# any crosscompiling
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory")
endif(NOT CMAKE_TOOLCHAIN_FILE)
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore) if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
set(WINRT TRUE) set(WINRT TRUE)

Loading…
Cancel
Save