【问题标题】:Emacs fastest C++ compilation process?Emacs 最快的 C++ 编译过程?
【发布时间】:2013-07-08 07:34:34
【问题描述】:

以下是用例:我在技术博客上阅读了一篇关于 C++ 的文章 (多重继承失败和多线程失败等:)。 通常它们带有一些代码。它几乎总是一个文件,我几乎总是 想运行它并玩弄它。

我想用 Emacs 做这件事,我想快速做, 与最少(或相当少)的击键一样。

所以假设我已经在它自己的文件夹中创建了一个multiple_inheritance.cc 文件 并粘贴代码。如何快速获得可执行文件?

这就是我现在正在做的事情(希望有人会改进它。)

(defun cpp-generate-makefile ()
  (interactive)
  (let* ((n-buffer (buffer-file-name))
         (n-file (file-name-nondirectory n-buffer))
         (n-target (file-name-sans-extension n-file))
         (n-makefile (concat (file-name-directory n-buffer) "Makefile")))
    (if (file-exists-p n-makefile)
        (when (called-interactively-p 'any)
          (message "Makefile already exists"))
      (with-current-buffer (find-file-noselect n-makefile)
        (insert 
         (concat n-target ": " n-file 
                 "\n\tg++ -g -O2 -std=c++0x -o $@ $^\n\n"
                 "clean: \n\trm -f " n-target "\n"))
        (save-buffer)))))

(defun cpp-run ()
  (interactive)
  (save-buffer)
  (cpp-generate-makefile)
  (compile "make"))

(add-hook 'c++-mode-hook
      (lambda()
            ;; ...
            (define-key c++-mode-map [f5] 'cpp-run)))

以下是目前让我慢下来的几件事:

  1. compile 询问我是否要保存任何与 C++ 完全无关的打开文件。
  2. 我想在*compilation* 缓冲区中有一个点,以防出现错误。 我查看了compile.el,其中定义了compilation-num-errors-found, 但该变量并未在该文件的任何地方使用。
  3. 另一方面,如果没有错误(我只需要一个谓词), 为什么不启动term 并运行程序?

【问题讨论】:

  • 为什么要指向编译缓冲区?!导航不需要它,只需使用M-g nM-g p 来导航错误。为什么要生成 Makefile? GNU Make 至少有implicit rules 可以compile C++。只需使用make CXXFLAGS=<flags> <name>,其中<flags> 是您想要的编译标志,<name> 是您要编译的文件的不带扩展名的名称。
  • 变量compilation-ask-about-save用于在编译前询问要保存哪些缓冲区。
  • @lunaryorn,感谢您提供快捷方式的建议。我不知道他们存在。我之前从*compilation* 跳到C-m 的错误。关于隐式规则,很高兴知道,但不如<f5> 快。此外,我当前的脚本添加了一个干净的目标,所以如果我愿意,我可以递归地清理我的所有源目录。如果我想添加更多文件,这也是一个好的开始。
  • 太好了,@juanleon!那件事一直困扰着我!
  • 而且您不需要谓词或 xterm 来启动二进制文件。只需直接从 make 命令启动它。只需将 && ./a.out 之类的内容附加到它。

标签: c++ emacs makefile


【解决方案1】:

总结一下cmets中的答案。

  1. 更改compilation-ask-about-save 的值。如果您不想全局更改它(使用 setq),您可以通过将其包装在 (let ((compilation-ask-about-save nil)) ...function contents...) 语句中来在函数内部更改它。
  2. 快速绑定下一个错误:(define-key c++-mode-map "\M-j" 'next-error)。我个人为此使用 global-set-key,只是因为它在很多模式中都很有用。
  3. 将函数中的编译命令替换为(compile "make && ./a.out")(当然使用可执行文件的名称)。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    我更新了代码,我必须将run 目标添加到Makefile。 我还为 C 添加了一个扩展:

    (defvar cpp-generate-compiler "g++ -g -O2 -std=c++0x")
    
    (defun cpp-generate-makefile ()
      (interactive)
      (let* ((n-buffer (buffer-file-name))
             (n-file (file-name-nondirectory n-buffer))
             (n-target (file-name-sans-extension n-file))
             (n-makefile (concat
                           (file-name-directory n-buffer)
                           "Makefile")))
        (if (file-exists-p n-makefile)
            (when (called-interactively-p 'any)
              (message "Makefile already exists"))
          (with-current-buffer (find-file-noselect n-makefile)
            (insert
             (concat n-target ": " n-file
                     (format "\n\t%s -o $@ $^"
                       cpp-generate-compiler)
                     "\n\nclean: \n\trm -f " n-target
                     "\n\nrun: " n-target "\n\t ./" n-target
                     "\n\n.PHONY: clean run\n"))
            (save-buffer)))))
    
    (defun cpp-run ()
      (interactive)
      (save-buffer)
      (cpp-generate-makefile)
      (compile "make run"))
    
    (defun c-run ()
      (interactive)
      (let ((cpp-generate-compiler "gcc -g -O2 -std=c99"))
        (cpp-run)))
    
    (add-hook 'c++-mode-hook
          (lambda()
                ;; ...
                (define-key c++-mode-map [f5] 'cpp-run)))
    (add-hook 'c-mode-hook
          (lambda()
                ;; ...
                (define-key c-mode-map [f5] 'c-run)))
                
    (setq compilation-ask-about-save nil)
    (setq compilation-finish-functions
          (list (lambda(buffer str)
                  (unless (string= str "finished\n")
                    (push-mark)
                    (next-error)))))
    

    有了(setq compilation-ask-about-save nil),就没有更多了 关于保存的警告(cpp-run 自动保存)。

    我只需要记住 M-g nM-g p 导航错误。

    现在我的过程几乎是最佳的:从源到结果的一键,以防万一 没有错误。

    如果有错误,它是一个额外的M-g n。 现在,如果compile 有办法调用(push-mark)(next-error)...

    更新:

    感谢@juanleon 的建议,解决了这个问题:

    (setq compilation-finish-functions
          (list (lambda(buffer str)
                  (unless (string= str "finished\n")
                    (push-mark)
                    (next-error)))))
    

    但由于某种原因,push-mark 在这种情况下无法正常工作。

    【讨论】:

    • 关于你最后的评论...如果有错误,你可以使用钩子compilation-finish-functions自动调用next-error
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2014-06-15
    相关资源
    最近更新 更多