unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Romanos Skiadas <rom.skiad@gmail.com>
To: "João Távora" <joaotavora@gmail.com>, emacs-devel@gnu.org
Cc: npostavs@users.sourceforge.net, lele@metapensiero.it,
	mvoteiza@udel.edu, monnier@iro.umontreal.ca,
	Eli Zaretskii <eliz@gnu.org>,
	sdl.web@gmail.com
Subject: Re: New Flymake rewrite in emacs-26
Date: Wed, 11 Oct 2017 18:49:00 +0100	[thread overview]
Message-ID: <43bcb3a1-118e-73fb-17d9-c32a74b829e3@gmail.com> (raw)
In-Reply-To: <87k2017qed.fsf@gmail.com>

Hi,

This looks very interesting. I haven't tried it out yet, but the idea 
behind it seems to be very similar to cmake-ide[1]. Would it make sense 
to spin this off in its own library instead of making it flymake 
specific? This way other packages like company/auto-complete/flycheck 
can use it too.

Best,
Romanos

[1][https://github.com/atilaneves/cmake-ide]

On 11/10/17 14:41, João Távora wrote:
> joaotavora@gmail.com (João Távora) writes:
>
>> No, I was aiming for something more generic that includes at least Emacs
>> and perhaps other GNU projects.
> FWIW, here's what I hacked up so far. Seems to work OK in two GNU
> projects: Emacs and Hello (after ./configure, of course).
>
> Probably flawed, but it's a start. Feedback welcome. To test, just load
> this file and M-x flymake-mode in a C file.
>
> Another option, as suggested previously, is to have a special Makefile
> target (that'll need reconfiguring for each project, though).
>
> João
>
> ;;; flymake-gcc.el --- naive gcc Flymake backend -*- lexical-binding: t; -*-
>
> (defvar flymake-gcc-program "gcc"
>    "GCC program")
>
> (defun flymake--gcc-heroic-unescape (string)
>    (with-temp-buffer
>      (let ((error-buffer (current-buffer)))
>        (with-temp-buffer
>          (cond
>           ((zerop
>             ;; I suspect "shell-command" makes windows even when called
>             ;; from lisp.
>             (save-window-excursion
>               (shell-command
>                (format
>                 "%s -Q --batch --eval \"%s\" -- %s"
>                 (expand-file-name invocation-name
>                                   invocation-directory)
>                 "(mapc 'print (nthcdr 4 command-line-args))"
>                 string)
>                (current-buffer)
>                error-buffer)))
>            (goto-char (point-min))
>            (cl-loop with eof = (make-symbol "eof")
>                     for form =
>                     (condition-case _err
>                         (read (current-buffer))
>                       (error eof))
>                     while (not (eq form eof))
>                     collect form))
>           (t
>            (with-current-buffer error-buffer
>              (error (buffer-string)))))))))
>
> (defvar flymake-gcc-flags 'flymake-gcc-guess-flags
>    "A list of flags passed to GCC.
> Alternatively, a symbol naming a function called with no
> arguments that should produce this list of flags, or error if it
> cannot do so.")
>
> (defvar flymake-gcc-extra-flags '("-Wextra" "-Wall")
>    "A list of extra flags passed to GCC.")
>
> (defvar-local flymake--gcc-cached-flags nil
>    "Internal variable for `flymake-gcc-guess-flags'")
>
> (defun flymake-gcc-guess-flags (&optional trash-cache)
>    "Guess GCC flags for compiling current buffer "
>    (interactive "P")
>    (unless (executable-find "make") (error "Cannot find a suitable make"))
>    (when trash-cache (setq flymake--gcc-cached-flags nil))
>    (catch 'retval
>      (unless (buffer-file-name)
>        ;; don't error and don't cache, so that when the buffer is saved
>        ;; we get another chance.
>        (throw 'retval nil))
>      (when-let* ((makefile-dir
>                   (locate-dominating-file default-directory "Makefile"))
>                  (makefile (expand-file-name "Makefile" makefile-dir))
>                  (mtime (file-attribute-modification-time
>                          (file-attributes makefile))))
>        (cond
>         ((equal (list makefile mtime)
>                 (cdr flymake--gcc-cached-flags))
>          (when (called-interactively-p 'interactive)
>            (message "cached hit for flags for this buffer: %s"
>                     (car flymake--gcc-cached-flags)))
>          (throw 'retval (car flymake--gcc-cached-flags)))
>         (t
>          (let*
>              ((sans-nothing
>                (file-name-nondirectory
>                 (file-name-sans-extension
>                  (buffer-file-name))))
>               (blob (shell-command-to-string
>                      (format "make -C %s -f %s --just-print %s.o"
>                              makefile-dir
>                              makefile
>                              sans-nothing)))
>               (match (string-match
>                       (format "gcc[[:space:]]+\\(\\(?:-.*\\)*\\)%s"
>                               sans-nothing)
>                       blob))
>               (flag-string (and match
>                                 (match-string 1 blob)))
>               (flags (and flag-string
>                           (flymake--gcc-heroic-unescape flag-string))))
>            (when (or flags (string= "" flag-string))
>              (setq flymake--gcc-cached-flags (list flags makefile mtime))
>              (when (called-interactively-p 'interactive)
>                (message "cached miss for flags for this buffer: %s" flags))
>              (throw 'retval flags))))))
>      (error "Could not guess gcc flags")))
>
>
> (defvar-local flymake--gcc-proc nil
>    "Internal variable for `flymake-gcc'")
>
> (defun flymake-gcc (report-fn &rest _args)
>    "Flymake backend for GCC"
>    (unless (executable-find flymake-gcc-program)
>      (error "Cannot find a suitable gcc"))
>    (when (process-live-p flymake--gcc-proc)
>      (kill-process flymake--gcc-proc))
>    (let ((source (current-buffer)))
>      (save-restriction
>        (widen)
>        (setq flymake--gcc-proc
>              (make-process
>               :name "gcc-flymake"
>               :buffer (generate-new-buffer "*gcc-flymake*")
>               :command `(,flymake-gcc-program
>                          "-fsyntax-only"
>                          ,@flymake-gcc-extra-flags
>                          ,@(if (symbolp flymake-gcc-flags)
>                                (funcall flymake-gcc-flags)
>                              flymake-gcc-flags)
>                          "-x" "c" "-")
>               :noquery t :connection-type 'pipe
>               :sentinel
>               (lambda (p _ev)
>                 (when (eq 'exit (process-status p))
>                   (unwind-protect
>                       (when (eq p flymake--gcc-proc)
>                         (with-current-buffer (process-buffer p)
>                           (goto-char (point-min))
>                           (cl-loop
>                            while (search-forward-regexp
>                                   "^<stdin>:\\([0-9]+\\):\\([0-9]+\\): \\(.*\\): \\(.*\\)$"
>                                   nil t)
>                            for msg = (match-string 4)
>                            for (beg . end) =
>                            (flymake-diag-region
>                             source
>                             (string-to-number (match-string 1))
>                             (string-to-number (match-string 2)))
>                            for type = (assoc-default
>                                        (match-string 3)
>                                        '(("error" . :error)
>                                          ("note" . :note)
>                                          ("warning" . :warning))
>                                        #'string-match)
>                            collect (flymake-make-diagnostic source beg end type msg)
>                            into diags
>                            finally (funcall report-fn diags))))
>                     ;; (display-buffer (process-buffer p)) ; use this instead of the next one for debug
>                     (kill-buffer (process-buffer p))
>                     ))
>                 )))
>        (process-send-region flymake--gcc-proc (point-min) (point-max))
>        (process-send-eof flymake--gcc-proc))))
>
> (defun flymake--setup-gcc-flymake ()
>    (add-hook 'flymake-diagnostic-functions 'flymake-gcc nil t))
>
> (add-hook 'c-mode-hook 'flymake--setup-gcc-flymake)
>
> ;;; flymake-gcc.el ends here
>
>
>




  reply	other threads:[~2017-10-11 17:49 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-03 14:05 New Flymake rewrite in emacs-26 João Távora
2017-10-03 15:00 ` Eli Zaretskii
2017-10-04 11:58   ` Lele Gaifax
2017-10-04 13:41     ` Lele Gaifax
2017-10-04 16:08       ` João Távora
2017-10-04 16:42         ` Lele Gaifax
2017-10-04 18:11           ` Lele Gaifax
2017-10-05  2:21             ` João Távora
2017-10-05 11:42               ` Lele Gaifax
2017-10-05 23:32                 ` Noam Postavsky
2017-10-06 13:16                   ` João Távora
2017-10-06 13:24                     ` Noam Postavsky
2017-10-06 15:48                       ` João Távora
2017-10-07  7:37                 ` Lele Gaifax
2017-10-07 16:08                   ` João Távora
2017-10-10 12:25   ` João Távora
2017-10-10 14:18     ` Eli Zaretskii
2017-10-10 15:09       ` João Távora
2017-10-10 15:53         ` Eli Zaretskii
2017-10-10 16:25           ` João Távora
2017-10-10 16:40             ` Eli Zaretskii
2017-10-10 17:03               ` João Távora
2017-10-10 17:20                 ` Noam Postavsky
2017-10-11  0:07                   ` João Távora
2017-10-11  0:59                     ` Noam Postavsky
2017-10-11 10:39                       ` Eli Zaretskii
2017-10-11 12:16                         ` Noam Postavsky
2017-10-11 12:25                           ` João Távora
2017-10-11 10:24                     ` Eli Zaretskii
2017-10-11 12:01                       ` João Távora
2017-10-11 12:13                         ` Eli Zaretskii
2017-10-11 13:41                         ` João Távora
2017-10-11 17:49                           ` Romanos Skiadas [this message]
2017-10-11 18:39                             ` guillaume papin
2017-10-12 13:17                               ` João Távora
2017-10-11 20:25                           ` Stefan Monnier
2017-10-12 13:10                             ` João Távora
2017-10-12 13:43                               ` Stefan Monnier
2017-10-12 13:56                                 ` João Távora
2017-10-11 13:11                     ` Mark Oteiza
2017-10-10 17:23                 ` Eli Zaretskii
2017-10-11 11:11             ` Lele Gaifax

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=43bcb3a1-118e-73fb-17d9-c32a74b829e3@gmail.com \
    --to=rom.skiad@gmail.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=joaotavora@gmail.com \
    --cc=lele@metapensiero.it \
    --cc=monnier@iro.umontreal.ca \
    --cc=mvoteiza@udel.edu \
    --cc=npostavs@users.sourceforge.net \
    --cc=sdl.web@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).