[PATCH bpf-next 0/7] tools: bpf: standardize make

STALE3144d

13 messages, 4 authors, 2018-03-09 · open the first message on its own page

[PATCH bpf-next 0/7] tools: bpf: standardize make

From: Jiri Benc <hidden>
Date: 2018-03-08 22:00:54

Currently, 'make bpf' in the tools/ directory does not provide the standard
quiet output except for bpftool (which is however listed with a wrong
directory). Worse, it does not respect the build output directory.

The 'make bpf_install' does not work as one would expect, either. It
installs unconditionally to /usr/bin without respecting DESTDIR and prefix.

This patchset improves that behavior.

Jiri Benc (7):
  tools: bpftool: silence 'missing initializer' warnings
  tools: bpf: respect output directory during build
  tools: bpf: consistent make bpf_install
  tools: bpf: make install should build first
  tools: bpf: call descend in Makefile
  tools: bpf: respect quiet/verbose build
  tools: bpf: silence make by not deleting intermediate file

 tools/bpf/Makefile         | 74 +++++++++++++++++++++++++++++++---------------
 tools/bpf/bpftool/Makefile |  2 +-
 2 files changed, 51 insertions(+), 25 deletions(-)

-- 
1.8.3.1

[PATCH bpf-next 1/7] tools: bpftool: silence 'missing initializer' warnings

From: Jiri Benc <hidden>
Date: 2018-03-08 22:00:55

When building bpf tool, gcc emits piles of warnings:

prog.c: In function ‘prog_fd_by_tag’:
prog.c:101:9: warning: missing initializer for field ‘type’ of ‘struct bpf_prog_info’ [-Wmissing-field-initializers]
  struct bpf_prog_info info = {};
         ^
In file included from /home/storage/jbenc/git/net-next/tools/lib/bpf/bpf.h:26:0,
                 from prog.c:47:
/home/storage/jbenc/git/net-next/tools/include/uapi/linux/bpf.h:925:8: note: ‘type’ declared here
  __u32 type;
        ^

As these warnings are not useful, switch them off.

Signed-off-by: Jiri Benc <redacted>
---
 tools/bpf/bpftool/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index 26901ec87361..4c2867481f5c 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -38,7 +38,7 @@ bash_compdir ?= /usr/share/bash-completion/completions
 CC = gcc
 
 CFLAGS += -O2
-CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow
+CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow -Wno-missing-field-initializers
 CFLAGS += -DPACKAGE='"bpftool"' -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/
 CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"'
 LIBS = -lelf -lbfd -lopcodes $(LIBBPF)
-- 
1.8.3.1

[PATCH bpf-next 2/7] tools: bpf: respect output directory during build

From: Jiri Benc <hidden>
Date: 2018-03-08 22:00:56

Currently, the programs under tools/bpf (with the notable exception of
bpftool) do not respect the output directory (make O=dir). Fix that.

Signed-off-by: Jiri Benc <redacted>
---
 tools/bpf/Makefile | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index c8ec0ae16bf0..e7b15967492e 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -1,4 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
+include ../scripts/Makefile.include
+
 prefix = /usr
 
 CC = gcc
@@ -7,7 +9,7 @@ YACC = bison
 MAKE = make
 
 CFLAGS += -Wall -O2
-CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
+CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/include/uapi -I$(srctree)/include
 
 ifeq ($(srctree),)
 srctree := $(patsubst %/,%,$(dir $(CURDIR)))
@@ -38,32 +40,36 @@ ifeq ($(feature-disassembler-four-args), 1)
 CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
 endif
 
-%.yacc.c: %.y
+$(OUTPUT)%.yacc.c: $(srctree)/tools/bpf/%.y
 	$(YACC) -o $@ -d $<
 
-%.lex.c: %.l
+$(OUTPUT)%.lex.c: $(srctree)/tools/bpf/%.l
 	$(LEX) -o $@ $<
 
-all: bpf_jit_disasm bpf_dbg bpf_asm bpftool
+$(OUTPUT)%.o: $(srctree)/tools/bpf/%.c
+	$(COMPILE.c) -o $@ $<
+
+all: $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg $(OUTPUT)bpf_asm bpftool
 
-bpf_jit_disasm : CFLAGS += -DPACKAGE='bpf_jit_disasm'
-bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl
-bpf_jit_disasm : bpf_jit_disasm.o
+$(OUTPUT)bpf_jit_disasm: CFLAGS += -DPACKAGE='bpf_jit_disasm'
+$(OUTPUT)bpf_jit_disasm: LDLIBS = -lopcodes -lbfd -ldl
+$(OUTPUT)bpf_jit_disasm: $(OUTPUT)bpf_jit_disasm.o
 
-bpf_dbg : LDLIBS = -lreadline
-bpf_dbg : bpf_dbg.o
+$(OUTPUT)bpf_dbg: LDLIBS = -lreadline
+$(OUTPUT)bpf_dbg: $(OUTPUT)bpf_dbg.o
 
-bpf_asm : LDLIBS =
-bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o
-bpf_exp.lex.o : bpf_exp.yacc.c
+$(OUTPUT)bpf_asm: LDLIBS =
+$(OUTPUT)bpf_asm: $(OUTPUT)bpf_asm.o $(OUTPUT)bpf_exp.yacc.o $(OUTPUT)bpf_exp.lex.o
+$(OUTPUT)bpf_exp.lex.o: $(OUTPUT)bpf_exp.yacc.c
 
 clean: bpftool_clean
-	rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.*
+	rm -rf $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \
+	       $(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.*
 
 install: bpftool_install
-	install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm
-	install bpf_dbg $(prefix)/bin/bpf_dbg
-	install bpf_asm $(prefix)/bin/bpf_asm
+	install $(OUTPUT)bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm
+	install $(OUTPUT)bpf_dbg $(prefix)/bin/bpf_dbg
+	install $(OUTPUT)bpf_asm $(prefix)/bin/bpf_asm
 
 bpftool:
 	$(MAKE) -C bpftool
-- 
1.8.3.1

[PATCH bpf-next 3/7] tools: bpf: consistent make bpf_install

From: Jiri Benc <hidden>
Date: 2018-03-08 22:00:57

Currently, make bpf_install in tools/ does not respect DESTDIR. Moreover, it
installs to /usr/bin/ unconditionally.

Let it respect DESTDIR and allow prefix to be specified. Also, to be more
consistent with bpftool and with the usual customs, default the prefix to
/usr/local instead of /usr.

Signed-off-by: Jiri Benc <redacted>
---
 tools/bpf/Makefile | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index e7b15967492e..c42ca24a072d 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -1,12 +1,13 @@
 # SPDX-License-Identifier: GPL-2.0
 include ../scripts/Makefile.include
 
-prefix = /usr
+prefix ?= /usr/local
 
 CC = gcc
 LEX = flex
 YACC = bison
 MAKE = make
+INSTALL ?= install
 
 CFLAGS += -Wall -O2
 CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/include/uapi -I$(srctree)/include
@@ -67,9 +68,10 @@ clean: bpftool_clean
 	       $(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.*
 
 install: bpftool_install
-	install $(OUTPUT)bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm
-	install $(OUTPUT)bpf_dbg $(prefix)/bin/bpf_dbg
-	install $(OUTPUT)bpf_asm $(prefix)/bin/bpf_asm
+	$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/bin
+	$(INSTALL) $(OUTPUT)bpf_jit_disasm $(DESTDIR)$(prefix)/bin/bpf_jit_disasm
+	$(INSTALL) $(OUTPUT)bpf_dbg $(DESTDIR)$(prefix)/bin/bpf_dbg
+	$(INSTALL) $(OUTPUT)bpf_asm $(DESTDIR)$(prefix)/bin/bpf_asm
 
 bpftool:
 	$(MAKE) -C bpftool
-- 
1.8.3.1

[PATCH bpf-next 4/7] tools: bpf: make install should build first

From: Jiri Benc <hidden>
Date: 2018-03-08 22:00:58

Make the 'install' target depend on the 'all' target to build the binaries
first.

Signed-off-by: Jiri Benc <redacted>
---
 tools/bpf/Makefile | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index c42ca24a072d..e8d9e4125bf3 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -50,7 +50,9 @@ $(OUTPUT)%.lex.c: $(srctree)/tools/bpf/%.l
 $(OUTPUT)%.o: $(srctree)/tools/bpf/%.c
 	$(COMPILE.c) -o $@ $<
 
-all: $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg $(OUTPUT)bpf_asm bpftool
+PROGS = $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg $(OUTPUT)bpf_asm
+
+all: $(PROGS) bpftool
 
 $(OUTPUT)bpf_jit_disasm: CFLAGS += -DPACKAGE='bpf_jit_disasm'
 $(OUTPUT)bpf_jit_disasm: LDLIBS = -lopcodes -lbfd -ldl
@@ -67,7 +69,7 @@ clean: bpftool_clean
 	rm -rf $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \
 	       $(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.*
 
-install: bpftool_install
+install: $(PROGS) bpftool_install
 	$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/bin
 	$(INSTALL) $(OUTPUT)bpf_jit_disasm $(DESTDIR)$(prefix)/bin/bpf_jit_disasm
 	$(INSTALL) $(OUTPUT)bpf_dbg $(DESTDIR)$(prefix)/bin/bpf_dbg
-- 
1.8.3.1

[PATCH bpf-next 5/7] tools: bpf: call descend in Makefile

From: Jiri Benc <hidden>
Date: 2018-03-08 22:00:59

Use the descend macro to properly propagate $(subdir) to bpftool.

Signed-off-by: Jiri Benc <redacted>
---
 tools/bpf/Makefile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index e8d9e4125bf3..daca0a4277d1 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -76,12 +76,12 @@ install: $(PROGS) bpftool_install
 	$(INSTALL) $(OUTPUT)bpf_asm $(DESTDIR)$(prefix)/bin/bpf_asm
 
 bpftool:
-	$(MAKE) -C bpftool
+	$(call descend,bpftool)
 
 bpftool_install:
-	$(MAKE) -C bpftool install
+	$(call descend,bpftool,install)
 
 bpftool_clean:
-	$(MAKE) -C bpftool clean
+	$(call descend,bpftool,clean)
 
 .PHONY: bpftool FORCE
-- 
1.8.3.1

[PATCH bpf-next 6/7] tools: bpf: respect quiet/verbose build

From: Jiri Benc <hidden>
Date: 2018-03-08 22:00:59

Default to quiet build, with V=1 enabling verbose build as is usual.

Signed-off-by: Jiri Benc <redacted>
---
 tools/bpf/Makefile | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index daca0a4277d1..757ea22c428a 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -17,6 +17,12 @@ srctree := $(patsubst %/,%,$(dir $(CURDIR)))
 srctree := $(patsubst %/,%,$(dir $(srctree)))
 endif
 
+ifeq ($(V),1)
+  Q =
+else
+  Q = @
+endif
+
 FEATURE_USER = .bpf
 FEATURE_TESTS = libbfd disassembler-four-args
 FEATURE_DISPLAY = libbfd disassembler-four-args
@@ -42,38 +48,48 @@ CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
 endif
 
 $(OUTPUT)%.yacc.c: $(srctree)/tools/bpf/%.y
-	$(YACC) -o $@ -d $<
+	$(QUIET_BISON)$(YACC) -o $@ -d $<
 
 $(OUTPUT)%.lex.c: $(srctree)/tools/bpf/%.l
-	$(LEX) -o $@ $<
+	$(QUIET_FLEX)$(LEX) -o $@ $<
 
 $(OUTPUT)%.o: $(srctree)/tools/bpf/%.c
-	$(COMPILE.c) -o $@ $<
+	$(QUIET_CC)$(COMPILE.c) -o $@ $<
+
+$(OUTPUT)%.yacc.o: $(OUTPUT)%.yacc.c
+	$(QUIET_CC)$(COMPILE.c) -o $@ $<
+$(OUTPUT)%.lex.o: $(OUTPUT)%.lex.c
+	$(QUIET_CC)$(COMPILE.c) -o $@ $<
 
 PROGS = $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg $(OUTPUT)bpf_asm
 
 all: $(PROGS) bpftool
 
 $(OUTPUT)bpf_jit_disasm: CFLAGS += -DPACKAGE='bpf_jit_disasm'
-$(OUTPUT)bpf_jit_disasm: LDLIBS = -lopcodes -lbfd -ldl
 $(OUTPUT)bpf_jit_disasm: $(OUTPUT)bpf_jit_disasm.o
+	$(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ -lopcodes -lbfd -ldl
 
-$(OUTPUT)bpf_dbg: LDLIBS = -lreadline
 $(OUTPUT)bpf_dbg: $(OUTPUT)bpf_dbg.o
+	$(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ -lreadline
 
-$(OUTPUT)bpf_asm: LDLIBS =
 $(OUTPUT)bpf_asm: $(OUTPUT)bpf_asm.o $(OUTPUT)bpf_exp.yacc.o $(OUTPUT)bpf_exp.lex.o
+	$(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^
+
 $(OUTPUT)bpf_exp.lex.o: $(OUTPUT)bpf_exp.yacc.c
 
 clean: bpftool_clean
-	rm -rf $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \
+	$(call QUIET_CLEAN, bpf-progs)
+	$(Q)rm -rf $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \
 	       $(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.*
 
 install: $(PROGS) bpftool_install
-	$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/bin
-	$(INSTALL) $(OUTPUT)bpf_jit_disasm $(DESTDIR)$(prefix)/bin/bpf_jit_disasm
-	$(INSTALL) $(OUTPUT)bpf_dbg $(DESTDIR)$(prefix)/bin/bpf_dbg
-	$(INSTALL) $(OUTPUT)bpf_asm $(DESTDIR)$(prefix)/bin/bpf_asm
+	$(call QUIET_INSTALL, bpf_jit_disasm)
+	$(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/bin
+	$(Q)$(INSTALL) $(OUTPUT)bpf_jit_disasm $(DESTDIR)$(prefix)/bin/bpf_jit_disasm
+	$(call QUIET_INSTALL, bpf_dbg)
+	$(Q)$(INSTALL) $(OUTPUT)bpf_dbg $(DESTDIR)$(prefix)/bin/bpf_dbg
+	$(call QUIET_INSTALL, bpf_asm)
+	$(Q)$(INSTALL) $(OUTPUT)bpf_asm $(DESTDIR)$(prefix)/bin/bpf_asm
 
 bpftool:
 	$(call descend,bpftool)
-- 
1.8.3.1

[PATCH bpf-next 7/7] tools: bpf: silence make by not deleting intermediate file

From: Jiri Benc <hidden>
Date: 2018-03-08 22:01:00

Even in quiet mode, make finishes with

rm tools/bpf/bpf_exp.lex.c

That's because it considers the file to be intermediate. Silence that by
mentioning the lex.c file instead of the lex.o file; the dependency still
stays.

Signed-off-by: Jiri Benc <redacted>
---
 tools/bpf/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index 757ea22c428a..c07b4e718eeb 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -75,7 +75,7 @@ $(OUTPUT)bpf_dbg: $(OUTPUT)bpf_dbg.o
 $(OUTPUT)bpf_asm: $(OUTPUT)bpf_asm.o $(OUTPUT)bpf_exp.yacc.o $(OUTPUT)bpf_exp.lex.o
 	$(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^
 
-$(OUTPUT)bpf_exp.lex.o: $(OUTPUT)bpf_exp.yacc.c
+$(OUTPUT)bpf_exp.lex.c: $(OUTPUT)bpf_exp.yacc.c
 
 clean: bpftool_clean
 	$(call QUIET_CLEAN, bpf-progs)
-- 
1.8.3.1

Re: [PATCH bpf-next 0/7] tools: bpf: standardize make

From: Alexei Starovoitov <hidden>
Date: 2018-03-09 05:11:21

On Thu, Mar 8, 2018 at 2:00 PM, Jiri Benc [off-list ref] wrote:
Currently, 'make bpf' in the tools/ directory does not provide the standard
quiet output except for bpftool (which is however listed with a wrong
directory). Worse, it does not respect the build output directory.

The 'make bpf_install' does not work as one would expect, either. It
installs unconditionally to /usr/bin without respecting DESTDIR and prefix.

This patchset improves that behavior.
Jakub,
please review this set.

Thanks!

Re: [PATCH bpf-next 0/7] tools: bpf: standardize make

From: Jakub Kicinski <hidden>
Date: 2018-03-09 07:36:13

On Thu, 8 Mar 2018 21:10:59 -0800, Alexei Starovoitov wrote:
On Thu, Mar 8, 2018 at 2:00 PM, Jiri Benc [off-list ref] wrote:
quoted
Currently, 'make bpf' in the tools/ directory does not provide the standard
quiet output except for bpftool (which is however listed with a wrong
directory). Worse, it does not respect the build output directory.

The 'make bpf_install' does not work as one would expect, either. It
installs unconditionally to /usr/bin without respecting DESTDIR and prefix.

This patchset improves that behavior.  
Jakub,
please review this set.

Thanks!
I stared at it for a while, and it looks good!

Reviewed-by: Jakub Kicinski <redacted>

In addition I found a GCC 7 warning in bpftool, .PHONY lacks some
targets and we don't clean up after feature detection.  I'll send
patches for that unless someone beats me to it.

Re: [PATCH bpf-next 1/7] tools: bpftool: silence 'missing initializer' warnings

From: Jakub Kicinski <hidden>
Date: 2018-03-09 07:38:15

On Thu,  8 Mar 2018 23:00:35 +0100, Jiri Benc wrote:
When building bpf tool, gcc emits piles of warnings:

prog.c: In function ‘prog_fd_by_tag’:
prog.c:101:9: warning: missing initializer for field ‘type’ of ‘struct bpf_prog_info’ [-Wmissing-field-initializers]
  struct bpf_prog_info info = {};
         ^
In file included from /home/storage/jbenc/git/net-next/tools/lib/bpf/bpf.h:26:0,
                 from prog.c:47:
/home/storage/jbenc/git/net-next/tools/include/uapi/linux/bpf.h:925:8: note: ‘type’ declared here
  __u32 type;
        ^

As these warnings are not useful, switch them off.

Signed-off-by: Jiri Benc <redacted>
FWIW I couldn't reproduce this one.  Out of curiosity what GCC did you
use?

Re: [PATCH bpf-next 1/7] tools: bpftool: silence 'missing initializer' warnings

From: Jiri Benc <hidden>
Date: 2018-03-09 08:42:49

On Thu, 8 Mar 2018 23:38:12 -0800, Jakub Kicinski wrote:
FWIW I couldn't reproduce this one.  Out of curiosity what GCC did you
use?
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)

 Jiri

Re: [PATCH bpf-next 0/7] tools: bpf: standardize make

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2018-03-09 09:29:02

On 03/08/2018 11:00 PM, Jiri Benc wrote:
Currently, 'make bpf' in the tools/ directory does not provide the standard
quiet output except for bpftool (which is however listed with a wrong
directory). Worse, it does not respect the build output directory.

The 'make bpf_install' does not work as one would expect, either. It
installs unconditionally to /usr/bin without respecting DESTDIR and prefix.

This patchset improves that behavior.

Jiri Benc (7):
  tools: bpftool: silence 'missing initializer' warnings
  tools: bpf: respect output directory during build
  tools: bpf: consistent make bpf_install
  tools: bpf: make install should build first
  tools: bpf: call descend in Makefile
  tools: bpf: respect quiet/verbose build
  tools: bpf: silence make by not deleting intermediate file

 tools/bpf/Makefile         | 74 +++++++++++++++++++++++++++++++---------------
 tools/bpf/bpftool/Makefile |  2 +-
 2 files changed, 51 insertions(+), 25 deletions(-)
Looks good to me as well, applied to bpf-next, thanks Jiri!
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help