[PATCH] Flymake support for C/C++

classic Classic list List threaded Threaded
37 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[PATCH] Flymake support for C/C++

João Távora
Hi,

Here's a proposal for supporting Flymake in C/C++. This patch:

- Sets up Flymake in c-mode buffers (heads up Alan), but doesn't
  automatically enable it.

- Adds a special target to src/Makefile so that Flymake can work with
  Emacs's C sources (using a default cc-flymake-use-special-make-target
  method).

- The special target's name is 'check-syntax' and uses CHK_SOURCES,
  which lets older Emacsen edit new Emacs sources with old Flymake
  implementations (dubious but harmless advantage).

- Is customizable by the user to use a zero-configuration method that
  guesses GCC flags from Makefiles (see
  cc-flymake-use-cc-directly). This probably works in the simplest
  scenarios(*)

- Is programmable by the user to use any other self-configuration
  technique (this includes per-file/dir manual configuration using a
  file-local cc-flymake-command)

*: Sadly, GNU Hello no longer works since it uses a backquoted shell
  expression that the current implementation can't intercept (my old
  use-emacs-as-a-shell-parser )
  Here it is, for reference

gcc -DLOCALEDIR=\"/usr/local/share/locale\" -DHAVE_CONFIG_H -I. -I. -I.. -I. -I. -I.. -I../intl -I../intl    -g -O2 -c `test -f 'hello.c' || echo './'`hello.c

Also, FTR, discovered that -M flags do not seem to harm syntax-checking.
No idea if dependencies files are still created anyway though.

João


From 41ef8318c8c539e475080e3b240b9c941d39caa9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= <[hidden email]>
Date: Thu, 12 Oct 2017 14:04:51 +0100
Subject: [PATCH] Add a Flymake backend for C(++)

* lisp/progmodes/cc-flymake.el: New file.

* lisp/progmodes/cc-mode.el (c-mode): Call c--setup-flymake.
(c--setup-flymake): New function.

* src/Makefile.in: Add check-syntax target.
---
 lisp/progmodes/cc-flymake.el | 214 +++++++++++++++++++++++++++++++++++++++++++
 lisp/progmodes/cc-mode.el    |   9 ++
 src/Makefile.in              |   5 +
 3 files changed, 228 insertions(+)
 create mode 100644 lisp/progmodes/cc-flymake.el

diff --git a/lisp/progmodes/cc-flymake.el b/lisp/progmodes/cc-flymake.el
new file mode 100644
index 0000000000..4baffdd3be
--- /dev/null
+++ b/lisp/progmodes/cc-flymake.el
@@ -0,0 +1,214 @@
+;;; cc-flymake.el --- Flymake backends for C/C++     -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; Author: João Távora <[hidden email]>
+;; Keywords: languages, c
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Flymake support for C/C++.
+
+;;; Code:
+
+(require 'subr-x) ; when-let*
+
+(defcustom cc-flymake-command 'cc-flymake-use-special-make-target
+  "Command used by the CC flymake backend.
+A list of strings, or a symbol naming a function that produces one
+such list when called with no arguments in the buffer where the
+variable `flymake-mode' is active.
+
+The command should invoke a GNU-style compiler that checks the
+syntax of a (Obj)C(++) program passed to it via its standard
+input and prints the result on its standard output."
+  :type '(choice
+          (symbol :tag "Function")
+          ((repeat :) string))
+  :group 'cc-flymake)
+
+(defvar-local cc-flymake--cached-flags nil)
+
+(defun cc-flymake--guess-flags (cc-program &optional trash-cache)
+  "Guess C(++) flags for compiling current buffer.
+Do this with by finding a suitable Makefile and intercepting an
+invocation of CC-PROGRAM, a string naming a C(++) compiler, in
+the output of \"make --just-print <file.o>\".
+
+Cache the result. TRASH-CACHE of a change to the Makefile rests
+the cache.
+
+This function signals an error if it encounters any problems,
+which normally causes using backends to be disabled.
+
+Can also function interactively for debug purposes."
+  (interactive (list (read-from-minibuffer "Compiler? ")
+                     current-prefix-arg))
+  (when trash-cache (setq cc-flymake--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 cc-program makefile mtime)
+               (cdr cc-flymake--cached-flags))
+        (when (called-interactively-p 'interactive)
+          (message "cache HIT for %s flags: %S" cc-program
+                   (car cc-flymake--cached-flags)))
+        (throw 'retval (car cc-flymake--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 "%s[[:space:]]+\\(\\(?:-.*\\)*\\)%s"
+                             cc-program
+                             sans-nothing)
+                     blob))
+             (flag-string (and match
+                               (match-string 1 blob)))
+             (flags (and flag-string
+                         ;; FIXME: shell unescaping: Nothing here to
+                         ;; deal with simple backslash-escaped spaces,
+                         ;; like quoted and backquoted expressions,
+                         ;; etc.
+                         (split-string
+                          flag-string
+                          nil
+                          nil
+                          "[[:space:]]+"))))
+          (when (or flags (string= "" flag-string))
+            (setq cc-flymake--cached-flags
+                  (list flags cc-program makefile mtime))
+            (when (called-interactively-p 'interactive)
+              (message "cache MISS for %s flags: %S" cc-program flags))
+            (throw 'retval flags))))))
+    (error "Could not guess %s flags" cc-program)))
+
+(require 'compile)
+(defun cc-flymake--make-diagnostics (source)
+  "Parse the current buffer of compilation messages.
+Return a list of diagnostics for the source buffer SOURCE."
+  ;; TODO: if you can understand it, use `compilation-mode's regexps
+  ;; or even some of its machinery here.
+  ;;
+  ;;    (set (make-local-variable 'compilation-locs)
+  ;;         (make-hash-table :test 'equal :weakness 'value))
+  ;;    (compilation-parse-errors (point-min) (point-max)
+  ;;                              'gnu 'gcc-include)
+  ;;    (while (next-single-property-change 'compilation-message)
+  ;;       ...)
+  ;;
+  ;; For now, this works minimaly well.
+  (cl-loop
+   while
+   (search-forward-regexp
+    "^\\(In file included from \\)?<stdin>:\\([0-9]+\\):\\([0-9]+\\):\n?\\(.*\\): \\(.*\\)$"
+    nil t)
+   for msg = (match-string 5)
+   for (beg . end) = (flymake-diag-region
+                      source
+                      (string-to-number (match-string 2))
+                      (string-to-number (match-string 3)))
+   for type = (if (match-string 1)
+                  :error
+                (assoc-default
+                 (match-string 4)
+                 '(("error" . :error)
+                   ("note" . :note)
+                   ("warning" . :warning))
+                 #'string-match))
+   collect (flymake-make-diagnostic source beg end type msg)))
+
+(defun cc-flymake-use-special-make-target ()
+  "Build command for checking a file with Make directly."
+  (unless (executable-find "make") (error "Make not found"))
+  `("make" "check-syntax" "CHK_SOURCES=-x c -"))
+
+(defvar-local cc-flymake-program "cc"
+  "C(++) compiler used by `cc-flymake-use-cc-directly'.")
+
+(defun cc-flymake-use-cc-directly ()
+  "Build command for checking a file with a C(++) compiler."
+  (unless (executable-find cc-flymake-program)
+    (error "%s not found" cc-flymake-program))
+  `(,cc-flymake-program
+    "-fsyntax-only"
+    ,@(cc-flymake--guess-flags cc-flymake-program)
+    "-x" "c" "-"))
+
+(defvar-local cc-flymake--proc nil
+  "Internal variable for `flymake-gcc'")
+
+;;;###autoload
+(defun cc-flymake (report-fn &rest _args)
+  "Flymake backend for GNU-style C compilers.
+This backend uses `cc-flymake-command' (which see) to launch a
+process that is passed the current buffer's contents via stdin.
+REPORT-FN is Flymake's callback."
+  (when (process-live-p cc-flymake--proc)
+    (kill-process cc-flymake--proc))
+  (let ((source (current-buffer)))
+    (save-restriction
+      (widen)
+      (setq
+       cc-flymake--proc
+       (make-process
+        :name "gcc-flymake"
+        :buffer (generate-new-buffer "*gcc-flymake*")
+        :command (if (symbolp cc-flymake-command)
+                     (funcall cc-flymake-command)
+                   cc-flymake-command)
+        :noquery t :connection-type 'pipe
+        :sentinel
+        (lambda (p _ev)
+          (when (eq 'exit (process-status p))
+            (unwind-protect
+                (when (eq p cc-flymake--proc)
+                  (with-current-buffer (process-buffer p)
+                    (goto-char (point-min))
+                    (let ((diags
+                           (cc-flymake--make-diagnostics source)))
+                      (if (or diags
+                              (zerop (process-exit-status p)))
+                          (funcall report-fn diags)
+                        ;; non-zero exit with no diags is cause
+                        ;; for alarm
+                        (funcall report-fn
+                                 :panic :explanation
+                                 (buffer-substring
+                                  (point-min) (progn (goto-char (point-min))
+                                                     (line-end-position))))))))
+              ;; (display-buffer (process-buffer p)) ; for debug
+              (kill-buffer (process-buffer p)))))))
+      (process-send-region cc-flymake--proc (point-min) (point-max))
+      (process-send-eof cc-flymake--proc))))
+
+(provide 'cc-flymake)
+;;; cc-flymake.el ends here
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index b0e5fe47a7..37c8ecfa98 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1842,6 +1842,7 @@ c-mode
   (c-common-init 'c-mode)
   (easy-menu-add c-c-menu)
   (cc-imenu-init cc-imenu-c-generic-expression)
+  (c--setup-flymake)
   (c-run-mode-hooks 'c-mode-common-hook))
 
 (defconst c-or-c++-mode--regexp
@@ -2297,6 +2298,14 @@ c-submit-bug-report
  (insert (format "Buffer Style: %s\nc-emacs-features: %s\n"
  style c-features)))))))
 
+(defun c--setup-flymake ()
+  "Setup flymake for cc buffers."
+  (add-hook 'flymake-diagnostic-functions 'cc-flymake nil t)
+  (defvar flymake-proc-allowed-file-name-masks)
+  ;; hackinly convince the legacy `flymake-proc' backend to disable
+  ;; itself.
+  (setq-local flymake-proc-allowed-file-name-masks nil))
+
 
 (cc-provide 'cc-mode)
 
diff --git a/src/Makefile.in b/src/Makefile.in
index 9a8c9c85f0..66c259902f 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -746,3 +746,8 @@ bootstrap-emacs$(EXEEXT):
 endif
  @: Compile some files earlier to speed up further compilation.
  $(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)"
+
+### Flymake support (for C only)
+check-syntax:
+ $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) ${CHK_SOURCES} || true
+.PHONY: check-syntax
--
2.11.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Mark Oteiza

[hidden email] (João Távora) writes:

> +;; Flymake support for C/C++.
> +
> +;;; Code:
> +
> +(require 'subr-x) ; when-let*

Should only need it at compile time, then.

> +(defun cc-flymake-use-cc-directly ()
> +  "Build command for checking a file with a C(++) compiler."
> +  (unless (executable-find cc-flymake-program)
> +    (error "%s not found" cc-flymake-program))
> +  `(,cc-flymake-program
> +    "-fsyntax-only"
> +    ,@(cc-flymake--guess-flags cc-flymake-program)
> +    "-x" "c" "-"))

If we're handling multiple languages, a case for the major mode seems
appropriate:

 ...
 "-x" (pcase major-mode
        (`c-mode "c")
        ...)
 "-")

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Alan Mackenzie
In reply to this post by João Távora
Hello, João.

On Thu, Oct 12, 2017 at 16:09:15 +0100, João Távora wrote:
> Hi,

> Here's a proposal for supporting Flymake in C/C++. This patch:

> - Sets up Flymake in c-mode buffers (heads up Alan), but doesn't
>   automatically enable it.

I must admit not to being too keen on CC Mode changing like this; it
would spoil the unity of purpose of the mode.  I've glanced through the
new code, but can't quite see why it needs to be an integral part of CC
Mode.  What is stopping the needed setup and initialisation being in a
function to be added to one of the mode's hooks: say c-mode-common-hook,
or even c-initialization-hook (which are documented in the CC Mode
manual)?

If there is any reason why it couldn't work on a CC Mode hook, I'd far
rather solve that reason (thus making the solution available for other
libraries too, and preserving the unity of CC Mode).

[ .... ]

--
Alan Mackenzie (Nuremberg, Germany).

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Stefan Monnier
> What is stopping the needed setup and initialisation being in a
> function to be added to one of the mode's hooks: say c-mode-common-hook,
> or even c-initialization-hook (which are documented in the CC Mode
> manual)?

The same could apply to font-lock support in CC-mode, or indentation
support in CC-mode, or imenu support, or ...

I'm not saying that the flymake support for C code has to be in CC-mode,
but I think it's a natural place for it.


        Stefan

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

João Távora
In reply to this post by Alan Mackenzie
Hi Alan,

Thanks for the quick reply.

Alan Mackenzie <[hidden email]> writes:

> I must admit not to being too keen on CC Mode changing like this; it
> would spoil the unity of purpose of the mode.  I've glanced through the
> new code, but can't quite see why it needs to be an integral part of CC
> Mode.

Does setting a variable in the mode function make it an "integral part"?

> What is stopping the needed setup and initialisation being in a
> function to be added to one of the mode's hooks: say c-mode-common-hook,
> or even c-initialization-hook (which are documented in the CC Mode
> manual)?

I may be wrong, but I thought hooks were reserved for the user and
should be empty by default. But even if they weren't I don't think it
would work:

c-initialization-hook doesn't work, as flymake-diagnostic-functions is
a hook which needs a buffer-local value.

c-mode-common-hook is where a user would turn on `flymake-mode'. I, for
example, have this in my .emacs, which is the recommended way to turn on
a minor mode:

  (add-hook 'c-mode-common-hook 'flymake-mode)

If the setup is also moved to c-mode-common-hook, then this won't work
(because flymake-mode activation comes before its setup).

> If there is any reason why it couldn't work on a CC Mode hook,

Absolutely no reason, but those two don't seem to fit. Perhaps some new
hook run before c-mode-common-hook.

> I'd far rather solve that reason (thus making the solution available
> for other libraries too, and pres<erving the unity of CC Mode).

I don't understand what the boundaries of that "unity" are, but I do
understand cc-mode.el seems to be a special citizen in Emacs
major-mode-land.

Anyway Flymake wants to be a part of the global infrastructure for major
modes, which includes setting variables for recent "fancy" stuff like
ElDoc (eldoc-documentation-function), and older stuff like newcomment.el
(comment-*), to give just two examples. My patch does the same for
Flymake and flymake-diagnostic-functions.

João


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Alan Mackenzie
Hello again, João.

On Thu, Oct 12, 2017 at 19:46:20 +0100, João Távora wrote:
> Hi Alan,

> Alan Mackenzie <[hidden email]> writes:

> > I must admit not to being too keen on CC Mode changing like this; it
> > would spoil the unity of purpose of the mode.  I've glanced through the
> > new code, but can't quite see why it needs to be an integral part of CC
> > Mode.

> Does setting a variable in the mode function make it an "integral part"?

Yes.  It tightly couples Flymake Mode with CC Mode.  It would render CC
Mode non-functional in the absence of Flymake Mode.  Distinct
functionalities should not be tightly coupled.

> > What is stopping the needed setup and initialisation being in a
> > function to be added to one of the mode's hooks: say c-mode-common-hook,
> > or even c-initialization-hook (which are documented in the CC Mode
> > manual)?

> I may be wrong, but I thought hooks were reserved for the user and
> should be empty by default.

But it would surely be a user action which would enable flymake-mode,
thus adding to a CC Mode hook.  Major mode hooks are usually not used by
Emacs itself, but I'm not aware of any convention which prohibits it.

> But even if they weren't I don't think it would work:

> c-initialization-hook doesn't work, as flymake-diagnostic-functions is
> a hook which needs a buffer-local value.

OK, so f-d-functions could be set in c-mode-common-hook then, couldn't
it?

> c-mode-common-hook is where a user would turn on `flymake-mode'. I, for
> example, have this in my .emacs, which is the recommended way to turn on
> a minor mode:

>   (add-hook 'c-mode-common-hook 'flymake-mode)

> If the setup is also moved to c-mode-common-hook, then this won't work
> (because flymake-mode activation comes before its setup).

I don't understand that last bit.  What's the difference between
activation and setup?  It would seem then, the activation has nothing to
do with the major mode, or else it could be done in a major mode hook.
What am I missing here?

> > If there is any reason why it couldn't work on a CC Mode hook,

> Absolutely no reason, but those two don't seem to fit. Perhaps some new
> hook run before c-mode-common-hook.

"Those two" being activation and setup?

What do they need which is in CC Mode?  And how would a new CC Mode hook
help?  Would you be wanting it to be run before CC Mode is fully
initialised?

> > I'd far rather solve that reason (thus making the solution available
> > for other libraries too, and pres<erving the unity of CC Mode).

> I don't understand what the boundaries of that "unity" are, ....

"Do one thing and do it well".  Let's not get into the "do it well" bit
here, but the "do one thing" is "edit C/C++/... buffers".  Flymake would
appear to be distinct from that one thing.  What does Flymake do,
anyway?  There's nothing in the Emacs manual about it, and it's doc
string consists purely of boilerplate, at least in Emacs 25.3.

> .... but I do understand cc-mode.el seems to be a special citizen in
> Emacs major-mode-land.

:-)  As a matter of interest CC Mode consists of ~14 files, one of which
is cc-mode.el.

> Anyway Flymake wants to be a part of the global infrastructure for major
> modes, which includes setting variables for recent "fancy" stuff like
> ElDoc (eldoc-documentation-function), and older stuff like newcomment.el
> (comment-*), to give just two examples. My patch does the same for
> Flymake and flymake-diagnostic-functions.

But it should be loosely coupled with major modes, not tightly coupled,
surely?

> João

--
Alan Mackenzie (Nuremberg, Germany).

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Alan Mackenzie
In reply to this post by Stefan Monnier
Hello, Stefan.

On Thu, Oct 12, 2017 at 14:45:39 -0400, Stefan Monnier wrote:
> > What is stopping the needed setup and initialisation being in a
> > function to be added to one of the mode's hooks: say c-mode-common-hook,
> > or even c-initialization-hook (which are documented in the CC Mode
> > manual)?

> The same could apply to font-lock support in CC-mode, or indentation
> support in CC-mode, or imenu support, or ...

Font-lock and indentation support are essential to the major mode.  But
all of these, bar indentation, are connected to major modes via hooks of
one sort or another.

> I'm not saying that the flymake support for C code has to be in CC-mode,
> but I think it's a natural place for it.

What does Flymake mode do, anyway?  There's no documentation for it in
the Emacs manual, and its doc string, at least in 25.3, only says how to
turn it on and off, not what it's for.

>         Stefan

--
Alan Mackenzie (Nuremberg, Germany).

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Stefan Monnier
>> > What is stopping the needed setup and initialisation being in a
>> > function to be added to one of the mode's hooks: say c-mode-common-hook,
>> > or even c-initialization-hook (which are documented in the CC Mode
>> > manual)?
>> The same could apply to font-lock support in CC-mode, or indentation
>> support in CC-mode, or imenu support, or ...
> Font-lock and indentation support are essential to the major mode.  But
> all of these, bar indentation, are connected to major modes via hooks of
> one sort or another.

AFAICT, imenu support in CC-mode is enabled by having the major mode
function explicitly calling cc-imenu-init, not via some kind of hook.

Maybe all you want is for flymake support to be moved to cc-flymake.el
and then calls to `cc-flymake-init` be added to the relevant major
mode functions?

>> I'm not saying that the flymake support for C code has to be in CC-mode,
>> but I think it's a natural place for it.
> What does Flymake mode do, anyway?

It runs a code-checker in the background and highlights the source code
with the various error/warnings found.  It's very much like flyspell
except design to check code sanity rather spelling.

I think nowadays Emacs should strive to enable flymake automatically as
much as possible.  It's currently not really possible because *very* few
major modes support it, and because for most major modes you can't get
it to work without some user intervention (typically we need to have
some knowledge of the overall project organization in order to know how
this file relates to others, in C code typically we need at least
information about -I and -D compilation options).

But for Emacs-27, we should at the very least aim to enable it in
emacs-lisp-mode (where checking can be done without needing extra user
intervention).

> There's no documentation for it in the Emacs manual,

It's definitely in the manual in the emacs-26 branch.


        Stefan

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Stefan Monnier
In reply to this post by Alan Mackenzie
>> Does setting a variable in the mode function make it an "integral part"?
> Yes.  It tightly couples Flymake Mode with CC Mode.  It would render CC
> Mode non-functional in the absence of Flymake Mode.

No.  It just sets a variable.  This variable is then only used if the
user elects to enable flymake mode.  Without flymake mode, or if the
user decides not to enable flymake mode, it will have no effect at all.


        Stefan

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

João Távora
In reply to this post by Alan Mackenzie
Hello again, Alan.

Alan Mackenzie <[hidden email]> writes:

> Yes.  It tightly couples Flymake Mode with CC Mode.  It would render CC
> Mode non-functional in the absence of Flymake Mode.

If this your criteria for "tightly coupled", then it does not apply
here. c--setup-flymake simply adds to a(n abnormal) hook, using
add-hook, which is designed to be used even if the hook variable isn't
defined yet.

(There is actually a bit of unglyness in the current patch, in which
c--setup-flymake also `defvar's and `setq-local's another obsolete
variable. I could remove that bit and come up with a pure add-hook
solution.)

> thus adding to a CC Mode hook.  Major mode hooks are usually not used by
> Emacs itself, but I'm not aware of any convention which prohibits it.

Perhaps the example that I gave you is one of the reaons.

> OK, so f-d-functions could be set in c-mode-common-hook then, couldn't
> it?

No, for the reasons that I restate below.

> I don't understand that last bit.  What's the difference between
> activation and setup?

Activation is enabling the minor mode via the flymake-mode
function. Setup is ensuring that that activation is met with suitable
circunstances for the correct operation of the minor mode, in this case
that cc-specific "backends" are set.

> It would seem then, the activation has nothing to
> do with the major mode, or else it could be done in a major mode hook.
> What am I missing here?

You are not mistaken that activation has nothing to do with the major
mode, but you are missing that there are two steps, activation and
setup, that the differ in the ways I hope to have clarified above.

> "Those two" being activation and setup?

No sorry, those two being the two hooks that you suggested.

> What do they need which is in CC Mode?

They need to hook on to the major mode's function.

> And how would a new CC Mode hook
> help?

That would appease your wish for very loose coupling in that no mention
of the word "flymake" needed to appear in cc-mode.el

> Would you be wanting it to be run before CC Mode is fully initialised?

Doesn't matter really, before the user's c-mode-common-hook is fine.

> "Do one thing and do it well".  Let's not get into the "do it well"
> bit here, but the "do one thing" is "edit C/C++/... buffers".  Flymake
> would appear to be distinct from that one thing.

Ah, I so do agree with you Alan... and let's get not into the million
ways Emacs is already the kitchen sink. Flymake can be as useful to a
pretty broad definition of "editing" as font-locking, or imenu, or
outline.el, or supporting add-log-current-defun-function. All those
things that really aren't "editing", but help you edit.

> What does Flymake do, anyway?

It highlights the bits where you make mistakes as you type, or are about
to.

> There's nothing in the Emacs manual
> about it, and it's doc string consists purely of boilerplate, at least
> in Emacs 25.3.

That is true, but the situation changes considerably, if not immensely,
in emacs 26 :-). I rewrote Flymake and wrote a fair amount of
documention. You can read the documentaion in Texinfo format in the
"Flymake" node (which is separate from the Emacs user manual, for now)
or just C-h f flymake-mode RET in a recent emacs-26 or master build.

> But it should be loosely coupled with major modes, not tightly coupled,
> surely?

For sure, we agree. If you analyse the situation I think you'll come to
the conclusion that it is.

João


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Eli Zaretskii
In reply to this post by Alan Mackenzie
> Date: Thu, 12 Oct 2017 20:45:23 +0000
> Cc: [hidden email], [hidden email], [hidden email],
>   João Távora <[hidden email]>, [hidden email]
> From: Alan Mackenzie <[hidden email]>
>
> What does Flymake mode do, anyway?  There's no documentation for it in
> the Emacs manual, and its doc string, at least in 25.3, only says how to
> turn it on and off, not what it's for.

Flymake has its own manual, it should be in your info subdirectory.

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Richard Stallman
In reply to this post by João Távora
[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > *: Sadly, GNU Hello no longer works since it uses a backquoted shell
  >   expression that the current implementation can't intercept (my old
  >   use-emacs-as-a-shell-parser )

It is important to fix this, since it is not good for Flymake to fail
on the GNU example of proper packaging.

It could be fixed in Flymake or fixed in GNU Hello.
Which one is better?

--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Reuben Thomas
On 14 October 2017 at 02:34, Richard Stallman <[hidden email]> wrote:
[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > *: Sadly, GNU Hello no longer works since it uses a backquoted shell
  >   expression that the current implementation can't intercept (my old
  >   use-emacs-as-a-shell-parser )

It is important to fix this, since it is not good for Flymake to fail
on the GNU example of proper packaging.

It could be fixed in Flymake or fixed in GNU Hello.
Which one is better?

These days, it seems much better to use Flycheck than Flymake (that's certainly what I do). See https://github.com/flycheck/flycheck

It would be a pity for Flymake to become yet another part of Emacs that developers spend time updating and users largely ignore; better to spin it off into ELPA, and if people still want to work on it there, fine. Meanwhile, why not use Flycheck by default (in the same way as we've "in-sourced" Org and other packages)?

--
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Sami Kerola
On 14 October 2017 at 08:10, Reuben Thomas <[hidden email]> wrote:

> On 14 October 2017 at 02:34, Richard Stallman <[hidden email]> wrote:
>>
>> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
>> [[[ whether defending the US Constitution against all enemies,     ]]]
>> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>>
>>   > *: Sadly, GNU Hello no longer works since it uses a backquoted shell
>>   >   expression that the current implementation can't intercept (my old
>>   >   use-emacs-as-a-shell-parser )
>>
>> It is important to fix this, since it is not good for Flymake to fail
>> on the GNU example of proper packaging.
>>
>> It could be fixed in Flymake or fixed in GNU Hello.
>> Which one is better?
>
>
> These days, it seems much better to use Flycheck than Flymake (that's
> certainly what I do). See https://github.com/flycheck/flycheck
>
> It would be a pity for Flymake to become yet another part of Emacs that
> developers spend time updating and users largely ignore; better to spin it
> off into ELPA, and if people still want to work on it there, fine.
> Meanwhile, why not use Flycheck by default (in the same way as we've
> "in-sourced" Org and other packages)?

I tried to reproduce following comple output[1] without luck[2].

gcc -DLOCALEDIR=\"/usr/local/share/locale\" -DHAVE_CONFIG_H -I. -I. -I.. -I.
-I. -I.. -I../intl -I../intl    -g -O2 -c `test -f 'hello.c' || echo
'./'`hello.c

Perhaps backticks are coming from autotools. Mine are:

autoconf (GNU Autoconf) 2.69
automake (GNU automake) 1.15.1

[1] as mentioned in earlier in thread:
https://lists.gnu.org/archive/html/emacs-devel/2017-10/msg00432.html

[2] tested using hello-2.10 distribution package, and latest upstream
version 4d0301f23b1666cf466a0ac281a0ea008abe70bb.

--
Sami Kerola
http://www.iki.fi/kerolasa/

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Eli Zaretskii
In reply to this post by Reuben Thomas
> From: Reuben Thomas <[hidden email]>
> Date: Sat, 14 Oct 2017 08:10:44 +0100
> Cc: João Távora <[hidden email]>,
> Sami Kerola <[hidden email]>, [hidden email], Alan Mackenzie <[hidden email]>,
> Eli Zaretskii <[hidden email]>, Noam Postavsky <[hidden email]>, [hidden email],
> Stefan Monnier <[hidden email]>
>
> These days, it seems much better to use Flycheck than Flymake (that's certainly what I do). See
> https://github.com/flycheck/flycheck
>
> It would be a pity for Flymake to become yet another part of Emacs that developers spend time updating and
> users largely ignore; better to spin it off into ELPA, and if people still want to work on it there, fine. Meanwhile,
> why not use Flycheck by default (in the same way as we've "in-sourced" Org and other packages)?

I don't understand: Flycheck is an external package; why should we
prefer it to Flymake, assuming that the latter will become supported
well by the built-in major modes?

IOW, what I see here is a serious effort to make Flymake a
sophisticated and flexible syntax-checking tool bundled with Emacs.  I
don't see why should we object to such an effort, when one of our
major goals is to provide a modern program development environment.
If this effort is successful, I presume that users will not ignore
Flymake.

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Reuben Thomas
On 14 October 2017 at 09:00, Eli Zaretskii <[hidden email]> wrote:
> From: Reuben Thomas <[hidden email]>
> Date: Sat, 14 Oct 2017 08:10:44 +0100
> Cc: João Távora <[hidden email]>,
>       Sami Kerola <[hidden email]>, [hidden email], Alan Mackenzie <[hidden email]>,
>       Eli Zaretskii <[hidden email]>, Noam Postavsky <[hidden email]>, [hidden email],
>       Stefan Monnier <[hidden email]>
>
> These days, it seems much better to use Flycheck than Flymake (that's certainly what I do). See
> https://github.com/flycheck/flycheck
>
> It would be a pity for Flymake to become yet another part of Emacs that developers spend time updating and
> users largely ignore; better to spin it off into ELPA, and if people still want to work on it there, fine. Meanwhile,
> why not use Flycheck by default (in the same way as we've "in-sourced" Org and other packages)?

I don't understand: Flycheck is an external package; why should we
prefer it to Flymake, assuming that the latter will become supported
well by the built-in major modes?


And I suggested precisely bundling Flycheck with Emacs.​

IOW, what I see here is a serious effort to make Flymake a
sophisticated and flexible syntax-checking tool bundled with Emacs.  I
don't see why should we object to such an effort, when one of our
major goals is to provide a modern program development environment.

​Because with Flycheck this is already accomplished. Why not work instead on things that Emacs lacks?​ There are already far too many duplicated packages, leading to duplicated maintenance effort.

--
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Dmitry Gutov
On 10/14/17 11:15 AM, Reuben Thomas wrote:

> ​Because with Flycheck this is already accomplished. Why not work
> instead on things that Emacs lacks?​ There are already far too many
> duplicated packages, leading to duplicated maintenance effort.

See the second part of this comment:
https://github.com/flycheck/flycheck/issues/1177#issuecomment-267445833

"...I'd rather let Flycheck die if no maintainer was left to work on it
than moving it into Emacs..."

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Reuben Thomas
On 14 October 2017 at 09:22, Dmitry Gutov <[hidden email]> wrote:
On 10/14/17 11:15 AM, Reuben Thomas wrote:

​Because with Flycheck this is already accomplished. Why not work instead on things that Emacs lacks?​ There are already far too many duplicated packages, leading to duplicated maintenance effort.

See the second part of this comment: https://github.com/flycheck/flycheck/issues/1177#issuecomment-267445833

"...I'd rather let Flycheck die if no maintainer was left to work on it than moving it into Emacs..."

​It doesn't have to be moved, just as Org was not moved into Emacs, but continues to be maintained externally, and its sources imported.

--
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

Eli Zaretskii
In reply to this post by Reuben Thomas
> From: Reuben Thomas <[hidden email]>
> Date: Sat, 14 Oct 2017 09:15:52 +0100
> Cc: Richard Stallman <[hidden email]>, João Távora <[hidden email]>,
> Sami Kerola <[hidden email]>, [hidden email], Alan Mackenzie <[hidden email]>,
> Noam Postavsky <[hidden email]>, [hidden email],
> Stefan Monnier <[hidden email]>
>
>  I don't understand: Flycheck is an external package; why should we
>  prefer it to Flymake, assuming that the latter will become supported
>  well by the built-in major modes?
>
> ​See ​http://www.flycheck.org/en/latest/user/flycheck-versus-flymake.html#flycheck-versus-flymake​

That compares with the old Flymake.

> And I suggested precisely bundling Flycheck with Emacs.​

Is this likely to happen?  The comments here seem to be clear evidence
to the contrary:

  https://github.com/flycheck/flycheck/issues/323#issuecomment-38094131
  https://github.com/flycheck/flycheck/issues/323#issuecomment-38169115

> ​Because with Flycheck this is already accomplished. Why not work instead on things that Emacs lacks?​
> There are already far too many duplicated packages, leading to duplicated maintenance effort.

See above: the Flycheck developers seem to be unwilling to work with
this project.  Having a good bundled alternative could very well
become a better one.

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Flymake support for C/C++

João Távora
In reply to this post by Richard Stallman
Richard Stallman <[hidden email]> writes:

> It could be fixed in Flymake or fixed in GNU Hello.
> Which one is better?

It's too soon to tell, but I lean towards Flymake. I think a slightly
better compiler flag guesser can be evolved there (in fact, my previous
version worked, though it probably has other problems) that works with
Hello and many others. As a bonus, this compiler flag guesser could work
for many other assistance functionality, like auto-completion, etc...

I think it would be bad for Flymake's popularity if it demanded too
strict compliance from the projects it is trying to check.

João

12