Flymake can't find Makefile in parent directory

255 Views Asked by At

I'm using Flymake for C code syntax checking. If the Makefile and the source file are located in the same directory, Flymake works fine. But if the Makefile is in the parent directory of the source code (like in most C projects), it seems like that Flymake can't find the Makefile anymore, and produces the following message in the *Flymake log* buffer:

Warning [flymake hello.c]: Disabling backend flymake-cc because make: *** No rule to make target `check-syntax'.  Stop.

I'm using the default configuration of Flymake. The C source code and the Makefile for testing are listed at the end of this post. I saw many people are using custom init functions for Flymake. But I found that the default init function for Flymake was able to locate the Makefile correctly, at least for C projects. For example, if I evaluate flymake-proc-simple-make-init within the src/hello.c buffer, I got this message:

("make" ("-s" "-C" "../" "CHK_SOURCES=src/hello_140332961481000_flymake.c" "SYNTAX_CHECK_MODE=1" "check-syntax"))

The "-C" "../" part indicates that it knows the Makefile is located in the directory one level up. I can't find out why it didn't work eventually.

What I want to achieve are:

  1. Make Flymake work for all the source code files in the testing project below.
  2. As few customization as possible.

Any help would be appreciated.

$ tree .
.
|-- Makefile
|-- main.c
`-- src
    |-- hello.c
    `-- hello.h
# Makefile
INCLUDE=src
check-syntax:
    clang -fsyntax-only -Wall -I${INCLUDE} ${CHK_SOURCES} || true
/* main.c */
#include "hello.h"
int main(void)
{
    hello()
    return 0;
}
/* src/hello.c */
#include "hello.h"
#include <stdio.h>
void hello(void)
{
    printf("hello\n")
}
/* src/hello.h */
#ifndef HELLO_H
#define HELLO_H
void hello(void);
#endif
1

There are 1 best solutions below

0
On

After some research, I've found my way to solve this problem. Note that I'm still very new to Emacs, so this is probably not the best solution. But it works for me, and requires very little customization. Any better solutions or further improvements are welcome.

When editing C source code, I was using c-mode. In c-mode, Flymake uses flymake-cc as its backend by default, not the legacy proc mode. In this case, flymake-cc-command is the command used by Flymake to generate the make command for syntax checking. The default output of flymake-cc-command on the src/hello.c buffer is

("make" "check-syntax" "CHK_SOURCES=-x c -c -")

which clearly doesn't try to locate the Makefile anywhere else other than the current directory.

But I already knew that the proc backend was able to find the Makefile correctly. Why don't I combine these two backends? Maybe I could achieve my goal with very little effort.

Then I found out that the flymake-proc--init-find-buildfile-dir function from the proc backend was what I needed. It produces the path of the Makefile of the project and does nothing more.

Here is the customized function I got now. Pretty much the same with the original value of flymake-cc-command, with only one new line added.

(defun flymake-cc-init ()
  "Construct proper make command with CHK_SOURCES and the correct Makefile."
  `("make" "check-syntax" "-C"
    ,(flymake-proc--init-find-buildfile-dir (buffer-file-name) "Makefile")
    ,(format "CHK_SOURCES=-x %s -c -"
             (cond ((derived-mode-p 'c++-mode) "c++")
                   (t "c")))))