为 cmake 配置 emacs

Posted

技术标签:

【中文标题】为 cmake 配置 emacs【英文标题】:configuring emacs for cmake 【发布时间】:2010-01-23 15:40:33 【问题描述】:

gcc 4.4.2 cmake 2.6

我刚刚开始使用 cmake。来自编写我自己的 Makefile。

但是,我有这个目录结构并使用源外构建。将源文件与构建文件分开。

project
    src
        my_c_files.c
        CMakeLists.txt
    build
        Makefile

在我在 src 目录中编写自己的 Makefile 并按 F5 之前,我能够编译我的程序。 emacs 会列出任何警告或错误。但是,看来我必须打开一个终端并进入构建目录才能运行

cmake ../src

然后

make

我想在 emacs 中运行 make,就像按 F5 一样。但是由于 Makefile 是在 build 目录中生成的,而 emacs 正在 src 目录中寻找它。

即使我在 src 目录中设置了指向 Makefile 的软链接以链接到 build 目录中的 Makefile。这一切只是给了我一个错误列表。

【问题讨论】:

能否将compile-command设置为“cmake ../src && make”,还是需要做一些更复杂的事情? 感谢您的评论,我会尽快尝试您的建议。 您好,我确实尝试过,它成功了。只要我在src目录下。但是,当我在客户端目录中处理 client.c 时。在 src/client/client.c 中它不起作用。即使我尝试了这个'cmake ../../src && make'。它编写了构建文件,但它给出了一条消息“没有指定目标并且没有找到生成文件”。我想我正在寻找一种方法来在我目前正在处理的任何目录中编译我的程序。谢谢。 【参考方案1】:

出于完全相同的目的,我发现.dir-locals.el 非常很有帮助,我的一个看起来是这样的:

((nil . ((tab-width . 8)
     (indent-tabs-mode . t)))
 (c++-mode . ((c-basic-offset . 8)
          (tab-width . 8)
          (indent-tabs-mode . t)
          (compile-command . "make -C ../build -j 2 run_tests")))
 ((c-mode . ((c-basic-offset . 8)
         (tab-width . 8)
         (indent-tabs-mode . t)
         (compile-command . "make -C ../build -j 2 run_tests")))))

显然,我可以根据它们的位置等在不同的.dir_locals.el 中指定路径,比如一些构建run_tests 用于单元测试,一些构建真正的目标等等。

然后我在构建目录中放了一个虚拟的makefile,看起来像这样:

all: run_tests

run_tests:
    @cmake ..
    @make -j 2

这样我就可以结帐并在我喜欢的任何文件中运行M-x compile,它会做正确的事情。我使用 git 并让 Makefile ignored 像这样被 git 监控:

git update-index --assume-unchanged Makefile

如果我想修改并提交它,我会这样做

git update-index --no-assume-unchanged Makefile

这样cmake新建的Makefile不会在git status中显示为已修改,也不会意外提交。

这种方法的好处:

由于 cmake 在内部使用绝对路径,因此只需在编译缓冲区中按 enter 即可跳过编译错误绝对没有问题。

你可以在那里指定你想要的任何缩进规则,如果你愿意,它们可以在不同的项目甚至目录中有所不同:)

你可以在不同的项目中指定任意数量的目标,甚至是目录,仍然使用相同的旧M-x compile(我将它绑定到C-c b)并让 Emacs 做正确的事情事情

唯一的缺点是您的子目录中有.dir-locals.el,我几乎不觉得这不好。

编辑: robUK,回答您的评论:

这里是documentation 用于每个目录的局部变量,正如他们在 Emacs 手册中所说的那样。它不是一个包,它是 Emacs 的一部分,虽然我不确定它是否在 23 之前的版本中可用,我使用的是 23.1.1。

EDIT2: liwp,回答您的问题:

正如查尔斯已经指出的那样,正如文档所说:

如果您放置一个具有特殊名称的文件 .dir-locals.el 在目录中,Emacs 当它访问任何文件时都会读取它 在该目录或其任何 子目录,并应用设置 它指定文件的缓冲区。 Emacs 搜索 .dir-locals.el 从目录开始 访问过的文件,并向上移动 目录树。 (为避免减速, 跳过此搜索以查找远程 文件。)

您的项目树中的任何地方都不需要.dir-locals.el。但是请注意,这可能取决于您的代码库结构的复杂性。

我通常会选择这样一个相当简单的布局:

/project_root_dir
    /build
    /src
    /test

我会在不同的.dir-locals.el 中指定稍微不同的目标,比如在/test 我只会构建testrunner 并让它执行,我会花费大部分开发时间来构建这个目标。然后在/src 中,我将首先构建相同的testrunner,并执行它,如果那里一切顺利,它将构建我的主要项目目标。如果你不需要这个,你可以在/project_root_dir 下只使用一个.dir-locals.el。如果您的源结构和要求更加复杂,则可能意味着您需要更多与路径和目标相关的魔法。

【讨论】:

您好,这看起来不错。我在哪里可以下载包 dir-locals.el。关于如何使用它的任何文档?谢谢。 谢谢。我会检查的。目前我使用的是 23.1.1。 @Dmitry:澄清一下,您是否需要在 each 子目录中有一个 .dir-locals.el 文件才能使其正常工作?我正在处理一个带有巨大 src 树的大型项目,我无法将特定于 emacs 的文件添加到存储库中,因此我每次签出时都必须生成 .dir-local.el 文件......跨度> @liwp:不,.dir-locals.el 文件适用于子目录。 我已将此标记为答案。我会的,我可以将每个人都标记为正确的。【参考方案2】:

编译命令的更通用解决方案是:

cd $PWD%/src/*/build && cmake ../src && make

环境变量 PWD 保存您正在编辑的文件所在的目录;用%/src/* 扩展它可以让你回到项目根目录,而不必担心你需要多少../s。

【讨论】:

更优雅的还是cd $PWD/%src*/build && cmake ../src && make 使用bash 的regexp-replace 机制。但是,如果您使用更多反斜杠,则需要小心转义。【参考方案3】:

简单的解决方案: 安装cpputils-cmake,然后你就可以开始了。

说明: CMake 已经将所有信息放在构建目录中。如果您从 cmake 获得正确的信息,您只需要破解 c++-mode-hookc-mode-hook 中的 ELisp 变量 compile-command

完美解决方案的两点:

    您的省略代码应该通过在破解compile-command之前扫描源目录来检测当前项目是否正在使用CMakecompile-command

    自动检测到源外构建目录的完整路径并将其附加到make -C 命令。

我写了一个 emacs 插件 cpputils-cmake https://github.com/redguardtoo/cpputils-cmake 来解决这两个问题。检查我的代码,你可以通过 Emacs 的包管理器安装它。

顺便说一句, 在 cmake 创建 build 目录后,通常不应在命令行中显式调用 cmake。 make -C out-of-source-build-dir 足够聪明,因为该目录中的 Makefile 无论如何都会调用 cmake。即使您更改了 CMakeLists.txt,调用make -C out-of-source-build-dir 仍然足够。我很确定这一点,因为我已经使用 cmake 四年了。

许多以前的答案都不起作用,因为:

    任何关于源树布局的假设都可能是错误的。例如,我将根源目录命名为“mysrc”而不是“src”

    我如何使用外源策略很复杂。例如,我可能只使用 out-of-source 构建一个组件。

【讨论】:

【参考方案4】:

我正在使用 Cedet 的 EDE 来配置项目以使用 CMake。查看into my CEDET config,从第 105 行开始,例如项目配置的代码。我为不同的构建使用单独的 Debug & Release 目录,默认情况下,编译仅在 Debug 模式下运行....

【讨论】:

我对 emacs 很陌生,而且我从来没有用 lisp 写过。我认为您正在设置 CMakelists.txt 和 boost 库的路径。但是,我不确定这一点。 cons 'compile-command 'alexott/gen-cmake-debug-compile-string" 对于我的 .emacs,我有以下内容(global-set-key [f5] 'compile)。任何建议都会很有帮助。谢谢。跨度> 我的配置使用 F9 - 请参阅第 165 行,它按照以下方式工作。 'cons compile-command ...' 用于设置特定于流程的编译命令,仅适用于具体项目。该命令将采用项目根目录,由 ':file path_to_cmakelists.txt' 确定,并将执行 'cd PROJECT_ROOT/Debug; make -j2'【参考方案5】:

您可以使用M-x cd<enter> <path to build dir><enter> 更改 emacs 使用的当前工作目录。之后,当您运行M-x compile 时,make 将在新的工作目录中执行。这实际上与在 build 目录中的终端上运行 make 相同,所以它应该对你很有效。

【讨论】:

【参考方案6】:

make 使用 -C 选项怎么样?

当 emacs 询问编译命令时,按 F5M-x compile,键入:

make -C ../build

【讨论】:

为什么要编辑我的帖子? F5在所有emacs中都没有设置为编译命令,在我的安装中也没有默认设置,所以命令 M-x compile 更合适,由人们将它绑定到一些fkeys【参考方案7】:

将命令更改为使用绝对值而不是相对值。例如:

cmake ~/workspace/project/src && make

【讨论】:

以上是关于为 cmake 配置 emacs的主要内容,如果未能解决你的问题,请参考以下文章

make如何指定cmake路径

如何将Emacs窗口/框架配置与屏幕位置一起存储

Emacs 全局配置选项卡

GUI版本的emacs

Emacs简单配置

cmake 在Windows 命令行怎么指定编译器