【问题标题】:Is there a smarter alternative to "watch make"?有没有比“手表制造”更聪明的选择?
【发布时间】:2011-11-24 06:29:39
【问题描述】:

我遇到了一个有用的提示,如果您经常处理文件并且希望它们自动构建,您可以运行:

观看制作

它会每隔几秒钟重新运行一次,然后事情就会建立起来。

但是……它似乎一直在吞噬所有的输出。我认为它可能更聪明 - 可能会显示一个输出流,但禁止对“所有”执行任何操作,这样如果没有构建任何内容,输出就不会滚动。

我想到了一些使用循环和 grep 的 shell 脚本方法……但也许还有更优雅的方法?有人看到了吗?

【问题讨论】:

  • watch make | grep -v "Nothing to be done"。也许你必须重定向标准错误。没查过
  • 和/或添加 --silent 选项,或使用 hack 来抑制“无事可做...”消息。这些都不是从煎锅(Unix 世界)跳入火中(Ruby 世界)的充分理由。
  • FWIW,还有entr,它可能更通用一些。您可以使用ag -l | entr makels -l | entr make 之类的方式调用它。

标签: makefile watch


【解决方案1】:

使用经典 gnu makeinotifywait,没有基于间隔的轮询:

watch:
    while true; do \
        make $(WATCHMAKE); \
        inotifywait -qre close_write .; \
    done

这种方式会在当前目录树中的每个文件写入时触发。您可以通过运行指定目标

make watch WATCHMAKE=foo

【讨论】:

  • 谢谢!虽然我宁愿把它移到一个独立的 shellscript 中,这样它就可以与任何基于 makefile 的项目一起使用,而无需修改 makefile。
  • 哇,太漂亮了,对于构建需要大约一分钟编译时间的大型 LaTeX 项目非常有用
  • 对于 macOS,brew install fswatch 并将第 4 行替换为 fswatch -1 .
  • 来自 node.js 的 c 菜鸟,`npm i -g nodemonnodemon --watch ./hello.c --exec "gcc ./hello.c && ./a.out" 在 MacOS 上为我工作。
【解决方案2】:

这个单行应该做到这一点:

while true; do make --silent; sleep 1; done

它将每秒运行一次make,并且仅在实际执行某些操作时才打印输出。

【讨论】:

  • 在 GNU/Linux 上,--silent 标志会抑制所有输出,包括在有更改的构建期间。我发布了an alternative one-liner
【解决方案3】:

这是一个单行:

while true; do make -q || make; sleep 0.5; done

使用make -q || make 而不仅仅是make 只会在有事情要做时运行构建,否则不会输出任何消息。

您可以将此作为规则添加到项目的 Makefile 中:

watch:
    while true; do $(MAKE) -q || $(MAKE); sleep 0.5; done

然后使用make watch 调用它。

此技术将防止 Make 用“make: Nothing to be done for TARGET”消息填充终端。

它也不像某些文件观察解决方案那样保留一堆打开的文件描述符,这可能导致 ulimit 错误。

【讨论】:

  • 如果我可以选择解决方案,我会选择此解决方案。它适用于 Linux、macOS、gmake 和 pmake。它非常兼容,因为它依赖于已经存在一段时间的查询/问题模式(freebsd.org/cgi/…freebsd.org/cgi/man.cgi?query=make&manpath=SunOS+4.1.3 都具有它)。在某些情况下有更优化的答案,但这取代了手表品牌。
【解决方案4】:

怎么样

# In the makefile:
.PHONY: continuously
continuously:
    while true; do make 1>/dev/null; sleep 3; done  

?

这样就可以跑了

连续制作

只有在出现问题时才会得到输出。

【讨论】:

  • 但这并不能解决问题,我想查看我运行的最后一个“make”的输出。事实上,这个解决方案丢弃了所有 make 调用的输出,所以它比“watch make”更糟糕。
  • @DobesVandermeer 将make 1>/dev/null 替换为make -s-s 表示不打印命令),它将按需要工作。
【解决方案5】:

Twitter Bootstrap 为此使用了 watchr ruby​​ gem。

https://github.com/twbs/bootstrap/blob/v2.3.2/Makefile

https://github.com/mynyml/watchr

编辑:

两年后,watchr 项目似乎不再维护。请在答案中寻找另一种解决方案。就个人而言,如果目标只是获得更好的输出,我会推荐the answer from wch here

【讨论】:

  • 谢谢,这可能是我能得到的最佳解决方案!
【解决方案6】:

我在我的 Makefile 中这样做:

watch:
    (while true; do make build.log; sleep 1; done) | grep -v 'make\[1\]'

build.log: ./src/*
    thecompiler | tee build.log

所以,它只会在我的源代码比我的 build.log 更新时构建,并且“grep -v”的东西会删除一些不必要的 make 输出。

【讨论】:

    【解决方案7】:

    有几个自动构建系统可以执行此操作以及更多功能 - 基本上,当您检查对版本控制的更改时,它们将进行/构建 - 寻找持续集成

    简单的是TeamCityHudson

    【讨论】:

    • 嗯,这当然很有用,但就我而言,我正在考虑每隔几秒钟构建一次的东西,所以我的更改会在我保存后立即处理,而不是在我将它们签入源代码控制时.所以,不是我想要的。
    【解决方案8】:

    @Dobes Vandermeer -- 我有一个名为“mkall”的脚本,它在每个子目录中运行 make。我可以将该脚本指定为每五分钟、一分钟或三十秒运行一次的 cron 作业。然后,为了查看输出,我将 gcc 结果(在每个单独的 makefile 中)重定向到每个子目录中的日志。

    这样的东西对你有用吗?

    它可以非常精细,以避免让它什么都不做。例如,脚本可以节省每个源文件的修改时间,并在那个人发生变化时进行制作。

    【讨论】:

    • 不完全是我的想法,但它给了我一个想法。如果我将 make 包装在一个脚本中,该脚本存储了以前 make 的唯一输出,它可以在每次运行时打印出以前的输出,并使用 watch 运行该脚本。
    【解决方案9】:

    您可以尝试使用类似 inotify-tools 的工具。当文件更改或保存或 inotify 可以监视的任何其他事件时,它将让您监视目录并运行命令。一个简单的脚本可以监视保存并在保存文件时启动 make 可能会很有用。

    【讨论】:

      【解决方案10】:

      此 shell 脚本使用 make 本身来检测带有 -q 标志的更改,然后当且仅当有更改时才进行完全重建。

      #!/bin/sh
      
      while true;
      do
        if ! make -q "$@";
        then
          echo "#-> Starting build: `date`"
          make "$@";
          echo "#-> Build complete."
        fi
        sleep 0.5;
      done
      
      • 除了make之外没有任何依赖。

      • 您可以将普通的make 参数(例如-C mydir)传递给它,因为它们被传递给make 命令。

      • 根据问题中的要求,如果没有要构建的内容,但不会吞下输出,它会保持沉默。

      • 您可以将此脚本放在手边,例如~/bin/watch-make 可跨多个项目使用。

      【讨论】:

        【解决方案11】:

        您可以更改您的 make 文件以输出 growl (OS X) 或 notify-send (Linux) 通知。对于 Ubuntu 中的我来说,这会在我的屏幕右上角显示一个通知气泡。

        那么你只会在构建失败时注意到它。

        您可能希望将watch 设置为仅以这些通知可以显示的速度循环(这样它们就不会堆积)。

        【讨论】:

        • 你真的能做到这一点吗? notify-send 不接受管道输入
        • 您可以使用 xargs 收集管道输出并将它们作为参数传递给程序。我想当我这样做时,我使用了一个 python API 来通知发送。 (我让它输出我每次保存时运行的鼻子测试的结果。也许我只是使用了nose-notify。)
        猜你喜欢
        • 2013-09-21
        • 1970-01-01
        • 2020-08-28
        • 1970-01-01
        • 2021-10-11
        • 2021-11-17
        • 2021-06-16
        • 2011-11-24
        • 1970-01-01
        相关资源
        最近更新 更多