Mxコンパイルの永続的な環境


8

実行M-x compileすると、新しいサブシェルが生成され、コンパイルコマンドが実行されます。コンパイルコマンドが戻るとすぐに、シェルプロセスは強制終了されます。これがほとんどの場合に望ましい理由はわかりますが、現在は役に立たない状況にあります。

現在、専用のビルド環境で作業しています。コンパイラーを実行する前に、ビルドをセットアップするためにいくつかの初期手順を実行する必要があります。環境が持続する限り、セットアップ手順を1回だけ実行する必要があります。しかし、それを使用M-x compileすると、コンパイルまたは再コンパイルするたびに手順を実行する必要があることを意味します。

バックグラウンドで持続するサブシェルを生成する方法はありますか?一つM-x compileM-x gdb彼らはシェルプロセスを実行する必要があるたびに使用することができますか?


動機:

xcc特別なプラットフォーム用のCコードをビルドするプログラム(これをと呼びます)があります。コードをビルドするには、まずプロンプトxccから始めtcshます。

$ xcc

プログラムの読み込みに10秒以上かかり、インタラクティブプロンプトでコマンドを入力できます

xcc>> add target myprogram
xcc>> set source myprogram $PROJDIR/src/
xcc>> set includes myprogram $PROJDIR/include/
xcc>> set type myprogram primitive
xcc>> set inputs myprogram int8,int8
xcc>> set outputs myprogram fix16,fix16
xcc>> build myprogram

上記の手順はカスタムマクロに組み込むことができるbuildmyprog.macroので、シェルから直接、またはemacsから実行できます。M-x compile

$ xcc buildmyprog.macro

このアプローチの主な問題は、xccコンパイルが始まるまでにプログラムのロードに10秒かかることです。私はすべての時間、私は私が実行し始めていることをコンパイルし、余分な10秒待っているの疲れ十分に得xccansi-term別のバッファでは。コードを変更して保存した後、ansi-termバッファに切り替えて実行します

xcc>> build myprogram

これは問題なく動作しますが、そのバッファーに切り替えるたびに、「プッシュするだけでF7コンパイルコマンドが既に実行中のインスタンスに送信されたら、すばらしいと思いませんxccか?」


セットアップは環境にどのような影響を与えますか?環境変数、一時ファイル?
T.バーロン2014年

環境は独自のプログラムです。環境変数と一時ファイルをある程度使用しますが、プログラム自体は、プログラムが閉じると消える独自の内部状態を維持します。
nispio 2014年

3
編集に基づいて、私comintはあなたの環境のために派生モードが必要だと思います。あなたが冒険心を持っているなら、ここにそれを書くためのガイドがあります。
Vamsi 2014年

@Vamsi私冒険心を感じており、それは素晴らしいリードのようです。ありがとう。
nispio 2014年

1
コマンドをcomintバッファーに送信する最も簡単で汚れた方法は、コマンドをバッファーに挿入してを呼び出すことcomint-send-inputです。これは基本的に手動で行うものであり、elispへの変換はそれほど難しくありません(特に、comintの設定と比較すると)。
T.バーロン2014年

回答:


2

emacsを開始する前に、シェルでセットアップを行うことができますか?compileサブシェルは、Emacsを経由してその祖父母から環境を継承する必要があります。


1
私が実行している「環境」がPythonであると想像してください。(これはPythonではありません。)PythonインタープリターからEmacsを起動できる場合でも、M-x compileそのコマンドをpythonインタープリターに送り返しません。
nispio 2014年

0

次に、eshellまたはのように、Emacs内で実際のシェルを使用しansi-termます。compileコンパイルに使用する必要がありますが、任意のコマンドの実行に使用できます。

コンパイルコマンドでは可能ではないと思いますが、何か足りないことがあります。それ以外の場合は、すべてのセットアップ手順をシェルスクリプトに入れ、そのスクリプトをで実行できますM-x compile


3
ええ、そうですが、問題はM-x compile、現在のファイルをコンパイルする代替コマンドまたはそれに接続する方法です。
Gilles 'SO-悪をやめる' 14年

OPの@Gillesは、M-x compile呼び出し間で一貫したシェル環境を望んでおり、それが実際のシェルの役割です。コンパイルコマンドでは可能ではないと思いますが、何か足りないことがあります。それ以外の場合、OPはすべてのセットアップ手順をシェルスクリプトに入れ、そのスクリプトを次のM-x compile
Tu Do

私はあなたの最初の提案を理解しているとは思いません。「eshellシェルcompile用、コンパイル用に使用」と言っていますか?それは全体のポイントを打ち負かします。
nispio 2014年

2番目の提案を試しましたが、いくつか問題がありました。(そのため、この質問を投稿しました。)各コンパイルに多くのオーバーヘッドを追加するため、遅すぎます。私は環境を一度セットアップするだけでよいので、これは不必要です。また、現在の環境で 1つのこと微調整して、再度コンパイルすることはできないため、結果的に十分に動的ではなくなります。ビルド環境はプログラムなので、制御するためのシェルスクリプトを書くことはできません。環境用にコンパイルされたマクロスクリプトを記述し、コンパイルコマンド自体をマクロに含める必要があります。
nispio 2014年

0

可能な解決策は、永続的なインタープリターを専用バッファー(バッファーのようなものです*compilation*が、基礎となるプロセスが戻らない場所)に常駐させることです。次に、recompile-likeコマンドを使用して、定義済みのコンパイルコマンドをインタープリターに送信し、結果を表示できます。

以下はそのような戦略の暫定的な実装です。このpersistent-compileコマンドは、プロセスの初期化(最初に呼び出されたとき、またはプレフィックス引数を使用したとき)と再コンパイル(インタープリタープロセスが既に稼働している場合)の両方を処理します。コンパイル結果は*persistent-compilation*バッファに表示されcompilation-shell-minor-mode、通常のcompilation-mode機能を利用してエラー間を移動できます。

次に、使用例と結果の*persistent-compilation*バッファの内容を示します。

  1. M-xpersistent-compileRET /bin/bashRET FOO=barRET echo $FOORET

    $ FOO=bar
    $ echo $FOO
    bar
    $
    
  2. M-xpersistent-compileRET

    $ echo $FOO
    bar
    $
    

次のコードはあまりテストされていません。たとえば、前回のコンパイルが終了する前に再コンパイルしようとするとどうなるかわかりません。

(defvar persistent-compile-interpreter "/bin/bash"
  "Interpreter to be used for persistent compilations.")

(defvar persistent-compile-init ""
  "Initialization command for persistent compilations.")

(defvar persistent-compile-command "make -k"
  "Compilation command for persistent compilations.")

;; Local variable in the persistent compilation buffer
(defvar persistent-compile--next-action)

(defun persistent-compile (&optional edit-command)
  "(Re-)run a persistent compilation.

The first time a persistent compilation is run, the user is asked
for an interpreter, an initialization command and a compilation
command.
The interpreter is started and optionally set up with the
initialization command.  The compilation command is then sent to
the interpreter.

All subsequent recompilations are sent to the same,
already-initialized interpreter, so as to keep the customized
environment.

If EDIT-COMMAND is non-nil, the user can edit the
parameters (interpreter, initialization command and compilation
command) and the interpreter is restarted."
  (interactive "P")
  (when (or edit-command
            (null (get-buffer "*persistent-compilation*"))
            (not persistent-compile-interpreter)
            (not persistent-compile-init)
            (not persistent-compile-command))
    (setq persistent-compile-interpreter (read-from-minibuffer "Interpreter: "
                                                               persistent-compile-interpreter)
          persistent-compile-init        (read-from-minibuffer "Initialization command: "
                                                               persistent-compile-init)
          persistent-compile-command     (read-from-minibuffer "Command: "
                                                               persistent-compile-command)))
  (with-current-buffer (get-buffer-create "*persistent-compilation*")
    (if (and edit-command
             (get-buffer-process (current-buffer)))
        ;; Kill an existing process and schedule for a recompilation with
        ;; the new parameters
        (progn
          (set-process-sentinel
           (get-buffer-process (current-buffer))
           (lambda (process event)
             (persistent-recompile nil)))
          (kill-process (get-buffer-process (current-buffer))))

      (if (not (get-buffer-process (current-buffer)))
          ;; Start and initialize a new process
          (progn
            (erase-buffer)
            (make-comint-in-buffer "persistent-compile" (current-buffer) persistent-compile-interpreter)
            (compilation-shell-minor-mode 1)
            (make-local-variable 'persistent-compile--next-action)
            (setq persistent-compile--next-action 'persistent-compile--initialize)
            (add-hook 'comint-output-filter-functions 'persistent-compile--at-prompt))

        ;; Run command
        (erase-buffer)
        (persistent-compile--send-command)))))

(defun persistent-compile--at-prompt (&optional output)
  (when persistent-compile--next-action
    ;; There is probably a better way of checking whether we are
    ;; just after a prompt, but I didn't find it...
    (let ((p1 (point))
          (p2 (save-excursion (comint-bol))))
      (unless (= p1 p2)
        (let ((action persistent-compile--next-action))
          (setq persistent-compile--next-action nil)
          (funcall action))))))

(defun persistent-compile--initialize ()
  (setq persistent-compile--next-action 'persistent-compile--send-command)
  (display-buffer (current-buffer))
  (insert persistent-compile-init)
  (comint-send-input nil t))

(defun persistent-compile--send-command ()
  (display-buffer (current-buffer))
  (insert persistent-compile-command)
  (comint-send-input nil t))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.