AtomBuild / atom-build-make

GNU Make plugin for atom-build
MIT License
13 stars 19 forks source link

No recursion when extracting targets from Makefile #28

Closed nathdwek closed 7 years ago

nathdwek commented 8 years ago

Using the MAKE variable in a recipe makes the recipe execute regardless of the -n option. Temporarily override this variable when extracting targets so that the $(MAKE) call does nothing.

This is useful for example when building drivers against the linux kernel. The database printed by make -prRn is so big it leads to this plugin not proposing any targets.

Note that this is a sane way to deal with this. What I mean by that is that if the plugin was handling "normally" the resulting huge database, then there would be a great number of extra invalid targets listed. So this allows the plugin to output something when using big recursive Makefiles and ensures that targets that are not available at the current level are not proposed.

As far as I'm aware this does not eliminate valid targets from the proposal list.

I first tried with MAKE= make -prRn, but then make would complain about the command not being valid and again, no plugin output. Using true ensures that every recursive returns immediately and happily.

Another solution would be to use make -w and to count the make[n]: entering directory ... and corresponding make[n]: leaving directory ... lines, but I don't know of a case where this would give a more correct output.

nathdwek commented 8 years ago

@noseglid , any feedback?

noseglid commented 8 years ago

Could you provide a minimal Makefile which exhibits the behavior of $(MAKE) being run when running with -n ?

nathdwek commented 8 years ago

For sure: here's a minimal kernel module makefile:

KDIR = /f/repos/linux
MODNAME ?= foo

obj-m := $(MODNAME).o

$(MODNAME)-objs = $(MODNAME).o

all:
        $(MAKE) $(MAKE_CROSS_ARGS) -C $(KDIR) M=$(PWD) modules

clean:
        $(MAKE) $(MAKE_CROSS_ARGS) -C $(KDIR) M=$(PWD) clean

With a prepared kernel at the right location the output of make -prRn is approximately 40 000 lines long, as so.

The output of MAKE=true make -prRn is

true  -C /f/repos/linux M=/tmp/ba4xx modules
# GNU Make 4.1
# Built for x86_64-pc-linux-gnu
# Copyright (C) 1988-2014 Free Software Foundation, Inc.
# License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
# This is free software: you are free to change and redistribute it.
# There is NO WARRANTY, to the extent permitted by law.

# Make data base, printed on Wed Oct  5 00:10:52 2016

# Variables

# automatic
<D = $(patsubst %/,%,$(dir $<))
# automatic
?F = $(notdir $?)
# environment
DESKTOP_SESSION = cinnamon
# default
.SHELLFLAGS := -c
# environment
XDG_SESSION_TYPE = x11
# automatic
?D = $(patsubst %/,%,$(dir $?))
# automatic
@D = $(patsubst %/,%,$(dir $@))
# environment
XAUTHORITY = /home/nathdwek/.Xauthority
# environment
GDMSESSION = cinnamon
# default
MAKE_VERSION := 4.1
# makefile
CURDIR := /tmp/ba4xx
# makefile
SHELL = /bin/sh
# environment
GDM_LANG = en_US
# environment
VTE_VERSION = 4205
# makefile (from 'Makefile', line 10)
ba4xx-objs :=  ba4xx_ctx.o ba4xx_cra.o ba4xx_drv.o ba4xx_crypto.o
# environment
_ = /usr/bin/make
# environment
XDG_CONFIG_DIRS = /etc/xdg/xdg-cinnamon:/etc/xdg
# makefile (from 'Makefile', line 1)
MAKEFILE_LIST :=  Makefile
# automatic
@F = $(notdir $@)
# 'override' directive
GNUMAKEFLAGS := 
# environment
MAKELEVEL := 0
# environment
MANDATORY_PATH = /usr/share/gconf/cinnamon.mandatory.path
# environment
XDG_DATA_DIRS = /usr/share/cinnamon:/usr/share/gnome:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
# environment
DBUS_SESSION_BUS_ADDRESS = unix:abstract=/tmp/dbus-avoQER8Eat,guid=bdb96906714bef18f31ea71a57f35538
# environment
LESSOPEN = | /usr/bin/lesspipe %s
# environment
LC_NAME = fr_BE.UTF-8
# environment
QT_STYLE_OVERRIDE = gtk
# environment
XDG_SESSION_PATH = /org/freedesktop/DisplayManager/Session0
# default
MAKE_HOST := x86_64-pc-linux-gnu
# environment
PATH = /home/nathdwek/.local/bin:/home/nathdwek/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/microchip/xc16/v1.26/bin
# environment
GPG_AGENT_INFO = /home/nathdwek/.gnupg/S.gpg-agent:0:1
# environment
SESSION_MANAGER = local/nathdwek-w740su:@/tmp/.ICE-unix/1850,unix/nathdwek-w740su:/tmp/.ICE-unix/1850
# environment
XDG_RUNTIME_DIR = /run/user/1000
# environment
WINDOWID = 56643730
# environment
GOPATH = /home/nathdwek/opt/gocode/
# environment
GIT_PS1_SHOWCOLORHINTS = yes
# environment
LC_NUMERIC = fr_BE.UTF-8
# default
.FEATURES := target-specific order-only second-expansion else-if shortest-stem undefine oneshell archives jobserver output-sync check-symlink load
# environment
XDG_GREETER_DATA_DIR = /var/lib/lightdm-data/nathdwek
# environment
LS_COLORS = rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=01;07;34:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
# environment
XDG_SESSION_DESKTOP = cinnamon
# environment
SSH_AUTH_SOCK = /run/user/1000/keyring/ssh
# automatic
%F = $(notdir $%)
# environment
DISPLAY = :0
# environment
PWD = /tmp/ba4xx
# environment
QT_QPA_PLATFORMTHEME = appmenu-qt5
# environment
XDG_SEAT = seat0
# environment
SSH_AGENT_PID = 1913
# environment
LANGUAGE = en_US
# environment
GTK_MODULES = gail:atk-bridge
# environment
HOME = /home/nathdwek
# environment
GIT_PS1_SHOWUNTRACKEDFILES = yes
# environment
LESSCLOSE = /usr/bin/lesspipe %s %s
# environment
LOGNAME = nathdwek
# environment
QT_LINUX_ACCESSIBILITY_ALWAYS_ON = 1
# automatic
+F = $(notdir $+)
# environment
GNOME_DESKTOP_SESSION_ID = this-is-deprecated
# automatic
^D = $(patsubst %/,%,$(dir $^))
# makefile (from 'Makefile', line 1)
KDIR = /f/repos/linux
# environment
GIT_PS1_STATESEPARATOR = 
# makefile (from 'Makefile', line 4)
obj-m := ba4xx.o
# environment
XDG_VTNR = 7
# environment
CLUTTER_BACKEND = x11
# environment
LC_TIME = fr_BE.UTF-8
# environment
MAKE = true
# environment
SHLVL = 1
# environment
XDG_SESSION_ID = c2
# environment
USER = nathdwek
# environment
LC_MONETARY = fr_BE.UTF-8
# makefile
.DEFAULT_GOAL := all
# environment
XDG_CURRENT_DESKTOP = X-Cinnamon
# automatic
%D = $(patsubst %/,%,$(dir $%))
# environment
LC_TELEPHONE = fr_BE.UTF-8
# default
MAKE_COMMAND := make
# environment
GIT_PS1_SHOWDIRTYSTATE = yes
# environment
OLDPWD = /tmp
# default
.VARIABLES := 
# automatic
*F = $(notdir $*)
# environment
NODE_PATH = /usr/lib/nodejs:/usr/lib/node_modules:/usr/share/javascript
# environment
XDG_SEAT_PATH = /org/freedesktop/DisplayManager/Seat0
# environment
GIT_PS1_SHOWUPSTREAM = auto
# makefile
MAKEFLAGS = nprR
# environment
MFLAGS = -nprR
# automatic
*D = $(patsubst %/,%,$(dir $*))
# automatic
+D = $(patsubst %/,%,$(dir $+))
# environment
LC_PAPER = fr_BE.UTF-8
# environment
GTK2_MODULES = overlay-scrollbar
# environment
CINNAMON_VERSION = 2.8.6
# environment
LC_IDENTIFICATION = fr_BE.UTF-8
# environment
QT_ACCESSIBILITY = 1
# environment
DEFAULTS_PATH = /usr/share/gconf/cinnamon.default.path
# default
MAKEFILES := 
# automatic
<F = $(notdir $<)
# environment
LC_MEASUREMENT = fr_BE.UTF-8
# environment
EDITOR = vim
# environment
PASS_CLIP_BY_DEFAULT = yes
# makefile (from 'Makefile', line 2)
MODNAME = ba4xx
# environment
GJS_DEBUG_TOPICS = JS ERROR;JS LOG
# automatic
^F = $(notdir $^)
# default
SUFFIXES := 
# default
.INCLUDE_DIRS = /usr/include /usr/local/include /usr/include
# environment
GJS_DEBUG_OUTPUT = stderr
# default
.RECIPEPREFIX := 
# default
MAKE_TERMERR := /dev/pts/0
# environment
LC_ADDRESS = fr_BE.UTF-8
# environment
LANG = en_US.UTF-8
# environment
TERM = xterm-256color
# variable set hash-table stats:
# Load=107/1024=10%, Rehash=0, Collisions=12/159=8%

# Pattern-specific Variable Values

# No pattern-specific variable values.

# Directories

# . (device 2065, inode 1181765): 15 files, no impossibilities.

# 15 files, no impossibilities in 1 directories.

# Implicit Rules

# No implicit rules.

# Files

all:
#  Implicit rule search has not been done.
#  Implicit/static pattern stem: ''
#  File does not exist.
#  File has been updated.
#  Successfully updated.
# automatic
# @ := all
# automatic
# % := 
# automatic
# * := 
# automatic
# + := 
# automatic
# | := 
# automatic
# < := 
# automatic
# ^ := 
# automatic
# ? := 
# variable set hash-table stats:
# Load=8/32=25%, Rehash=0, Collisions=2/15=13%
#  recipe to execute (from 'Makefile', line 13):
    $(MAKE) $(MAKE_CROSS_ARGS) -C $(KDIR) M=$(PWD) modules

# Not a target:
.SUFFIXES:
#  Implicit rule search has not been done.
#  Modification time never checked.
#  File has not been updated.

# Not a target:
Makefile:
#  Implicit rule search has been done.
#  Last modified 2016-10-05 00:08:08.446602181
#  File has been updated.
#  Successfully updated.

# Not a target:
.DEFAULT:
#  Implicit rule search has not been done.
#  Modification time never checked.
#  File has not been updated.

clean:
#  Implicit rule search has not been done.
#  Modification time never checked.
#  File has not been updated.
#  recipe to execute (from 'Makefile', line 16):
    $(MAKE) $(MAKE_CROSS_ARGS) -C $(KDIR) M=$(PWD) clean

# files hash-table stats:
# Load=5/1024=0%, Rehash=0, Collisions=0/17=0%
# VPATH Search Paths

# No 'vpath' search paths.

# No general ('VPATH' variable) search path.

# strcache buffers: 1 (0) / strings = 21 / storage = 200 B / avg = 9 B
# current buf: size = 8162 B / used = 200 B / count = 21 / avg = 9 B

# strcache performance: lookups = 27 / hit rate = 22%
# hash-table stats:
# Load=21/8192=0%, Rehash=0, Collisions=1/27=4%
# Finished Make data base on Wed Oct  5 00:10:52 2016

Which is much more reasonable and proposes targets nearly all accessible from the current directory.

Another example is for instance cryptodev which generates approximately 50 000 lines of output (2.5MB), and roughly a thousand targets (counted with egrep '^[^#] *[^:]+:').

noseglid commented 8 years ago

Hmm, I've been thinking a bit about this and I'm not quite sure.

Overriding $(MAKE) to be true seems very likely to break some compatability (as true behaves nothing like make 😄 ). There may be other instances where $(MAKE) is expected to work like a make program.

But I do want to make it work for you and the general use case of kernel modules. Would you be okay with adding a configuration variable, which toggles this functionality you've proposed?

nathdwek commented 8 years ago

Will do.