我想禁止人们使用生成的CMake文件混乱我们的源代码树...更重要的是,不允许他们踩到不属于同一构建过程的现有 Makefile 我们'重新使用CMake。 (最好不要问)

我提出的方法是在 CMakeLists.txt 的顶部添加几行,如下所示:

if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
   message(SEND_ERROR "In-source builds are not allowed.")
endif("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")

然而,这样做似乎太冗长了。此外,如果我尝试在源代码构建中,它仍然会在抛出错误之前在源代码树中创建 CMakeFiles / 目录和 CMakeCache.txt 文件。 / p>

我错过了更好的方法吗?

有帮助吗?

解决方案

我想我喜欢你的方式。 cmake邮件列表在回答这些类型的问题方面做得很好。

作为旁注:你可以创建一个“cmake”。目录中的可执行文件失败。取决于是否“。”在他们的路径(在Linux上)。你甚至可以用symlink / bin / false。

在Windows中,我不确定是否首先找到当前目录中的文件。

其他提示

CMake有两个未记录的选项: CMAKE_DISABLE_SOURCE_CHANGES 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;
}

包含此内容等功能。它与您对这些差异的处理方式类似:

  1. 它封装在一个函数中,当您包含 PreventInSourceBuilds.cmake 模块时会调用该函数。您的主要CMakeLists.txt必须包含它:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
    include(PreventInSourceBuilds)
    
  2. 它使用带有REALPATH参数的 get_filename_component()在比较路径之前解析符号链接。

  3. 如果github链接发生变化,这里是模块源代码(应该放在 PreventInSouceBuilds.cmake 中,在一个名为 CMake 的目录中,在上面的例子中) ):

    #
    # 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()
    

我的 .bashrc / .zshrc 中有一个 cmake() shell函数,类似于这个:

function cmake() {
  # Don't invoke cmake from the top-of-tree
  if [ -e "CMakeLists.txt" ]
  then
    echo "CMakeLists.txt file present, cowardly refusing to invoke cmake..."
  else
    /usr/bin/cmake $*
  fi
}

我更喜欢这种低级礼仪解决方案。当我们切换到CMake时,它摆脱了我同事们最大的抱怨,但它并没有阻止那些真正想要做这样的源内/顶级树构建的人&#8212 ;他们可以直接调用 / usr / bin / cmake (或根本不使用包装函数)。这是愚蠢的简单。

您可以配置.bashrc文件,例如这个

查看函数 cmakekde kdebuild 。设置BUILD和SRC环境。变量并根据您的需要编辑这些功能。这将只在 buildDir 而不是 srcDir

中构建

对于Linux上的人:

添加到顶级CMakeLists.txt:

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)

在您的顶级创建文件'dotme'或添加到.bashrc(全局):

#!/bin/bash
cmk() { if [ ! -e $1/CMakeLists.txt ] || ! grep -q "set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)" $1/CMakeLists.txt;then /usr/bin/cmake $*;else echo "CMAKE_DISABLE_IN_SOURCE_BUILD ON";fi }

alias cmake=cmk

现在运行:

. ./dotme

当您尝试在顶级源代码树中运行cmake时:

$ cmake .
CMAKE_DISABLE_IN_SOURCE_BUILD ON

没有生成CMakeFiles /或CMakeCache.txt。

在进行源外构建时,您需要首次运行cmake才能调用实际的可执行文件:

$ cd build
$ /usr/bin/cmake ..

只需让执行构建的人员/进程只读目录。有一个单独的进程从源代码控制检出目录(你正在使用源代码控制,对吧?),然后将其设置为只读。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top