【问题标题】:Using flycheck/flymake on kernel source tree在内核源代码树上使用 flycheck/flymake
【发布时间】:2015-04-17 21:49:06
【问题描述】:

是否有一种简单/自动化的方式来配置 flycheck 或 flymake 在写入文件时显示错误注释 在linux内核源代码树中?假设我正在工作 fs/proc/cmdline.c 我想让flycheck下去 两个目录并执行“make fs/proc/cmdline.o”和 然后注释结果。假设 ARCH 和 CROSS_COMPILE 是在外部设置的。

【问题讨论】:

    标签: linux emacs flycheck


    【解决方案1】:

    我一直在考虑自己做这件事 - 这就是我所拥有的:

    您需要找到内核源代码树的基础,因此默认的flymake 寻找Makefile 的交易适得其反。我们将添加我们自己的文件,该文件可用于定位源代码库,并用于包装正常的内核 makefile:

    在内核源代码树的基础上添加一个文件flymake.mk(根据您自己的交叉编译需要进行配置):

    ARCH=mips
    CROSS_COMPILE=mips-linux-gnu-
    
    export ARCH
    export CROSS_COMPILE
    
    .PHONY: check-syntax
    check-syntax:
        make -f Makefile $(patsubst %_flymake.o,%.o,$(patsubst %.c,%.o,$(CHK_SOURCES)))
    

    要点是去掉“_flymake.c”,只编译真正的文件,真正地构建文件,而不仅仅是语法。这样可以避免我们意外创建file_flymake.o

    我们需要说服 flymake 寻找 flymake.mk 并针对它运行 check-syntax - 将这些添加到您的 .emacs 中:

    ;; Build a custom command-line using flymake.mk
    (defun flymake-get-kernel-make-cmdline (source base-dir)
      (list "make"
        (list "-s"
                  "-f"
                  "flymake.mk"
              "-C"
              base-dir
              (concat "CHK_SOURCES=" source)
              "SYNTAX_CHECK_MODE=1"
              "check-syntax")))
    
    ;; Search for flymake.mk to locate kernel tree base
    (defun flymake-kernel-make-init ()
      (flymake-simple-make-init-impl 'flymake-create-temp-inplace t t "flymake.mk" 'flymake-get-kernel-make-cmdline))
    
    ;; Register against .c files under /linux/ or /kernel/
    ;; Since the list is parsed in order use `push`
    (push '(".+/\\(linux\\|kernel\\)/.+\\.c$" flymake-kernel-make-init) flymake-allowed-file-name-masks)
    

    限制:

    • 无法解析头文件
    • 无法解析 flymake 临时文件source_flymake.c(请确保忽略 flymake 标记,直到它运行过保存的文件)。我有一个按键可以强制重新运行 flymake。
    • 外部模块不支持 flymake
    • 需要预先注册路径匹配器(请参阅上面的 push 行)- 我对 flymake 的了解不够,无法让它一次性覆盖单个缓冲区。

    可以通过修补内核 Makefile 本身来克服标头、临时和外部模块的限制,目前我想避免这种情况。

    【讨论】:

    • 嗨,感谢 flymake sn-p。我摆弄了一下,想出了下面的 flycheck sn-p(见下面的帖子)。问候康拉德
    【解决方案2】:

    类似于 Gregs flymake sn-p 这是我想出的一种用于 flycheck 的方法:

    (defun utils/flycheck-search-linux-makefile ()
      "Search for linux top `Makefile' "
      (labels
          ((find-makefile-file-r (path)
            (let* ((parent (file-name-directory path))
                   (file (concat parent "Makefile")))
              (cond
               ((file-exists-p file)
                (progn
                  (with-temp-buffer
                    (insert-file-contents file)
                    (if (string-match "VERSION = [0-9]+[[:space:]]*PATCHLEVEL" (buffer-string))
                        (throw 'found-it parent)
                      (find-makefile-file-r (directory-file-name parent))
                      ))))
               ((equal path parent) (throw 'found-it nil))
               (t (find-makefile-file-r (directory-file-name parent)))))))
        (if (buffer-file-name)
            (catch 'found-it
              (find-makefile-file-r (buffer-file-name)))
          (error "buffer is not visiting a file"))))
    
    (flycheck-define-checker utils/flycheck-linux-makefile-checker
      "Linux source checker"
      :command
      (
       "make" "C=1" "-C" (eval (utils/flycheck-search-linux-makefile))
       (eval (concat (file-name-sans-extension (file-relative-name buffer-file-name (utils/flycheck-search-linux-makefile))) ".o"))
       )
      :error-patterns
      ((error line-start
              (message "In file included from") " " (file-name) ":" line ":"
              column ":"
          line-end)
       (info line-start (file-name) ":" line ":" column
             ": note: " (message) line-end)
       (warning line-start (file-name) ":" line ":" column
                ": warning: " (message) line-end)
       (error line-start (file-name) ":" line ":" column
              ": " (or "fatal error" "error") ": " (message) line-end))
      :error-filter
      (lambda (errors)
        (let ((errors (flycheck-sanitize-errors errors)))
          (dolist (err errors)
            (let* ((fn (flycheck-error-filename err))
                   (rn0 (file-relative-name fn default-directory)) ; flycheck-fix-error-filename converted to absolute, revert                                                                                  
                   (rn1 (expand-file-name rn0 (utils/flycheck-search-linux-makefile))) ; make absolute relative to "make -C dir"                                                                                
                   (ef (file-relative-name rn1 default-directory)) ; relative to source                                                                                                                         
                   )
              (setf (flycheck-error-filename err) ef)
              )))
        errors)
      :modes (c-mode c++-mode)
      )
    
    (defun utils/flycheck-mode-hook ()
      "Flycheck mode hook."
      (make-variable-buffer-local 'flycheck-linux-makefile)
      (setq flycheck-linux-makefile (utils/flycheck-search-linux-makefile))
      (if flycheck-linux-makefile
          (flycheck-select-checker 'utils/flycheck-linux-makefile-checker))
      )
    
    (add-hook 'flycheck-mode-hook 'utils/flycheck-mode-hook)
    
    • utils/flycheck-search-linux-makefile :这将搜索包含 VERSION = .. PATCHLEVEL = ... 的顶级 linux Makefile
    • utils/flycheck-linux-makefile-checker :flycheck 检查器,它使用需要安装 sparse 的“make”“C=1”“-c”“...”

    不完美但可用。

    【讨论】:

      【解决方案3】:

      我正在使用 flymake.mk 之类的生成文件

      ## case 2: called within docker and cross env
      ifeq (${_FLYMAKE_WRAPPED},)
      
      _c_sources := $(filter %.c,$(CHK_SOURCES))
      _h_sources := $(filter %.h,$(CHK_SOURCES))
      
      _make_wrapped = $(MAKE) \
              kbuild-file=$(abspath $(firstword ${MAKEFILE_LIST})) \
              _FLYMAKE_WRAPPED=$1 _FLYMAKE_TYPE=$2 M=$(dir $*) $3
      
      check-syntax:   $(addprefix .check-syntax_,${_c_sources} ${_h_sources})
      
      $(addprefix .check-syntax_,${_c_sources} ${_h_sources}):.check-syntax_%:
              +$(call _make_wrapped,2,c)
      
      ## case 3: checking the files
      else ifeq (${_FLYMAKE_WRAPPED},2)
      
      -include $(dir ${CHK_SOURCES})/Makefile
      -include $(dir ${CHK_SOURCES})/Kbuild
      
      # Reset object/module list
      obj-y :=
      obj-m :=
      lib-y :=
      lib-m :=
      always :=
      targets :=
      subdir-y :=
      subdir-m :=
      
      __build: check-syntax
      .PHONY: check-syntax
      
      clean_checkflags = $(filter-out -M% -g% -Wp,-M%,$1)
      
      check-syntax: ${CHK_SOURCES}
              $(CC) $(call clean_checkflags,$(c_flags)) -c -o /dev/null -S $<
      
      endif
      

      它既适用于头文件,也适用于临时 flymake 文件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-09
        • 2015-05-03
        • 2013-10-23
        相关资源
        最近更新 更多