With cmake, how would you disable in-source builds?

后端 未结 8 1242
说谎
说谎 2020-12-28 12:21

I want to disallow people from cluttering our source tree with generated CMake files... and, more importantly, disallow them from stepping on existing Makefiles

相关标签:
8条回答
  • 2020-12-28 12:54

    CMake has two undocumented options: CMAKE_DISABLE_SOURCE_CHANGES and CMAKE_DISABLE_IN_SOURCE_BUILD

    cmake_minimum_required (VERSION 2.8)
    
    # add this options before PROJECT keyword
    set(CMAKE_DISABLE_SOURCE_CHANGES ON)
    set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
    
    project (HELLO)
    
    add_executable (hello hello.cxx)
    

    -

    andrew@manchester:~/src% cmake .
    CMake Error at /usr/local/share/cmake-2.8/Modules/CMakeDetermineSystem.cmake:160 (FILE):
      file attempted to write a file: /home/andrew/src/CMakeFiles/CMakeOutput.log
      into a source directory.
    

    /home/selivanov/cmake-2.8.8/Source/cmMakefile.cxx

    bool cmMakefile::CanIWriteThisFile(const char* fileName)
    {
      if ( !this->IsOn("CMAKE_DISABLE_SOURCE_CHANGES") )
        {
        return true;
        }
      // If we are doing an in-source build, than the test will always fail
      if ( cmSystemTools::SameFile(this->GetHomeDirectory(),
                                   this->GetHomeOutputDirectory()) )
        {
        if ( this->IsOn("CMAKE_DISABLE_IN_SOURCE_BUILD") )
          {
          return false;
          }
        return true;
        }
    
      // Check if this is subdirectory of the source tree but not a
      // subdirectory of a build tree
      if ( cmSystemTools::IsSubDirectory(fileName,
          this->GetHomeDirectory()) &&
        !cmSystemTools::IsSubDirectory(fileName,
          this->GetHomeOutputDirectory()) )
        {
        return false;
        }
      return true;
    }
    
    0 讨论(0)
  • 2020-12-28 12:56

    Include a function like this one. It is similar to what you do with these differences:

    1. It is encapsulated in a function, which is called when you include the PreventInSourceBuilds.cmake module. Your main CMakeLists.txt must include it:

      set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
      include(PreventInSourceBuilds)
      
    2. It uses get_filename_component() with REALPATH parameter that resolves symlinks before comparing the paths.

    In case the github link changes, here's the module source code (which should be placed in a PreventInSouceBuilds.cmake, in a directory called CMake, in the above example):

    #
    # This function will prevent in-source builds
    function(AssureOutOfSourceBuilds)
      # make sure the user doesn't play dirty with symlinks
      get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
      get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
    
      # disallow in-source builds
      if("${srcdir}" STREQUAL "${bindir}")
        message("######################################################")
        message("# ITK should not be configured & built in the ITK source directory")
        message("# You must run cmake in a build directory.")
        message("# For example:")
        message("# mkdir ITK-Sandbox ; cd ITK-sandbox")
        message("# git clone http://itk.org/ITK.git # or download & unpack the source tarball")
        message("# mkdir ITK-build")
        message("# this will create the following directory structure")
        message("#")
        message("# ITK-Sandbox")
        message("#  +--ITK")
        message("#  +--ITK-build")
        message("#")
        message("# Then you can proceed to configure and build")
        message("# by using the following commands")
        message("#")
        message("# cd ITK-build")
        message("# cmake ../ITK # or ccmake, or cmake-gui ")
        message("# make")
        message("#")
        message("# NOTE: Given that you already tried to make an in-source build")
        message("#       CMake have already created several files & directories")
        message("#       in your source tree. run 'git status' to find them and")
        message("#       remove them by doing:")
        message("#")
        message("#       cd ITK-Sandbox/ITK")
        message("#       git clean -n -d")
        message("#       git clean -f -d")
        message("#       git checkout --")
        message("#")
        message("######################################################")
        message(FATAL_ERROR "Quitting configuration")
      endif()
    endfunction()
    
    AssureOutOfSourceBuilds()
    
    0 讨论(0)
提交回复
热议问题