如何在Emacs中设置编译的默认目录?

问题描述:

我在Emacs下编码OCaml,在工作文件夹中有一个makefile,以及几个包含.ml文件的子文件夹。如果我启动M-x compilemake正常工作的上一个makefile缓冲,但在一个.ml文件的缓冲区是不行的,它给了我一个错误:如何在Emacs中设置编译的默认目录?

-*- mode: compilation; default-directory: "..." -*- 
Compilation started at Fri Jan 27 18:51:35 

make -k 
make: *** No targets specified and no makefile found. Stop. 

Compilation exited abnormally with code 2 at Fri Jan 27 18:51:35 

这是可以理解的,因为默认的目录是子不包含makefile的文件夹。有谁知道如何将makefile的文件夹始终设置为编译的默认目录?

马蒂亚斯PUECH都有一个solution涉及.dir-local文件在项目的根目录:

((nil . ((eval . (setq default-directory 
        (locate-dominating-file buffer-file-name 
        ".dir-locals.el") 
))))) 

这大概也可以使用类似于:(shell-command-to-string "git rev-parse --show-toplevel")作为最里面的位。

+0

不不不不不不:no这样会破坏一切,包括'find-file'。 – 2016-03-24 19:30:29

可以调用make用正确的参数:

make -C .. -k 

其中..是路径到您的Makefile

+0

[whoa](http://i.memeful.com/media/post/PM0aaRL_700wa_0.gif) – vagoberto 2017-05-31 16:16:24

+0

哈,正在四处寻找这个问题,而你的回答是事后最明显的一个,我更喜欢它在_define-your-own-custom-function-with-a-hook-and-change-it-you-need-a-different-path_上面回答。谢谢! – agam 2018-03-01 00:17:37

我用这样的脚本,让我从运行任何子目录使(假设你处于类似posix的环境)。只是把这个脚本在PATH为类似“sub_make.sh”并调用它,你将调用做出同样的方式:通过编写一个(暂时)设置default-directory功能

#!/bin/bash 

# search for project base 
INIT_DIR=`pwd` 
while [ "$PWD" != "/" ] ; do 
    if [ -e "makefile" ] ; then 
    break 
    fi 

    cd .. 
done 

if [ ! -e "makefile" ] ; then 
    echo "Couldn't find 'makefile'!" 
    exit 1 
fi 

# indicate where we are now 
echo "cd "`pwd` 
echo make "[email protected]" 

# now run make for real 
exec make "[email protected]" 
+1

你可以修改如下:'if [-e“makefile”] || [-e“Makefile”] || [-e“GNUmakefile”];然后'允许标准的makefile名称 – 2013-03-09 17:32:07

您可以从emacs的内控制这种并致电compile

(defun compile-in-parent-directory() 
    (interactive) 
    (let ((default-directory 
      (if (string= (file-name-extension buffer-file-name) "ml") 
       (concat default-directory "..") 
      default-directory)))) 
    (call-interactively #'compile)) 

当使用compile-in-parent-directory所有ml文件将在他们在哪里父目录进行编译。当然,如果他们嵌套得更深,你可以改变逻辑来反映这一点。实际上有一个version on the EmacsWiki,它搜索父目录,直到找到一个makefile。在我写这个答案后我发现了这个,否则我会在那里指出你的。 感叹。关于我的方法的好处是,它不是特定于make,因此您可以对其他命令使用相同的“技巧”。

如果您确切知道您想要的命令是什么,那么您也可以将调用编译为非交互式。如果它在适当的模式钩子中绑定到一个键,这将特别有效。

+0

感谢您的回答......我已将您的代码添加到'。emacs',但在'Mx'之后,它找不到'compile-in-parent-directory' – SoftTimur 2012-01-31 14:02:32

+0

我已经把EmacsWiki上的代码改为'.emacs',按'F5'给我一个错误:'Symbol的函数定义是void:loop'。 – SoftTimur 2012-01-31 14:11:03

+0

要使功能可用于与M-x的交互呼叫,您必须将(交互式)作为第一条语句添加到您的功能中。 – 2012-01-31 14:27:39

这就是我在我的一些CONFIGS :)

(defun* get-closest-pathname (&optional (max-level 3) (file "Makefile")) 
    (let* ((root (expand-file-name "/")) 
     (level 0) 
     (dir (loop 
       for d = default-directory then (expand-file-name ".." d) 
       do (setq level (+ level 1)) 
       if (file-exists-p (expand-file-name file d)) 
       return d 
       if (> level max-level) 
       return nil 
       if (equal d root) 
       return nil))) 
    (if dir 
     (expand-file-name file dir) 
     nil))) 

(add-hook 'c-mode-hook 
      (lambda() 
      (unless (file-exists-p "Makefile") 
       (set (make-local-variable 'compile-command) 
        (let ((file (file-name-nondirectory buffer-file-name)) 
         (mkfile (get-closest-pathname))) 
        (if mkfile 
         (progn (format "cd %s; make -f %s" 
          (file-name-directory mkfile) mkfile)) 
         (format "%s -c -o %s.o %s %s %s" 
           (or (getenv "CC") "gcc") 
           (file-name-sans-extension file) 
           (or (getenv "CPPFLAGS") "-DDEBUG=9") 
           (or (getenv "CFLAGS") "-ansi -pedantic -Wall -g") 
           file))))))) 
+0

感谢您的回答......我已将您的代码添加到'.emacs'中,但启动emacs后,它会给我一个警告:Warning(initialization):加载'〜/ .emacs'时发生错误:Symbol的函数定义无效:defun *' – SoftTimur 2012-01-31 14:05:06

+2

hm ...尝试在此功能之前添加(需要'cl')。 – 2012-01-31 14:23:33

+0

谢谢Bad_ptr。我用你的代码有一个命令,可以在任何模式下执行主目录中的make命令,而不仅仅是C,如果缓冲区处于目录模式。 我希望它不做任何事情,但如果它没有找到Makefile的主目录。不幸的是我的功能仍然执行make。你能建议吗? (全球设置键[F1] \t \t(拉姆达() \t \t(互动) \t \t(编译 (让((mkfile(GET-最接近-路径名))) \t \t(如果mkfile \t \t(格式为 “CD%S;使” \t \t \t \t(文件名,目录(GET-最接近-路径名)))) \t \t \t \t)))) – SFbay007 2013-08-14 18:11:21