如何在Emacs中设置编译的默认目录?
我在Emacs下编码OCaml,在工作文件夹中有一个makefile
,以及几个包含.ml
文件的子文件夹。如果我启动M-x compile
和make
正常工作的上一个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")
作为最里面的位。
可以调用make
用正确的参数:
make -C .. -k
其中..
是路径到您的Makefile
我用这样的脚本,让我从运行任何子目录使(假设你处于类似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]"
你可以修改如下:'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
,因此您可以对其他命令使用相同的“技巧”。
如果您确切知道您想要的命令是什么,那么您也可以将调用编译为非交互式。如果它在适当的模式钩子中绑定到一个键,这将特别有效。
这就是我在我的一些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)))))))
感谢您的回答......我已将您的代码添加到'.emacs'中,但启动emacs后,它会给我一个警告:Warning(initialization):加载'〜/ .emacs'时发生错误:Symbol的函数定义无效:defun *' – SoftTimur 2012-01-31 14:05:06
hm ...尝试在此功能之前添加(需要'cl')。 – 2012-01-31 14:23:33
谢谢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
不不不不不不:no这样会破坏一切,包括'find-file'。 – 2016-03-24 19:30:29